一个让所有交易者都血压升高的场景
你判断螺纹钢要涨,在3080开多,止损设在3060。
结果价格下探到3058,把你的止损打掉了。然后它转头一路涨到3140。
你没错方向,你错在被扫出去了。
这种事发生一次是运气不好,发生十次,就说明你的止损方式和这个品种的波动特性不匹配。
固定止损的根本问题:它假设波动率是不变的
大多数人的止损是这两种:
固定点数:亏20个点就走
固定百分比:亏2%就走
这两种方式有一个共同的隐含假设——价格每天的正常波动幅度差不多。
但事实是,波动率一直在变。同一个品种,在震荡期和趋势启动期、在数据公布前后、在长假前后,它的"呼吸幅度"可能差好几倍。
于是你会遇到两种失败:
波动大的时候,你的止损太窄→ 被正常的市场噪音扫出去,方向对了也赚不到钱。这是上面那个场景。
波动小的时候,你的止损太宽→ 你承担了远超必要的风险,一次真正的反向行情就把你伤得很重。
更麻烦的是跨品种的问题:同样设20个点止损,在螺纹钢和沪金上完全不是一回事,因为两个品种的每点价值和日常波动量级差得很远。你以为在统一管理风险,实际上你在给低波动品种发补贴。
ATR:把"这个品种现在呼吸多大"变成一个数字
ATR(Average True Range,平均真实波幅)衡量的就是一段时间内价格波动的绝对幅度。它的计算逻辑是先取"真实波幅"——当日高低价之差、当日高价与昨收之差、当日低价与昨收之差,三者取最大——然后对一段周期做平滑平均。
周期常用20日,也就是回溯20个交易日的成交数据。这个参数在期魔方的因子体系里就是标准的波动率因子实现方式。
ATR给你一个非常有用的东西:当前这个品种的正常波动尺度。
比如某品种20日ATR是45元/吨,意思大致是"它最近每天的正常波动幅度在45元左右"。那么你把止损设在20元,等于是在正常呼吸范围内放了一根针——它不需要发生任何异常,就能把你扫掉。
动态止损:让止损距离跟着波动率走
核心思路一句话:止损距离 = k × ATR。
波动变大 → ATR变大 → 止损距离自动放宽,不被噪音扫出
波动变小 → ATR变小 → 止损距离自动收紧,风险敞口同步缩小
k 是倍数,常见取值区间在 2 到 3 之间。但我要明确说一句:不存在一个通用的"最佳倍数。趋势类策略通常需要放宽(否则扛不过趋势中的正常回调),短线类策略通常收紧(否则单次亏损过大)。这个数必须自己在回测里试,而且要试出"在一个区间内表现都还行",而不是"某一个值表现特别好"——后者大概率是过拟合。
进阶用法一:移动止损(吊灯式)
固定入场止损解决的是"错了要认",移动止损解决的是"对了要拿住"。
做法是:以持仓期间出现过的最高价(做多时)为锚,止损位 = 最高价 − k × ATR,并且只上移不下移。
行情往你方向走,止损位跟着抬,利润被逐步锁住;行情回撤超过 k 倍正常波动幅度,说明这可能不是噪音而是反转,触发离场。
这比"赚了3%就止盈"这种固定止盈合理得多——固定止盈会在趋势行情里把你提前请下车。
进阶用法二:用ATR反推手数(这是它最实用的功能)
大多数人只把ATR当止损工具,其实它更大的价值在仓位管理。
思路是:让每一笔交易的最大亏损额固定,然后反推该开几手。
单笔风险额 = 账户资金 × 风险比例
止损距离 = k × ATR
每手亏损额 = 止损距离 × 合约乘数
开仓手数 = 单笔风险额 ÷ 每手亏损额
一个纯算术演示(下面所有价格都是假设值,不是任何品种的真实行情,只为说明公式怎么算):
假设账户资金 100,000 元,单笔风险比例取 1%,那么单笔风险额 = 100,000 × 1% = 1,000 元。
假设某品种 ATR = 45 元/吨,k 取 2,止损距离 = 2 × 45 = 90 元/吨。
假设该品种合约乘数为 10 吨/手,每手亏损额 = 90 × 10 = 900 元/手。
开仓手数 = 1,000 ÷ 900 ≈ 1.11,向下取整为 1 手。
换到另一个品种:假设 ATR = 120 元/吨,k 仍取 2,止损距离 = 240 元/吨,合约乘数 5 吨/手,每手亏损额 = 240 × 5 = 1,200 元/手。开仓手数 = 1,000 ÷ 1,200 ≈ 0.83,不足1手,说明按这个风险标准,这笔交易你要么不做,要么降低风险比例。
这个"算出来不足1手"的结果非常有价值——它在告诉你:以你现在的资金规模,这个品种的波动你扛不起。很多人是亏了大钱之后才明白这件事的。
用ATR做仓位归一化之后,你在螺纹钢、沪金、原油上的每一笔交易承担的风险是等量的,账户的波动才会平滑,策略的表现才可比较。
在期魔方里怎么落地
上面这些逻辑,落到工具上有几个关键点:
- ATR 直接可用,不用自己写。
期魔方内置 Python 运行环境,预装 ta_lib、pandas、numpy 等库,ATR 属于 ta_lib 里的标准函数,直接调用即可。你也可以把它做成图表上的自定义指标,直观看到波动率的起伏——它的指标是基于 Python 实现的,形态可以自定义,柱状、曲线、动态大屏样式都行。
- 把参数做成外置参数,改参数不用改代码。
这一点很实用。策略里的 ATR 周期、倍数 k、风险比例,都应该做成外置参数。这样你在回测里调参数、在不同品种上换参数,都不需要动代码本体。同一套策略可以在多个品种上跑不同参数组合,也支持同一品种跑多个策略。
- 多周期配合:日线定波动尺度,分钟线做执行。
期魔方支持多周期订阅(通过 subscribe_symbols 全局变量,格式为"合约ID:周期",多个合约用 & 连接)。典型做法是用大周期算 ATR 和趋势方向,用小周期找入场点、做风控触发。
- 用三档回测验证,别只看一档。
ATR 止损这类逻辑对盘中价格行为极度敏感——它本质上就是在处理盘中波动。如果你的回测只用收盘价序列,那盘中插针、假突破这些最关键的信息全被抹平了,回测结果没有任何参考价值。
期魔方的回测分三档:收盘价序列、模拟 Tick、真实 Tick。测 ATR 止损,至少要跑到模拟 Tick,认真做的应该跑真实 Tick。三档结果的差异本身就是策略稳健性的体检报告。
- 用 K 线标注看清你到底在哪儿被扫的。
回测报告是图解化的,每一笔开仓平仓都直接标在 K 线上,配逐笔运行日志。调 ATR 参数的时候,这个功能比任何统计数字都有用——你能直接看见"如果 k 从 2 改成 2.5,那一笔就不会被扫掉了"。
- 执行层交给风控模型。
参数调好之后,实盘执行可以用自动止损止盈风控模型:按百分比给每个合约设置止盈止损比例,触发后按预设报单方式(市价/现价/对价)自动平仓,跟踪对象可以选"全局"或"指定合约"。它的规则是账户级的,即使你从文华财经、博易大师这类第三方终端下单,在期魔方里设的风控同样生效。
如果你要做短周期,2.2.41 版本之后支持 5s/10s/15s/30s 秒周期,K线看盘、回测、实盘全场景适配。
三个必须知道的坑
坑一:ATR 是滞后的。
它衡量的是过去一段时间的波动,不预测未来。波动率突变(比如突发消息、政策公布)时,ATR 还没来得及反应,你的止损距离还是按旧的波动尺度算的。所以 ATR 不能替代对重大事件时点的判断——该减仓的时候还是要减仓。
坑二:跳空缺口下,ATR 止损不保证成交价。
止损是一个触发条件,不是一个价格承诺。如果开盘直接跳空穿过你的止损位,成交价会在跳空后的位置,而不是你设的位置。
这一点在长假期间尤其致命。今天9月30日是节前最后一个交易日,今晚不开夜盘,10月1日至7日休市,10月8日恢复。**你的仓位要扛过七天无法操作的空窗期,中间外盘照常波动。**ATR 算得再准,也管不了节后开盘那个跳空。所以节前该做的事是重新评估持仓比例,不是调参数。
坑三:k 值调到小数点后一位,就是过拟合了。
如果你在回测里发现 k=2.3 明显好于 k=2.0 和 k=2.5,那不是发现了规律,那是拟合了历史噪音。一个稳健的参数,应该在一个区间内表现都不差。看到"某个特定值一枝独秀",先怀疑自己。
最后
ATR 不是什么高级东西,它就是把"这个品种现在波动多大"变成一个数字,然后让你的止损和仓位跟着这个数字走,而不是跟着你的心情走。
它解决的问题很具体:别再让正常的市场噪音把你扫出去,也别再在低波动时期承担过大的敞口。
至于用了 ATR 就能赚钱吗?不能。任何止损方式都只决定你亏多少、怎么亏,不决定你赚不赚。赚不赚取决于你的入场逻辑,那是另一件事。