AI时代个人量化实战:从零搭建backtrader策略工作流
1. 为什么个人做量化这件事在AI时代突然变得可行了三年前如果有人跟我说你一个人也能搞出一套能跑的量化策略我大概率会笑笑不说话。那时候做量化是什么门槛你得有Wind或者聚宽的终端账号得会写Python还得懂金融工程得自己搭数据库存行情得租服务器跑回测还得有人帮你盯着实盘的风控。一套流程下来没个团队根本转不动。但这两年情况变了而且变得很彻底。我自己从2023年开始断断续续折腾个人量化中间踩了无数坑也见证了整个工具链的成熟。现在我的判断是AI时代给个人投资者最大的红利不是让AI帮你选股而是让AI帮你把从想法到可回测策略这条链路的成本压到了几乎为零。这个判断背后有三个具体的变化值得展开说。1.1 写代码这件事的门槛被AI削平了以前写一个backtrader策略你得先啃文档搞清楚next()和notify_order()的调用时机搞清楚self.datas[0].close[0]和self.data.close[0]的区别搞清楚cheat_on_open到底什么时候该开。光是这些API细节就能劝退一大半人。现在你完全可以用自然语言描述你的想法让AI帮你生成骨架代码然后你只负责改逻辑、调参数、验证结果。我实测下来一个中等复杂度的策略比如双均线加ATR止损加仓位管理从想法到能跑通回测熟练之后两三个小时就能搞定。这个效率在以前是不可想象的。但这里有个关键点必须说清楚AI帮你写的是代码不是策略。策略的逻辑、参数的选择、风险的判断这些还是得你自己来。很多人误以为让AI生成一个策略就能赚钱这是最大的认知陷阱。AI是加速器不是印钞机。1.2 数据获取的成本大幅下降以前个人拿不到干净的行情数据要么买要么爬要么用别人整理好的但质量存疑的。现在主流的开源数据源比如akshare、tushare的免费额度、yfinance已经能覆盖大部分日线和分钟线需求。对于个人做策略验证来说这些数据完全够用。我自己的做法是先用免费数据源做策略逻辑验证确认逻辑成立之后再考虑要不要上更精细的数据。不要一上来就追求完美数据那是本末倒置。策略逻辑不成立给你再干净的数据也白搭。1.3 回测框架的成熟让验证变得简单backtrader、vectorbt、qlib这些框架现在文档和社区都相对成熟了。特别是backtrader虽然它有点老但胜在稳定、灵活、社区案例多。你遇到的大部分问题网上都能搜到答案。我选backtrader的原因很简单它的编程模型清晰策略逻辑和数据处理分离得好而且支持多股回测。这一点对个人做组合策略特别重要因为你不可能只交易一只股票。提示如果你刚开始接触量化不要一上来就追求最先进的框架。选一个社区活跃、文档齐全、你能看懂的比选一个性能最强但你搞不定的要强一百倍。2. 从零搭一套个人量化工作流的完整拆解这一节我把自己的实际工作流完整拆开讲。不是理论是我每天在用的东西。2.1 环境准备别在环境上浪费时间我的环境配置很朴素Python 3.103.11也行但有些库对3.12支持还不完善backtrader 1.9.78pandas、numpy、matplotlibakshare做数据获取jupyter notebook做策略探索安装就是标准的pip流程pip install backtrader akshare pandas numpy matplotlib jupyter这里有个坑我踩过backtrader和某些版本的pandas有兼容性问题。如果你发现回测跑出来的结果明显不对先检查pandas版本。我目前用的是pandas 2.0.3配合backtrader 1.9.78没问题。另一个坑是akshare的接口经常变。这个没办法开源项目就是这样。我的建议是把数据获取和策略逻辑彻底分开。数据获取写成一个独立的模块接口变了只改那一个地方策略代码不动。2.2 数据层怎么拿到干净可用的行情数据我用的数据获取逻辑大概是这样import akshare as ak import pandas as pd def get_stock_data(symbol, start_date, end_date): df ak.stock_zh_a_hist( symbolsymbol, perioddaily, start_datestart_date, end_dateend_date, adjustqfq # 前复权 ) df df.rename(columns{ 日期: datetime, 开盘: open, 最高: high, 最低: low, 收盘: close, 成交量: volume }) df[datetime] pd.to_datetime(df[datetime]) df df.set_index(datetime) return df[[open, high, low, close, volume]]几个关键决策点复权方式选前复权。后复权适合做长期收益分析前复权适合做策略回测因为前复权后的价格和当前价格一致你看到的信号更直观。这个选择没有绝对对错但回测场景下前复权更常用。数据频率选日线起步。分钟线数据量大、噪音多、对执行要求高个人做策略验证阶段完全没必要。日线策略跑通了再考虑要不要下沉到分钟级。多股回测的数据对齐。这是backtrader多股回测最容易出问题的地方。不同股票的交易日可能不一致停牌、新股等你需要确保所有数据在同一个时间轴上对齐。我的做法是先用pandas把所有股票的数据合并到一个DataFrame处理完缺失值再喂给backtrader。2.3 策略层一个可复用的策略骨架下面这个骨架是我自己用的你可以直接抄import backtrader as bt class MyStrategy(bt.Strategy): params ( (fast_period, 10), (slow_period, 30), (atr_period, 14), (atr_mult, 2.0), (risk_per_trade, 0.02), ) def __init__(self): self.fast_ma bt.indicators.SMA( self.data.close, periodself.params.fast_period ) self.slow_ma bt.indicators.SMA( self.data.close, periodself.params.slow_period ) self.atr bt.indicators.ATR( self.data, periodself.params.atr_period ) self.crossover bt.indicators.CrossOver( self.fast_ma, self.slow_ma ) self.order None def next(self): if self.order: return if not self.position: if self.crossover 0: size self.calc_position_size() self.order self.buy(sizesize) else: if self.crossover 0: self.order self.close() def calc_position_size(self): cash self.broker.getcash() price self.data.close[0] atr_value self.atr[0] risk_amount cash * self.params.risk_per_trade size int(risk_amount / (atr_value * self.params.atr_mult)) max_size int(cash * 0.95 / price) return min(size, max_size) def notify_order(self, order): if order.status in [order.Completed, order.Canceled, order.Margin]: self.order None这个骨架里有几个设计决策值得解释为什么用ATR做仓位管理因为固定手数在不同波动率环境下风险敞口完全不同。ATR能自适应波动率波动大的时候自动减仓波动小的时候自动加仓。这是从机构做法里简化来的个人用完全够。为什么用self.order做状态锁防止重复下单。backtrader的next()每个bar都会调用如果你不锁状态可能在同一个bar里反复触发买入信号。为什么仓位上限是95%留5%的现金缓冲防止因为滑点或者手续费导致保证金不足。这个比例可以根据你的标的调整。2.4 回测层怎么跑出可信的结果回测配置我一般这样写import backtrader as bt cerebro bt.Cerebro() cerebro.addstrategy(MyStrategy) # 添加多只股票 for symbol in [600519, 000858, 601318]: data bt.feeds.PandasData(datanameget_stock_data(symbol, 20200101, 20241231)) cerebro.adddata(data, namesymbol) # 设置初始资金 cerebro.broker.setcash(1000000) # 设置手续费 cerebro.broker.setcommission(commission0.0003) # 设置滑点 cerebro.broker.set_slippage_perc(0.001) # 添加分析器 cerebro.addanalyzer(bt.analyzers.SharpeRatio, _namesharpe) cerebro.addanalyzer(bt.analyzers.DrawDown, _namedrawdown) cerebro.addanalyzer(bt.analyzers.Returns, _namereturns) cerebro.addanalyzer(bt.analyzers.TradeAnalyzer, _nametrades) results cerebro.run()手续费和滑点必须设。我见过太多人回测不设手续费跑出来年化50%实盘一跑亏成狗。A股的手续费大概万三加上印花税和滑点实际成本比你想的高。滑点设0.1%是个保守估计流动性好的票可以设低一点。多股回测的资金分配。backtrader默认是共享资金池这意味着你的策略需要在多个标的之间做资金分配。我的做法是每个标的分配固定比例的资金比如三只股票各分30%留10%现金。这个逻辑需要在策略里自己实现。3. AI在量化工作流里到底该放在哪个位置这是我最想聊的部分因为大部分人把AI用错了地方。3.1 AI最该干的事代码生成和调试我现在的习惯是任何重复性的代码工作先问AI。比如帮我写一个backtrader的MACD策略骨架这段代码报错KeyError帮我看看问题在哪怎么在backtrader里实现移动止损帮我把这个策略改成多股回测的版本这些场景AI的表现非常好因为它有大量的backtrader代码训练数据。你描述清楚需求它给的代码大概率能跑你只需要微调。但注意AI生成的代码一定要自己读一遍。我遇到过AI生成的代码里用了未来函数比如在next()里用了self.data.close[1]这种未来数据回测结果漂亮得离谱实盘根本没法用。这种坑必须自己识别。3.2 AI不该干的事替你决定策略逻辑这是我最想强调的一点。策略的核心逻辑必须来自你自己的市场理解不能来自AI。为什么因为AI不知道当前的市场环境不知道你的风险偏好不知道你的资金规模不知道你的执行能力。它只能给你一个统计上看起来合理的逻辑但这个逻辑在真实市场里能不能赚钱AI不知道。我自己的做法是策略想法来自我对市场的观察AI只负责帮我把想法变成代码。比如我观察到某个板块在特定条件下有动量效应我会先手动验证这个观察确认逻辑成立再让AI帮我写回测代码。3.3 用AI做策略迭代的正确姿势策略开发不是一次性的是一个迭代过程。我的迭代流程大概是这样提出假设基于市场观察提出一个可验证的假设AI生成代码让AI把假设变成可回测的代码跑回测看结果是否符合预期分析问题如果不符合是逻辑问题还是参数问题调整再跑修改逻辑或参数重复这个流程里AI在第2步和第4步能帮上大忙。第4步尤其重要你可以把回测结果贴给AI让它帮你分析可能的问题。但最终的判断还是得你自己做。注意不要陷入参数优化的陷阱。很多人跑回测发现结果不好就疯狂调参数调到回测曲线漂亮为止。这是典型的过拟合实盘必死。参数应该基于逻辑设定而不是基于回测结果反推。4. 个人量化最容易踩的五个坑这一节全是血泪教训每一条我都亲自踩过。4.1 未来函数回测漂亮实盘亏钱的元凶未来函数是指你在回测中使用了当时不可能知道的信息。最常见的几种在next()里用了self.data.close[1]下一个bar的收盘价用当天的最高价最低价做信号判断但实际执行时你不知道当天的高低点用复权后的价格做信号但复权信息是事后才知道的检测方法把你的策略逻辑逐行读一遍问自己这个信息在当时的时点能拿到吗如果答案是否定的就是未来函数。4.2 过拟合回测曲线越漂亮越危险过拟合的典型表现策略在历史数据上表现完美但换个时间段或者换个标的就崩了。防范方法样本内和样本外分开。用2020-2022的数据开发策略用2023-2024的数据验证。参数不要太多。一个策略超过5个参数过拟合风险就很高了。逻辑要简单。越简单的逻辑越不容易过拟合。4.3 忽略交易成本纸面富贵我早期做过一个高频策略回测年化40%实盘一跑手续费和滑点吃掉了35%净收益5%。这就是忽略交易成本的代价。正确做法回测时把手续费设成实际水平滑点设成保守估计。如果你的策略在扣除成本后还有正收益才值得进一步研究。4.4 数据质量问题垃圾进垃圾出数据问题包括缺失值、异常值、复权错误、停牌处理不当。这些问题在回测里可能不明显但实盘会要命。我的检查清单检查数据是否有缺失的交易日检查是否有价格异常比如一天涨跌超过50%检查复权是否正确对比不同数据源检查停牌期间的数据处理4.5 心理陷阱回测和实盘是两回事回测里你可以冷静地执行每一个信号实盘里你会恐惧、会贪婪、会犹豫。这是最大的坑也是最难克服的。我的建议先用小资金实盘跑一段时间感受一下真实的市场压力。不要一上来就重仓那是在交学费。5. 一套完整的策略开发实例双均线加ATR止损这一节我把一个完整的策略开发过程走一遍从想法到回测结果。5.1 策略逻辑核心逻辑很简单快线上穿慢线买入快线下穿慢线卖出用ATR做动态止损用ATR做仓位管理这个逻辑不新鲜但胜在简单、可解释、不容易过拟合。5.2 参数选择参数选择基于逻辑不是基于回测快线10日代表短期趋势慢线30日代表中期趋势ATR 14日标准的波动率周期ATR倍数2.0止损设在2倍ATR之外给价格足够的波动空间这些参数都是行业常用值不是我调出来的。用常用值的好处是如果策略不赚钱大概率是逻辑问题不是参数问题。5.3 回测结果分析跑完回测后重点看这几个指标指标含义参考标准年化收益策略的盈利能力跑赢基准指数最大回撤最坏情况下的亏损控制在20%以内夏普比率风险调整后收益大于1算合格胜率盈利交易占比40%-60%都正常盈亏比平均盈利/平均亏损大于1.5比较健康交易次数策略的活跃度太少说明信号稀疏不要只看年化收益。一个年化30%但最大回撤50%的策略和一个年化15%但最大回撤10%的策略后者更适合个人。5.4 策略改进方向如果回测结果不理想可以从这几个方向改进加入趋势过滤比如只在长期均线之上做多加入波动率过滤高波动率时降低仓位加入时间过滤避开财报发布等特殊时期优化出场逻辑比如用移动止损代替固定止损每次改进只改一个地方改完重新回测对比结果。这样才能知道哪个改动真正有效。6. 从回测到实盘最后一段路怎么走回测跑通只是第一步实盘才是真正的考验。6.1 模拟盘验证在实盘之前先用模拟盘跑至少一个月。模拟盘能帮你发现很多回测发现不了的问题信号延迟、执行滑点、数据更新问题等。6.2 小资金实盘模拟盘没问题后用小资金实盘。这个阶段的目标不是赚钱是验证策略在真实环境下的表现。资金量控制在你能承受的亏损范围内。6.3 逐步加仓小资金实盘跑通后逐步加仓。每次加仓后观察一段时间确认策略表现稳定再加下一次。不要一次性把资金全投进去。6.4 持续监控实盘不是一劳永逸的。市场环境会变策略表现会衰减。你需要持续监控策略的表现发现异常及时处理。我自己的监控指标包括滚动夏普比率、滚动最大回撤、连续亏损次数。任何一个指标超出历史范围就要警惕了。7. 个人量化的现实预期最后说点实在的。个人做量化能做成什么样我的观察是大部分人做不出稳定盈利的策略但这不代表做量化没有价值。做量化的过程本身会极大地提升你对市场的理解。你会被迫去思考什么是趋势什么是波动什么是风险这些问题想清楚了即使策略不赚钱你的投资决策也会更理性。如果你真的想做出一套能用的策略我的建议是降低预期不要想着年化50%能跑赢指数就是胜利控制风险活着比赚钱重要持续学习市场在变策略也要变保持耐心策略开发是长期工程不是一蹴而就的AI时代给了个人做量化的工具和效率但没给个人做量化的圣杯。工具再好也得靠人来用。这个道理放在哪个时代都成立。