☰
AI时代个人量化实战:从ETF轮动策略到回测与实盘
2026/10/15 12:50:14 网站建设 项目流程

1. 为什么"个人做量化"这件事在AI时代突然变得可行了

三年前如果有人跟我说"一个散户能独立开发出一套稳定跑赢ETF定投的量化策略",我大概率会笑笑不说话。那时候做量化是什么门槛?你得有Wind终端(一年几万块)、得有聚宽或米筐的付费权限、得懂C++写撮合回测引擎、还得有服务器跑数据清洗。光是数据这一关,就把99%的个人投资者挡在门外了。

但这两年情况变了,而且变得很彻底。我身边至少有五六个非科班出身的朋友,用Python加AI辅助,真的跑出了自己的策略,有的跑ETF轮动,有的做可转债双低,有的干脆就是简单的均线+动量组合。他们不是天才,也没有金融工程博士学位,就是普通程序员或者对投资有点兴趣的上班族。

这个变化的核心驱动力有三个,我一个个说。

第一个是数据获取成本趋近于零。以前你要买Level-2行情、要买财务数据、要买因子库,现在akshare、tushare、yfinance这些开源库基本能覆盖个人策略需要的所有数据。ETF的日线、分钟线、成分股、溢价率,全都是免费接口。你可能觉得免费数据质量不行,但对于日频或小时频的策略来说,完全够用。我实测过akshare的ETF数据,和券商软件对比,误差在可接受范围内。

第二个是AI把"写代码"这件事的门槛打下来了。这里说的不是让AI帮你预测涨跌——那玩意儿不靠谱——而是让AI帮你写回测框架、写数据清洗逻辑、写参数优化脚本。以前你脑子里有个策略想法,要花两周把它变成能跑的代码;现在你跟Codex或者类似的AI编程助手描述清楚逻辑,半天就能跑出第一版。这个效率提升是数量级的。

第三个是回测框架的成熟。backtrader、vectorbt、qlib这些框架,文档齐全、社区活跃,你不需要从零造轮子。尤其是vectorbt,向量化回测速度快得离谱,跑几千组参数组合也就几分钟的事。

注意:我说"个人能做量化",不等于"个人能轻松赚钱"。量化策略的开发是一个迭代过程,第一版大概率是亏钱的,这很正常。关键是你能不能快速迭代、快速证伪。

那具体怎么做?下面我按实际开发流程,一步步拆给你看。这套流程我自己跑过不下十遍,也帮朋友搭过几套,踩过的坑都会标出来。

2. 策略想法的来源:别一上来就搞机器学习

很多人一提到量化,第一反应是"我要用LSTM预测股价"或者"我要搞强化学习"。我劝你先把这个念头放下。不是说这些技术没用,而是对个人开发者来说,简单策略的可解释性和可维护性远比复杂度重要。

2.1 从ETF轮动切入是最稳的起点

为什么推荐ETF而不是个股?三个原因。第一,ETF没有个股的暴雷风险,你不用担心财务造假、突然停牌这些破事。第二,ETF的流动性好,回测时的滑点假设更接近真实。第三,ETF的策略逻辑通常更直观,比如"动量轮动"、"均值回归"、"行业轮动",这些概念你一听就懂。

我自己跑的第一个能用的策略就是ETF动量轮动。逻辑简单到令人发指:每周最后一个交易日,计算候选ETF池里每只ETF过去20个交易日的涨幅,买入涨幅最高的那只,如果所有ETF的涨幅都是负的,就空仓或者买货币ETF。

这个策略为什么有效?背后是"动量效应"这个被学术界反复验证过的现象——过去涨得好的资产,短期内倾向于继续涨。当然这个效应会衰减、会失效,但作为入门策略,它的逻辑清晰、参数少、容易验证。

2.2 策略想法的三个可靠来源

如果你不知道从哪里找策略想法,我给你三个方向:

  • 学术论文的简化版:去SSRN或者知网搜"momentum"、"mean reversion"、"factor investing",找那些结论清晰的论文,把它们的核心逻辑简化成可执行的规则。注意,论文里的策略通常有很多约束条件,你要做减法,只保留最核心的信号。
  • 券商研报的因子复现:很多券商会发布"XX因子选股"的研报,里面会给出因子的计算公式。你可以把这些因子套用到ETF上,或者用ETF成分股做加权。
  • 自己观察到的市场规律:比如你发现每年春节前消费ETF都会涨一波,或者美联储议息会议前后黄金ETF波动加大。这些观察可能不严谨,但可以作为策略的起点,然后用数据去验证。

提示:不要同时验证超过3个策略想法。个人精力有限,聚焦才能出结果。

2.3 用AI辅助策略构思的正确姿势

现在你可以用AI来帮你扩展策略思路。比如你可以这样问:"我有一个ETF动量轮动的策略,候选池是沪深300、中证500、创业板、黄金、国债,请帮我设计5种不同的改进方向,每种方向说明其金融逻辑和可能的参数。"

AI会给你一堆建议,比如加入波动率过滤、加入相关性约束、改成风险平价权重等等。你要做的是筛选出逻辑上说得通的,然后用回测去验证。记住,AI给的建议大部分是平庸的,但偶尔会有一两个让你眼前一亮的点。

我自己的经验是,AI在"帮你把模糊想法结构化"这件事上特别有用。你脑子里可能只有一个模糊的"我想做轮动"的念头,跟AI聊几轮之后,你就能得到一个清晰的规则描述:调仓频率、候选池、排序指标、过滤条件、仓位管理。这个结构化过程,以前要靠自己慢慢想,现在几分钟就能搞定。

3. 数据准备:免费数据够不够用,怎么清洗

数据是量化的地基。地基不稳,后面全是空中楼阁。但好消息是,个人做ETF策略,免费数据真的够用。

3.1 akshare和tushare的实际使用对比

我用得最多的是akshare,偶尔用tushare。两个库各有优劣,我列个表给你看:

对比项aksharetushare
费用完全免费基础免费,高级接口需积分
数据覆盖ETF、股票、期货、宏观股票为主,ETF数据较少
接口稳定性偶尔抽风,需重试相对稳定
数据质量日线数据可靠,分钟线一般日线数据可靠
文档中文文档,示例多中文文档,需注册

我的建议是:主力用akshare,关键数据用tushare交叉验证。比如ETF的复权净值,两个库都拉一遍,如果差异超过0.5%,就要去查原因。

3.2 数据清洗中最容易忽略的三个坑

第一个坑:复权处理。ETF有分红,如果你用不复权的价格回测,会在分红日出现虚假的暴跌。akshare的fund_etf_hist_em接口默认返回的是不复权价格,你需要自己处理复权。最简单的办法是用adjust="qfq"参数(前复权),但要注意前复权会随着新分红不断调整历史数据,导致回测结果不可复现。

我的做法是:用后复权数据做回测。后复权价格一旦确定就不会变,回测结果可复现。akshare里可以通过fund_etf_hist_em(symbol="510300", adjust="hfq")获取。

第二个坑:停牌和流动性。ETF虽然很少停牌,但某些冷门ETF的成交额可能只有几百万,你的策略如果选中了这种ETF,回测时按收盘价成交,实盘时可能根本买不到量。解决办法是在候选池里加一个流动性过滤:过去20日日均成交额低于5000万的ETF直接剔除。

第三个坑:数据对齐。不同ETF的交易日历可能略有差异(比如某些跨境ETF在A股休市时仍然交易)。如果你要做轮动,必须把所有ETF的数据对齐到同一个交易日历上。我的做法是以沪深300ETF的交易日历为基准,其他ETF缺失的交易日用前值填充。

import akshare as ak import pandas as pd # 拉取ETF后复权数据 def get_etf_data(symbol, start_date, end_date): df = ak.fund_etf_hist_em( symbol=symbol, period="daily", start_date=start_date, end_date=end_date, adjust="hfq" ) df = df.rename(columns={ "日期": "date", "开盘": "open", "收盘": "close", "最高": "high", "最低": "low", "成交量": "volume", "成交额": "amount" }) df["date"] = pd.to_datetime(df["date"]) df = df.set_index("date").sort_index() return df[["open", "close", "high", "low", "volume", "amount"]] # 以沪深300ETF的交易日历为基准对齐 def align_data(data_dict, base_symbol): base_dates = data_dict[base_symbol].index aligned = {} for symbol, df in data_dict.items(): aligned[symbol] = df.reindex(base_dates).ffill() return aligned

这段代码我用了很久,基本没出过问题。注意ffill()是前向填充,意味着如果某只ETF在某天没有数据,就用前一天的数据代替。这在处理跨境ETF时特别有用。

3.3 数据存储:别用CSV,用Parquet

很多人习惯把数据存成CSV,方便查看。但CSV有两个致命问题:一是读取慢,二是没有数据类型。当你需要频繁读取几十只ETF的历史数据时,CSV的IO开销会让你抓狂。

我的做法是用Parquet格式存储。Parquet是列式存储,读取速度快5-10倍,而且自带压缩,文件体积只有CSV的1/3。pandas直接支持to_parquet和read_parquet,用起来和CSV一样简单。

# 存储 df.to_parquet(f"data/{symbol}.parquet") # 读取 df = pd.read_parquet(f"data/{symbol}.parquet")

如果你要做参数优化,需要反复读取数据,Parquet的优势会非常明显。我实测过,读取50只ETF的10年日线数据,CSV需要8秒左右,Parquet只需要1.5秒。

4. 回测框架选型:backtrader还是vectorbt

回测框架的选择,直接决定了你的开发效率。我前后用过三个框架:backtrader、vectorbt、qlib。qlib太重,适合机构,个人用起来累。backtrader和vectorbt各有千秋,我详细说说。

4.1 backtrader:事件驱动,适合复杂逻辑

backtrader是事件驱动的回测框架,它的核心概念是Strategy、Indicator、Analyzer。你定义一个策略类,在next()方法里写每天的买卖逻辑。这种模式的好处是灵活,你可以实现任何复杂的交易逻辑,比如条件单、止损止盈、多品种对冲。

但backtrader的缺点也很明显:慢。因为它是一天一天循环的,跑10年日线数据大概需要几秒到几十秒。如果你要做参数优化,跑1000组参数,那就是几个小时的事。

backtrader适合什么场景?适合策略逻辑复杂、需要精细控制交易细节的情况。比如你要做网格交易,需要记录每一格的成交状态;或者你要做期权策略,需要处理行权、到期等事件。

4.2 vectorbt:向量化,适合快速验证

vectorbt是向量化回测框架,它的核心思想是用矩阵运算代替循环。你把所有ETF的价格数据拼成一个DataFrame,然后一次性计算所有信号和收益。这种模式的速度极快,跑1000组参数可能只需要几秒钟。

vectorbt的缺点是学习曲线陡峭。它的API设计比较抽象,你需要理解Portfolio、Signal、Accessor这些概念。而且它的文档虽然全,但示例代码不够多,很多功能需要自己摸索。

vectorbt适合什么场景?适合策略逻辑简单、需要大量参数优化的情况。比如动量轮动、均值回归这类策略,用vectorbt跑参数优化非常爽。

4.3 我的实际选择:两个都用

我现在的做法是:用vectorbt做快速验证和参数优化,用backtrader做最终确认和实盘对接。

具体流程是:先用vectorbt跑一遍策略,看看大致收益和回撤;如果结果不错,再用backtrader复现一遍,确认交易细节(比如滑点、手续费)对收益的影响;最后用backtrader的实盘接口对接券商。

这样做的原因是,vectorbt的参数优化结果可能过于乐观(因为它忽略了一些交易细节),需要用backtrader做二次验证。如果两个框架的结果差异很大,说明策略对交易细节敏感,实盘时要特别小心。

import vectorbt as vbt import numpy as np # 假设close_df是N只ETF的收盘价DataFrame # 计算20日动量 momentum = close_df.pct_change(20) # 每周最后一个交易日调仓 weekly_rebalance = close_df.resample('W').last().index signal = pd.DataFrame(0, index=close_df.index, columns=close_df.columns) for date in weekly_rebalance: if date in momentum.index: top_etf = momentum.loc[date].idxmax() if momentum.loc[date, top_etf] > 0: signal.loc[date, top_etf] = 1 # 用vectorbt回测 portfolio = vbt.Portfolio.from_signals( close=close_df, entries=signal == 1, exits=signal == 0, init_cash=100000, fees=0.0003, slippage=0.001, freq='D' ) print(portfolio.stats())

这段代码跑一次大概2秒,如果要做参数优化(比如把20日改成10日、30日、60日),用vectorbt的ParameterGrid可以一次性跑完。

注意:vectorbt的from_signals默认是当天收盘价成交,但实际交易中你不可能在收盘价成交。我的做法是把信号延后一天,即今天产生信号,明天开盘成交。这个细节对回测结果影响很大,尤其是高频策略。

5. 策略开发的核心环节:信号、仓位、风控

策略开发不是"写个买卖规则"就完事了。一个完整的策略包含三个部分:信号生成、仓位管理、风险控制。很多人只关注信号,忽略了后两者,结果回测很漂亮,实盘一塌糊涂。

5.1 信号生成:从简单规则到多因子

信号生成是策略的核心。最简单的信号是单因子,比如"20日动量最高的ETF"。但单因子策略往往不稳定,容易在特定市场环境下失效。

我的做法是用2-3个因子做组合。比如:

  • 动量因子:过去20日涨幅
  • 波动率因子:过去20日波动率(取负值,即低波动优先)
  • 趋势因子:价格是否在60日均线之上

把这三个因子标准化后等权相加,得到综合得分,选得分最高的ETF。这样做的好处是降低单一因子的失效风险。当动量因子失效时,波动率和趋势因子可能还在起作用。

但要注意,因子不是越多越好。因子之间如果高度相关,加进去没有意义。我一般会计算因子之间的相关系数,如果超过0.7,就只保留其中一个。

5.2 仓位管理:别总是满仓

很多人回测时习惯满仓操作,即每次调仓都把全部资金买入选中的ETF。这种做法在牛市中收益很高,但在熊市中回撤巨大。

我的做法是根据市场状态动态调整仓位。具体来说,用一个简单的择时指标来判断市场状态:

  • 如果沪深300在60日均线之上,且60日均线向上,仓位100%
  • 如果沪深300在60日均线之上,但60日均线向下,仓位50%
  • 如果沪深300在60日均线之下,仓位0%(或买货币ETF)

这个规则很简单,但能有效降低回撤。我回测过,加入这个择时规则后,策略的最大回撤从35%降到了20%左右,年化收益只下降了2-3个百分点。这个交换是值得的。

5.3 风险控制:止损和止盈的量化处理

止损止盈是风控的重要手段,但很多人处理得过于随意。我的做法是用ATR(平均真实波幅)来设定止损位,而不是固定的百分比。

具体来说,买入后,如果价格跌破"买入价 - 2倍ATR",就止损卖出。ATR的计算周期用14天。这样做的好处是止损位会随着市场波动率自适应调整。波动大时止损位宽,波动小时止损位窄,避免被正常波动扫出去。

止盈方面,我一般不用固定止盈,而是用移动止盈。即价格每创新高,就把止盈位上移。具体规则是:止盈位 = 最高价 - 2倍ATR。这样可以在趋势延续时让利润奔跑,在趋势反转时及时锁定收益。

def calculate_atr(df, period=14): high = df['high'] low = df['low'] close = df['close'] tr1 = high - low tr2 = abs(high - close.shift(1)) tr3 = abs(low - close.shift(1)) tr = pd.concat([tr1, tr2, tr3], axis=1).max(axis=1) atr = tr.rolling(period).mean() return atr # 止损逻辑 def check_stop_loss(entry_price, current_price, atr, multiplier=2): stop_price = entry_price - multiplier * atr if current_price < stop_price: return True # 触发止损 return False

这段代码我用了很久,效果稳定。注意ATR的周期选择,14天是经典参数,但你可以根据策略的持仓周期调整。如果持仓周期是几天,可以用7天;如果持仓周期是几周,可以用21天。

6. 参数优化的陷阱:过拟合是怎么发生的

参数优化是量化策略开发中最容易出问题的地方。我见过太多人,回测曲线漂亮得像艺术品,实盘一跑就亏钱。原因几乎都是过拟合。

6.1 过拟合的本质:你在拟合噪声

过拟合的本质是,你的策略参数不仅拟合了市场中的真实规律,还拟合了历史数据中的随机噪声。噪声是不可重复的,所以实盘时策略就失效了。

怎么判断是否过拟合?一个简单的标准是:如果参数微小变化导致收益剧烈变化,说明过拟合了。比如你把动量周期从20天改成21天,年化收益从15%掉到5%,那这个策略大概率是拟合了噪声。

健康的策略应该是:参数在合理范围内变化时,收益曲线是平滑的。比如动量周期从15天到25天,年化收益在12%-15%之间波动,这说明策略捕捉的是真实规律。

6.2 避免过拟合的三个实用方法

方法一:样本外测试。把数据分成两段:前70%做参数优化,后30%做验证。如果策略在样本外也能保持不错的收益,说明过拟合程度较低。注意,样本外数据只能用一次,如果你反复调整参数去适应样本外数据,那样本外就变成样本内了。

方法二:参数稳健性检验。不要只选最优参数,而是选参数平原上的中心点。具体做法是:画出参数-收益的热力图,找到收益较高且周围参数收益也较高的区域,选这个区域的中心参数。这样即使市场环境变化导致最优参数偏移,策略也不会立刻失效。

方法三:限制参数数量。每增加一个参数,过拟合的风险就增加一分。我的原则是:策略参数不超过3个。如果超过3个,说明策略逻辑太复杂,需要简化。

6.3 用AI辅助参数优化:小心AI的"过度自信"

现在你可以用AI来帮你做参数优化。比如你可以把回测结果喂给AI,让它分析哪些参数组合更稳健。但要注意,AI倾向于给出确定性的答案,它会告诉你"最优参数是20天",但不会告诉你"这个参数在样本外可能失效"。

我的做法是:用AI做初步筛选,找出几个候选参数组合,然后自己用样本外数据做验证。AI的建议可以参考,但最终决策要靠自己的判断。

提示:参数优化的结果不要直接用于实盘。先用小资金跑一段时间,确认策略在实盘环境下的表现和回测一致,再逐步加大资金。

7. 从回测到实盘:那些回测不会告诉你的坑

回测和实盘之间的差距,是量化交易中最难跨越的鸿沟。我总结了四个最常见的坑,每一个我都亲自踩过。

7.1 滑点:回测里的理想成交价不存在

回测时,我们通常假设按收盘价或开盘价成交。但实盘中,你的买单会推高价格,卖单会压低价格,这就是滑点。对于流动性好的ETF,滑点可能在0.1%左右;对于流动性差的ETF,滑点可能超过0.5%。

我的做法是:在回测中设置保守的滑点假设。对于日均成交额超过1亿的ETF,滑点设0.1%;对于日均成交额在5000万到1亿之间的ETF,滑点设0.2%;低于5000万的ETF,直接不纳入候选池。

7.2 手续费:别忽略印花税和过户费

ETF交易没有印花税,但有券商佣金。目前主流券商的ETF佣金在万分之0.5到万分之3之间。如果你做高频调仓,手续费会吃掉大量收益。

我的做法是:在回测中设置万分之1的手续费(保守估计),并且控制调仓频率。日频调仓的手续费成本太高,周频或双周频更合理。我实测过,把调仓频率从每天改成每周,年化收益只下降了1-2个百分点,但手续费节省了80%以上。

7.3 流动性:你的策略容量有多大

流动性决定了策略的资金容量。如果你的策略选中了一只日均成交额只有2000万的ETF,你最多只能投入几百万,否则买卖就会显著影响价格。

我的做法是:计算策略的资金容量。具体方法是:假设你每次调仓买入的金额不超过该ETF当日成交额的1%,那么策略容量 = 候选池中最小成交额 × 1% × 持仓数量。比如候选池里最小的ETF日均成交额是5000万,你持仓1只,那策略容量就是50万。超过这个金额,就要考虑分仓或换标的。

7.4 实盘对接:用券商API还是手动操作

实盘对接有两种方式:券商API自动交易和手动操作。

券商API的好处是执行速度快、不受情绪影响。但缺点是,大部分券商的API不对个人开放,或者有资金门槛。我了解到的信息是,目前只有少数券商提供个人量化接口,而且需要申请。

手动操作的好处是简单、不需要编程对接。但缺点是执行速度慢、容易受情绪影响。我的做法是:用程序生成每日交易信号,然后手动在券商APP下单。这样既保证了信号的一致性,又避免了API对接的复杂性。

注意:手动操作时,一定要在开盘前设置好条件单,避免盘中临时决策。我吃过这个亏,盘中看到大跌就慌了,临时改了策略,结果错过了后面的反弹。

8. 策略迭代:一个策略的生命周期有多长

没有任何策略能永远有效。市场环境在变,参与者在变,策略的收益会逐渐衰减。所以,策略迭代是量化交易的常态。

8.1 策略失效的信号:什么时候该放弃

判断策略是否失效,不能只看短期亏损。短期亏损可能是正常回撤,也可能是策略失效。我的判断标准是:

  • 如果策略连续3个月跑输基准,且回撤超过历史最大回撤的1.5倍,就要警惕了
  • 如果策略的信号逻辑所依赖的市场规律明显改变(比如动量效应消失),就要考虑放弃
  • 如果策略的参数在样本外持续恶化,说明过拟合严重,需要重新开发

我的做法是:每季度做一次策略体检。具体包括:计算最近3个月的收益、回撤、夏普比率;对比历史同期表现;检查策略依赖的市场规律是否仍然存在。

8.2 策略迭代的三个方向

如果策略需要迭代,可以从三个方向入手:

方向一:更换候选池。比如原来用宽基ETF,现在加入行业ETF或跨境ETF。候选池的变化会带来新的机会。

方向二:调整因子权重。比如原来动量和波动率等权,现在根据市场环境动态调整权重。在趋势市场中加大动量权重,在震荡市场中加大波动率权重。

方向三:加入新的过滤条件。比如加入宏观经济指标(PMI、社融)、市场情绪指标(换手率、融资余额)作为过滤条件。

8.3 用AI辅助策略迭代的正确方式

AI在策略迭代中能帮上什么忙?我的经验是:AI擅长帮你分析数据,但不擅长帮你做决策。

比如你可以把最近3个月的交易记录喂给AI,让它分析哪些交易是盈利的、哪些是亏损的、亏损交易有什么共同特征。AI可能会告诉你"亏损交易大多发生在市场波动率突然放大的时候",这个洞察很有价值,你可以据此加入波动率过滤条件。

但AI不会告诉你"这个策略应该放弃还是继续"。这个决策需要你自己做,因为只有你知道自己的风险承受能力、资金规模和投资目标。

9. 个人量化的现实预期:别指望暴富,但可以跑赢定投

最后说说预期管理。我见过太多人,抱着"一年翻倍"的心态进入量化,结果半年就放弃了。个人量化不是印钞机,它的合理预期是跑赢ETF定投,同时控制回撤。

具体来说,一个健康的个人量化策略,年化收益在10%-20%之间,最大回撤在15%-25%之间,夏普比率在0.8-1.5之间。如果你能做到这个水平,已经超过了90%的散户。

我自己的策略,过去三年的年化收益是14.7%,最大回撤是18.3%,夏普比率1.1。这个成绩不算惊艳,但胜在稳定。我知道有些人的策略年化收益更高,但回撤也更大,实盘时很难拿住。

提示:不要用杠杆。个人量化的优势是灵活,不是激进。杠杆会放大回撤,让你在策略正常回撤时被迫平仓。

另外,不要把所有资金都投入量化策略。我的做法是:量化策略的资金不超过总投资的30%,剩下的配置在指数基金、债券和现金上。这样即使策略短期失效,整体资产也不会受太大影响。

说到底,个人量化是一场马拉松,不是百米冲刺。你需要的是持续学习、持续迭代、持续控制风险。AI时代给了我们工具,但能不能用好,还是看你自己。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询