1. 为什么"个人做量化"这件事在AI时代突然变得可行了
三年前如果有人跟我说"你一个人也能搞出一套能跑的量化策略",我大概率会笑笑不说话。那时候做量化是什么门槛?你得有Wind或者聚宽的终端账号,得会写Python还得懂金融工程,得自己搭数据库存行情,得写回测框架,还得有台像样的服务器跑数据。光是数据这一块,一年下来就是几万块的成本,个人根本玩不起。
但现在情况完全变了。我最近半年重新捡起量化这件事,最大的感受就是:AI把量化开发的门槛从"团队级"拉到了"个人级"。这不是一句空话,我拆开来讲讲到底变了什么。
1.1 从"写代码"到"描述需求"的转变
以前写一个双均线策略,你得自己写数据获取、写信号计算、写回测循环、写绩效统计,一套下来两三百行代码,中间任何一个地方写错,回测结果就是错的,而且你还未必能发现。现在呢?你把需求描述清楚,AI能帮你把框架代码生成出来,你只需要做审查和调优。
我实测过一个场景:让AI帮我写一个"基于布林带突破+成交量过滤"的策略骨架,从描述到能跑通,大概花了二十分钟。这二十分钟里,我大部分时间是在跟AI确认逻辑细节,而不是在敲代码。这个效率提升是实打实的。
但这里有个坑我必须提前说:AI生成的策略代码,逻辑正确性必须你自己把关。我见过太多人直接把AI生成的代码拿去回测,跑出来年化50%就兴奋得不行,结果一看是未来函数(用了当天收盘价做当天开盘的决策),这种错误AI不一定会主动帮你规避。
1.2 数据获取不再是拦路虎
以前个人做量化,数据是最大的成本项。现在免费的数据源虽然质量参差不齐,但对于个人学习和策略验证来说,已经够用了。像A股日线数据,通过一些公开的接口就能拿到,虽然可能需要自己做一些清洗和拼接,但至少不用花大价钱买终端了。
我自己的做法是:先用免费数据源把策略逻辑跑通,确认策略有效之后,再考虑要不要上更高质量的数据。这个顺序很重要,很多人一上来就纠结数据质量,结果策略逻辑还没验证清楚,钱先花出去了。
1.3 回测框架的成熟让"造轮子"成为过去式
Backtrader、vnpy这些开源框架现在已经很成熟了。你不需要从零写回测引擎,直接用现成的框架,把精力放在策略逻辑本身。Backtrader的多股回测能力尤其适合个人做组合策略验证,这个后面我会详细讲。
提示:不要一上来就追求"全自动交易"。个人做量化,第一步应该是"能回测出一个靠谱的策略",而不是"能自动下单"。顺序搞反了,容易亏钱。
2. 个人量化策略开发的核心链路拆解
很多人对量化有个误解,觉得量化就是"写个公式让电脑自动买卖"。实际上,一套完整的量化策略开发链路要复杂得多。我把它拆成五个环节,每个环节都有各自的坑。
2.1 策略想法的来源:别凭空造轮子
策略想法从哪来?我的经验是三个渠道:经典策略的变种、市场观察的量化表达、学术论文的工程化落地。
经典策略变种是最容易上手的。比如双均线策略,你可以改成三均线、可以加成交量过滤、可以改成自适应均线。这些变种不需要你有多深的金融理论功底,但需要你有耐心去测试不同参数组合。
市场观察的量化表达更有意思。比如你发现"每次大盘暴跌之后,小盘股反弹力度更大",这就是一个可以量化的观察。你需要把它翻译成明确的规则:什么叫"暴跌"?跌多少算暴跌?"反弹力度更大"怎么衡量?持有周期多长?把这些模糊的观察变成精确的规则,就是量化的核心工作。
学术论文的工程化落地门槛最高,但收益也可能最大。很多金融工程论文里提出的因子,在A股市场可能还有效。但论文里的假设条件和实际市场有差距,你需要做大量的适配工作。
2.2 数据清洗:80%的时间花在这里
我做过统计,一个策略从想法到能回测,大概80%的时间花在数据清洗上。这不是夸张。
A股数据有几个典型的坑:停牌、除权除息、涨跌停、新股上市初期数据异常。停牌期间的数据怎么处理?除权除息后的价格怎么复权?涨跌停当天能不能成交?这些问题不处理好,回测结果就是失真的。
我自己的处理原则是:停牌期间不交易,除权除息用前复权价格,涨跌停当天如果策略信号是买入且开盘就涨停,那就放弃这笔交易。这些规则看起来简单,但每一条都会显著影响回测结果。
2.3 回测框架选型:Backtrader还是自己写
回测框架的选择,我的建议是:除非你有特殊需求,否则直接用Backtrader。
Backtrader的优势在于:社区活跃、文档相对完善、支持多股回测、支持多种数据源。它的多股回测能力对个人做组合策略特别友好,你可以同时回测几十只股票,看策略在不同标的上的表现。
自己写回测框架的唯一理由是:你有非常特殊的策略需求,现有框架满足不了。但这种情况对个人来说很少见。我见过有人花三个月自己写回测框架,结果写出来的东西还不如Backtrader稳定。
2.4 参数优化:过拟合的重灾区
参数优化是量化里最容易自欺欺人的环节。你把均线周期从5到60全跑一遍,总能找到一组参数在历史上表现特别好。但这组参数在未来大概率会失效。
我的做法是:参数不要太多,每个参数的范围不要太大,优化目标要看夏普比率而不是收益率。一个策略如果有超过5个参数,过拟合的风险就很高了。参数范围太宽,找到的"最优参数"往往是噪声。
2.5 实盘验证:回测和实盘的差距
回测年化30%,实盘可能只有10%,甚至亏损。这个差距来自几个方面:滑点、手续费、流动性、信号延迟。
滑点是最容易被忽略的。回测里你假设按收盘价成交,但实盘里你可能是第二天开盘才能成交,这个价格差异可能就把利润吃掉了。手续费看起来不多,但高频策略里手续费能占到收益的一半以上。
3. AI在量化开发中到底能帮上什么忙
现在回到标题里的"AI时代"。AI在量化开发中的角色,我的定位是:它是一个高效的助手,但不是决策者。
3.1 代码生成:从策略描述到可运行代码
这是AI最直接的价值。你把策略逻辑用自然语言描述清楚,AI帮你生成Backtrader的策略类代码。我实测下来,对于中等复杂度的策略,AI生成的代码大概有70%可以直接用,剩下30%需要你调整。
调整的地方主要集中在:数据接口的适配、特殊处理逻辑(比如涨跌停过滤)、绩效统计的定制。这些调整需要你对Backtrader的API有一定了解,但不需要你从零写起。
3.2 代码审查:帮你发现逻辑漏洞
AI的第二个价值是代码审查。你把写好的策略代码丢给AI,让它帮你检查有没有逻辑错误。我试过几次,AI确实能发现一些我忽略的问题,比如变量作用域错误、循环边界条件错误。
但AI审查有个局限:它不懂金融逻辑。比如你写了一个"用未来数据做决策"的代码,AI可能不会主动指出来,因为它不知道这在量化里是严重错误。所以代码审查之后,金融逻辑的正确性还得你自己把关。
3.3 策略解释:把黑箱变成白箱
有些策略逻辑比较复杂,你自己写完之后可能都忘了当初为什么这么设计。这时候可以让AI帮你反向解释代码逻辑,生成一份策略说明文档。这个功能对于策略复盘和迭代特别有用。
3.4 AI的边界:它不能替你做的三件事
第一,AI不能替你判断策略是否有效。回测结果好不好,需要你自己结合市场环境、策略逻辑、风险收益特征来综合判断。
第二,AI不能替你控制风险。仓位管理、止损规则、最大回撤控制,这些需要你自己根据风险承受能力来设定。
第三,AI不能替你承担亏损。这一点最重要。AI生成的代码,最终执行的是你的账户,盈亏都是你的。所以任何AI生成的内容,你都必须自己审查、自己负责。
4. 从零搭建一套个人量化策略的实操步骤
这一节我给出一个完整的实操流程,以"基于动量的多股轮动策略"为例。这个策略的逻辑是:每周选过去20个交易日涨幅最大的5只股票,等权买入,持有一周后轮换。
4.1 环境准备与依赖安装
首先你需要一个Python环境,建议用Anaconda创建一个独立环境。核心依赖是:backtrader、pandas、numpy、akshare(免费数据源)。
conda create -n quant python=3.10 conda activate quant pip install backtrader pandas numpy akshare这里有个细节:backtrader对pandas的版本有一定要求,太新的pandas可能会有兼容性问题。我实测下来,pandas 1.5.x版本比较稳定。
4.2 数据获取与清洗
用akshare获取A股日线数据,然后做前复权处理。这一步的关键是处理停牌和涨跌停。
import akshare as ak import pandas as pd def get_stock_data(code, start_date, end_date): df = ak.stock_zh_a_hist(symbol=code, period="daily", start_date=start_date, end_date=end_date, adjust="qfq") df['date'] = pd.to_datetime(df['日期']) df = df.set_index('date') df = df[['开盘', '最高', '最低', '收盘', '成交量']] df.columns = ['open', 'high', 'low', 'close', 'volume'] return df清洗的时候要注意:如果某只股票在回测期间有停牌,停牌期间的数据要剔除,但复牌后的价格要衔接上。这个处理逻辑需要根据你的数据源来调整。
4.3 策略类的编写
Backtrader的策略类核心是next()方法,每个交易日调用一次。在这个方法里实现你的交易逻辑。
import backtrader as bt class MomentumRotation(bt.Strategy): params = ( ('lookback', 20), ('hold_num', 5), ('rebalance_days', 5), ) def __init__(self): self.day_count = 0 self.momentum = {} for data in self.datas: self.momentum[data._name] = bt.indicators.ROC( data.close, period=self.params.lookback) def next(self): self.day_count += 1 if self.day_count % self.params.rebalance_days != 0: return # 计算所有股票的动量 momentum_list = [] for data in self.datas: if len(data) < self.params.lookback: continue momentum_list.append((data._name, self.momentum[data._name][0])) # 按动量排序,选前N只 momentum_list.sort(key=lambda x: x[1], reverse=True) target = [x[0] for x in momentum_list[:self.params.hold_num]] # 调仓 for data in self.datas: if data._name in target: if not self.getposition(data): self.order_target_percent(data, target=1.0/self.params.hold_num) else: if self.getposition(data): self.close(data)这段代码有几个关键点:ROC是动量指标,rebalance_days控制调仓频率,order_target_percent按比例下单。注意这里用了1.0/hold_num作为单只股票的仓位,保证总仓位不超过100%。
4.4 回测运行与结果分析
回测运行的时候,要设置初始资金、手续费、滑点。手续费我一般设万分之三,滑点设千分之一。
cerebro = bt.Cerebro() cerebro.broker.setcash(100000) cerebro.broker.setcommission(commission=0.0003) cerebro.broker.set_slippage_perc(perc=0.001) # 添加数据 for code in stock_list: data = bt.feeds.PandasData(dataname=get_stock_data(code, '2020-01-01', '2023-12-31')) cerebro.adddata(data, name=code) cerebro.addstrategy(MomentumRotation) cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name='sharpe') cerebro.addanalyzer(bt.analyzers.DrawDown, _name='drawdown') cerebro.addanalyzer(bt.analyzers.Returns, _name='returns') results = cerebro.run() strat = results[0] print(f"夏普比率: {strat.analyzers.sharpe.get_analysis()}") print(f"最大回撤: {strat.analyzers.drawdown.get_analysis()}") print(f"收益率: {strat.analyzers.returns.get_analysis()}")回测结果出来之后,不要只看收益率。夏普比率、最大回撤、胜率、盈亏比这几个指标要综合看。一个策略如果夏普比率低于1,基本上不值得实盘。
4.5 参数敏感性测试
这一步很多人会跳过,但我觉得特别重要。你把lookback从15到30、hold_num从3到10、rebalance_days从3到10都跑一遍,看结果稳不稳定。
如果策略只在某一组参数下表现好,其他参数下表现很差,那这个策略大概率是过拟合的。好的策略应该在参数的小幅变动下,表现相对稳定。
5. 回测中最容易踩的五个坑
这一节我专门讲坑,因为我自己踩过,也见过太多人踩。
5.1 未来函数:最隐蔽也最致命
未来函数是指你在做决策的时候,用了当时还不可能知道的信息。最常见的场景是:用当天收盘价计算信号,然后假设当天开盘就能成交。这在现实中是不可能的。
排查方法:检查你的信号计算和下单逻辑,确保信号用的是T-1日的数据,下单用的是T日的开盘价或者T+1日的开盘价。
5.2 幸存者偏差:你选的股票池本身就有问题
如果你回测的时候,股票池用的是"现在还在上市的股票",那你就忽略了那些已经退市的股票。这些退市股票在退市前的表现往往很差,忽略它们会让回测结果虚高。
解决方法:尽量用历史成分股数据,或者至少把退市股票也纳入回测。这个数据获取有难度,但至少你要意识到这个偏差的存在。
5.3 过拟合:参数优化出来的"完美策略"
过拟合的表现是:回测曲线特别漂亮,但实盘一跑就亏。根本原因是策略学到了历史数据里的噪声,而不是真正的规律。
判断方法:把数据分成样本内和样本外。在样本内优化参数,在样本外验证。如果样本外表现和样本内差距很大,那就是过拟合了。
5.4 手续费和滑点低估:小成本吃掉大利润
很多人回测的时候手续费设万分之零点五,滑点设零。实盘的时候手续费是万分之二点五,滑点是千分之一。这一来一回,高频策略的利润就被吃光了。
我的建议:手续费按万分之三设,滑点按千分之一设。宁可高估成本,也不要低估。
5.5 流动性忽略:小盘股买不进也卖不出
回测里你假设想买多少就能买多少,但实盘里小盘股的流动性很差,你买多了会推高价格,卖多了会砸盘。
解决方法:在回测里加入成交量限制,比如单日买入量不超过该股票当日成交量的10%。这个限制会让回测结果更接近实盘。
6. 策略从回测到实盘之间还差什么
回测跑通了,不代表就能实盘。中间还有几道坎。
6.1 交易接口的对接
实盘需要对接券商接口。个人做量化,一般用券商的API或者第三方交易接口。这个环节的坑在于:接口的稳定性和延迟。回测里你假设下单立刻成交,实盘里可能延迟几秒甚至几十秒。
我的建议:先用模拟盘跑一段时间,熟悉接口的特性和延迟情况,再上实盘。
6.2 风控模块的加入
回测里你不需要风控,因为回测不会真的亏钱。实盘里风控是必须的。基本的