在 MetaTrader 5 中实施多货币交易模式
一、传统 OnTick 模式的缺陷
最朴素的多货币做法是:在 OnTick/OnCalculate 里依次请求各品种分析。它有两个结构性缺陷,越小的周期越明显。
- 睡眠问题:系统依赖当前图表品种的价格变动触发。慢速市场(如夜间)tick 稀少,整个多货币系统跟着“睡”,其他活跃品种也无法计算。
- 历史不同步:MT5 中每个品种第 N 根柱的开盘时间可能不同,按柱序号对齐会错位。
二、同步数据缓冲
为每个品种预分配同步缓冲区,统一用 CopyRates 按时间区间拉取,再以时间轴为基准对齐,而不是按柱序号。
// 为每个品种预分配同步缓冲区
class CSynchronizedBufferRSI
{
double m_buf[];
int m_handle;
void Sync(void) { CopyRates(_Symbol, PERIOD_M15, 0, 100, m_rates); }
};
三、用图表事件驱动刷新
放弃“等当前图表 tick”的思路,改用定时器或自定义图表事件统一触发全市场重算,避免慢速品种拖累。
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
{
if(id == CHARTEVENT_TICK || id == CHARTEVENT_CUSTOM+1)
RecalcAll(); // 统一重算所有品种
}
四、历史同步的关键
五、性能与节流
- 用定时器或自定义事件节流,避免每个 tick 全市场重算。
- 缓存同步缓冲,只在相关品种更新时局部刷新。
- 大周期品种可降低重算频率。
六、多品种 OnTick 循环
多货币模式让一个 EA 监控几十个品种:在 OnTick 里遍历关注列表,对每个品种独立算信号、独立管理持仓。关键是所有状态按品种建索引(如用字典或数组),别用全局单例串台。
注意 OnTick 只在当前图表品种 tick 时触发,要监控其他品种需用定时器或给每个品种挂一个图表。多品种 EA 通常跑在「主图表」,用 SymbolInfo 系列读其他品种数据,不依赖各自图表。
七、跨品种资金分配
总资金要在多品种间分配:等权、按波动反比(波动大的少分)、或按信号强度分配。分配逻辑决定了「一个品种亏了不影响整体」,是组合管理的核心。
double perSym = Balance * RiskPct / ArraySize(WatchList); for(symbol in WatchList) if(Signal(symbol)) trade.Buy(LotOf(perSym, symbol), symbol);
八、性能与同步
监控几十个品种,每 tick 全算一遍会吃 CPU。优化:用定时器分品种错峰计算、只在必要时刷新、信号去重避免重复发单。实盘里还要处理「部分品种休市」的异常。
同步上,多品种下单要控制并发与总持仓上限,避免瞬间铺满导致保证金失控。组合的优势在分散,分散的前提是纪律化的分配与上限。
九、组合层面的风险预算
多品种不只是「多开几单」,更是「分散风险」。真正的风险预算是按相关性分配:高度相关的品种(如 EURUSD 与 GBPUSD)合并算敞口,别当独立仓重复下注,否则分散变集中。
实务用「相关性矩阵」定期重算,相关性升高时自动减配,避免黑天鹅时一荣俱荣一损俱损。这是组合管理比单品种多开更聪明的核心。
还要设组合层总回撤上限:单品种小亏没事,但全组合单日回撤超阈值就全局降仓或暂停,防止「每单都小亏、加起来崩盘」。
十、多品种 EA 的部署形态
生产级多品种 EA 通常跑在一个「主图表」上,通过 SymbolInfo 系列与交易类读取并交易其他品种,不依赖每个品种各挂一个终端。这样资源集中、状态统一,便于监控与风控。
部署时要处理品种休市、流动性中断、部分品种点差突变等异常,绝不能假设所有品种全天同质。健壮的多品种系统有大量「异常分支」,这恰恰是它和 demo 的区别,也是能不能长期跑的关键。
部署时给每个货币对单独记录 tick 与每点价值,严禁共用一套常量,否则跨品种手数会错位、回测与实盘对不上。多货币模式最怕共用可变状态,给每个品种独立上下文是稳定运行底线。另注意不同品种交易时段重叠时的资金占用峰值,提前算好总保证金上限。
十一、小结
完备的多货币模式 = 同步缓冲 + 事件驱动 + 时间对齐。它让多币种 EA 不再受当前图表品种的节奏绑架,也便于在策略测试器中正确回测。