交易货币篮子时可用的形态·进阶篇
(2/3)·从动态入场到均线参考,4类形态拆解篮子内货币的强弱转换逻辑
◍ 篮子离场点与组合WPR的视觉校验
假设已在信号触发那一刻入场,离场点必须事先定义:当指标值逼近或即将下穿零轴时,不论盈亏都退出,这个时刻通常落在当天早七点。用垂直标线把入场与离场两个节点画出来,EUR篮子内其余货币对也照此处理。实际截图中EURNZD为负收益,EURGBP近似为零,另外五对均为盈利,说明篮子内部结果分化是常态。 组合WPR(粗蓝线)与标准WPR(浅蓝线)叠图对比,能直接看出组合版本更平滑,和标准随机振荡指标的结论一致。但父级与组合的超买/超卖阈值是否该保持一致,原文只做了粗略的视觉评估,没给统计证据,不宜主观下定论。 离场有两种思路:按价格行为规则逐对退出,可用熟悉工具和尾随止损,但篮子可能关不全,亏损超过利润的概率存在,需交易者主动防失控;按指标读数统一退,例如-60%交叉后买篮子,-10%或零轴卖出,篮子能全平,但会牺牲部分预期利润。 形态3可落地:蜡烛收盘后穿阈值作为可能的入场信号,超买超卖级别明确,但入场离场规则不严。显著缺陷是不看每个货币对的第二货币,容易带来长期回撤和亏损;掉期、佣金、点值差异也会侵蚀篮子利润。想压回撤提效率,得看下一个形态。
双币强弱差触发单一货币对入场
形态 #4 的核心不在单币种动能,而在货币对两端各自的强弱分化。以 EURJPY 为例,欧元走强、日元疲软同时发生,比仅一端变化更能抬升逆转与顺势移动的概率,这种双向背离才是入场依据。 具体识别靠两个组合 WPR 指标:一个跟踪基准币(如 EUR),一个跟踪报价币(如 JPY),同窗叠放。两者读数差约在 0% 附近时行情平坦;差值向 -200% 或 +200% 极端走,意味着两币动力拉开。为去掉不雅的 200% 边界,实盘把差值除以 2,压缩到 ±100% 区间,超买/超卖线设在 ±60%。 策略上等待差值线逼近年边界后反转,并突破超卖线向下或超买线向上,且突破以蜡烛收盘确认——类似形态 #3,但只做篮子内某一个货币对,而非整篮下单,回撤倾向更低。 下面这段 testDistance.mq5 就是算 EUR 与 JPY 组合 WPR 半差值的独立窗口指标: //+------------------------------------------------------------------+
| // | testDistance.mq5 |
|---|---|
| // | 2016 MetaQuotes Software Corp. |
| // | [MQL5官方文档] |
//+------------------------------------------------------------------+ #property copyright "版权所有 2016, MetaQuotes 软件公司" #property link "[MQL5官方文档] #property version "1.00" #property indicator_separate_window #property indicator_minimum -100 #property indicator_maximum 100 #property indicator_buffers 1 #property indicator_plots 1 input int WPR = 14; //Period WPR input color clr= clrGreen; double ind[]; //+------------------------------------------------------------------+
| // | 自定义指标初始化函数 |
|---|
//+------------------------------------------------------------------+ int h,h1; int OnInit() { //--- 指标缓存区映射 h = iCustom(NULL,0,"testWPR",WPR); if(h == INVALID_HANDLE) { Print("创建 testWPR 出错"); return(INIT_FAILED); } h1 = iCustom(NULL,0,"testWPRjpy",WPR); if(h1 == INVALID_HANDLE) { Print("创建 testWPRjpy 出错"); return(INIT_FAILED); } ArraySetAsSeries(ind, true); SetIndexBuffer(0,ind); IndicatorSetString(INDICATOR_SHORTNAME,"testWPRdistance"); IndicatorSetInteger(INDICATOR_DIGITS,2); IndicatorSetInteger(INDICATOR_LEVELS,2); IndicatorSetInteger(INDICATOR_LEVELSTYLE,0,STYLE_SOLID); IndicatorSetInteger(INDICATOR_LEVELSTYLE,1,STYLE_SOLID); IndicatorSetInteger(INDICATOR_LEVELCOLOR,0,clrRed); IndicatorSetInteger(INDICATOR_LEVELCOLOR,1,clrRed); IndicatorSetInteger(INDICATOR_LEVELWIDTH,0,1); IndicatorSetInteger(INDICATOR_LEVELWIDTH,1,1); IndicatorSetDouble(INDICATOR_LEVELVALUE,0,-60); IndicatorSetDouble(INDICATOR_LEVELVALUE,1,60); PlotIndexSetInteger(0,PLOT_DRAW_TYPE,DRAW_LINE); PlotIndexSetInteger(0,PLOT_LINE_STYLE,STYLE_SOLID); PlotIndexSetInteger(0,PLOT_LINE_WIDTH,2); PlotIndexSetInteger(0,PLOT_LINE_COLOR,clr); PlotIndexSetString(0,PLOT_LABEL,"_tstWPRdistance_"); //--- return(INIT_SUCCEEDED); } double GetValue(int shift) { double dBuf[1],dBuf1[1]; double res=0.0; CopyBuffer(h,0,shift,1,dBuf); CopyBuffer(h1,0,shift,1,dBuf1); return(NormalizeDouble((dBuf[0]-dBuf1[0])/2,_Digits)); } //+------------------------------------------------------------------+
| // | 自定义指标迭代函数 |
|---|
//+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) {
| if(prev_calculated==0 | rates_total>prev_calculated+1) |
|---|
{ int rt=rates_total-WPR; for(int i=1;i<rt;i++) { ind[i]=GetValue(i); } } else { } //--- 返回 prev_calculated 值用于下次调用 return(rates_total); } void OnDeinit(const int reason) { IndicatorRelease(h); IndicatorRelease(h1); } //+------------------------------------------------------------------+ 逐行拆解要点:iCustom 分别加载 testWPR 与 testWPRjpy 两个句柄,失败即终止初始化;IndicatorSetDouble 把 ±60 写成红实线水平位,对应前面说的压缩后超买超卖边界;GetValue 里 CopyBuffer 取两指标当前值,相减除以 2 即得半差值并归一化;OnCalculate 仅在首次或跳变时回填 ind 数组,避免每 tick 重算。 把该指标挂到 EURJPY 副窗,能直接看强弱差绿线。实例中 10 月 21 日 11:00 差值下破 -60 且收线确认,至 11 月 1 日那段下行趋势仍延续,单一订单即可吃到这段。外汇与贵金属杠杆高,这类信号失效时局部reverse可能以其它币对为代价发生,实盘务必自验。 形态 #4 还能当形态 #3 的过滤器:篮内全开按 #3,用 #4 差值剔掉弱势组合,理论上网总收益接近 #3 且保留低回撤优点,不过作者未在真实账户验证过组合。缺点也直白——合适条件不常出现,且总利润因仅单笔下注而偏低。
class=class="str">"cmt">//+------------------------------------------------------------------+ //| testDistance.mq5 | //| class="num">2016 MetaQuotes Software Corp. | //| [MQL5官方文档] | //+------------------------------------------------------------------+ class="macro">#class="kw">property copyright "版权所有 class="num">2016, MetaQuotes 软件公司" 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_minimum -class="num">100 class="macro">#class="kw">property indicator_maximum class="num">100 class="macro">#class="kw">property indicator_buffers class="num">1 class="macro">#class="kw">property indicator_plots class="num">1 input class="type">int WPR = class="num">14; //Period WPR input class="type">color clr= clrGreen; class="type">class="kw">double ind[]; //+------------------------------------------------------------------+ //| 自定义指标初始化函数 | //+------------------------------------------------------------------+ class="type">int h,h1; class="type">int OnInit() { //--- 指标缓存区映射 h = iCustom(NULL,class="num">0,"testWPR",WPR); if(h == INVALID_HANDLE) { Print("创建 testWPR 出错"); class="kw">return(INIT_FAILED); } h1 = iCustom(NULL,class="num">0,"testWPRjpy",WPR); if(h1 == INVALID_HANDLE) { Print("创建 testWPRjpy 出错"); class="kw">return(INIT_FAILED); } ArraySetAsSeries(ind, true); SetIndexBuffer(class="num">0,ind); IndicatorSetString(INDICATOR_SHORTNAME,"testWPRdistance"); IndicatorSetInteger(INDICATOR_DIGITS,class="num">2); IndicatorSetInteger(INDICATOR_LEVELS,class="num">2); IndicatorSetInteger(INDICATOR_LEVELSTYLE,class="num">0,STYLE_SOLID); IndicatorSetInteger(INDICATOR_LEVELSTYLE,class="num">1,STYLE_SOLID); IndicatorSetInteger(INDICATOR_LEVELCOLOR,class="num">0,clrRed); IndicatorSetInteger(INDICATOR_LEVELCOLOR,class="num">1,clrRed); IndicatorSetInteger(INDICATOR_LEVELWIDTH,class="num">0,class="num">1); IndicatorSetInteger(INDICATOR_LEVELWIDTH,class="num">1,class="num">1); IndicatorSetDouble(INDICATOR_LEVELVALUE,class="num">0,-class="num">60); IndicatorSetDouble(INDICATOR_LEVELVALUE,class="num">1,class="num">60); 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,"_tstWPRdistance_"); //--- class="kw">return(INIT_SUCCEEDED); } class="type">class="kw">double GetValue(class="type">int shift) { class="type">class="kw">double dBuf[class="num">1],dBuf1[class="num">1]; class="type">class="kw">double res=class="num">0.0; CopyBuffer(h,class="num">0,shift,class="num">1,dBuf); CopyBuffer(h1,class="num">0,shift,class="num">1,dBuf1); class="kw">return(NormalizeDouble((dBuf[class="num">0]-dBuf1[class="num">0])/class="num">2,_Digits)); } //+------------------------------------------------------------------+ //| 自定义指标迭代函数 | //+------------------------------------------------------------------+ 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-WPR; for(class="type">int i=class="num">1;i<rt;i++) { ind[i]=GetValue(i); } } else { } //--- 返回 prev_calculated 值用于下次调用 class="kw">return(rates_total); } class="type">void OnDeinit(class="kw">const class="type">int reason) { IndicatorRelease(h); IndicatorRelease(h1); } //+------------------------------------------------------------------+
「把均线搬进 WPR 组合找穿越信号」
移动平均线的滞后性是老生常谈,但在 WPR 组合图形里加一条 MA,能直接把“指标线穿越均线”变成可执行的形态 #5 入场逻辑。假设穿越发生在当前周期蜡烛收盘时,信号才算数,这样能过滤掉盘中毛刺。 用快速 MA 时穿越非常频繁, fourth 形态检测图上的交易次数会明显变多;原文建议重点看第四种形态检测图,第三种图留给你自己验证。形态 #4(边界突破)和形态 #5(穿越 MA)有时会几乎同时发生,两者相互强化,硬分主次没意义,但形态 #4 也可能独立出现,与 MA 无关。 规则要钉死:如果形态 #5 先于形态 #4 出现在“范围边界和超卖/超买级别之间”,直接放弃交易;其他情况无论谁先谁后都允许入场。外汇与贵金属杠杆高,穿越信号假突破概率不低,实盘前先在 MT5 用历史数据数一下穿越次数再决定周期。 为落地形态 #5 的分析,需要新建一个指标(也是本系列最后一个),把 MA 画进第四种形态检测图即可手动回看信号分布。
◍ 用双品种 WPR 差值过滤假交叉
把两个不同报价来源的 WPR 指标(例如主品种与交叉盘变体)同时加载,用 iCustom 取各自缓冲,再算 (Buf0 - Buf1)/2 作为差值序列,就能得到一条独立于绝对超买超卖的「背离距离」线。下面这段代码在副图窗口跑,上下界设 ±100,并画了 ±60 两条红色参考线。
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 "版权所有 class="num">2016, MetaQuotes 软件公司" 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_minimum -class="num">100 class="macro">#class="kw">property indicator_maximum class="num">100 class="macro">#class="kw">property indicator_buffers class="num">2 class="macro">#class="kw">property indicator_plots class="num">2 input class="type">int WPR = class="num">14; class=class="str">"cmt">// WPR 周期 input class="type">int maperiod = class="num">10; class=class="str">"cmt">// MA 周期 input class="type">color clr = clrGreen; input class="type">color clrMA = clrMagenta; class="type">class="kw">double ind[],ma[]; 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">//--- 指标缓存区映射 h = iCustom(NULL,class="num">0,"testWPR",WPR); if(h==INVALID_HANDLE){ Print("创建 testWPR 出错"); class="kw">return(INIT_FAILED);} h1 = iCustom(NULL,class="num">0,"testWPRjpy",WPR); if(h1==INVALID_HANDLE){ Print("创建 testWPRjpy 出错"); class="kw">return(INIT_FAILED);} ArraySetAsSeries(ind,true); SetIndexBuffer(class="num">0,ind); IndicatorSetString(INDICATOR_SHORTNAME,"testWPRdistance"); IndicatorSetInteger(INDICATOR_DIGITS,class="num">2); IndicatorSetInteger(INDICATOR_LEVELS,class="num">2); IndicatorSetInteger(INDICATOR_LEVELSTYLE,class="num">0,STYLE_SOLID); IndicatorSetInteger(INDICATOR_LEVELSTYLE,class="num">1,STYLE_SOLID); IndicatorSetInteger(INDICATOR_LEVELCOLOR,class="num">0,clrRed); IndicatorSetInteger(INDICATOR_LEVELCOLOR,class="num">1,clrRed); IndicatorSetInteger(INDICATOR_LEVELWIDTH,class="num">0,class="num">1); IndicatorSetInteger(INDICATOR_LEVELWIDTH,class="num">1,class="num">1); IndicatorSetDouble(INDICATOR_LEVELVALUE,class="num">0,-class="num">60); IndicatorSetDouble(INDICATOR_LEVELVALUE,class="num">1,class="num">60); 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,"_tstWPRdistance_"); 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); PlotIndexSetInteger(class="num">1,PLOT_LINE_WIDTH,class="num">1); PlotIndexSetInteger(class="num">1,PLOT_LINE_COLOR,clrMA); PlotIndexSetString(class="num">1,PLOT_LABEL,"Middle_Basket_line_MA"); class=class="str">"cmt">//--- class="kw">return(INIT_SUCCEEDED); } class="type">class="kw">double GetValue(class="type">int shift) { class="type">class="kw">double dBuf[class="num">1],dBuf1[class="num">1]; class="type">class="kw">double res=class="num">0.0; CopyBuffer(h,class="num">0,shift,class="num">1,dBuf); CopyBuffer(h1,class="num">0,shift,class="num">1,dBuf1); class="kw">return(NormalizeDouble((dBuf[class="num">0]-dBuf1[class="num">0])/class="num">2,_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-WPR; 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); } } else { } class=class="str">"cmt">//--- 返回 prev_calculated 值用于下次调用 class="kw">return(rates_total); } class="type">void OnDeinit(class="kw">const class="type">int reason) { IndicatorRelease(h); IndicatorRelease(h1); class="type">class="kw">string text; class="kw">switch(reason) { case REASON_PROGRAM: text="指标通过调用 ExpertRemove() 函数终端其操作"; class="kw">break; case REASON_INITFAILED: text="此值意味着 OnInit() 处理器 "+__FILE__+" 已返回一个非零值"; class="kw">break; case REASON_CLOSE: text="终端已关闭"; class="kw">break; case REASON_ACCOUNT: text="账户已改变"; class="kw">break; case REASON_CHARTCHANGE: text="品种或时间帧已改变"; class="kw">break; case REASON_CHARTCLOSE: text="图表已关闭"; class="kw">break; case REASON_PARAMETERS: text="输入参数已变更"; class="kw">break; case REASON_RECOMPILE: text="程序 "+__FILE__+" 已编译"; class="kw">break; case REASON_REMOVE: text="程序 "+__FILE__+" 已从图表上移除"; class="kw">break; case REASON_TEMPLATE: text="新模板已应用于图表"; class="kw">break; class="kw">default:text="其它原因"; } PrintFormat("%s",text); } class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">class="kw">double GetMA(class="kw">const class="type">class="kw">double &arr[],class="type">int index,class="type">int period,class="type">int digit) { class="type">class="kw">double m=class="num">0; for(class="type">int j=class="num">0;j<period;j++) m+=arr[index+j]; m/=period; class="kw">return(NormalizeDouble(m,digit)); }
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 "版权所有 class="num">2016, MetaQuotes 软件公司" 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_minimum -class="num">100 class="macro">#class="kw">property indicator_maximum class="num">100 class="macro">#class="kw">property indicator_buffers class="num">2 class="macro">#class="kw">property indicator_plots class="num">2 input class="type">int WPR = class="num">14; class=class="str">"cmt">// WPR 周期 input class="type">int maperiod = class="num">10; class=class="str">"cmt">// MA 周期 input class="type">color clr = clrGreen; input class="type">color clrMA = clrMagenta; class="type">class="kw">double ind[],ma[]; 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">//--- 指标缓存区映射 h = iCustom(NULL,class="num">0,"testWPR",WPR); if(h==INVALID_HANDLE){ Print("创建 testWPR 出错"); class="kw">return(INIT_FAILED);} h1 = iCustom(NULL,class="num">0,"testWPRjpy",WPR); if(h1==INVALID_HANDLE){ Print("创建 testWPRjpy 出错"); class="kw">return(INIT_FAILED);} ArraySetAsSeries(ind,true); SetIndexBuffer(class="num">0,ind); IndicatorSetString(INDICATOR_SHORTNAME,"testWPRdistance"); IndicatorSetInteger(INDICATOR_DIGITS,class="num">2); IndicatorSetInteger(INDICATOR_LEVELS,class="num">2); IndicatorSetInteger(INDICATOR_LEVELSTYLE,class="num">0,STYLE_SOLID); IndicatorSetInteger(INDICATOR_LEVELSTYLE,class="num">1,STYLE_SOLID); IndicatorSetInteger(INDICATOR_LEVELCOLOR,class="num">0,clrRed); IndicatorSetInteger(INDICATOR_LEVELCOLOR,class="num">1,clrRed); IndicatorSetInteger(INDICATOR_LEVELWIDTH,class="num">0,class="num">1); IndicatorSetInteger(INDICATOR_LEVELWIDTH,class="num">1,class="num">1); IndicatorSetDouble(INDICATOR_LEVELVALUE,class="num">0,-class="num">60); IndicatorSetDouble(INDICATOR_LEVELVALUE,class="num">1,class="num">60); 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,"_tstWPRdistance_"); 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); PlotIndexSetInteger(class="num">1,PLOT_LINE_WIDTH,class="num">1); PlotIndexSetInteger(class="num">1,PLOT_LINE_COLOR,clrMA); PlotIndexSetString(class="num">1,PLOT_LABEL,"Middle_Basket_line_MA"); class=class="str">"cmt">//--- class="kw">return(INIT_SUCCEEDED); } class="type">class="kw">double GetValue(class="type">int shift) { class="type">class="kw">double dBuf[class="num">1],dBuf1[class="num">1]; class="type">class="kw">double res=class="num">0.0; CopyBuffer(h,class="num">0,shift,class="num">1,dBuf); CopyBuffer(h1,class="num">0,shift,class="num">1,dBuf1); class="kw">return(NormalizeDouble((dBuf[class="num">0]-dBuf1[class="num">0])/class="num">2,_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-WPR; 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); } } else { } class=class="str">"cmt">//--- 返回 prev_calculated 值用于下次调用 class="kw">return(rates_total); } class="type">void OnDeinit(class="kw">const class="type">int reason) { IndicatorRelease(h); IndicatorRelease(h1); class="type">class="kw">string text; class="kw">switch(reason) { case REASON_PROGRAM: text="指标通过调用 ExpertRemove() 函数终端其操作"; class="kw">break; case REASON_INITFAILED: text="此值意味着 OnInit() 处理器 "+__FILE__+" 已返回一个非零值"; class="kw">break; case REASON_CLOSE: text="终端已关闭"; class="kw">break; case REASON_ACCOUNT: text="账户已改变"; class="kw">break; case REASON_CHARTCHANGE: text="品种或时间帧已改变"; class="kw">break; case REASON_CHARTCLOSE: text="图表已关闭"; class="kw">break; case REASON_PARAMETERS: text="输入参数已变更"; class="kw">break; case REASON_RECOMPILE: text="程序 "+__FILE__+" 已编译"; class="kw">break; case REASON_REMOVE: text="程序 "+__FILE__+" 已从图表上移除"; class="kw">break; case REASON_TEMPLATE: text="新模板已应用于图表"; class="kw">break; class="kw">default:text="其它原因"; } PrintFormat("%s",text); } class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">class="kw">double GetMA(class="kw">const class="type">class="kw">double &arr[],class="type">int index,class="type">int period,class="type">int digit) { class="type">class="kw">double m=class="num">0; for(class="type">int j=class="num">0;j<period;j++) m+=arr[index+j]; m/=period; class="kw">return(NormalizeDouble(m,digit)); }