交易货币篮子时可用的形态。第三部分(基础篇)
用 MT5 跑货币篮子形态先看这组基数
- 年 8 月 18 日,一篇关于货币篮子交易形态的文章在 MetaTrader 5 社区发布,截至统计时点获得 4699 次浏览与 7 条讨论,说明这类多品种联动玩法在零售交易者中一直有稳定关注度。
货币篮子不是单看一个直盘,而是把若干相关性品种当成一个组合来处理。MT5 本身支持多符号同时订阅与批量下单,这是做篮子形态验证的基础设施。 想自己复现这类思路,先在 MT5 市场观察里挑 3~5 个高相关货币对(如 EURUSD、GBPUSD、AUDUSD),用 MQL5 脚本把它们的归一化价格差画到同一副图,再观察共振反转。外汇与贵金属杠杆高,篮子放大了波动,实盘前务必在策略测试器用历史数据跑一遍。
◍ 从单一形态切到指标组合视角
前面几篇已经把货币对篮子的主要、次要形态和战术用法拆完了,波浪、VSA 这类复杂框架故意没碰,但入门所需的素材已经齐了。 这一节把镜头转到指标叠加:当振荡器和趋势跟踪类指标同时挂在图上,会催生出哪些可识别的形态。 我们重点放在组合趋势跟踪指标上——这类搭配在 MT5 里随手就能拖出来验证,不需要额外脚本。
「用篮子指数算WPR为何会卡在极值」
把标准 WPR 公式直接套到货币篮子指数图表上,思路很自然:篮子指数是篮内多货币对收盘价的几何均值,相当于一揽子的“清算价”,那对它跑一遍 WPR 不就得到组合动能了?参考指标 testWPRusd 用 EURUSD、GBPUSD、AUDUSD、NZDUSD、USDCAD、USDCHF、USDJPY 七个对美元品种取 WPR 再平均,本来是想拿来和这条新路子对比。 实盘挂上去就露馅了。测试指标放在 EURUSD 主图下的第一个子窗口,参考曲线在第二个子窗口,价格只是平稳下滑,测试 WPR 却一路顶到 0 附近(公式上限),梯度高得离谱。不过两边极值出现的位置意外地吻合——说明方向感应没坏,只是数值标定疯了。 病根在 WPR 方程本身:R% = -((H-C)/(H-L))×100,需要周期最高价 H 和最低价 L。篮子指数只用收盘价算出来,根本没有 H、L 输入,于是测试指标频繁触顶。这不是方法全盘错,而是数据源缺了高低价维度。外汇与贵金属杠杆高、跳空频繁,这类隐性数据缺失会让指标在重大新闻段给出失真读数,验证前别直接拿来信号化。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| testIndex+WPR.mq5 | class=class="str">"cmt">//| class="num">2016 MetaQuotes Software Corp. | class=class="str">"cmt">//| [MQL5官方文档] | class=class="str">"cmt">//+------------------------------------------------------------------+ class="macro">#class="kw">property copyright "版权所有 class="num">2016, MetaQuotes Software Corp." class="macro">#class="kw">property link "[MQL5官方文档] class="macro">#class="kw">property version "class="num">1.00" class="macro">#class="kw">property indicator_separate_window class="macro">#class="kw">property indicator_buffers class="num">2 class="macro">#class="kw">property indicator_plots class="num">1 class="kw">input class="type">color clrWPR = clrGreen; class="kw">input class="type">int wprperiod = class="num">14; class="type">class="kw">double ind[],ma[]; class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| 自定义指标初始化函数 | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">int OnInit() { class=class="str">"cmt">//--- 指标缓存区映射 IndicatorSetDouble(INDICATOR_MINIMUM,-class="num">100); IndicatorSetDouble(INDICATOR_MAXIMUM, class="num">0); ArraySetAsSeries(ma,true); SetIndexBuffer(class="num">0,ma); PlotIndexSetInteger(class="num">0, PLOT_DRAW_TYPE, DRAW_LINE ); PlotIndexSetInteger(class="num">0, PLOT_LINE_STYLE, STYLE_SOLID ); PlotIndexSetInteger(class="num">0, PLOT_LINE_WIDTH, class="num">1 ); PlotIndexSetInteger(class="num">0, PLOT_LINE_COLOR, clrWPR ); PlotIndexSetString(class="num">0, PLOT_LABEL, "_tstdistance_MA" ); ArraySetAsSeries(ind,true); SetIndexBuffer(class="num">1,ind , INDICATOR_CALCULATIONS); class=class="str">"cmt">//---
美元指数合成与指标迭代的落地写法
这段把七组直盘收价拧成一个几何均值,当作自定义美元强度参考。EURUSD 到 NZDUSD 四个货币对设为 false,意味着取倒数后再乘,相当于站在美元视角看;USDCAD、USDCHF、USDJPY 三个设为 true,直接乘原值。iCount=7 控制循环次数,少一个数组元素就会越界报错。 GetIndex 里先取各对 shift 根 K 线的 Close,CopyClose 只拉 1 根放进 dBuf。非直盘分支把 dBuf[0] 翻成 1/价格,所有值连乘后开 7 次方,再用 NormalizeDouble 按 _Digits 截断。这样算出的数,在 EURUSD 1.1000、USDJPY 110.00 这类组合下,量级会被压到接近 1 附近,方便跨周期比对。 OnCalculate 分两种跑法:首根或缺口大于 1 时全量回填 ind[] 和 ma[];否则只更新 0 号位。注意 rt 减掉 wprperiod 后才跑均线循环,否则 ma 前面几根会拿到未初始化内存。外汇与贵金属杠杆高,这类合成指数只反映历史比价,不预示方向,实盘前请在 MT5 策略测试器用 2020—2023 年数据核对数值稳定性。
class="type">class="kw">string pair[]={"EURUSD","GBPUSD","AUDUSD","NZDUSD","USDCAD","USDCHF","USDJPY"}; class="type">bool bDirect[]={false,false,false,false,true,true,true}; class="type">int iCount=class="num">7; class=class="str">"cmt">//计算. 索引 class="type">class="kw">double GetIndex(class="type">int shift) { class="type">class="kw">double res=class="num">1.0,t; class="type">class="kw">double dBuf[class="num">1]; for(class="type">int i=class="num">0; i<iCount; i++) { t=CopyClose(pair[i],PERIOD_CURRENT,shift,class="num">1,dBuf); if(!bDirect[i]) dBuf[class="num">0]=class="num">1/dBuf[class="num">0]; res*=dBuf[class="num">0]; }class=class="str">"cmt">//结束 for (class="type">int i = class="num">0; i < iCount; i++) class="kw">return (NormalizeDouble(MathPow(res, class="num">1/(class="type">class="kw">double)iCount), _Digits) ); } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| 自定义指标迭代函数 | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">class="kw">double HH,LL; class="type">int OnCalculate(class="kw">const class="type">int rates_total, class="kw">const class="type">int prev_calculated, class="kw">const class="type">class="kw">datetime &time[], class="kw">const class="type">class="kw">double &open[], class="kw">const class="type">class="kw">double &high[], class="kw">const class="type">class="kw">double &low[], class="kw">const class="type">class="kw">double &close[], class="kw">const class="type">long &tick_volume[], class="kw">const class="type">long &volume[], class="kw">const class="type">int &spread[]) { if(prev_calculated==class="num">0 || rates_total>prev_calculated+class="num">1) { class="type">int rt=rates_total; for(class="type">int i=class="num">1; i<rt; i++) { ind[i]= GetIndex(i); } rt -= wprperiod; for (class="type">int i = class="num">1; i< rt; i++) { ma[i] = GetMA(ind, i, wprperiod, _Digits); } } else { ind[class="num">0] = GetIndex(class="num">0); ma[class="num">0] = GetMA(ind, class="num">0, wprperiod, _Digits); } class="kw">return(rates_total);