尽管自动化交易变得越来越常见,但很多交易者仍在进行手动交易。Expert Advisor 只要几毫秒时间即可评估当前市场情况,而人则需要花费许多时间、精力和最为重要的关注度才能完成当前市场状况评估。
几年前,很多交易者使用一个或多个技术指标。一些策略同时考虑多个时间范围的指标值。
那么,如何能够“抓住”重要的信号?有多种选择:
我个人认为,第一种选择最为合适。但是,需要有编程技能或支付相关费用才能实现。第二种方式非常耗时、累人,而且效率低下。第三种选择介于前两种方式之间。只要少得多的技能和时间即可实现,但的确可以帮助很多手动交易用户。
本文专门介绍第三种选择的实施情况。阅读本文后,每位交易者将能够将便捷的提醒添加到指标中。
有很多种方式来解释指标。人们甚至对 MetaTrader 4 客户端的指标的含义都存在不同的理解,更别提各种自定义指标...
一名交易者会在 MACD 的主线触及信号线时买入,另一名交易者会等到与零线相交时才买入,而还有交易者会在 MACD 小于 0 且开始向上移动时才建立多头头寸。我觉得自己无法统计所有可能的不同解释,因此,我将仅介绍如何将提醒模块加入到指标的原则。这样,您将能够根据喜好将任意类型的提醒添加到几乎所有的指标中。
下面列出了最可能的提醒:
很可能还有其他一些我已遗忘或根本不了解的解释,因此,我们将介绍上述列出的五种类型。
MetaTrader 4 和 MQL4 允许实现多种可视和音频提醒方式。
除此之外,还有用于将文件发送至 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
全部完毕,提醒将正常工作!
本文介绍了用于将声音提醒添加到指标中的各种方法。定义了提醒解释方法(提醒类型)、提醒的方式和提醒频率滤波器等术语。
定义并实现了以下提醒类型:
我使用了五个对应于五种提醒的指标来研究它们的提醒块。您可以下载结果指标 - 它们已随附本文提供。
我希望您能明白,在将提醒块添加到指标的过程中没有任何复杂的操作 - 每个人都可以做到。
本社区仅针对特定人员开放
查看需注册登录并通过风险意识测评
5秒后跳转登录页面...
移动端课程