1. 为什么个人量化在AI时代突然变得可行了
三年前我跟几个做量化的朋友聊天,大家有个共识:个人做量化基本是给券商和交易所打工。数据要买、服务器要租、策略要反复调,最后跑出来的收益还不够覆盖成本。但这两年情况完全变了,我自己从零开始搭了一套还算能用的策略系统,整个过程踩了不少坑,也积累了一些真正管用的经验。这篇文章就把我走过的路完整拆一遍,从思路设计到代码落地,再到回测验证和实盘注意事项,尽量说透。
先说清楚这篇文章适合谁看。如果你是对量化交易感兴趣但还没入门的新手,我会把每个环节的原理和操作都讲明白,你照着做能跑通第一套策略。如果你已经有一些编程基础,想用AI工具加速策略开发,那中间关于Codex辅助编码、Backtrader多股回测的部分会对你有直接帮助。如果你纯粹是想了解个人量化到底能不能赚钱、需要投入多少精力,我也会给出真实的成本收益分析。
核心观点先摆出来:AI时代个人做量化的最大红利,不是AI能帮你预测涨跌,而是它把策略开发的门槛从“会写代码+懂金融+有数据”降到了“有想法+会提问+能验证”。以前一个策略从想法到回测需要几天甚至几周,现在借助AI辅助编码和成熟的回测框架,几个小时就能跑出第一版结果。这个效率提升才是真正改变游戏规则的地方。
但这里有个关键前提:你得知道怎么问、怎么验、怎么调。AI生成的代码经常有逻辑漏洞,回测框架的参数设置稍有不慎就会产生未来函数,策略在样本内表现完美、样本外一塌糊涂。这些问题我在实操中都遇到过,后面会逐一拆解。
2. 策略开发的核心思路与工具选型
2.1 个人量化的策略定位:别想着战胜市场
刚开始做量化的人最容易犯的错误,是想着找一个能稳定跑赢指数的策略。我当初也是这个心态,花了两三个月研究各种技术指标组合,结果实盘一跑就亏。后来想明白了:个人量化的优势不在于预测能力,而在于灵活性和纪律性。
机构做量化有资金规模限制,策略容量小了不值得做,大了又会影响市场。个人没这个问题,几万到几十万的本金,很多小容量策略都能跑。而且个人没有排名压力,不需要每季度向投资人交代,可以承受更长的回撤周期。所以个人策略的定位应该是:找到几个逻辑清晰、容量不大但收益稳定的策略,通过分散配置来控制整体风险。
具体到策略类型,我建议从趋势跟踪和均值回归这两个大类入手。趋势跟踪的逻辑是“涨了还会涨”,适合波动性大的品种;均值回归的逻辑是“涨多了会跌”,适合震荡市场。这两种策略在不同市场环境下表现互补,组合起来能平滑收益曲线。
2.2 工具链选型:为什么是Python+Backtrader+Codex
工具选型这块我试过不少方案,最终稳定在Python+Backtrader+Codex这个组合。逐个说下理由。
Python不用多解释,量化领域的绝对主流。pandas处理数据、numpy做数值计算、matplotlib画图,整个生态非常成熟。而且AI辅助编码工具对Python的支持最好,Codex生成Python代码的准确率明显高于其他语言。
Backtrader是我对比了多个回测框架后的选择。vnpy功能全但太重,适合机构级应用;zipline环境配置麻烦,对新手不友好;Backtrader刚好在中间,轻量但功能完整,支持多股回测、多策略并行、参数优化,文档也还算清楚。最关键的是它的事件驱动架构和实盘逻辑一致,回测通过的策略改几行就能接实盘。
Codex在这里的角色是加速器。我自己的用法是:先用自然语言描述策略逻辑,让Codex生成基础代码框架,然后自己逐行审查逻辑,修改参数和边界条件。这样比从零手写快很多,但又不会完全依赖AI导致逻辑失控。实测下来,一个中等复杂度的策略,从想法到可回测的代码,用Codex辅助大概能节省60%到70%的时间。
注意:Codex生成的代码必须逐行审查,尤其是涉及买卖信号判断、仓位计算、止损止盈的部分。我遇到过AI把“大于”写成“大于等于”导致信号提前触发的情况,回测结果差异很大。
2.3 数据源的获取与清洗
数据是量化的基础,这块不能省。个人能获取的数据源主要有几类:免费的历史行情数据、券商提供的接口数据、以及一些开源数据项目。
免费数据源里,tushare和akshare是我常用的。tushare需要积分,但基础行情数据够用;akshare完全免费,数据覆盖面也广。如果做A股回测,这两个基本能满足日线级别的需求。分钟级数据获取难度大一些,但个人策略用日线已经足够。
数据清洗这块有几个关键点。首先是复权处理,前复权适合回测,后复权适合看历史真实价格。其次是停牌和涨跌停的处理,停牌期间不能交易,涨跌停时可能买不进也卖不出,回测时必须考虑这些约束,否则结果会严重高估。最后是幸存者偏差,如果你只用当前还在上市的股票做回测,那些退市的股票就被排除了,这会导致回测收益虚高。
我的做法是:用akshare获取全市场股票列表,包括已退市的,然后逐个拉取历史数据,存入本地数据库。清洗时统一做前复权处理,标记停牌和涨跌停日期,回测时这些日期不产生交易信号。
3. 用Codex辅助开发策略代码的实操流程
3.1 如何向Codex描述策略逻辑
跟Codex沟通策略逻辑,关键是把模糊的想法转化成明确的规则。我总结了一个描述模板,包含五个要素:标的范围、信号条件、仓位规则、止损止盈、调仓频率。
举个例子,我想做一个简单的双均线趋势策略。描述给Codex的提示词是这样的:
请用Python和Backtrader框架编写一个双均线策略: - 标的:沪深300成分股,最多同时持有5只 - 信号:5日均线上穿20日均线买入,下穿卖出 - 仓位:每只股票等权分配,总仓位不超过80% - 止损:单只股票亏损超过8%强制卖出 - 调仓:每日收盘前检查信号,次日开盘执行这样描述比“帮我写个均线策略”要明确得多,Codex生成的代码基本框架不会跑偏。但即便如此,生成后还是要检查几个关键点:均线计算用的是收盘价还是开盘价、金叉死叉的判断是否包含当日数据、仓位分配是否考虑了已持仓股票。
3.2 代码审查的重点清单
Codex生成的代码我一般按这个清单逐项检查:
| 检查项 | 常见问题 | 后果 |
|---|---|---|
| 数据对齐 | 不同股票日期不对齐 | 回测结果错乱 |
| 未来函数 | 用了当日收盘价判断当日交易 | 回测虚高 |
| 仓位计算 | 未考虑已持仓和现金 | 超仓或资金不足 |
| 止损逻辑 | 止损价与成交价混淆 | 实际亏损超预期 |
| 手续费 | 未扣除或扣除不足 | 收益高估 |
未来函数是新手最容易踩的坑。比如你用当日收盘价计算均线,然后以当日收盘价成交,这就是典型的未来函数——实际交易中你不可能在收盘的瞬间同时完成计算和下单。正确的做法是用前一日收盘价计算信号,当日开盘价成交。
3.3 参数调优的边界控制
策略代码跑通后,下一步是参数调优。这里有个陷阱:过度优化。如果你把均线周期从5到60全部跑一遍,选收益最高的那组,大概率是过拟合了。
我的做法是分两步:先用逻辑确定参数的大致范围,再用回测验证。比如双均线策略,短周期均线通常选5到20,长周期选20到60,这是基于市场参与者习惯的经验范围。然后在这个范围内选几组有代表性的参数跑回测,看收益是否稳定。如果只有某一组参数表现特别好,其他都一般,那大概率是运气。
参数敏感性分析也很重要。好的策略应该在参数小幅变动时收益变化不大。如果均线周期从20改成21收益就腰斩,说明策略不稳定,实盘很容易失效。
4. Backtrader多股回测的完整实现
4.1 回测环境搭建与数据加载
Backtrader的环境搭建不复杂,pip安装后基本能用。但多股回测的数据加载需要一些技巧。我一般把数据存成CSV文件,每个股票一个文件,然后用Backtrader的PandasData加载。
import backtrader as bt import pandas as pd class MultiStockData(bt.feeds.PandasData): params = ( ('datetime', None), ('open', 'open'), ('high', 'high'), ('low', 'low'), ('close', 'close'), ('volume', 'volume'), ) cerebro = bt.Cerebro() stock_list = ['000001', '000002', '000003'] for stock in stock_list: df = pd.read_csv(f'data/{stock}.csv', parse_dates=['date']) df.set_index('date', inplace=True) data = MultiStockData(dataname=df) cerebro.adddata(data, name=stock)这里有个细节:不同股票的上市时间不同,早期数据可能缺失。Backtrader默认会用NaN填充,但策略逻辑里要处理这种情况,否则会报错。我的做法是在策略的next方法里先检查数据是否有效,无效就跳过。
4.2 策略类的核心逻辑编写
Backtrader的策略类继承自bt.Strategy,核心是next方法,每个bar调用一次。多股回测时,next方法会对每只股票分别调用,所以需要用self.datas来区分。
class DualMAStrategy(bt.Strategy): params = ( ('short_period', 5), ('long_period', 20), ('stop_loss', 0.08), ('max_positions', 5), ) def __init__(self): self.short_ma = {} self.long_ma = {} for data in self.datas: self.short_ma[data._name] = bt.indicators.SMA( data.close, period=self.params.short_period) self.long_ma[data._name] = bt.indicators.SMA( data.close, period=self.params.long_period) def next(self): positions = len([d for d in self.datas if self.getposition(d).size > 0]) for data in self.datas: if not data.close[0] or data.close[0] != data.close[0]: continue pos = self.getposition(data) short = self.short_ma[data._name][0] long = self.long_ma[data._name][0] prev_short = self.short_ma[data._name][-1] prev_long = self.long_ma[data._name][-1] if not pos.size and positions < self.params.max_positions: if prev_short <= prev_long and short > long: cash_per_stock = self.broker.getcash() / self.params.max_positions size = int(cash_per_stock / data.close[0] / 100) * 100 if size > 0: self.buy(data=data, size=size) positions += 1 elif pos.size: if prev_short >= prev_long and short < long: self.close(data=data) positions -= 1 elif data.close[0] < pos.price * (1 - self.params.stop_loss): self.close(data=data) positions -= 1这段代码有几个关键点。第一,用prev_short和prev_long判断信号,避免未来函数。第二,仓位按等权分配,但买入时按100股取整,这是A股的实际约束。第三,止损用持仓成本价计算,而不是当日开盘价。
4.3 回测结果的分析与解读
回测跑完后,Backtrader会输出一堆指标。新手容易只看总收益率,这是不够的。我一般重点看这几个:年化收益率、最大回撤、夏普比率、胜率、盈亏比。
年化收益率反映盈利能力,但必须结合最大回撤看。一个年化30%但最大回撤50%的策略,实际很难坚持执行。夏普比率衡量风险调整后收益,大于1算不错,大于2算优秀。胜率和盈亏比要一起看,高胜率低盈亏比和低胜率高盈亏比都可能盈利,但前者心理压力小,后者需要更强的纪律性。
我还会看收益曲线的形态。如果收益主要集中在某几个月,其他时间横盘或亏损,说明策略依赖特定市场环境,实盘时要谨慎。理想的收益曲线是稳步向上,回撤可控。
提示:回测结果好不代表实盘能赚钱。回测和实盘之间隔着滑点、手续费、流动性、心理因素等多道坎。我一般要求回测的夏普比率至少1.5,才会考虑小仓位实盘验证。
5. 常见问题与排查技巧实录
5.1 回测收益异常高的排查思路
回测收益高得离谱,通常是这几个原因:未来函数、幸存者偏差、手续费设置过低、滑点未考虑。
排查未来函数,最直接的方法是检查信号计算和成交价格的时间关系。如果用了当日收盘价计算信号,又用当日收盘价成交,基本可以确定有问题。另一个方法是把回测周期分成两段,如果前半段和后半段收益差异巨大,可能存在过拟合。
幸存者偏差的排查:确认股票池是否包含已退市股票。如果只用了当前上市的股票,回测收益会偏高。我的做法是每年年初重新获取一次全市场股票列表,包括当时已退市的,用这个列表做回测。
手续费和滑点:A股手续费一般按万分之三算,卖出还有千分之一的印花税。滑点按千分之一到千分之二估算。这些参数在Backtrader里通过setcommission和setslippage设置。
5.2 策略在样本外失效的应对
样本外失效是量化最头疼的问题。我的应对策略是:多策略分散、动态仓位调整、定期重新验证。
多策略分散是指同时跑几个逻辑不同的策略,比如趋势跟踪和均值回归各一个,这样单一策略失效时整体影响可控。动态仓位调整是指根据策略近期的表现调整仓位,表现好时加仓,表现差时减仓。定期重新验证是指每季度用最新数据重新跑一遍回测,看策略逻辑是否还成立。
还有一个经验:策略失效往往有前兆,比如回撤开始变大、胜率下降、盈亏比恶化。我会设置一个监控指标,当策略的滚动夏普比率低于某个阈值时,自动降低仓位或暂停。
5.3 实盘对接的注意事项
回测通过后接实盘,有几个坑要提前避开。
第一是数据延迟。回测用的是历史数据,实盘用的是实时数据,两者可能有差异。我的做法是实盘前先用模拟盘跑一段时间,对比模拟成交和回测成交的差异。
第二是订单执行。回测假设订单立即成交,实盘可能部分成交或未成交。特别是流动性差的股票,滑点可能很大。我的做法是只选日成交额大于5000万的股票,避免流动性问题。
第三是心理因素。回测时看到回撤30%可能觉得没什么,实盘时真金白银亏30%很难淡定。我的做法是实盘初期只用计划资金的20%,等跑顺了再逐步加仓。
| 问题类型 | 排查方法 | 解决方案 |
|---|---|---|
| 回测收益异常高 | 检查未来函数、幸存者偏差 | 用前一日数据计算信号 |
| 样本外失效 | 分段回测、参数敏感性分析 | 多策略分散、动态仓位 |
| 实盘滑点大 | 对比模拟盘和回测成交价 | 限制股票流动性门槛 |
| 心理压力大 | 从小仓位开始 | 逐步加仓,设定最大回撤线 |
6. 个人量化的成本收益与持续迭代
6.1 真实成本拆解
个人做量化的成本比想象中低,但也不是零。数据方面,免费源基本够用,如果要更高质量的数据,一年几千块。服务器方面,个人策略用本地电脑跑回测足够,实盘可以用云服务器,一年几百到一千。AI辅助工具方面,Codex有免费额度,超出后按月付费,几十块一个月。
时间成本是大头。从零开始学Python和Backtrader,每天投入两小时,大概需要一个月能跑通第一个策略。之后每个新策略的开发周期,熟练后大概一周左右。这个投入对于想认真做量化的人来说是必要的。
6.2 持续迭代的节奏
策略开发不是一劳永逸的事。市场环境在变,策略也需要迭代。我的节奏是:每月检查一次策略表现,每季度做一次参数重新验证,每半年评估一次策略逻辑是否还成立。
迭代的方向有两个:一是优化现有策略,比如调整参数、增加过滤条件;二是开发新策略,补充现有策略的不足。我一般保持3到5个策略同时运行,其中1到2个在开发验证阶段。
6.3 给新手的起步建议
如果你刚开始接触量化,我的建议是:先用模拟盘跑通一个简单策略,别急着上实盘。策略逻辑越简单越好,双均线、布林带突破这些经典策略足够入门。代码写完后逐行审查,确认没有未来函数。回测结果不要只看收益率,重点看最大回撤和夏普比率。
等模拟盘跑顺了,用小仓位实盘验证。实盘初期重点关注执行层面的问题,比如滑点、成交率、数据延迟。这些问题解决了,再考虑加大仓位或开发新策略。
最后分享一个我自己的习惯:每个策略都写一份文档,记录策略逻辑、参数设置、回测结果、实盘表现、迭代记录。这份文档在策略失效时特别有用,能快速定位问题。而且写文档的过程本身也是梳理思路的过程,经常写着写着就发现逻辑漏洞了。