10万块钱做量化,到底行不行?这个问题我被问了不下几十次。答案其实不复杂:行,但你得先接受一个现实——10万块的策略和大资金的策略,从来就不是一回事。大资金要讲容量、讲冲击成本,10万块要的是灵活和狠准。今天我想聊的是一套我自己跑了大半年的ETF短线实战策略,以10万元初始资金为基准,核心目标是把收益风险比稳稳控制在2:1以上——每一块钱的亏损风险背后,至少预期赚回两块钱。
这套策略的本质很简单:做趋势跟随,不做预测。用均线系统判断方向,用MACD和成交量做入场确认,用ATR动态止损控制风险,然后把仓位计算交给数学而不是交给感觉。整个过程我用Python实现了完整回测,也经历过实盘打脸,踩过的坑我会一个一个说清楚。如果你手里正好有5到20万资金,想系统性地把ETF短线交易做成一件事、而不是靠盘感瞎买瞎卖,这篇文章应该能帮你省下不少学费。
1. 10万元本金做量化的真实处境:为什么我押注ETF短线
1.1 10万在A股的选择题:股票、期货、ETF怎么选
10万元放在今天的A股市场里,是个很微妙的体量。说少吧,能做的品种其实挺多;说多吧,又处处受限制。科创板需要50万门槛,期权更不用说,北交所虽然门槛低但流动性和标的质量参差不齐。股票倒是可以买,但10万块钱挖到一只财报爆雷的个股,一次闷杀可能就是30%起步,本金恢复起来需要很久。再加上个股的涨跌停制度、T+1限制、印花税和冲击成本,10万块做股票短线,实际上是在跟信息优势远强于你的资金同场竞技,胜率天然不利。
期货呢?10万确实可以开户,商品期货的保证金门槛并不高。但期货自带杠杆,即使你只使用三成仓位,一次反向波动打穿止损都是常有的事。对于没有全职盯盘条件的人来说,日内强平、跳空高开低开这些事会把心态搞得非常乱。我见过不止一个人用10万做商品期货,三个月后账户只剩下六成,问题不在技术,在于杠杆放大了人性的弱点。
再看ETF,情况就完全不一样了。ETF跟踪指数或行业板块,没有个股爆雷风险,规则透明,手续费极低。最关键的是一手只要几百块,10万资金买卖起来完全不存在冲击成本的问题。ETF场内交易不收印花税,佣金普遍能谈到万分之一左右,这比股票的交易成本低了一个量级。也就是说,同样的短线策略,交易频次越高,ETF在成本上的优势就越明显。10万做ETF,恰好是资金量、品种特性和交易成本三者最匹配的组合。
1.2 为什么短线趋势跟随在这个体量上反而好做
很多人一听"短线"就觉得是天天盯盘、频繁交易。其实我所说的短线,持仓周期是3到15天,属于波段级别。这个周期和趋势跟随策略是高度匹配的。大资金做趋势,往往被流动性限制,不敢快进快出;10万块则完全没有这个问题,看准了买进去,信号变差立刻走得掉。
更关键的在于,ETF的短期波动具有明显的"趋势延续"特征。指数或板块一旦形成趋势,很少会在三五天内立刻反转,尤其是经过均线系统确认过的趋势。这就给了短线趋势跟随策略一个有利的战场:不需要预测顶底,只需要在趋势启动初期进场、在趋势衰竭时离场,就能吃到中间的利润段。反过来说,如果去做逆势抄底或猜顶,ETF的波动弹性并不支持,做错了还有损耗。所以这个策略从一开始就定了一个基调:只做顺势,不做逆向。
1.3 策略的边界:什么行情下这套打法会失效
任何策略都有失效期,提前知道边界比提前知道收益更重要。这套策略最大的天敌是低波动的震荡市。当ETF价格在一个区间里来回横盘,均线反复交叉,信号会频繁假突破,连续小亏会让净值慢慢阴跌。我统计过回测数据,在2021年下半年的宽幅震荡行情中,这套策略连续12次交易里只有3次盈利,全靠最后两波趋势行情才把净值拉回来。
另一个弱点是急跌行情。如果ETF受突发利空影响单日暴跌超过5%,止损单会以远低于止损价的价格成交,也就是滑点放大。这种情况下,策略的单笔亏损会超出预期。想对冲这种风险,就得在标的池选择阶段就把波动率过大的品种排除掉,并且保持足够低的仓位上限。后面我会详细讲这两个问题怎么处理。
2. 高收益风险比是设计出来的:策略框架与参数逻辑
2.1 收益风险比的数学定义和我设的目标
做交易之前,先把收益风险比这件事用数学讲清楚。我常用两个口径。第一个是单笔盈亏比,平均盈利除以平均亏损,这个值至少要大于1.5,最好在2以上。第二个是账户层面的Sharpe比率,每承担一单位波动能换来多少超额收益,我给自己定的标准是年化Sharpe不低于1.2。这两个指标,一个管单次交易质量,一个管整体资金曲线平滑度。
为什么强调收益风险比而不是单纯追求胜率?因为趋势跟随策略的胜率天然不高,通常在30%到45%之间。但趋势行情一旦抓到,单笔盈利往往是止损金额的2到5倍,靠的就是"小亏大赚"。如果只盯着胜率不放,很容易变成赚一点就跑、亏了就死扛,结果胜率看着有七八成,账户资金却在慢慢缩水,这就是典型的收益风险比倒挂。
我给自己定的目标是:平均单笔盈利不低于平均单笔亏损的2倍,账户最大回撤控制在15%以内,年化收益预期放在15%到25%这个区间。这里要强调一句,这个数字是我在特定标的历史回测中观察到的水平,不代表未来一定能复制,更不构成任何收益承诺。策略的作用是提高概率优势,而不是消除不确定性。
2.2 双均线、MACD、ATR的组合逻辑:每个指标都在干自己的活
很多新手一见量化策略就以为参数越复杂越好,堆一大堆指标进去。我早期也干过这事,指标一多,信号互相矛盾,复盘时根本分不清哪笔交易是哪个逻辑触发的。后来我做了减法,最终只留下三类指标,分工非常明确。
第一类是均线,负责回答"趋势方向是什么"。我用EMA5和EMA20判断短期动能,用EMA120判断大方向。EMA(指数移动平均)比SMA对近期的价格变化更敏感,短线交易用EMA更合适。第二类是MACD,负责回答"趋势力度够不够"。MACD的DIF线在零轴上方说明多头动能占优,这个条件用来过滤掉均线假交叉的信号。第三类是ATR,负责回答"今天的波动有多大"。ATR不直接产生买卖信号,它决定止损距离和仓位大小,是整个风控体系的基石。
这三个指标各干各的事,互不干扰。方向不对,后面的信号一律不认;方向对了但动能不足,也不进场;真正进场时能买多少,由ATR算出来的止损距离决定。逻辑链条是完整且自洽的。
2.3 交易池构建:宽基与行业ETF的筛选标准
标的池决定了策略的天花板。我目前的池子里有8只ETF,分两类。第一类是宽基,包括沪深300ETF(510300)、中证500ETF(510500)、创业板ETF(159915)、科创50ETF(588000),这类品种代表整体市场风格,趋势相对稳定。第二类是行业或主题ETF,包括证券ETF(512880)、半导体ETF(512480)、医药ETF(512010)、酒ETF(512690),这类品种波动弹性大,趋势一旦启动,利润空间很可观。
筛选标准我给了三条硬性条件。第一,日均成交额不低于1亿元,保证流动性足够,买卖价差小。第二,场内份额规模不低于50亿份,避免清盘风险。第三,近20日平均真实波幅ATR大于某个阈值但不过高,太安静的趋势走不动,太吵的止损会被反复打掉。这几条标准看着简单,实际上能过滤掉大部分不适合做短线的品种。我一开始用的是冷门行业ETF,比如煤炭、钢铁之类,虽然有过大行情,但平时交易太冷清,滑点严重,后来果断放弃,只保留成交活跃的品种。
3. 精准择时的落地:入场信号与离场信号的完整规则
3.1 趋势过滤:先用EMA120把多空方向定死
择时的第一步不是找买点,而是先看方向。我规定:只有在收盘价站上EMA120的前提下,才允许做多,否则一律空仓等待。这等于给整个策略加了一个总开关。
为什么用EMA120而不是更短的均线?因为EMA120代表的是过去半年左右的市场平均成本。当价格在它上方运行时,说明持仓成本在抬升,多头结构没有被破坏;跌破它,则说明中期趋势已经转弱,此时任何短线买入都是逆势。这一条规则不追求买在最低点,而是保证每笔交易都处在中期趋势还算健康的环境中。
过滤效果我举个例子。2024年一季度创业板ETF有一波反弹,EMA20和EMA5频繁金叉,但如果只看双均线不加上层过滤,会在下跌中继的反弹里连续吃止损。而加了EMA120过滤之后,那段时间根本不会出现任何买入信号。震荡行情里不交易,本身就赢了一半。
3.2 入场信号的四维共振条件
当EMA120方向过滤通过后,入场信号需要同时满足四个条件,缺一不可。
第一,EMA5上穿EMA20,形成金叉,这是短期动能转向的最直接证据。第二,MACD的DIF值大于零,说明多头力度已经进入强势区间。第三,当日成交量大于5日均量的1.2倍,放量是资金真金白银参与的信号,缩量上涨的可靠性要打折。第四,前一日收盘价站在EMA120之上,确保进场时点处在大方向内的首次或者二次确认阶段,而不是已经离均线太远。
这四个条件同时满足的概率并不高,有时候一周才出现一两次。但这样做的好处是过滤掉了绝大多数低质量信号。宁可错过,不可做错。我统计过,加上共振条件后,月度交易次数大约在4到8次,跟纯双均线系统相比减少了一半左右,但每笔交易的平均盈利有明显提升。
3.3 离场逻辑:死叉离场与跟踪止损的联动
入场决定盈亏比的上限,离场才决定实际能赚多少。我的离场规则分两套,一套是主动的,一套是被动的。
主动离场看信号:EMA5下穿EMA20形成死叉,当天收盘前清仓离场。这个规则不掺杂任何主观判断,信号出现就执行。被动离场看价格:入场后设定初始止损价,初始止损价等于入场价减去2倍ATR。随着价格朝有利方向移动,止损线不是固定不动的,而是采用"回撤跟踪"的方式:每日收盘后,如果最新收盘价减2倍ATR大于当前止损价,就向上移动止损;如果价格回落触发止损,无条件离场。
这种双重离场设计的好处是,一轮强势上涨中,主动死叉信号往往迟迟不出现,而跟踪止损会不断上移,最终在价格从高点回落2倍ATR的位置锁定利润。不管是急跌还是慢跌,总有至少一道防线在起作用。
4. 严格风控的具体推演:仓位、熔断与回撤预案
4.1 单笔风险1%的仓位反推计算
风控不是喊口号,而是一套可以落地的规则。我的第一原则是:单笔交易的最大亏损不能超过总资金的1%。10万本金,也就是单笔最多亏1000元。这个额度看起来不大,但连续亏损20次,账户也才回撤18%,还有翻身的资本。
仓位怎么算?用止损距离反推。假设现在沪深300ETF价格4元,ATR(14日)为0.10元,初始止损距离是2倍ATR,也就是0.20元。此时买入数量 = 单笔风险金额 ÷ 止损价差 = 1000 ÷ 0.20 = 5000份,市值约2万元,占总资金20%。如果ATR扩大到0.15元,止损距离变成0.30元,同样1000元风险预算,就只能买3333份,仓位降到13%。
这个公式的逻辑很清晰:波动越大的品种,仓位越小;止损越近的入场点,仓位可以越重。它把风险和仓位之间的关系变成了一道简单的算术题,而不是靠盘感拍脑袋。实际执行时我会再预留一点缓冲,买入金额不超过总资金的30%,即使多个信号同时触发,也能保证账户不会瞬间顶着满仓。
4.2 组合层面的熔断机制:连续亏损怎么办
单笔风控守住了下限,但账户层面的回撤还要另设防线。我的熔断规则有三层。第一层,当日账户亏损超过2%,第二天强制空仓一天,不管出现什么信号都不交易,让情绪降温。第二层,账户净值从最高点回撤8%,暂停开新仓,只保留持仓离场权限,直到净值重新回到止损线以上。第三层,回撤达到12%,清仓所有持仓,休息一到两周,重新审视策略逻辑和市场环境,确认没有根本性变化再重启。
这三层机制每一层我都在实盘中触发过。印象最深的是有一次连续一周的震荡行情里,策略一周连亏四次,净值回撤到5%附近。我当时看过回测数据,知道这种连亏在震荡期正常,但真金白银的亏损还是让人焦虑。熔断机制的好处就是它自动帮你在情绪失控前踩住刹车。空仓几天之后,果然等到了一波像样的趋势,账户净值很快就修复了。
4.3 一张表把交易计划写到执行前
风控的最后一道关卡是交易记录。我每做一笔交易之前都会先填一张表,把入场理由、止损价、目标价、仓位数量全部写清楚。这张表不复杂,但能有效防止临时起意的乱操作。
列名包括:标的代码、买入日期、买入价格、止损价(入场价减2倍ATR)、买入数量、单笔风险金额、预期盈利目标(2倍风险距离)、当前EMA120状态、信号类型。每次填完这张表,如果任何一项填不出来,说明这笔交易根本不符合策略要求,就该放弃。交易结束后,再把实际结果填进去。几个月下来,这张记录表就是调整策略参数的重要依据。我见过太多人过于依赖回测报告,却从不记录实盘中的真实执行质量,这是很可惜的。
5. Python实现整套策略:数据获取、指标计算与回测
5.1 数据源与回测框架的选型
策略有了,剩下的就是把它写成代码跑起来。数据源我用的是akshare,免费、无需Token、接口稳定,对个人研究完全够用。如果你熟悉的tushare或baostock也可以,逻辑是一样的。
回测框架我不建议一上来就上backtrader这类重型框架,它功能强大但要写一堆模板代码,对新手不友好。我更推荐用pandas自己搭一个简化的回测循环。原因很简单:策略逻辑本身不复杂,自己写回测循环能让每一步都清清楚楚,知道净值是怎么算出来的,避免框架里的隐藏逻辑干扰判断。等到策略逐渐稳定、需要更精细的模拟撮合时,再迁移到专业框架也不迟。
先看数据获取部分:
import pandas as pd import numpy as np import akshare as ak # 获取沪深300ETF(510300)的日线数据 df = ak.fund_etf_hist_em( symbol="510300", period="daily", start_date="20200101", end_date="20250101", adjust="qfq" ) # 重命名列名并提取需要的字段 df = df.rename(columns={ "日期": "date", "开盘": "open", "收盘": "close", "最高": "high", "最低": "low", "成交量": "volume" }) df = df[["date", "open", "high", "low", "close", "volume"]] df["date"] = pd.to_datetime(df["date"]) df = df.sort_values("date").reset_index(drop=True)注意adjust="qfq"表示前复权。ETF分红除息虽然影响不大,但长周期回测里前复权能保证价格连续性,避免跳空导致的假信号。
5.2 策略核心代码的逐段拆解
接下来是技术指标的计算。EMA、MACD、ATR这些指标用pandas和numpy实现都很直接,一批代码全部算好:
def calc_ema(series, period): return series.ewm(span=period, adjust=False).mean() def calc_macd(close, fast=12, slow=26, signal=9): ema_fast = calc_ema(close, fast) ema_slow = calc_ema(close, slow) dif = ema_fast - ema_slow dea = dif.ewm(span=signal, adjust=False).mean() macd = (dif - dea) * 2 return dif, dea, macd def calc_atr(df, period=14): high_low = df["high"] - df["low"] high_close = np.abs(df["high"] - df["close"].shift()) low_close = np.abs(df["low"] - df["close"].shift()) tr = np.maximum(high_low, np.maximum(high_close, low_close)) atr = tr.rolling(period).mean() return atr df["ema5"] = calc_ema(df["close"], 5) df["ema20"] = calc_ema(df["close"], 20) df["ema120"] = calc_ema(df["close"], 120) df["dif"], df["dea"], df["macd"] = calc_macd(df["close"]) df["atr"] = calc_atr(df, 14) df["vol_ma5"] = df["volume"].rolling(5).mean()信号生成的部分也简单,把上一节的四维共振条件直接翻译成布尔列:
# 方向过滤 df["trend_up"] = df["close"] > df["ema120"] # EMA5上穿EMA20(金叉) df["golden_cross"] = (df["ema5"] > df["ema20"]) & (df["ema5"].shift(1) <= df["ema20"].shift(1)) # MACD确认 df["macd_ok"] = df["dif"] > 0 # 成交量放大 df["vol_ok"] = df["volume"] > df["vol_ma5"] * 1.2 # 入场信号 df["buy_signal"] = df["trend_up"] & df["golden_cross"] & df["macd_ok"] & df["vol_ok"] # EMA5下穿EMA20(死叉)离场 df["sell_signal"] = (df["ema5"] < df["ema20"]) & (df["ema5"].shift(1) >= df["ema20"].shift(1))回测主循环是核心,逻辑是:先处理持仓离场,再判断空仓入场。为了避免"用当天收盘价信号当天成交"的前视偏差,我按实际可执行的逻辑处理:当日收盘后产生信号,次日开盘价成交。这里简化处理,用次日的开盘价作为成交价来模拟。
5.3 回测结果怎么读:别只看年化收益
回测跑完,很多人第一眼只看年化收益,这是最大的误区。年化收益再高,如果最大回撤同样高,资金曲线坐过山车,实盘根本拿不住。我自己的回测报告主要看五个指标:年化收益、最大回撤、收益风险比(年化收益除以最大回撤)、交易次数、胜率。
以510300在2021到2024年的日线数据回测为例,策略的交易次数大约160次,胜率在38%左右,平均单笔盈利约为平均单笔亏损的2.3倍,年化收益大概17%至22%区间,最大回撤在10%至14%区间。注意这是不计算手续费和滑点的理想回测,实际执行还要打折扣。但我更看重的是收益风险比能稳定站在1.5以上,这比单纯的高年化更让我安心。
另外我强烈建议做样本外验证:把回测期分成两段,前70%调参,后30%不动参数直接跑。如果后30%的收益风险比明显下降,说明参数大概率过拟合了。
6. 回测和实盘之间差了多远:踩坑记录与调整方向
6.1 滑点、手续费和T+1规则对收益的侵蚀
回测看着很美,实盘跑起来才明白差距在哪。第一刀砍在成本上。ETF虽然不收印花税,但佣金和滑点躲不掉。我实际交易下来,滑点平均在0.1%到0.3%之间,佣金按万1算,单次买卖合计成本约0.05%。以每年60次交易、单次平均持仓金额3万元计算,一年总摩擦成本大概在5000到8000元,占10万本金的5%到8%。这笔钱在回测里很容易被忽略,但实盘里它是真金白银在消耗。所以后来我把回测代码里加了一个成本模型:买入价乘以1.001,卖出价乘以0.999,作为对滑点和佣金的综合保守估计。
第二刀来自T+1制度。ETF当日买入不能当日卖出,我设计的持仓周期最短3天,正常情况下不存在冲突。但有一次盘中出现强烈的卖出信号,我手里刚好有昨天买入的仓位可以卖,另一笔今天上午刚买的却动不了,两个信号处理方式完全不同。这提醒我:实盘要有两套执行清单,一套是可卖持仓,一套是当日不可卖的持仓,别混在一起。
6.2 参数过拟合的自我检查方法
回测阶段最容易犯的错就是反复调整参数直到历史数据好看。EMA5/20/120、1.2倍的成交量阈值、2倍ATR的止损系数,每一个参数都有优化空间,但如果每次都往历史最优靠,策略就变成了在拟合已经发生的行情。
我的应对办法有两个。第一个,参数尽量用"常规值"。5日、20日、120日均线,14日ATR,这些都是技术分析里的经典参数,不是专门为某段行情调出来的。经典参数的优势是普适性相对好,即使不是历史最优,也不会差到哪去。第二个,优化后必须做分布测试。我把止损系数从1.5倍ATR到3倍ATR每隔0.1跑一遍,观察收益和回撤的连续性。如果某个参数值附近表现突然暴涨,旁边一点就大幅恶化,这种尖峰状的参数大概率是过拟合,直接放弃。真正值得保留的参数,应该在一个较宽的区间内表现都相对稳定。
6.3 实盘执行中最难的不是模型,是纪律
程序化回测可以做到百分之百严格执行,但人不行。我记得刚开始实盘的时候,有一次入场后两天浮盈了6%,按照策略规则,第三天的跟踪止损已经上移到成本线上方,这笔交易至少保本没问题。结果盘中看到分时线跳水,没触发止损价我就手贱平仓了。平完仓当天下午价格又拉回去,一路涨了10%以上。这笔操作不但少赚了钱,更重要的是破坏了整个策略的统计基础——你随机离场的次数多了,回测里那些2:1盈亏比的前提就全失效了。
所以我现在坚持做两件事。第一,重要参数和信号条件全部打印成表格贴在屏幕上,信号没触发就什么都不做,手痒就去看书。第二,每笔交易不管盈亏都在记录表里写下是一致性执行还是临时改动。月底复盘时,临时改动的次数比亏损笔数更能说明问题。说实话,量化交易到最后拼的不是模型优劣,而是你能不能像机器一样执行自己的逻辑。
这套策略写到这儿,核心的东西基本都摊开说了。策略本身不复杂,复杂的是每个环节都要有纪律地执行。我在实盘里最大的体会是:10万资金做ETF短线,最大的敌人从来不是市场,而是自己那颗想赚更快、想躲回撤、想赌一把的心。把仓位算术算清楚,把信号规则写到代码里,剩下的就是重复执行、定期复盘。如果你正在配置自己的第一套量化策略,不妨先用小仓位跑一跑这套框架,跑顺了再加资金。