创建瞬时报价指标
在 MetaEditor 里运行 MQL 向导, 设置名称和两个输入参数:
-
ticks — 计算标准差时所用的瞬时报价数量
-
gap — 获取标准差的间隔系数。
接下来, 勾选 "指标位于单独窗口" 并指定 2 块图形作图板, 它们将在子窗口里显示信息: 一条瞬时报价线和有关价格尖峰出现的彩色信号箭头。
编辑
添加图片注释,不超过 140 字(可选)
在结果草案里用黄色标记变化
//+------------------------------------------------------------------+ //| TickSpikeHunter.mq5 | //| 版权所有 2016, MetaQuotes 软件公司| //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "版权所有 2016, MetaQuotes 软件公司" #property link "https://www.mql5.com" #property version "1.00" #property indicator_separate_window #property indicator_buffers 3 #property indicator_plots 2 //--- 绘制瞬时报价 #property indicator_label1 "瞬时报价" #property indicator_type1 DRAW_LINE #property indicator_color1 clrGreen #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //--- 绘制信号 #property indicator_label2 "信号" #property indicator_type2 DRAW_COLOR_ARROW #property indicator_color2 clrRed,clrBlue,C'0,0,0',C'0,0,0',C'0,0,0',C'0,0,0',C'0,0,0',C'0,0,0' #property indicator_style2 STYLE_SOLID #property indicator_width2 1 //--- 输入参数 input int ticks=50; // 计算所用瞬时报价数量 input double gap=3.0; // 通道宽度的标准差 //--- 指标缓存区 double TickPriceBuffer[]; double SignalBuffer[]; double SignalColors[]; //--- 价格变化计数器 int ticks_counter; //--- 第一次指标调用 bool first; //+------------------------------------------------------------------+ //| 自定义指标初始化函数 | //+------------------------------------------------------------------+ int OnInit() { //--- 指标缓存区映射 SetIndexBuffer(0,TickPriceBuffer,INDICATOR_DATA); SetIndexBuffer(1,SignalBuffer,INDICATOR_DATA); SetIndexBuffer(2,SignalColors,INDICATOR_COLOR_INDEX); //--- 设置空值, 在绘图时应被忽略 PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0); PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0); //--- 信号将作为图标输出 PlotIndexSetInteger(1,PLOT_ARROW,159); //--- 初始化全局变量 ticks_counter=0; first=true; //--- 程序初始化成功 return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| 自定义指标迭代函数 | //+------------------------------------------------------------------+ 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[]) { //--- //--- 返回 prev_calculated 的数值用于下次调用 return(rates_total); } //+------------------------------------------------------------------+
现在, 将其它部分代码加入接收瞬时报价的 OnCalculate() 预定义处理器。在首次调用函数期间要明确将指标缓存区清零, 并且出于便利, 将它们标记为序列 — 因此, 它们将会从右至左索引。这样就可以使用索引 0 来调用最近的指标缓存区数值, 即最后的瞬时报价值将会保存在 TickPriceBuffer[0]。
另外, 主要的瞬时报价处理将移至单独的 ApplyTick() 函数:
//+------------------------------------------------------------------+ //| 自定义指标迭代函数 | //+------------------------------------------------------------------+ 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(first) { ZeroMemory(TickPriceBuffer); ZeroMemory(SignalBuffer); ZeroMemory(SignalColors); //--- 序列数组向后定位, 在这种情况下最方便 ArraySetAsSeries(SignalBuffer,true); ArraySetAsSeries(TickPriceBuffer,true); ArraySetAsSeries(SignalColors,true); first=false; } //--- 使用当前的收盘价作为价格 double lastprice=close[rates_total-1]; //--- 瞬时报价计数 ticks_counter++; ApplyTick(lastprice); // 执行计算和缓存区移位 //--- 返回 prev_calculated 的数值用于下次调用 return(rates_total); } //+------------------------------------------------------------------+ //| 应用瞬时报价进行计算 | //+------------------------------------------------------------------+ void ApplyTick(double price) { int size=ArraySize(TickPriceBuffer); ArrayCopy(TickPriceBuffer,TickPriceBuffer,1,0,size-1); ArrayCopy(SignalBuffer,SignalBuffer,1,0,size-1); ArrayCopy(SignalColors,SignalColors,1,0,size-1); //--- 保存最后的价格值 TickPriceBuffer[0]=price; //--- }
目前, ApplyTick() 执行最简单地操作 — 将所有缓存区数值向后挪一位并将最后的瞬时报价写入 TickPriceBuffer[0]。在调试模式里运行指标并观察一段时间。
编辑切换为居中
添加图片注释,不超过 140 字(可选)
正如可以看到的那样, 供给价用作当前蜡烛的基准收盘价一般保持不变, 所以图表上绘出了一片 "高地"。稍微调整代码, 以便仅得到 "锯齿" - 这更加直观。
//--- 只在价格变化时计算 if(lastprice!=TickPriceBuffer[0]) { ticks_counter++; // 瞬时报价计数 ApplyTick(lastprice); // 执行计算和缓存区移位 }
如此, 指标的第一个版本已经创建, 现在价格没有零增量。
编辑切换为居中
添加图片注释,不超过 140 字(可选)