用 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)、风险控制、实盘接口等。但所有这些都建立在可靠的数据基础上,先把数据获取和清洗做好。