利用迪纳波利 (DiNapoli) 等级进行交易

Dmitriy Zabudskiy | 29 十二月, 2017


引言

如同我们的现实生活, 市场也在不断发展。昨日的完美表现, 今天却得到令人沮丧的结果。然而, 有一些根本性的策略, 随着时间的推移会产生些微改变, 但它们的思想基础不会改变。其中之一就是 "迪纳波利等级", 一个以其创始人之名命名的策略。它所代表的是 菲波纳奇回撤 简化实现。 

策略的初始点 - 菲波纳奇等级 38.2% 和 61.8%。对于止盈点, 接受如下: COP (约定目标点) — 61.8%, OP (目标点) — 100%,  XOP (延伸目标点) — 161.8%。所有距离都以趋势长度的百分比指定 (参见图例 1)。

图例 1. 当前货币对 EURUSD H4 图表上的 "迪纳波利等级"

图例 1. 当前货币对 EURUSD H4 图表上的 "迪纳波利等级"

在图例 1 中, 使用 MetaTrader 软件包内置的菲波纳奇工具设置等级 - 菲波纳奇 回撤 (红色) 和 扩展 (蓝色)。此外, 图例还显示了如何设定等级。带有两个箭头标记的垂线示意 61.8% 的级别, 此数值取自趋势 (红色下行线) 向下的最大回滚价格, 形成 COP 等级。

入场有四种变形: "灌木丛", "盆景", "扫雷 A" 和 "扫雷 B"。前两种最激进。它们会在首次调整时即入场。后两种场景意味着在第二次调整时开仓。这些变形之间的其它差异是放置止损位。这些方法在 "迪纳波利交易系统" 一文中有详细介绍, 所以在此我们无需赘述。

在上面提供的图例中, 我们只是想展示迪纳波利等级的经典图片, 即所说的策略基础。如您所见, 入场的最佳选择是在 61.8% 等级 (在这里您可以看到一个红色的价格标记), 但是, 这一等级并非总会达到。所以, 一些交易者在 38.2% 的位置就开始积极抛售手中份额: 下行蜡烛 20:00 时得以证明。根据 "灌木丛" 方法, 这样的入场点更具激进交易的特征。随后, 交易者在距离开仓价位更高的位置设置停止位。持仓将会在 COP 级别 (61.8%) 平仓。图例上标为蓝色价签。

这看起来相当简单, 但实际上由于趋势的频繁变化, 所描述的级别并非总能被触发。为了更明确地判断趋势, 策略作者提议使用级别之外的指标: 移动平均线 (MA) 和随机振荡指标。在此基础上, 我提出开发一个可盈利的策略, 并在智能交易系统中实现它。


标准 MetaTrader 5 工具形成的策略

有效的迪纳波利等级交易策略意味着大量因素的联合运作。所以, 其编程实现相当复杂和有趣。此外, 组织交易也有困难: 按照这个策略, 有时您需要等待很长时间才会入场。对于一名交易者来说, 连续人工监控是一项艰巨的任务, 因此, 这种交易机器将占优势。

我将尝试最大限度地简单和全面地解释作为智能交易系统基础的策略。

图例 2. 带有辅助指标的迪纳波利等级 EURUSD H4 (上升趋势)

图例 2. 带有辅助指标的迪纳波利等级 EURUSD H4 (上升趋势)

图例 2 显示了货币对 EURUSD H4 的图表。标记如下: 迪纳波利等级, 随机指标 (8,3,3) 和两条移动平均线, 偏移 5, 周期 25 (红色) 和 7 (蓝色)。

我们逐一开始。在图表中我们可以看到菲波纳奇网格叠加的上升趋势, 分别为 23.6%, 38.2%, 50%, 61.8%。在此, 比之经典实现有更多的等级: 实践表明, 价格可受阻于它们当中的任何一处。 

回滚 (调整) 菲波纳奇扩展是叠加的: 这是 COP 和 OP 的产生方式。不过, 在这两种情况下, 以及在一般策略中, 这些等级都略显不足。在此, 它们是专门为设置止盈而计算的 (稍后我们将在代码中看到的)。

清算结果是可以在四个点入场。图例所示, 如果最初就捕捉到趋势反转, 在 23.6% 处开仓, 则将获利; 只是, 回撤将会非明显。诚然, 这不能令我们满意, 所以我们会继续寻找更可靠的入场点。 

  • 规则一: 可入场的迪纳波利等级从 23.6% 至 61.8%。这是一个相当广泛的范围, 这就是为什么我们应该进入第二阶段的分析。

随后的信号滤波器是随机指标 (参数 8,3,3), 带有两个等级 - 30 和 70。

  • 规则二: 当随机指标的信号和主线处于 30 以下时买入; 并在处于 70 以上时卖出。

现在, 我们来确定趋势。为此, 使用了移动平均线 (偏移 5, 周期 25)。事实证明, 当价格高于趋势线时, 买入是可行的, 而当价格较低时, 卖出是可行的。但这是一个相当宽阔的范围, 为了将之降低, 我们再引入一条移动平均线 (偏移 5, 周期 7)。但即使用它时, 范围仍可能太宽。在这种情况下, 引入额外的降低: 只允许在偏差的 "上半部分", 接近周期 25 均线时开仓交易。

  • 规则三: 在时间间隔的第二个一半处, 接近周期 25 均线时买入; 而此处时间间隔较短的均线位于上方。
  • 规则四: 在时间间隔的第二个一半处, 接近周期 25 均线时卖出; 而此处时间间隔较短的均线位于下方。

假设以上列举条件已经解决, 我们就会开仓。现在, 我们来安排平仓的规则。为此, 我们将使用菲波纳奇扩展形成的等级, 以及随机指标。

  • 规则五: 如果价格抵达目标迪纳波利等级 (COP, OP, XOP) 之一, 或者随机指标给出收盘信号, 则平仓。

在图例 2 和图例 3 中, 符合这些规则的区域以黄色矩形显示。

图例 3. 带有辅助指标的迪纳波利等级 EURUSD H4 (下行趋势)

图例3. 带有辅助指标的迪纳波利等级 EURUSD H4 (下行趋势)

如您所见, 得到的规则是清晰且合乎逻辑的。其中尚未厘定放置止盈位或止损位, 以及次要的将尾随停止移至盈亏平衡点的逻辑。所有这些将在下面研究。


策略代码

输入参数

首先, 连接类 CTrade (Trade.mqh)。然后, 建立迪纳波利等级的参数 - 最小和最大入场级别。默认时, 它们如同上述指定设置: 从 23.6% 至 61.8%。但是对于不同的货币对, 它们可能会有所不同, 并存在不同的界限。

以下参数是止盈和止损。止损位于峰值价位。在图例 2 和 3 中, 它们显示为红色。止盈位则自订单价格中下调。

也就是说, 假设买入级别是 50%, 止损定为 70%, 止盈定为 70%。这意味着, 假设 100% 为 100 点, 止损将低于买入价 20 点, 而止盈 - 高达 70 点。在 EA 优化时必须考虑这一点。

此外, 我们必须定义尾随或盈亏平衡保护。根据当前代码中的参数, 当价格超过 400 点时, 止损将移到盈利一侧 10 点。

其余的参数无需置评。

//+------------------------------------------------------------------+
//|                                               Dinapoli_v1.01.mq5 |
//|                                                          Aktiniy |
//|                                            https://www.mql5.com/ |
//+------------------------------------------------------------------+
#property copyright "Aktiniy"
#property link      "https://www.mql5.com/"
#property version   "1.01"
#include<Trade\Trade.mqh>
//--- 输入参数
//--- 菲波纳奇级数
input double   percent_min_enter=23.6;      // 最小入场百分比
input double   percent_max_enter=61.8;      // 最大入场百分比
input double   percent_for_tp=60;           // 可能的止盈百分比
input double   percent_for_sl=70;           // 可能的止损百分比
input int      trailing_sl=400;             // 切换到盈亏平衡点所需的超越点数
input int      trailing_profit=10;          // 盈亏平衡价位点数
//--- 订单
input long     magic_number=65758473787389; // 魔幻数字
input double   order_volume=0.01;           // 手数
input int      order_deviation=100;         // 开仓所需的偏差
//--- 随机振荡
input int      stochastic_k=8;              // 随机振荡器指标 "周期 %К"
input int      stochastic_d=3;              // 随机振荡器指标 "慢速"
input int      stochastic_slowing=3;        // 随机振荡器指标 "周期 %D"
input double   stochastic_up_level=70;      // 随机振荡器指标 "距顶部的信号级别"
input double   stochastic_down_level=30;    // 随机振荡器指标 "距底部的信号级别"
//--- 红色均线 25 5
input int      ma_red_period=25;            // 红色均线指标 "周期"
input int      ma_red_shift=5;              // 红色均线指标 "偏移"
//--- 蓝色均线 7 5
input int      ma_blue_period=7;            // 蓝色均线指标 "周期"
input int      ma_blue_shift=5;             // 蓝色均线指标 "偏移"
//--- 变量
CTrade trade;
int stochastic_handle=0;
char answer_stochastic=0;
int ma_red_handle=0;
int ma_blue_handle=0;
char answer_ma=0;
int fractals_handle=0;


概言之, 确定变量能够保存指标句柄以及信号函数的应答。

初始化

以下是初始化函数。在此, 我们建立了 CTrade 并接收指标句柄。

//+------------------------------------------------------------------+
//| 智能系统初始化函数                                                 |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   trade.SetExpertMagicNumber(magic_number);
   trade.SetDeviationInPoints(order_deviation);
   trade.SetTypeFilling(ORDER_FILLING_FOK);
   trade.SetAsyncMode(false);

   stochastic_handle=iStochastic(_Symbol,_Period,stochastic_k,stochastic_d,stochastic_slowing,MODE_SMA,STO_LOWHIGH);
   ma_red_handle=iMA(_Symbol,_Period,ma_red_period,ma_red_shift,MODE_SMA,PRICE_CLOSE);
   ma_blue_handle=iMA(_Symbol,_Period,ma_blue_period,ma_blue_shift,MODE_SMA,PRICE_CLOSE);
   fractals_handle=iFractals(_Symbol,_Period);
//---
   return(INIT_SUCCEEDED);
  }


在处理主函数之前, 我们先研究一下信号函数的原理。

自随机振荡器获取信号

//+------------------------------------------------------------------+
//| 自随机振荡器获取信号                                               |
//+------------------------------------------------------------------+
void Stochastic(char &answer)                                                                          // 0 - 无信号; 1 - 信号向上; 2 - 信号向下
  {
   answer=0;                                                                                           // 应答
   double stochastic_line_main[3];
   double stochastic_line_signal[3];
   int line_main=CopyBuffer(stochastic_handle,0,0,3,stochastic_line_main);
   int line_signal=CopyBuffer(stochastic_handle,1,0,3,stochastic_line_signal);
   if(line_main!=3 || line_signal!=3)
     {Alert("复制 iStochastic: 主线出错=",line_main,", 信号线=",line_signal);}          // 检查复制随机振荡器数据

   if(stochastic_line_main[1]>stochastic_up_level && stochastic_line_signal[1]>stochastic_up_level)
     {answer=2;}                                                                                       // 卖出有益
   if(stochastic_line_main[1]<stochastic_down_level && stochastic_line_signal[1]<stochastic_down_level)
     {answer=1;}                                                                                       // 买入有益
  }


这是终极简化: 复制指标的最后三个数值, 将它们当中的最后一个与设置中的预设级别进行比较。该函数通过一个变量传递应答结果。

从指标 MA 中获得信号

//+------------------------------------------------------------------+
//| 从指标 MA 中获得信号                                              |
//+------------------------------------------------------------------+
void MA(char &answer,                                               // 0 - 无信号; 1 - 信号向上; 2 - 信号向下
        double &line_blue,
        double &line_red,
        double ask,
        double bid)
  {
   answer=0;                                                        // 应答
   double ma_red[3];
   double ma_blue[3];
   int red=CopyBuffer(ma_red_handle,0,0,3,ma_red);
   int blue=CopyBuffer(ma_blue_handle,0,0,3,ma_blue);
   if(red!=3 || blue!=3)
     {Alert("复制 iMA 出错: MA 红=",red,", MA 蓝=",blue);}   // 检查复制红/蓝两色均线数据

   line_blue=ma_blue[2];
   line_red=ma_red[2];

   if(ma_blue[2]>ma_red[2])                                         // 假定趋势向上
      if(ask<ma_blue[2])                                            // 假定价格处于回滚位置
         if(ask>ma_red[2])
           {answer=1;}                                              // 很快向趋势方向 (向上) 移动成为可能

   if(ma_blue[2]<ma_red[2])                                         // 假定趋势向下
      if(bid>ma_blue[2])                                            // 假定价格处于回滚位置
         if(bid<ma_red[2])
           {answer=2;}                                              // 很快向趋势方向 (向下) 移动成为可能
  }


此处, 最后三个数值也被复制到缓冲区中; 之后, 通过比较来定义价格是否在两条指标线之间。早前, 我们已讨论过, 经常可以进行交易的时间间隔应该很窄。正是由于这个原因, 函数不仅传递了答案, 还传递了两条移动平均线的最后数值。交易间隔变窄的机制将在稍后研究。

接收来自分形指标的数据

趋势大小函数的建立更为复杂。它是在分形数据上实现。在函数开始时复制最后的 100 个数据, 然后在两个循环中执行上部和下部信号的检查。在此, 实现了对分形可用性的测试: 超过 10000 的数值将被过滤掉, 然后从末端比较相邻值搜索第一个最大和最小分形。

//+------------------------------------------------------------------+
//| 接收来自分形指标的数据                                             |
//+------------------------------------------------------------------+
void Fractals(double &price_up,
              double &price_down)
  {
   price_up=0;
   price_down=0;
   double fractals_up[100];
   double fractals_down[100];
   int up=CopyBuffer(fractals_handle,0,0,100,fractals_up);
   int down=CopyBuffer(fractals_handle,1,0,100,fractals_down);
   if(up!=100 || down!=100)
     {Alert("复制 iFractals 出错: 上分形=",up,", 下分形=",down);} // 检查复制上/下分形数据

   double price_high=0;
   double price_low=0;

   for(int x=99; x>0; x--)                                                        // 顶部分形循环
     {
      if(fractals_up[x]<10000)                                                    // 检查分形可用性
        {
         if(price_high==0){price_high=fractals_up[x];}                            // 初始化检查
         if(price_high>fractals_up[x]){break;}                                    // 如果分形正在向下停止循环
         else{price_high=fractals_up[x];}                                         // 如果分形正在向上, 复制
        }
     }

   for(int x=99; x>0; x--)                                                        // 重复循环检查底部分形
     {
      if(fractals_down[x]<10000)                                                  // 检查分形可用性
        {
         if(price_low==0){price_low=fractals_down[x];}                            // 初始化检查
         if(price_low<fractals_down[x]){break;}                                   // 如果分形正在向上停止循环
         else{price_low=fractals_down[x];}                                        // 如果分形正在向下, 复制
        }
     }

   double price_ask=SymbolInfoDouble(_Symbol,SYMBOL_ASK);                         // 买入价格请求
   double price_bid=SymbolInfoDouble(_Symbol,SYMBOL_BID);                         // 卖出价格请求

   if(price_high>price_ask && price_high>price_bid)                               // 检查竞卖/竞卖价是否在上/下分形之间
      if(price_low<price_ask && price_low<price_bid)
        {
         price_up=price_high;                                                     // 分派应答值
         price_down=price_low;
        }
  }
//+------------------------------------------------------------------+


为了确保信号是可靠的, 在应答之前检查价格是否在发现的范围之内。这是因为可能的最后关键分形是在最后两根蜡烛创建之后才形成 (根据分形形成规则)。

开仓价格计算

最重要的是负责计算迪纳波利等级的函数。早些时候收到价格的最大值和最小值, 以及假设趋势方向的数据, 和传入的来自移动平均线的最后一个数值。首先将所有得到的距离转换成点数, 并根据参数部分预设的百分比计算出来。这些部分是分数, 因此我们将它们归一化。

//+------------------------------------------------------------------+
//| 计算开仓价格                                                      |
//+------------------------------------------------------------------+
void Price_for_order(double high_price,
                     double low_price,
                     double &p_enter_min,
                     double &p_enter_max,
                     double &p_tp,
                     double &p_sl,
                     char trend,                                      // 1 - 向上; 2 - 向下
                     double blue_line,
                     double red_line
                     )
  {
   double point_price=(high_price-low_price);
   double point_enter_min=point_price*percent_min_enter/100;
   double point_enter_max=point_price*percent_max_enter/100;
   double point_tp=point_price*percent_for_tp/100;
   double point_sl=point_price*percent_for_sl/100;
   double point_ma_line=MathAbs(blue_line-red_line)/2;

   point_enter_min=NormalizeDouble(point_enter_min,_Digits);
   point_enter_max=NormalizeDouble(point_enter_max,_Digits);
   point_ma_line=NormalizeDouble(point_ma_line,_Digits);

   point_tp=NormalizeDouble(point_tp,_Digits);
   point_sl=NormalizeDouble(point_sl,_Digits);

   if(trend==1)                                                       // 向上
     {
      p_enter_min=high_price-point_enter_min;
      double p_ma_min=red_line+point_ma_line;
      if(p_enter_min>p_ma_min)
        {p_enter_min=p_ma_min;}
      p_enter_max=high_price-point_enter_max;
      if(p_enter_max>p_enter_min)
        {p_enter_max=red_line;}

      p_tp=p_enter_min+point_tp;
      p_sl=high_price-point_sl;
     }

   if(trend==2)                                                       // 向下
     {
      p_enter_min=low_price+point_enter_min;
      double p_ma_min=red_line-point_ma_line;
      if(p_enter_min<p_ma_min)
        {p_enter_min=p_ma_min;}
      p_enter_max=low_price+point_enter_max;
      if(p_enter_max<p_enter_min)
        {p_enter_max=red_line;}

      p_tp=p_enter_min-point_tp;
      p_sl=low_price+point_sl;
     }
  }


进而, 根据趋势方向, 计算价格并由函数返回应答。

修改和平仓

首先, 获取最后一笔仓位的所有数据。进而, 如果随机指标给出相反的信号, 则根据订单类型进行更新 (移动到盈亏平衡点) 或平仓。

//+------------------------------------------------------------------+
//| 修改和平仓                                                        |
//+------------------------------------------------------------------+
void Position_mod(double ask,
                  double bid,
                  int point,
                  int profit,
                  char stochastic)
  {
   double price=trade.RequestPrice();
   double tp=trade.RequestTP();
   double sl=trade.RequestSL();
   double sl_point=point*_Point;
   double sl_profit=profit*_Point;
   double tp_point=(MathAbs(tp-price))/2;

   if(trade.RequestType()==ORDER_TYPE_BUY)              // 买入订单
     {
      if(sl<price && bid>(price+sl_point))
        {
         sl_profit=sl_profit+price;
         trade.PositionModify(_Symbol,sl_profit,tp);
        }
      if(stochastic==2)                                 // 预计下行
        {
         trade.PositionClose(_Symbol,order_deviation);
        }
     }
   if(trade.RequestType()==ORDER_TYPE_SELL)             // 卖出订单
     {
      if(sl>price && ask<(price-sl_point))
        {
         sl_profit=sl_profit-price;
         trade.PositionModify(_Symbol,sl_profit,tp);
        }
      if(stochastic==1)                                 // 预计上行
        {
         trade.PositionClose(_Symbol,order_deviation);
        }

     }
  }


整合函数

最后一个函数整合了所有先前所研究的函数。一开始, 声明所有的协调变量。然后, 通过指标函数接收当前的 "顶部策略规则" 的主要数值。进而, 依据收到的 "顶部规则" 应答进行划分。计算有利入场的趋势大小和价格。如果未发现早前的已开仓位, 且价格在计算的范围之内, 开仓。

//+------------------------------------------------------------------+
//| 智能系统分笔报价函数                                               |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   double price_high=0;                                           // 分形计算的最高价格
   double price_low=0;                                            // 分形计算的最低价格

   double price_enter_min=0;                                      // 最小入场价格
   double price_enter_max=0;                                      // 最大入场价格
   double price_tp=0;                                             // 止盈位
   double price_sl=0;                                             // 止损位

   double price_ask=SymbolInfoDouble(_Symbol,SYMBOL_ASK);         // 买入价格请求
   double price_bid=SymbolInfoDouble(_Symbol,SYMBOL_BID);         // 卖出价格请求

   double ma_blue_line=0;                                         // 较低周期的蓝色均线值
   double ma_red_line=0;                                          // 多周期的红色均线值

   Stochastic(answer_stochastic);
   MA(answer_ma,ma_blue_line,ma_red_line,price_ask,price_bid);

   if(answer_stochastic==1)                                       // 预计上行
     {
      if(answer_ma==1)                                            // 我们处于买入范围 
        {
         Fractals(price_high,price_low);
         Price_for_order(price_high,price_low,price_enter_min,price_enter_max,price_tp,price_sl,1,ma_blue_line,ma_red_line);

         if(price_ask<price_enter_min && price_ask>price_enter_max)
           {
            if(PositionsTotal()==0)
              {
               trade.Buy(order_volume,_Symbol,price_ask,price_sl,price_tp,"Buy");
              }
           }
        }
     }

   if(answer_stochastic==2)                                        // 我们处于卖出区间
     {
      if(answer_ma==2)                                             // 预计下行
        {
         Fractals(price_high,price_low);
         Price_for_order(price_high,price_low,price_enter_min,price_enter_max,price_tp,price_sl,2,ma_blue_line,ma_red_line);

         if(price_bid>price_enter_min && price_bid<price_enter_max)
            if(PositionsTotal()==0)
              {
               trade.Sell(order_volume,_Symbol,price_bid,price_sl,price_tp,"Sell");
              }
        }
     }

   if(PositionsTotal()!=0)
     {
      Position_mod(price_ask,price_bid,trailing_sl,trailing_profit,answer_stochastic);
     }

  }


如果有持仓的情况下, 则调用仓位更新/删除函数。这是代码的结尾。现在, 到我们测试智能交易系统的时候了。


测试结果

智能交易系统 Dinapoli_v1.01 已在 H4 时间帧上针对各种货币对进行了测试。我们使用的历史记录从 2017.01.01 至 2017.11.12。

品种: EURUSD

参数:

percent_min_enter=33.6 magic_number=65758473787389 stochastic_up_level=70
percent_max_enter=56 order_volume=0.01 stochastic_down_level=30
percent_for_tp=145 order_deviation=100 ma_red_period=25
percent_for_sl=100 stochastic_k=8 ma_red_shift=5
trailing_sl=675 stochastic_d=3 ma_blue_period=7
trailing_profit=40 stochastic_slowing=3 ma_blue_shift=5



Fig.4. Testing results EURUSD H4 (2017.01.01 - 2017.11.12)

品种: GBPUSD

参数:

percent_min_enter=23.6 magic_number=65758473787389 stochastic_up_level=90
percent_max_enter=50 order_volume=0.01 stochastic_down_level=30
percent_for_tp=335 order_deviation=100 ma_red_period=15
percent_for_sl=63 stochastic_k=3 ma_red_shift=5
trailing_sl=425 stochastic_d=1 ma_blue_period=4
trailing_profit=20 stochastic_slowing=4 ma_blue_shift=5



图例 5. 测试结果 GBPUSD H4 (2017.01.01 - 2017.11.12)

品种: NZDUSD

参数:

percent_min_enter=31.6 magic_number=65758473787389 stochastic_up_level=60
percent_max_enter=88 order_volume=0.01 stochastic_down_level=30
percent_for_tp=45 order_deviation=100 ma_red_period=24
percent_for_sl=95 stochastic_k=10 ma_red_shift=5
trailing_sl=550 stochastic_d=2 ma_blue_period=4
trailing_profit=100 stochastic_slowing=1 ma_blue_shift=5



图例 6. 测试结果 NZDUSD H4 (2017.01.01 - 2017.11.12)

品种: USDCAD

参数:

percent_min_enter=23.6 magic_number=65758473787389 stochastic_up_level=60
percent_max_enter=73 order_volume=0.01 stochastic_down_level=20
percent_for_tp=315 order_deviation=100 ma_red_period=25
percent_for_sl=69 stochastic_k=10 ma_red_shift=5
trailing_sl=325 stochastic_d=1 ma_blue_period=3
trailing_profit=10 stochastic_slowing=1 ma_blue_shift=5



图例 7. 测试结果 USDCAD H4 (2017.01.01 - 2017.11.12)

品种: USDCHF

参数:

percent_min_enter=49.6 magic_number=65758473787389 stochastic_up_level=70
percent_max_enter=69 order_volume=0.01 stochastic_down_level=40
percent_for_tp=55 order_deviation=100 ma_red_period=20
percent_for_sl=98 stochastic_k=13 ma_red_shift=5
trailing_sl=900 stochastic_d=6 ma_blue_period=12
trailing_profit=40 stochastic_slowing=3 ma_blue_shift=5



图例 8. 测试结果 USDCHF H4 (2017.01.01 - 2017.11.12)

品种: USDJPY

参数:

percent_min_enter=23.6 magic_number=65758473787389 stochastic_up_level=60
percent_max_enter=50 order_volume=0.01 stochastic_down_level=20
percent_for_tp=295 order_deviation=100 ma_red_period=22
percent_for_sl=53 stochastic_k=3 ma_red_shift=5
trailing_sl=750 stochastic_d=1 ma_blue_period=5
trailing_profit=10 stochastic_slowing=1 ma_blue_shift=5



图例 9. 测试结果 USDJPY H4 (2017.01.01 - 2017.11.12)

品种: AUDUSD

参数:

percent_min_enter=23.6 magic_number=65758473787389 stochastic_up_level=80
percent_max_enter=81 order_volume=0.01 stochastic_down_level=40
percent_for_tp=305 order_deviation=100 ma_red_period=13
percent_for_sl=69 stochastic_k=3 ma_red_shift=5
trailing_sl=250 stochastic_d=4 ma_blue_period=1
trailing_profit=20 stochastic_slowing=4 ma_blue_shift=5



图例10. 测试结果 AUDUSD H4 (2017.01.01 - 2017.11.12)

对所获结果进行分析揭示一些入场位置的不稳定性。对于除 USHCHF 以外的所有品种, 都观察到几乎水平的直线。

其原因如下: 为了降低余额回撤, 策略所设止损位尽可能接近。但以这种方式, 需要提高信号质量。分别来说, 信号质量越高, 入场的次数越少, 但同时图表上的价格上涨趋于稳定 (例如, 品种 USDCHF)。不过实际上, 我们计划尽可能多地赢得利润。我们应确保智能交易系统能够在复杂的行情下稳步减少亏损。

因此, 在优化和测试中, 您应参照较长时间周期所示入场次数较大的结果。

品种: XAUUSD

智能交易系统经过所有流行货币对的测试之后, 最好也了解以下它在商品市场的表现。因此, 我测试了 XAUUSD (黄金兑美元期货), 这就是我所得到的:

参数:

percent_min_enter=23.6 magic_number=65758473787389 stochastic_up_level=90
percent_max_enter=50 order_volume=0.2 stochastic_down_level=10
percent_for_tp=255 order_deviation=100 ma_red_period=23
percent_for_sl=80 stochastic_k=3 ma_red_shift=5
trailing_sl=750 stochastic_d=1 ma_blue_period=6
trailing_profit=10 stochastic_slowing=1 ma_blue_shift=5




图例11. 测试结果 XAUUSD H4 (2017.01.01 - 2017.11.12)

对于黄金的结果令人感兴趣: 智能交易系统计算的入场准确度为 83.3% (盈利交易), 利润为 461%, 回撤不超过 40%。这意味着利润远超回撤10 倍。这是一个有趣的指标, 但由于交易较少 (总共只有 18 笔交易), 我们不能根据所执行的测试做出严肃的结论。


交易策略的缺点

像其它策略一样, 我们开发的智能交易系统也有其缺点。

图例12. 智能交易系统在趋势区间 (NZDUSD H4)

图例12. 智能交易系统在趋势区间 (NZDUSD H4)

图例 12 表明智能交易系统在某种通道中的行为。一切看起来相当稳定, 但主要的缺点也是显而易见的: 交易离场过早。

图例 13. 智能交易系统在横盘区间 (EURUSD H4)

图例 13. 智能交易系统在横盘区间 (EURUSD H4)

另一个 "瓶颈": 智能交易系统在横盘时工作消极。图例 13 表明在这种走势当中利润不高; 且入场计算也不是很正确。

结果表格

品种交易盈利交易 (%)总计净盈利, $ 最大余额回撤 %预期收益, $盈利因子恢复因子锋锐指数
AUDUSD4116 (39.0%)49.9411.81.222.262.800.19
EURUSD5228 (53.8%)124.7917.72.402.234.010.28
GBPUSD4017 (42.5%)126.3919.03.164.845.020.24
NZDUSD13151 (38.9%)111.6311.90.852.255.290.26
USDCAD23145 (19.4%)85.7128.70.371.921.930.12
USDCHF1714 (82.3%)77.114.34.547.167.240.94
USDJPY21045 (21.4%)50.8852.30.241.350.960.07
XAUUSD1815 (83.3%)461.995.1
25.679.009.880.47

从表中可以看出结果不尽相同, 尽管不同货币对之间的共同趋势是直观的。在相同的设置下, 有些货币对获利 (尽管只是中等)。查找: 为了增加利润, 您应该针对每个货币对彻底优化智能交易系统的设置。 

结束语

又一次, 我们确定了 "旧学院派" 交易者长期以来建立的强大的基础。迪纳波利等级交易策略已被证明属于高瞻远瞩; 进而, 我计划继续开发它。至今, 它也有缺点: 例如, 在横盘时, 智能交易系统的表现相当糟糕。此外, 价格并非总能抵达 COP 线; 大多数情况下, 遵照随机指标平仓是有效的。

所开发的智能交易系统其优势包括足够的激进入场, 这在图例 13 中尤其明显。智能交易系统严格遵照算法执行, 所以当交易者手工入场时, 它很可能不会开仓。但是, 其结果就是实现了盈利, 且回撤不大。

存档文件

# 名称 类型 描述
1 Dinapoli_v1.01.mq5 智能交易系统 智能交易系统实现了利用迪纳波利等级和辅助指标的策略
2 AUDUSDH4.set 智能交易系统设置文件 用于品种 AUDUSD Н4 的测试和优化设置
3 EURUSDH4.set 智能交易系统设置文件 用于品种 EURUSD Н4 的测试和优化设置
4 GBPUSDH4.set 智能交易系统设置文件 用于品种 GBPUSD Н4 的测试和优化设置
5 NZDUSDH4.set 智能交易系统设置文件 用于品种 NZDUSD Н4 的测试和优化设置
6 USDCADH4.set 智能交易系统设置文件 用于品种 USDCAD Н4 的测试和优化设置
7 USDCHFH4.set 智能交易系统设置文件 用于品种 USDCHF Н4 的测试和优化设置
8 USDJPYH4.set 智能交易系统设置文件 用于品种 USDJPY Н4 的测试和优化设置
9 XAUUSDH4.set 智能交易系统设置文件 用于品种 XAUUSD Н4 的测试和优化设置