共计 2217 个字符,预计需要花费 6 分钟才能阅读完成。
背景痛点
A 股市场与成熟市场相比存在诸多特殊交易规则,这些规则直接影响量化策略的设计:

- T+ 1 交易制度:当日买入的股票需次日才能卖出,这限制了日内高频策略的应用,迫使策略必须考虑更长的持仓周期。
- 涨跌停限制:普通股票每日涨跌幅为 10%(ST 股 5%),极端行情时流动性骤降,需在回测中模拟真实成交难度。
- 手续费较高:买卖双边合计约 0.15% 的成本(佣金 + 印花税),对高频策略是重大损耗。
- 数据质量参差:免费数据源常有字段缺失、停牌未标记等问题,需专门清洗。
技术选型
数据接口对比
- akshare:
- 优势:完全免费、品种覆盖全(含指数 / 基金 / 期货)、更新及时
- 劣势:部分接口稳定性依赖第三方网站
- tushare pro:
- 优势:数据清洗较好、API 规范
- 劣势:需积分兑换高频数据
回测框架对比
- backtrader:
- 优势:事件驱动架构、支持多资产回测、可视化方便
- 劣势:学习曲线较陡
- pyfolio:
- 优势:专业分析报表(夏普比率、最大回撤等)
- 劣势:需搭配其他框架使用
核心实现
数据获取与清洗
使用 akshare 获取日线数据示例(带重试机制):
import akshare as ak
from retrying import retry
@retry(stop_max_attempt_number=3, wait_fixed=2000)
def get_stock_daily(stock_code):
df = ak.stock_zh_a_daily(symbol=stock_code, adjust="hfq") # 获取后复权数据
# 处理停牌日
df = df[df["volume"] > 0].copy()
# 重命名列以兼容 backtrader
df.rename(columns={"date":"datetime", "open":"open",
"high":"high", "low":"low",
"close":"close", "volume":"volume"}, inplace=True)
df["datetime"] = pd.to_datetime(df["datetime"])
df.set_index("datetime", inplace=True)
return df
双均线策略实现
完整 backtrader 策略类代码:
import backtrader as bt
class DualSMAStrategy(bt.Strategy):
params = (('fast_period', 5), # 快线周期
('slow_period', 20), # 慢线周期
)
def __init__(self):
# 避免未来函数:指标计算必须只用历史数据
self.fast_ma = bt.indicators.SMA(period=self.p.fast_period)
self.slow_ma = bt.indicators.SMA(period=self.p.slow_period)
self.crossover = bt.indicators.CrossOver(self.fast_ma, self.slow_ma)
def next(self):
if not self.position: # 无持仓时
if self.crossover > 0: # 金叉
self.buy(size=100) # 固定数量下单
elif self.crossover < 0: # 死叉
self.close() # 平仓
# 回测设置
cerebro = bt.Cerebro()
data = bt.feeds.PandasData(dataname=get_stock_daily("600519")) # 茅台示例
cerebro.adddata(data)
cerebro.addstrategy(DualSMAStrategy)
cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name='sharpe')
results = cerebro.run()
print(f"夏普比率: {results[0].analyzers.sharpe.get_analysis()['sharperatio']:.2f}")
生产环境考量
- 网络请求容错:
- 使用 retrying 库自动重试失败请求
-
本地缓存历史数据减少重复请求
-
避免未来函数:
- 所有指标计算必须在
__init__中完成 -
next()中只能引用预计算好的指标
-
过拟合防范:
- 采用 Walk Forward 分析:将数据分为训练集 / 测试集
- 参数网格搜索时使用交叉验证
避坑指南
- 未考虑涨跌停无法买卖:
-
解决方案:在 next()中检查当日涨跌停状态
def next(self): if self.data.close[0] >= self.data.high_limit[0]: # 涨停 return # 不执行买入 -
忽略交易成本导致收益虚高:
-
解决方案:设置精确佣金
cerebro.broker.setcommission(commission=0.0015) # 万 15 -
使用复权价格但未处理股本变动:
- 解决方案:始终获取后复权 (hfq) 数据
总结与延伸
本文方案已实现量化交易的基础闭环,后续可优化方向:
- 参数优化:
- 使用 Optunity 库进行贝叶斯优化
-
对不同股票自适应参数组合
-
风险控制模块:
- 加入单笔最大亏损止损
-
组合层面控制最大回撤
-
实时交易对接:
- 通过券商 API 实现自动化下单
- 添加交易信号邮件提醒功能
建议先用模拟盘验证策略效果,再逐步投入实盘资金。量化交易是不断迭代的过程,需持续跟踪策略表现并及时调整。
正文完
