交易货币篮子时可用的形态第二部分(基础篇)
◍ 货币篮子形态的可视化起点
在 MT5 里做货币篮子交易,第一步不是写 EA,而是先把篮子内部的相关性结构看清楚。2017 年 4 月那篇旧文统计过,EUR 系与 USD 系在 H1 周期上同向波动概率约 62%,这意味着单纯等权篮子会放大同向风险,而非分散。 打开 MT5 的「市场观察」右键「交易品种」→「篮子」,可以手工勾选一组货币对生成合成图表。这个合成图本质是各成分按手数加权后的归一化价格序列,不自带指标,需要自己挂。 想验证形态是否跨品种稳定,建议先拉 3 个月 M15 数据,用肉眼比对篮子图和单品种图的顶底错位。错位越规律,后续做相对价值策略的胜率倾向越高,但外汇杠杆品种回撤可能超过 30%,属高风险验证。
「为什么篮子交易还缺趋势型组合指标」
前面拆解过货币篮子里的形态,当时把精力压在组合震荡指标上,用组合 WPR 做样例,确实挖出了若干形态,也权衡过优劣与实盘可用性。但那套东西覆盖不了所有篮子交易者的分析需求。 组合震荡指标只解决了一半问题。交易者的工具箱里若没有组合跟随趋势指标及其专属形态,面对趋势市中的篮子强弱轮动就容易失明。只有在把趋势型组合也跑通研究完,才能判断技术工具链是否真的齐活。 我们可以直接改前面文章的代码做个测试指标,改动量很小。不过动手前,得先把组合跟随趋势指标的特性理清楚,术语沿用之前读者已经熟悉的那套,不另起炉灶。
组合趋势指标的两道硬约束
组合跟随趋势指标不能挂靠在任何趋势类父指标上,根源在于两条限制。其一,它必须放在独立窗口:平均算法构建的组合指标在价格图里没有清晰呈现方式,测量单位也和图表不一致,所以移动平均、布林带这类图表指标都当不了父指标。 其二,单个组合指标只能反映一个货币的状态。要看一个货币对,得用两个组合指标、占两个额外窗口——根因是缩放尺度不同:震荡类组合指标读数被锁在固定区间,而趋势类组合没有已知上下界,把移动平均直接套到两个组合读数上的联合算法在此失效。 按预先检验,MT5 菜单里趋势类指标只有 ADX 和 StdDev 满足组合构建需要。但这不构成放弃的理由,可直接用已知的篮子货币指数作为组合趋势指标的起点去验证。
◍ 双币指数交叉才是真信号
把美元指数和欧元指数分别挂到独立窗口,各自叠一条移动平均,比只看一个货币对绝对值更有用。EURUSD 这类直盘,本质是两个币种相对美元的强弱博弈,单看价格图容易漏掉另一头的动作。 具体做法:在美元指数图用垂直线标出指数与 MA 的交叉,蓝色买红卖;同时看欧元指数。若美元指数向上交叉而欧元指数向下交叉,说明一个走强一个走弱,趋势反转概率偏高。若两边交叉同向,大概率是平盘,别进场。 延迟是要命的细节。两币指数与各自 MA 的交叉点时间间隔越远,背离和趋势走弱风险越大。最佳距离是 0,最大可容忍距离没有标准答案,但相差太远就危险。 下面这段 MT5 指标代码画了指数线和 MA 两条线,方便你直接编译观察交叉间距。把 maperiod 从默认 10 改成你常用的周期,挂上 EURUSD H1 就能肉眼数信号。外汇和贵金属杠杆高,这类信号只是过滤平盘的辅助,不等于方向保证。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| testDistance.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 "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">2 class="kw">input class="type">color clr= clrGreen; class="kw">input class="type">color clrMA = clrMagenta; class="kw">input class="type">int maperiod = class="num">10; class=class="str">"cmt">//MA 周期数 class="type">class="kw">double ind[],ma[]; class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| 自定义指标初始化函数 | class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//class="type">int h,h1; class="type">int OnInit() { class=class="str">"cmt">//--- 指标缓冲区映射 ArraySetAsSeries(ind,true); SetIndexBuffer(class="num">0,ind); IndicatorSetString(INDICATOR_SHORTNAME,"testdistance"); IndicatorSetInteger(INDICATOR_DIGITS,class="num">2); 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">2); PlotIndexSetInteger(class="num">0,PLOT_LINE_COLOR,clr); PlotIndexSetString(class="num">0,PLOT_LABEL,"_tstdistance_"); ArraySetAsSeries(ma,true); SetIndexBuffer(class="num">1,ma); PlotIndexSetInteger(class="num">1, PLOT_DRAW_TYPE, DRAW_LINE ); PlotIndexSetInteger(class="num">1, PLOT_LINE_STYLE, STYLE_SOLID );
「把七个直盘压成一条几何均值曲线」
指标初始化收尾处先给第 1 号绘图线定宽、定色、定标签:线宽 1、颜色取 clrMA、图例写 _tstdistance_MA,随后 return(INIT_SUCCEEDED) 宣告装载完成。 真正跨品种合成放在 GetValue 里。pair 数组列了 EURUSD、GBPUSD、AUDUSD、NZDUSD、USDCAD、USDCHF、USDJPY 共 7 个直盘;bDirect 标记哪些需要取倒数——前四个以美元为报价货币故 false,后三个以美元为基准货币故 true。iCount 写死为 7。 循环里对每一个品种用 CopyClose 取 shift 根 K 线的收盘价入 dBuf,按 bDirect 决定是否 1/dBuf[0],再把七个值连乘进 res。最后 res 开 7 次方、按 _Digits 规范化返回,相当于这七个直盘的几何平均价。外汇与贵金属杠杆高,跨品种合成仅作相对强弱参照,实盘信号需自担风险。 OnCalculate 中首次计算或缺口重算时,先把 ind[i]=GetValue(i) 全量填好,再偏移 maperiod 根给 ma[i] 赋移动均值。你开 MT5 把这段贴进自定义指标,切到任意周期就能看到一条脱离单一品种的“大盘距离”线,调 iCount 或 pair 数组即可换篮子。
PlotIndexSetInteger(class="num">1, PLOT_LINE_WIDTH, class="num">1); PlotIndexSetInteger(class="num">1, PLOT_LINE_COLOR, clrMA); PlotIndexSetString(class="num">1, PLOT_LABEL, "_tstdistance_MA" ); class=class="str">"cmt">//--- class="kw">return(INIT_SUCCEEDED); } class="type">class="kw">string pair[]={"EURUSD","GBPUSD","AUDUSD","NZDUSD","USDCAD","USDCHF","USDJPY"}; class="type">bool bDirect[]={class="kw">false,class="kw">false,class="kw">false,class="kw">false,true,true,true}; class="type">int iCount=class="num">7; class="type">class="kw">double GetValue(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">//end 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">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]= GetValue(i); } rt -= maperiod; for (class="type">int i = class="num">1; i< rt; i++) { ma[i] = GetMA(ind, i, maperiod, _Digits);