实用且奇特的自动交易技术·综合运用
「用回撤比给技术稳定性打分」
判断一个交易技术到底有没有用,不能只看最终利润。回测里最容易被误读的就是「赚了」和「碰巧没爆仓」——前者可能只是样本太小,后者可能靠的是浮盈扛单。我更看重两组比值:利润相对平均回撤、利润相对最大回撤,它们能直接暴露技术是真增强还是假平稳。 策略测试器默认只给最终利润、最大余额回撤、最大净值回撤。平均余额回撤和平均净值回撤报告里没有,但逻辑上很关键:当交易费用趋零、策略本身有正期望时,无数个半波(上涨净值段接下跌段)的平均回撤会收敛到总利润值。换句话说,平均回撤越小,同等利润下系统越「密实」,不是靠几笔运气单撑着。 基于上面的关系,可以拼一个综合量具:A = 利润/平均余额回撤,B = 利润/平均净值回撤,C = 利润/最大余额回撤,D = 利润/最大净值回撤。A、B 更准但缺数据;C、D 能直接从回测报告算,所以我实战只用后两个。C 或 D 比裸策略提高,说明加的技术真的降了极端回撤或抬了效率,外汇和贵金属杠杆高、点差跳空频繁,这种比值改善比绝对收益更有参考价值。 用法上,先找一段(或几段)策略本身已经盈利的历史区间,再叠你的技术算 C、D。若 C、D 倾向变大,该技术可保留;若变小,大概率在拖后腿。注意这只能说「概率上更有效」,不是稳赚,实盘前务必在 MT5 用真实点差重跑。
用余额半波给马丁手数踩刹车
把账户余额曲线按相邻涨跌段拆开,每两段构成一个半波。任何余额图本质都是这种半波的堆叠,而半波幅度在不同分组里忽大忽小——幅度小的分组安全,幅度大的分组藏着严重回撤。 思路是在马丁格尔里加两个外部参数:DealsMinusToBreak 记录前一周期亏损单数,触顶就把周期起始手数复位;LotDecrease 定义新周期开启时起始手数的递减步长。安全分组慢慢加手数,危险分组提前减手数,理论上能抬高整体平均量具。 实测中,原始马丁的 D 值约 1.744,开启这套手数调节后变为 1.758,盈利能力轻微偏向正方向。外汇与贵金属属高风险品种,该数值仅单次回测,多跑几次可能回落,但平均倾向略增。 下方代码只算上一周期并决定是否降手数,是策略测试器内的验证函数,直接拷进 MT5 跑一遍比看结论更快。
class="type">class="kw">double DecreasedLot=Lot;class=class="str">"cmt">//lot to decrease class="type">class="kw">double CalcSmartLot()class=class="str">"cmt">//calculate previous cycle { class="type">bool ord; class="type">int PrevCycleDeals=class="num">0; HistorySelect(TimeCurrent()-HistoryDaysLoadI*class="num">86400,TimeCurrent()); for ( class="type">int i=HistoryDealsTotal()-class="num">1; i>=class="num">0; i-- ) { class="type">class="kw">ulong ticket=HistoryDealGetTicket(i); ord=HistoryDealSelect(ticket); if ( ord && HistoryDealGetString(ticket,DEAL_SYMBOL) == _Symbol && HistoryDealGetInteger(ticket,DEAL_MAGIC) == MagicC && HistoryDealGetInteger(ticket,DEAL_ENTRY) == DEAL_ENTRY_OUT ) { if ( HistoryDealGetDouble(ticket,DEAL_PROFIT) > class="num">0 ) { for ( class="type">int j=i+class="num">1; j>=class="num">0; j-- )class=class="str">"cmt">//found a profitable deal followed by losing(count them) { ticket=HistoryDealGetTicket(j); ord=HistoryDealSelect(ticket); if ( ord && HistoryDealGetString(ticket,DEAL_SYMBOL) == _Symbol && HistoryDealGetInteger(ticket,DEAL_MAGIC) == MagicC && HistoryDealGetInteger(ticket,DEAL_ENTRY) == DEAL_ENTRY_OUT ) { if ( HistoryDealGetDouble(ticket,DEAL_PROFIT) < class="num">0 ) { PrevCycleDeals++; } else { class="kw">break; }
◍ 逆序平仓后的手数回补逻辑
上面这段收尾代码决定了一轮逆序减仓循环结束之后,下一笔下单手数怎么定。核心判断是:如果上一轮周期内成交次数 PrevCycleDeals 小于阈值 DealsMinusToBreak,就在当前 DecreasedLot 基础上再减去 LotDecrease;否则把 DecreasedLot 重置回基础 Lot。 手数不会无限往下砍。若扣减后 DecreasedLot 降到 0 或负值,直接拉回 SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN) 拿到的品种最小交易量,避免报单被拒。最后函数 return DecreasedLot 把算好的手数交还给调用方。 在 MT5 里把 DealsMinusToBreak 和 LotDecrease 打印出来对照成交历史,能看清手数阶梯是不是按你预期在收缩。外汇与贵金属杠杆高,逆序减仓仍可能连续亏损,需自行回测验证风险。
}
}
class="kw">break;
}
else
{
class="kw">break;
}
}
}
if ( PrevCycleDeals < DealsMinusToBreak ) DecreasedLot-=LotDecrease;
else DecreasedLot=Lot;
if ( DecreasedLot <= class="num">0.0 ) DecreasedLot=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
class="kw">return DecreasedLot;
}「把这条线请下神坛」
前面几节拆的这套多机器人协同与动态模板思路,本质只是工具箱里的一件器械,不是能自动印钱的圣杯。作者随文给的 Test_Bots.zip 约 380 KB,里面是可直接在 MT5 加载验证的样例机器人,跑通后你会看到它仍依赖两个指标交汇的底层逻辑。 外汇与贵金属自带高杠杆高风险,即便把这类技术摸熟,也只能降低盲目试错的概率,无法消除亏损可能。真要往前走,得自己改参数、加过滤,而不是等着现成系统替你赚钱。