English Русский Español Deutsch 日本語 Português
在指标中添加声音提醒

在指标中添加声音提醒

MetaTrader 4交易 | 29 二月 2016, 16:44
4 609 0
Andrey Khatimlianskii
Andrey Khatimlianskii

简介

尽管自动化交易变得越来越常见,但很多交易者仍在进行手动交易。Expert Advisor 只要几毫秒时间即可评估当前市场情况,而人则需要花费许多时间、精力和最为重要的关注度才能完成当前市场状况评估。

几年前,很多交易者使用一个或多个技术指标。一些策略同时考虑多个时间范围的指标值。

那么,如何能够“抓住”重要的信号?有多种选择:

  • 编写一个能够分析市场并对重要事件进行提醒的 Expert Advisor;
  • 坐在显示器前,在数十个图表中来回切换,尝试分析所有图表中的信息;
  • 将提醒系统添加到使用的所有指标中。

我个人认为,第一种选择最为合适。但是,需要有编程技能或支付相关费用才能实现。第二种方式非常耗时、累人,而且效率低下。第三种选择介于前两种方式之间。只要少得多的技能和时间即可实现,但的确可以帮助很多手动交易用户。

本文专门介绍第三种选择的实施情况。阅读本文后,每位交易者将能够将便捷的提醒添加到指标中。



提醒的类型

有很多种方式来解释指标。人们甚至对 MetaTrader 4 客户端的指标的含义都存在不同的理解,更别提各种自定义指标...

一名交易者会在 MACD 的主线触及信号线时买入,另一名交易者会等到与零线相交时才买入,而还有交易者会在 MACD 小于 0 且开始向上移动时才建立多头头寸。我觉得自己无法统计所有可能的不同解释,因此,我将仅介绍如何将提醒模块加入到指标的原则。这样,您将能够根据喜好将任意类型的提醒添加到几乎所有的指标中。

下面列出了最可能的提醒:

  • 指标的两条线的相交(在上例中为 MACD 的主线和信号线);
  • 指标线与某水平的相交(例如,MACD 的主线与零线,Stoсhastic 与 70 和 30 水平,CCI 与 -100 和 100 水平);
  • 指标的反向移动(例如,AC 与 AO,正常 MA);
  • 位置朝向价格而变化(抛物线 SAR);
  • 出现高于或低于价格值的箭头(分形)。

很可能还有其他一些我已遗忘或根本不了解的解释,因此,我们将介绍上述列出的五种类型。


提醒的方式

MetaTrader 4 和 MQL4 允许实现多种可视和音频提醒方式。

  • 常见的屏幕消息(备注函数);
  • 日志中的记录(打印函数);
  • 消息窗口及声音(提醒函数);
  • 特殊声音,待选择和播放的文件(PlaySound 函数)。

除此之外,还有用于将文件发送至 FTP 服务器的函数(SendFTP() 函数)、用于显示消息/对话框的函数(MessageBox() 函数) 和用于发送邮件的函数(SendMail() 函数)。函数 SendFTP() 几乎不被普通用户所使用;函数 MessageBox() 因其在消息框关闭之后才停止操作而不适用于在指标中使用;尽管函数 SendMail() 很适合发送短信,但使用过程中相当“危险” - 在图表上绘制大量指标,会无休止地收到不受控的消息。可使用此函数,但最好是在以下情况下使用,例如,当多个指标上同时出现一个提醒时,从 EA 发送一条消息,对其给予密切关注。

在本文中,我们将仅考虑 MetaTrader 4 客户端中的音频和可视提醒方式。

这些函数中的一个最便捷和最简单函数就是提醒函数,因为它同时包含文本和声音内容。除此之外,终端将存储提醒的历史记录,因此可查看一个小时之前收到了什么信号。

但是大家都知道,每个人的偏好各有不同。因此,我将为上述所有方法(SendFTP、MessageBox、SendMail 除外)制定一个类似预制定的模型,您只需选择合适的选项。


提醒频率过滤器

如果您在指标中使用了提醒,您当然得处理它们的过频率,尤其是有关较小时间范围的过频率。有一些方法解决此问题:

  • 在已形成的柱上定义提醒。此解决方案最为合适。
  • 交替提醒 - 先买后卖,反之亦然(这也是一种非常合理的方式,可与其他方式一起使用)。
  • 在两次提醒之间设置暂停(不是个好主意)。
  • 每个柱仅提供一次提醒(此限制相当受影响)。

是否使用从零而非从已形成的柱定义的提醒取决于个人。例如,我认为这不对。但是,存在需要即时响应的指标,对于它们而言,一个柱也太久了。因此,我们允许用户做出自己的选择。多次购买提醒几乎没有什么意义,因此我们将交替发出所有提醒。我认为,我们不会引入任何人为的暂停。如果确实需要,可在本文的备注中了解具体情况。

因此,让我们开始实施。


第一种提醒 - 指标的两条线的相交

让我们开始使用上述示例中给出的 MACD。

我们的主要任务是检测出指标线存储在哪个数组中。我们来看看相关代码:

//---- indicator settings
#property  indicator_separate_window
#property  indicator_buffers 2
#property  indicator_color1  Silver
#property  indicator_color2  Red
#property  indicator_width1  2
//---- indicator parameters
extern int FastEMA = 12;
extern int SlowEMA = 26;
extern int SignalSMA = 9;
//---- indicator buffers
double MacdBuffer[];
double SignalBuffer[];

请注意,“指标缓冲器”的备注是我们要查找的内容。这些数组大多数都有直观而全面的名称(MacdBuffer 是 MACD 主线值缓冲器,SignalBuffer - 信号线的缓冲器),并且始终处于函数 init、deinit、start 之外。

如果有很多数组并且难以查看哪个数组为必要数组,请查看函数 init - 图表中显示的所有数组都被固定到某个使用函数 SetIndexBuffer 的数字:

int init()
  {
//---- drawing settings
   SetIndexStyle(0, DRAW_HISTOGRAM);
   SetIndexStyle(1, DRAW_LINE);
   SetIndexDrawBegin(1, SignalSMA);
   IndicatorDigits(Digits + 1);
//---- indicator buffers mapping
   SetIndexBuffer(0, MacdBuffer);
   SetIndexBuffer(1, SignalBuffer);
//---- name for DataWindow and indicator subwindow label
   IndicatorShortName("sMACD(" + FastEMA + "," + SlowEMA + "," + SignalSMA + ")");
   SetIndexLabel(0, "sMACD");
   SetIndexLabel(1, "sSignal");
//---- initialization done
   return(0);
  }

这是序列(0 至 7),在此序列中,指标线的值显示在 DataWindow 中。您在那里看到的名称是由函数 SetIndexLabel 给定的 - 这是第三种标识方法。

现在,当我们了解了必要数据存储在何处时,我们可以开始实现提醒模块。为此,我们将转到函数 start 的结尾部分 - 正好位于前一操作符 return 的上方:

for(i = 0; i < limit; i++)
       SignalBuffer[i] = iMAOnArray(MacdBuffer, Bars,S ignalSMA, 0, MODE_SMA, i);
//---- done
 
// we will add our code here
 
   return(0);
  }
//+------------------------------------------------------------------+

在任何情况下,都不得在指标的计算回路中添加任何提醒块 - 这会减慢执行速度,而且没有任何作用。

让我们开始编写我们的“composition”:

//---- Static variables where the last bar time
    //---- and the last alert direction are stored
    static int PrevSignal = 0, PrevTime = 0;
 
    //---- If the bar selected to be analyzed is not a zero bar, 
    //     there is no sense to check the alert
    //---- several times. If no new bar starts to be formed, quit.
    if(SIGNAL_BAR > 0 && Time[0] <= PrevTime ) 
        return(0);
    //---- Mark that this bar was checked
    PrevTime = Time[0];

每次开始执行函数 start 时,也会执行我们的代码。每次执行此函数之后,正常变量都会归零。因此,我们声明了两个静态变量以存储最新提醒和计算出的柱编号。

然后进行简单的检查:我们检查新的柱是否已启动(它只有在 SIGNAL_BAR 大于 0 时才有效)。

顺便说一下,我们稍早于函数 init 之前声明了变量 SIGNAL_BAR 本身:

double     SignalBuffer[];
 
//---- Bar number the alert to be searched by
#define SIGNAL_BAR 1
 
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {

请注意指令 #define - 在整个代码中,编译器将仅用给定值 (1) 替换变量 SIGNAL_BAR。

下面是提醒代码本身:

//---- If the preceding alert was SELL or this is the first launch (PrevSignal=0)
    if(PrevSignal <= 0)
      {
        //---- Check whether the lines have met in the preceding bar:
        if(MacdBuffer[SIGNAL_BAR] - SignalBuffer[SIGNAL_BAR] > 0 && 
           SignalBuffer[SIGNAL_BAR+1] - MacdBuffer[SIGNAL_BAR+1] >= 0)
          {
            //---- If yes, mark that the last alert was BUY
            PrevSignal = 1;
            //---- and display information:
            Alert("sMACD (", Symbol(), ", ", Period(), ")  -  BUY!!!");
//            Print("sMACD (", Symbol(), ", ", Period(), ")  -  BUY!!!");
//            Comment("sMACD (", Symbol(), ", ", Period(), ")  -  BUY!!!");
//            PlaySound("Alert.wav");
          }
      }

这也非常简单。如果之前的提醒为 SELL,检查线的相交情况:

如果柱 #1 上的 MACD 主线值超过了柱 # 1 上的信号线的值
并且
柱 #2 上的信号线值超过了柱 #2 上的 MACD 线的值,

线相交。

然后,标记最后一个提醒用于 BUY,并显示通知消息。请注意 三个有注释的线 - 它们是另外三种提醒。您可以取消注释 或删除它们中的任意或全部项。我将提醒默认为最便捷的方法。

在函数 PlaySound 中,可指定应播放的波形文件。此文件必须位于目录 MetaTrader 4\sounds\ 中并且必须具有扩展名 wav。例如,可将特殊声音指派给 BUY 提醒,另一个 - 用于 SELL 提醒,或者不同的指标使用不同的声音

SELL 提醒完全相同:

//---- Completely the same for the SELL alert
    if(PrevSignal >= 0)
      {
        if(SignalBuffer[SIGNAL_BAR] - MacdBuffer[SIGNAL_BAR] > 0 && 
           MacdBuffer[SIGNAL_BAR+1] - SignalBuffer[SIGNAL_BAR+1] >= 0)
          {
            PrevSignal = -1;
            Alert("sMACD (", Symbol(), ", ", Period(), ")  -  SELL!!!");
//            Print("sMACD (", Symbol(), ", ", Period(), ")  -  SELL!!!");
//            Comment("sMACD (", Symbol(), ", ", Period(), ")  -  SELL!!!");
//            PlaySound("Alert.wav");
          }
      }


其他提醒

现在,在我们了解了指标代码后,对于我们而言,编写其他提醒块要简单得多。将仅更改“公式”,代码的其他部分将仅进行复制和粘贴。

用于发出触及某水平的信号的提醒非常类似于各线相交的提醒。我将它添加到了 Stochastic 中,但是您可以为任何其他指标制定类似的提醒:

if(PrevSignal <= 0)
      {
        if(MainBuffer[SIGNAL_BAR] - 30.0 > 0 && 
           30.0 - MainBuffer[SIGNAL_BAR+1] >= 0)
          {
            PrevSignal = 1;
            Alert("sStochastic (", Symbol(), ", ", Period(), ")  -  BUY!!!");
          }
      }
    if(PrevSignal >= 0)
      {
        if(70.0 - MainBuffer[SIGNAL_BAR] > 0 && 
           MainBuffer[SIGNAL_BAR+1] - 70.0 >= 0)
          {
            PrevSignal = -1;
            Alert("sStochastic (", Symbol(), ", ", Period(), ")  -  SELL!!!");
          }
      }

正如您所看到的,如果线路 %K (MainBuffer) 自下而上达到了 30 水平,指标会提示“买入”,而如果自上而下达到了 70 水平,则会提示“卖出”。

第三种提

//---- indicator buffers
double     ExtBuffer0[];
double     ExtBuffer1[];
double     ExtBuffer2[];
double     ExtBuffer3[];
double     ExtBuffer4[];

ExtBuffer3 和 ExtBuffer4 用于中间计算,ExtBuffer0 始终存储指标值,ExtBuffer2 和 ExtBuffer3“颜色”列使用 2 种颜色。由于我们只需要指标值,因此我们将使用 ExtBuffer0:

if(PrevSignal <= 0)
      {
        if(ExtBuffer0[SIGNAL_BAR] - ExtBuffer0[SIGNAL_BAR+1] > 0 &&
           ExtBuffer0[SIGNAL_BAR+2] - ExtBuffer0[SIGNAL_BAR+1] > 0)
          {
            PrevSignal = 1;
            Alert("sAC (", Symbol(), ", ", Period(), ")  -  BUY!!!");
          }
      }
    if(PrevSignal >= 0)
      {
        if(ExtBuffer0[SIGNAL_BAR+1] - ExtBuffer0[SIGNAL_BAR] > 0 &&
           ExtBuffer0[SIGNAL_BAR+1] - ExtBuffer0[SIGNAL_BAR+2] > 0)
          {
            PrevSignal = -1;
            Alert("sAC (", Symbol(), ", ", Period(), ")  -  SELL!!!");
          }
      }

如果指标值在减小后开始增大,则我们会给出 BUY 提醒。反之,我们将给出 SELL 提醒。

第四种提醒 - 通知位置朝向价格而变化 - 这种提醒很少见。

但是,Parabolic 中偶尔会出现这种提醒。在示例中,我们使用它来编写“公式”:

if(PrevSignal <= 0)
      {
        if(Close[SIGNAL_BAR] - SarBuffer[SIGNAL_BAR] > 0)
          {
            PrevSignal = 1;
            Alert("sParabolic Sub (", Symbol(), ", ", Period(), ")  -  BUY!!!");
          }
      }
    if(PrevSignal >= 0)
      {
        if(SarBuffer[SIGNAL_BAR] - Close[SIGNAL_BAR] > 0)
          {
            PrevSignal = -1;
            Alert("sParabolic Sub(", Symbol(), ", ", Period(), ")  -  SELL!!!");
          }
      }

它在此处非常简单 - 我们将指标值与柱接近价格进行比较。注意,如果 SIGNAL_BAR 设置为 0,Parabolic 的每次价格触及都会伴随提醒。

最后一次提醒通知图表中出现箭头。它在标准指标中极少出现,但在自定义的“枢轴查找器”中相当常见。我将考虑这种使用指标“分形”(其在 MQL4 中编写的源代码可在代码库:分形中找到)的提醒。

这种指标有一个共同的特点:在图表上绘制它们的地方,它们不等于0(或  EMPTY_VALUE)。在所有其他柱上,它们的缓冲区是空的。这意味着,您只需要将缓冲区的值与零作比较来确定信号:

if(PrevSignal <= 0 )
      {
        if(ExtDownFractalsBuffer[SIGNAL_BAR] > 0)
          {
            PrevSignal = 1;
            Alert("sFractals (", Symbol(), ", ", Period(), ")  -  BUY!!!");
          }
      }
    if(PrevSignal >= 0)
      {
        if(ExtUpFractalsBuffer[SIGNAL_BAR] > 0)
          {
            PrevSignal = -1;
            Alert("sFractals (", Symbol(), ", ", Period(), ")  -  SELL!!!");
          }
      }

但是,如果您将具有此类代码的指标添加到图表上,您永远不会收到任何提醒。分形有一个特殊功能 - 它们使用 2 个未来的柱进行分析,因此仅柱 #2 上显示箭头(第三个柱以零开始)。要使提醒开始工作,需要将 SIGNAL_BAR 设置为 2:

//---- Bar number to search an alert by
#define SIGNAL_BAR 2

全部完毕,提醒将正常工作!



总结

本文介绍了用于将声音提醒添加到指标中的各种方法。定义了提醒解释方法(提醒类型)、提醒的方式提醒频率滤波器等术语。

定义并实现了以下提醒类型:

  • 指标的两条线的相交;
  • 指标线与某个水平的相交;
  • 指标的反向移动;
  • 位置朝向价格而变化;
  • 出现高于或低于价格值的箭头。
为提醒选择以下函数:
  • Comment() - 显示正常消息;
  • Print() - 在日志中显示消息;
  • Alert() - 在特殊窗口中显示消息并显示声音提醒;
  • PlaySound() - 播放任何波形文件。
降低提醒频率:
  • 使用确定提醒时已形成的柱;
  • 所有提醒交替出现 - 仅在卖出后买入,反之亦然。

我使用了五个对应于五种提醒的指标来研究它们的提醒块。您可以下载结果指标 - 它们已随附本文提供。

我希望您能明白,在将提醒块添加到指标的过程中没有任何复杂的操作 - 每个人都可以做到。

本文由MetaQuotes Ltd译自俄文
原文地址: https://www.mql5.com/ru/articles/1448

附加的文件 |
sAccelerator.mq4 (4.38 KB)
sFractals.mq4 (7.4 KB)
sMACD.mq4 (4.25 KB)
sParabolic_Sub.mq4 (8.46 KB)
sStochastic.mq4 (5.22 KB)
图形界面 I: 图形界面的动画 (第三章) 图形界面 I: 图形界面的动画 (第三章)
在前面的文章中, 我们开始开发了一个容纳控件的表单类. 在本文中, 我们将继续丰富此表单类的内容, 增加在图表区域内移动表单的方法. 接着我们会把这个界面组件与核心库整合. 而且我们会实现这样的功能, 在鼠标光标移动到表单之上时, 表单控件会改变它的颜色.
什么是马丁格尔? 什么是马丁格尔?
人们使用马丁格尔赌博策略进行交易或者滥用尖峰和类似方法时所出现的各种错觉的简短描述。
图形界面 I: 用于表单按钮的函数与删除界面元素 (第四章) 图形界面 I: 用于表单按钮的函数与删除界面元素 (第四章)
在本文中, 我们将继续开发CWindow类, 增加它的类方法, 可以通过点击它的控件来对它进行管理. 我们将可以通过表单按钮来关闭程序, 也会实现表单的最小化和最大化功能.
终端 MetaTrader 4 中的测试程序:应该了解 终端 MetaTrader 4 中的测试程序:应该了解
终端 MetaTrader 4 精心设计的界面是最前面的部分,但除此之外,它包括一个巧妙设计的策略测试程序。尽管 MetaTrader 4 作为交易终端的价值显而易见,但此测试程序的策略测试的质量只能在实践中进行评估。本文将介绍在 MetaTrader 4 中进行测试的优势和便捷性。