Python量化交易入门:获取股票数据

用 Python 做量化交易的第一步是获取行情数据。本文介绍如何用 akshare 获取 A 股数据,并进行基本的 K 线分析和可视化。

环境准备

pip install akshare pandas matplotlib mplfinance

akshare 是一个开源的金融数据接口库,免费且不需要注册,适合入门练手。

获取个股日K数据

import akshare as ak
import pandas as pd

# 获取平安银行(000001)的日K数据
df = ak.stock_zh_a_hist(
    symbol="000001",
    period="daily",
    start_date="20210101",
    end_date="20210401",
    adjust="qfq"  # 前复权
)

print(df.head())
print(f"共 {len(df)} 条记录")
print(f"列名: {list(df.columns)}")

返回的 DataFrame 包含:日期、开盘、收盘、最高、最低、成交量、成交额、振幅、涨跌幅、涨跌额、换手率。

数据清洗

# 重命名列,方便后续使用
df.columns = ['date', 'open', 'close', 'high', 'low',
              'volume', 'amount', 'amplitude', 'pct_change',
              'change', 'turnover']

# 转换日期格式
df['date'] = pd.to_datetime(df['date'])
df.set_index('date', inplace=True)

# 数据类型转换
for col in ['open', 'close', 'high', 'low', 'volume']:
    df[col] = df[col].astype(float)

print(df.dtypes)
print(df.describe())

计算均线

# 计算 5日、10日、20日 均线
df['ma5'] = df['close'].rolling(window=5).mean()
df['ma10'] = df['close'].rolling(window=10).mean()
df['ma20'] = df['close'].rolling(window=20).mean()

# 查看最近几天的均线
print(df[['close', 'ma5', 'ma10', 'ma20']].tail(10))

均线的含义:MA5 反映短期趋势,MA20 反映中期趋势。当短期均线上穿长期均线(金叉)时通常被认为是买入信号,反之(死叉)是卖出信号。

简单的金叉/死叉信号

# 标记金叉和死叉
df['signal'] = 0
# 金叉:MA5 上穿 MA20
df.loc[(df['ma5'] > df['ma20']) &
       (df['ma5'].shift(1) <= df['ma20'].shift(1)), 'signal'] = 1
# 死叉:MA5 下穿 MA20
df.loc[(df['ma5'] < df['ma20']) &
       (df['ma5'].shift(1) >= df['ma20'].shift(1)), 'signal'] = -1

golden_cross = df[df['signal'] == 1]
death_cross = df[df['signal'] == -1]
print(f"金叉次数: {len(golden_cross)}")
print(f"死叉次数: {len(death_cross)}")

画K线图

用 mplfinance 画专业的 K 线图:

import mplfinance as mpf

# 准备数据格式(mplfinance 要求 OHLCV 列名)
plot_df = df[['open', 'high', 'low', 'close', 'volume']].copy()
plot_df.columns = ['Open', 'High', 'Low', 'Close', 'Volume']

# 添加均线
add_plots = [
    mpf.make_addplot(df['ma5'], color='orange', width=0.8),
    mpf.make_addplot(df['ma10'], color='blue', width=0.8),
    mpf.make_addplot(df['ma20'], color='purple', width=0.8),
]

# 画图
mpf.plot(
    plot_df,
    type='candle',
    style='charles',
    title='000001 Daily K-Line',
    ylabel='Price',
    ylabel_lower='Volume',
    volume=True,
    addplot=add_plots,
    figsize=(14, 8),
    savefig='kline_000001.png'
)
print("K线图已保存到 kline_000001.png")

用 matplotlib 手动画均线图

import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'] = ['SimHei']  # 中文显示
plt.rcParams['axes.unicode_minus'] = False

fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(14, 8),
                                gridspec_kw={'height_ratios': [3, 1]})

# 价格和均线
ax1.plot(df.index, df['close'], label='收盘价', linewidth=1)
ax1.plot(df.index, df['ma5'], label='MA5', linewidth=0.8)
ax1.plot(df.index, df['ma10'], label='MA10', linewidth=0.8)
ax1.plot(df.index, df['ma20'], label='MA20', linewidth=0.8)

# 标记金叉死叉
for idx in golden_cross.index:
    ax1.annotate('金', xy=(idx, df.loc[idx, 'close']),
                 fontsize=8, color='red')
for idx in death_cross.index:
    ax1.annotate('死', xy=(idx, df.loc[idx, 'close']),
                 fontsize=8, color='green')

ax1.set_title('平安银行(000001) 2021Q1')
ax1.legend()
ax1.grid(True, alpha=0.3)

# 成交量
colors = ['red' if c >= o else 'green'
          for c, o in zip(df['close'], df['open'])]
ax2.bar(df.index, df['volume'], color=colors, width=0.8)
ax2.set_ylabel('成交量')
ax2.grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig('analysis_000001.png', dpi=100)
print("分析图已保存")

关于 tushare

tushare pro 是另一个常用的数据源,需要注册获取 token:

import tushare as ts
ts.set_token('你的token')
pro = ts.pro_api()

df = pro.daily(ts_code='000001.SZ', start_date='20210101', end_date='20210401')

tushare 的数据质量更高,字段更全,但有积分限制。akshare 完全免费,入门阶段足够用。

小结

获取数据只是量化的第一步。后续还需要学习策略回测(backtrader)、风险控制、实盘接口等。但所有这些都建立在可靠的数据基础上,先把数据获取和清洗做好。