跳空缺口 - 是能够获利的策略还是五五开?

12 十二月 2018, 10:29
Vladimir Karputov
0
2 707

简介

在这里我们将会在股票市场上检验 D1 上的跳空缺口,市场继续按照缺口方向变化会有多么频繁呢?市场在出现跳空缺口后会反转吗?我将会在这篇文章中尝试回答这些问题, 同时会使用自定义的 CGraphic 图表来显示结果。交易品种的文件是使用系统的 GetOpenFileName DLL 函数来选择的。


选择哪一个市场?

我只对D1时段中的跳空缺口有兴趣,

很明显,与外汇交易品种相比, 股票中发现的跳空缺口要多得多, 因为股票是从早上到晚上交易的, 而不是连续的。我对股票特别有兴趣,因为它们有相对长的历史,而期货从另一方面看就不是非常适合,因为它们的生命周期经常只有三或六个月,这对于在D1时段上对历史做研究就不够。

在文档"数据访问处理"部分中的 TestLoadHistory.mq5 脚本可以定义当前交易品种的数量和服务其上存在的D1时段的柱数。下面是一个用于检查 ABBV 交易品种D1时段柱数的例子:

交易品种 ABBV

图 1. ABBV 交易品种

过程如下:

  1. 首先,保存在文档中所描述的脚本,为此,要在 MetaEditor 5 ("创建一个脚本") 中创建一个新的脚本,让我们把它命名为 TestLoadHistory.mq5。现在,我们需要从文档中复制脚本文本,然后粘贴到 TestLoadHistory.mq5 脚本中 (所粘贴的文字应当替换掉脚本中的全部文字)。
  2. 编译得到的脚本 (在编译之后,脚本在终端的导航器窗口中就可以看到了),
  3. 在 MetaTrader 5 中运行脚本。因为检查是为 ABBV 交易品种进行的, 我们需要准备图表: 打开 ABBV 交易品种的图表并把时段设为 D1,从导航器窗口选择脚本并且在 ABBV 图表上运行它,在脚本参数中,把交易品种名称设为 ABBV,选择 D1 时段并把1970年设为日期:

运行脚本

图 2. 运行 TestLoadHistory.mq5 脚本

脚本运行结果:

TestLoadHistory (ABBV,D1)       Start loadABBV,Dailyfrom1970.03.16 00:00:00
TestLoadHistory (ABBV,D1)       Loaded OK 
TestLoadHistory (ABBV,D1)       First date 2015.09.18 00:00:00 - 758 bars

历史从 2015 年开始并且含有 758 个 D1 柱。这个数字对于分析是足够了。

操作一组交易品种

为了分析和计算任何标准,我们都需要比较一个交易品种组中的交易品种。按照规则,MetaTrader 5 终端中的交易品种已经分组 (在市场报价窗口中用鼠标右键点击和选择交易品种,或者按下 Ctrl + U):

NASDAQ 交易品种组 (SnP100)

图 3. NASDAQ (SnP100) 组的交易品种

在图中NASDAQ(SnP100)组就被选中了,这个组中就包括 ABBV 交易品种。操作一组交易品种的最方便的方法就是确保脚本是从这个组的交易品种中运行的,为了在每个组中做迭代,我们需要从每个组中手动打开一个交易品种图表并运行 Symbols on symbol tree.mq5 工具脚本 — 这个脚本会把所有组里的交易品种 (交易品种名称) 收集到一个单独的文件中。

Symbols on symbol tree.mq5 脚本是根据下面的算法来工作的: 在 SYMBOL_PATH 交易品种树中取得路径;从取得的路径中读取最终的交易品种组 (这里就是 NASDAQ(SnP100) 组); 从这个组中选择所有的交易品种并把选中的交易品种保存到一个文件中。在交易品种树中,路径中的文件名称里面,所有的 "/" 和 "\" 字符都使用 "_" 代替(代替过程是在脚本中自动进行的,文件名称也是自动生成的)。在替换了字符之后,为 NASDAQ(SnP100) 交易品种组生成的名称如下: "Stock Markets_USA_NYSE_NASDAQ(SnP100)_.txt".

为什么我们需要把每个组放到单独的文件中呢?因为这样我们就能够从组文件中直接简单读取交易品种名称了,而不用迭代所有的交易品种再进行缺口的分析。也就是说,Symbols on symbol tree.mq5 工具脚本可以去掉从指定的交易品种组中选择交易品种的过程。


Symbols on symbol tree.mq5 script

让我们研究一下脚本的运行。

请注意: 只有在专家页面中出现 "Everything is fine. There are no errors" 的文字信息才能保证脚本的工作已经成功,并且所得到的文件可以用于将来的工作!

为了缩短文件操作的代码, 包含了 CFileTxt 类, 而对文本文件的操作是由 m_file_txt — CFileTxt 类对象来完成的。脚本的工作可以分成七步:

//+------------------------------------------------------------------+
//|                                       Symbols on symbol tree.mq5 |
//|                              Copyright © 2018, Vladimir Karputov |
//|                                           http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2018, Vladimir Karputov"
#property link      "http://wmua.ru/slesar/"
#property version   "1.000"
//---
#include <Files\FileTxt.mqh>
CFileTxt       m_file_txt;       // 文本文件对象
//---
string   m_file_name="";         // 文件名
//+------------------------------------------------------------------+
//| 脚本程序起始函数                                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- 第一步
   string current_path="";
   if(!SymbolInfoString(Symbol(),SYMBOL_PATH,current_path))
     {
      Print("ERROR: SYMBOL_PATH");
      return;
     }
//--- 第二步
   string sep_="\\";                 // 分隔符字符 
   ushort u_sep_;                    // 用于分隔字符的代码 
   string result_[];                 // 用于取得字符串的数组 
//--- 取得分隔符代码 
   u_sep_=StringGetCharacter(sep_,0);
//--- 把字符串分成子字符串 
   int k_=StringSplit(current_path,u_sep_,result_);
//--- 第三步
//--- 现在输出所有取得的字符串 
   if(k_>0)
     {
      current_path="";
      for(int i=0;i<k_-1;i++)
         current_path=current_path+result_[i]+sep_;
     }
//--- 第四步
   string symbols_array[];
   int symbols_total=SymbolsTotal(false);
   for(int i=0;i<symbols_total;i++)
     {
      string symbol_name=SymbolName(i,false);
      string symbol_path="";
      if(!SymbolInfoString(symbol_name,SYMBOL_PATH,symbol_path))
         continue;
      if(StringFind(symbol_path,current_path,0)==-1)
         continue;

      int size=ArraySize(symbols_array);
      ArrayResize(symbols_array,size+1,10);
      symbols_array[size]=symbol_name;
     }
//--- 第五步
   int size=ArraySize(symbols_array);
   if(size==0)
     {
      PrintFormat("ERROR: On path \"%s\" %d symbols",current_path,size);
      return;
     }
   PrintFormat("On path \"%s\" %d symbols",current_path,size);
//--- 第六步
   m_file_name=current_path;
   StringReplace(m_file_name,"\\","_");
   StringReplace(m_file_name,"/","_");
   if(m_file_txt.Open("5220\\"+m_file_name+".txt",FILE_WRITE|FILE_COMMON)==INVALID_HANDLE)
     {
      PrintFormat("ERROR: \"%s\" 文件没有在通用数据文件夹中创建",m_file_name);
      return;
     }
//--- 第七步
   for(int i=0;i<size;i++)
      m_file_txt.WriteString(symbols_array[i]+"\r\n");
   m_file_txt.Close();
   Print("Everything is fine. There are no errors");
//---
  }
//+------------------------------------------------------------------+

脚本运行的算法:

  • 第一步: 为当前交易品种定义 SYMBOL_PATH (交易品种树中的路径);
  • 第二步: 取得的路径使用"\"分隔符分成子字符串;
  • 第三步: 重新组装当前路径,不包括最后的子字符串,因为它包含着交易品种名称;
  • 第四步: 在所有可用交易品种中循环;如果交易品种的路径与当前路径匹配,就选择交易品种名称并把它加到侦测到的交易品种数组中;
  • 第五步: 检查侦测到的交易品种数组的大小;
  • 第六步: 生成文件名 (从名字中删除 "/" 和 "\" 字符,生成文件);
  • 第七步: 把侦测到的交易品种数组写到文件中并关闭它。

注意第六步: 文件是在通用文件目录(使用了FILE_COMMON标志)创建的。

另外,要确保脚本的运行没有错误,应该在专家页面的记录中出现下面的信息: "Everything is fine. There are no errors. Create file:". 文件的名称在下一行显示 — 复制它并把它粘贴到 "Getting gap statistics ..." 脚本中。成功生成的 文件在下面显示:

On path "Stock Markets\USA\NYSE/NASDAQ(SnP100)\" 100 symbols
Everything is fine. There are no errors. Create file:
Stock Markets_USA_NYSE_NASDAQ(SnP100)_

这样,我们就取得了文件 (这里它是 Stock Markets_USA_NYSE_NASDAQ(SnP100)_) 每行一个交易品种。文件的前五行:

AAPL
ABBV
ABT
ACN
AGN

收集数据

根据交易品种的 OHLC 历史数据和统计计算是在主脚本 Getting gap statistics.mq5 中进行的,为每个交易品种都要填充 SGapStatistics 结构:

   struct SGapStatistics
     {
      string            name;                // 交易品种名称
      int               d1_total;            // D1 柱的总数
      int               gap_total;           // 缺口的总数
      int               gap_confirmed;       // 确认的缺口数量
     };

name — 交易品种名称
d1_total — 根据交易品种的D1柱的数量
gap_total — 侦测到的缺口数量
gap_confirmed — 确认过的缺口数量 (例如,一天是以向上的缺口开始,而收盘是上升的柱)

最适合用于为每个交易品种取得 OHLC 价格的函数就是 CopyRates. 我们将会使用它的第三种形式 — 根据所需时间段的起始和结束日期。对于开始时间,我们会使用 TimeTradeServer 交易服务器的当前时间加上一天,而结束日期是1970年1月1日。

现在,我们所要做的就是定义如何处理错误 (请求结果返回了 "-1" ) 或者如何判断是否所有的根据请求的数据都已返回 (例如,并不是所有数据都已经从服务器上下载了)。我们可以用简单的方法来做 (请求 — 暂停 N — 秒 — 新的请求),或者使用正确的方法。正确的方案是基于从文档的"数据访问处理" 部分中的TestLoadHistory.mq5脚本改进而得到的。

脚本中请求执行结果的代码列在下面:

   switch(res) 
     { 
      case -1 : Print("未知的交易品种",InpLoadedSymbol);                        break; 
      case -2 : Print("请求的柱数超过了可以在图表中显示的数量"); break; 
      case -3 : Print("用户中断了执行");                    break; 
      case -4 : Print("指标无法上传自身数据");          break; 
      case -5 : Print("上传失败");                              break; 
      case  0 : Print("所有的数据都已上传");                                      break; 
      case  1 : Print("现有的时间序列数据足够了");               break; 
      case  2 : Print("时间序列是由已有终端数据生成的");         break; 
      default : Print("执行结果未定义"); 
     }

— 也就是表示执行结果小于0 — 这就是一个错误。在这种情况下,运行的算法如下: 打开交易品种文件,每个交易品种都进行一次请求,再综合所有的负数结果。如果至少有一个负数的结果,就显示请求错误的信息。如果出现这种情况,用户需要再次运行脚本 (历史可能已经在这之前上传或者构建了),如果没有错误,就读取 OHLC 数据并计算缺口的数量。


Getting gap statistics.mq5 script

这个脚本在终端的专家页面显示了缺口的统计信息。另外,我们还将使用 "gap confirmation" 的字样,确认的缺口(confirmed gap)意思是柱形的收盘和缺口的方向一致,而未确认的缺口意思是每日柱形的收盘与缺口的方向相反:


缺口

图 4. 确认与未确认的缺口

脚本只包含一个 "File name" 参数 — 由 Symbols on symbol tree.mq5 辅助脚本生成的文件名称 (您也许记得,这个文件是在通用目录的 5220 文件夹中创建的)。指定文件名称时不需要指定目录和扩展名,例如,就像这样:

取得缺口统计数据的输入参数

图 5. "Getting gap statistics" 脚本的输入参数

这样,我们就需要进行几步来取得统计数据了:

  1. 选择一个用于计算缺口的交易品种组
  2. 从选中的组中选择一个交易品种再打开它的图表
  3. Symbols on symbol tree.mq5 脚本放到图表上 — 这样结果就会创建一个包含选中交易品种组中所有交易品种的文件。确认在脚本运行中没有错误,应该在专家页面出现这样的信息: "Everything is fine. There are no errors"
  4. Getting gap statistics.mq5 脚本放到图表上

这样,专家页面就会包含了以下关于缺口数量的统计信息,前五个交易品种:

      [name] [d1_total] [gap_total] [gap_confirmed]
[ 0] "AAPL"        7238        3948            1640
[ 1] "ABBV"         759         744             364
[ 2] "ABT"          762         734             374
[ 3] "ACN"          759         746             388
[ 4] "AGN"          761         754             385

使用 CGraphic

在专家页面显示所有数据不是很清晰,所以 Getting gap statistics CGraphic.mq5 脚本将会使用 CGraphic 自定义图画。脚本有以下参数:

  • File name — 交易品种的文件名 (这个文件应当是使用 "Symbols on symbol tree.mq5" 工具脚本来进一步创建的)
  • Log CheckLoadHistory — 隐藏/显示上传到专家页面的交易品种历史结果
  • Log Statistics — 在专家页面隐藏/显示缺口统计数据

运行结果 — 已确认缺口的百分比图表:

Getting gap statistics CGraphic

图 6. Getting gap statistics CGraphic.mq5 脚本的执行结果

图形编号:

  • 1 — 确认的缺口名称
  • 2 — 百分比度量
  • 3 — 交易品种来源文件的名称

这个图表清晰地显示出,缺口值在50%上下波动6%,尽管有三个小于42%的尖峰。这三个尖峰中确认小于42%表示的是每日柱形在三个交易品种中移动的方向与缺口相反的概率是58%。

现在,我们可以查看另一组交易品种 — Stock Markets\RussiaMICEX20. Getting gap statistics CGraphic.mq5 对于 Stock Markets\RussiaMICEX20 脚本的运行结果:

Stock Markets_Russia_MICEX20_

图 7. Gap statistics for Stock Markets\RussiaMICEX20 group

这里有两个类似的尖峰,然而,在当前版本中我们不能把图片和交易品种关联起来,这就是为什么我们需要少许改进脚本。


Getting gap statistics CGraphic 2.mq5 脚本

修改: 在 2.0 版本中, 专家页面将会以百分比方式显示确认的缺口的统计信息。这样,当启用了 Log Statistics 后, 两个另类的交易品种就可以在 Stock Markets\RussiaMICEX20 组中很容易地检测到了:

          [name] [d1_total] [gap_total] [gap_confirmed] [confirmed_per]
***
[14] "NVTK.MM"          757         737             347           47.08
[15] "PIKK.MM"          886         822             282           34.31
[16] "ROSN.MM"          763         746             360           48.26
[17] "RSTI.MM"          775         753             357           47.41
[18] "RTKM.MM"          753         723             324           44.81
[19] "SBER.MM"          762         754             400           53.05
[20] "SBER_p.MM"        762         748             366           48.93
[21] "SNGS.MM"          762         733             360           49.11
[22] "TATN.MM"          765         754             370           49.07
[23] "SNGS_p.MM"        751         708             305           43.08
[24] "URKA.MM"          765         706             269           38.10
[25] "VTBR.MM"          763         743             351           47.24
[26] "RASP.MM"          778         756             354           46.83

对于 PIKK.MM 和 URKA.MM 交易品种, 34% 和 38% 的确认缺口意思是,在这些交易品种中,每日柱形将有对应 66% 和 62% 的概率方向与缺口方向相反。


在文件中限制交易品种(工具)的数量

当分析各种交易品种组时,我发现有的组包含了超过1000个交易品种。操作这么大的组很不方便: 把这样大量的交易品种加到市场报价窗口中要花费很长时间,而最后的图表变得没法读了 - 数据太多,它们的位置太过接近。

所以,我决定升级 Symbols on symbol tree.mq5 脚本,而开发了 Symbols on symbol tree 2.mq5。在这个版本中,文件中交易品种的最大数量不能超过200,而部分编号也会加到文件名中。例如,Stock Markets\USA\NYSE/NASDAQ(SnP100)\ 交易品种组包含了 100 个交易品种,也就是只有一个部分,文件名看起来如下: Stock Markets_USA_NYSE_NASDAQ(SnP100)_part_0.txt.


使用 "选择文本文件" 系统对话框来选择文件

在操作了本文中的脚本后,我发现在 Getting gap statistics CGraphic 2.mq5 脚本输入参数中加上文件名称很不方便,我们必须采取几项工作: 在所有终端中打开公用文件夹,把文件名称复制和粘贴到脚本中。

所以,文件的选择使用了系统DLL中的 GetOpenFileName 函数来进行,为此,我包含了 GetOpenFileNameW.mqh 文件。这个文件中的 OpenFileName 函数可以返回所选中的 *.txt 文件的完整路径。例如,路径可能如下使用: "C:\Users\barab\AppData\Roaming\MetaQuotes\Terminal\Common\Files\5220\Stock Markets_USA_NYSE_NASDAQ(SnP100)_part_0.txt". 现在我们需要从中取得文件名。

Getting gap statistics CGraphic 3.mq5 脚本使用 GetOpenFileName DLL 函数:

允许 DLL

图 8. 当运行 Getting gap statistics CGraphic 3.mq5 脚本时要请求允许使用DLL

这里是使用 "选择文本文件" 对话框时如何选择文件:

选择文件

图 9. 选择文件


在其它交易品种上的统计分析

现在我们可以为其它交易品种组收集缺口统计信息了。


Stock Markets\USA\NYSE\NASDAQ(ETFs) 组

组里的交易品种分成了7个文件:

Stock Markets_USA_NYSE_NASDAQ(ETFs)_part_0

图 10. Stock Markets\USA\NYSE\NASDAQ(ETFs) group, part 0


Stock Markets_USA_NYSE_NASDAQ(ETFs)_part_1

图 11. Stock Markets\USA\NYSE\NASDAQ(ETFs) group, part 1


Stock Markets_USA_NYSE_NASDAQ(ETFs)_part_2

图 12. Stock Markets\USA\NYSE\NASDAQ(ETFs) group, part 2


Stock Markets_USA_NYSE_NASDAQ(ETFs)_part_3

图 13. Stock Markets\USA\NYSE\NASDAQ(ETFs) group, part 3


Stock Markets_USA_NYSE_NASDAQ(ETFs)_part_4

图 14. Stock Markets\USA\NYSE\NASDAQ(ETFs) group, part 4


Stock Markets_USA_NYSE_NASDAQ(ETFs)_part_5

图 15. Stock Markets\USA\NYSE\NASDAQ(ETFs) group, part 5


Stock Markets_USA_NYSE_NASDAQ(ETFs)_part_6

图 16. Stock Markets\USA\NYSE\NASDAQ(ETFs) group, part 6


Stock Markets\United Kngdom\LSE Int. (ADR/GDR)\ group

Stock Markets_United Kngdom_LSE Int. (ADR_GDR)_

图 17. Stock Markets\United Kngdom\LSE Int. (ADR/GDR)\ group


Stock Markets\United Kngdom\LSE (FTSE350)\ group

这个组含有350个交易品种,所以交易品种被分为两个文件。

Stock Markets_United Kngdom_LSE (FTSE350)_part_0

图 18. Stock Markets\United Kngdom\LSE (FTSE350)\ group, part 0


Stock Markets_United Kngdom_LSE (FTSE350)_part_1

图 19. Stock Markets\United Kngdom\LSE (FTSE350)\ group, part 1


Stock Markets\Germany\XETRA (IBIS)\Dax100\ group

Stock Markets_Germany_XETRA (IBIS)_Dax100_part_0

图 20. Stock Markets\Germany\XETRA (IBIS)\Dax100\ group


Stock Markets\France\Eurnext (CAC40)\ group

Stock Markets_France_Eurnext (CAC40)_part_0

图 21. Stock Markets\France\Eurnext (CAC40)\ group

结论

当分析多个证券市场时,我发现在跳空缺口之后,走向继续和反转的概率都接近50%,也就是说尝试抓住跳空缺口也就是五五开的成功率。同时,有些证券的概率(包括持续和反转)的可观地超过了65%,这些证券可以用于根据缺口交易。

包含了本文所描述脚本的档案在下面的附件中:

脚本名称 描述
Symbols on symbol tree.mq5 工具脚本. 这个脚本定义了交易品种树的组,并且把这个组中的所有交易品种都保存到文件中 (公用目录, 文件夹为 5220)
Symbols on symbol tree 2.mq5  工具脚本. 这个脚本定义了交易品种树的组,并且把这个组中的所有交易品种都保存到文件中 (公用目录,文件夹为 5220). 它也把交易品种组分成每个文件200个交易品种。
Getting gap statistics.mq5 这个脚本把工具脚本创建的文件中的交易品种上传,并在专家页面显示缺口的统计信息。
Getting gap statistics CGraphic.mq5 这个脚本把工具脚本创建的文件中的交易品种上传,并在图表中显示缺口的统计信息,使用了自定义的 CGraphic 图表。
Getting gap statistics CGraphic 2.mq5 这个脚本把工具脚本创建的文件中的交易品种上传,并在图表中显示缺口的统计信息,使用了自定义的 CGraphic 图表,统计信息也在专家页面以百分比显示。
Getting gap statistics CGraphic 3.mq5 这个脚本把工具脚本创建的文件中的交易品种上传,并在图表中显示缺口的统计信息,使用了自定义的 CGraphic 图表,统计信息也在专家页面以百分比显示。使用了 "选择文本文件" 的系统对话框来选择交易品种文件。 
GetOpenFileNameW.mqh 包含文件,可以用于操作 "选择文本文件" 的系统对话框。  


本文译自 MetaQuotes Software Corp. 撰写的俄文原文
原文地址: https://www.mql5.com/ru/articles/5220

附加的文件 |
MQL5.zip (20.34 KB)
使用限价订单替代止盈且无需修改 EA 的原始代码 使用限价订单替代止盈且无需修改 EA 的原始代码

使用限价订单来替代传统的止盈是论坛讨论的长期话题。 这种方法的优点是什么?如何在您的交易中实施? 在本文中,我将向您介绍我对此主题的看法。

走势延续模型 - 搜索图表和执行统计 走势延续模型 - 搜索图表和执行统计

本文提供了一种走势延续模型的程序化定义。 主要思路是定义两个波浪 — 主浪和修正浪。 对于极值点,我应用分形以及“潜在”分形 - 尚未形成分形的极值点。

逆转形态:测试双顶/双底形态 逆转形态:测试双顶/双底形态

交易者经常寻找趋势逆转点,因为在趋势新形成的最初阶段价格走势具有最大潜力。 因此,在技术分析中考虑了各种逆转形态。 双顶/双底是最著名和最常用的形态之一。 本文提出了程序检测形态的方法。 它还测试了形态在历史数据上的盈利能力。

反向交易: 减少最大回撤以及在其它市场上测试 反向交易: 减少最大回撤以及在其它市场上测试

在这篇文章中, 我们继续致力于反向交易技巧。我们将会尝试减少最大余额回撤,直到对之前探讨的交易工具可以接受的水平。我们将会看看这样是否将会减少利润,我们还将在其它市场中检验反转方法的运行,包括股票、商品、指数、ETF和农产品市场。注意,本文包含了很多图片!