交易者的黄金法则

Genkov | 11 四月, 2016

简介

交易者的主要任务不仅仅是找到进入市场的恰当时机。 而且还需要找到退出市场的恰当时机。 交易黄金法则有云: “迅速斩断亏损,让利润奔跑起来”。

为了在较高的数学预期基础上获利,我们必须理解良好交易的三个基本原则:

  1. 进入市场时了解所面临的风险(即初始止损值);
  2. 迅速止盈,并使利润奔跑起来(不要在系统要求之前平仓);
  3. 了解你系统的数学预期——定期对其测试和调整。


使利润奔跑起来的逐步仓位跟踪法

很多人认为无法获利,因为我们不知道市场的目标在哪里。 但我们真的需要了解市场的目标才能成功交易吗? 成功的交易主要基于正确设计的系统,该系统考虑了进入市场的适当时机。 做出这种考虑是利用了预期的力量和使利润奔跑起来以达到可能最高水平的逐步仓位跟踪法。

可以通过多种方式找到进入市场的时机,例如,使用蜡烛图模型、波浪模型等。同时,必须考虑利润因子(利润/亏损比例)。

该方法基于以下要求:交易者在开仓时选择可能最低的止损值。 该值可以使用各种方法确定,例如,可以等于保证金的 1.5%。 当市场达到等于止损值的利润时,对一半的手数进行平仓,但止损值不变!

这样,我们建立了一种安全网,以防市场进入相反的趋势。 也就是说,通过将最小损失锁定来降低风险。 如果朝有利方向移动的市场在一段时间后开始反转,则触发止损(图 1-3)。

图 1. 开仓

图 2. 设置止损

如果市场反转:

图 3. 如果市场出现反转,你也处于保本水平。



仓位跟踪程序代码

我们提供了跟踪未平仓头寸并实践第二黄金法则的程序代码,因为它可以使利润奔跑起来以达到可能的最高水平。

如果市场仍朝有利的方向移动并达到某个预定值,例如,100 个价格利润点,则止损重置为保本水平。 当达到预定间隔的利润水平时,例如,50 个价格利润点,则继续进行重置。 我们总可以在下一个柱时移动止损值,但经纪人并不喜欢频繁重置,尤其对于以较小的时间范围进行的交易。 对于这种情形,库文件夹中的错误文件中(stdlib.mq4)甚至有专门的错误提示 - # 8 error="too frequent requests"。

确定下一个止损水平的方法是根据斐波那契水平获利时由价格位置所选定。 这里采用的斐波那契水平是根据 Vegas 通道方法建立的。

斐波那契水平计算由 LevelFibo() 水平生成函数执行:

//+------------------------------------------------------------------+
   void LevelFibo()
   {
   double Fb1,Fb2,Fb3,Fb4,Fb5,Fb6,Fb7,Fb8,Fb9,Fb10,Fb11,Fb12,Fb13;
   // "Vegas" channel
   double Ma144_1 = iMA(NULL,0,144,0,MODE_EMA,PRICE_CLOSE,1);
   double Ma169_1 = iMA(NULL,0,169,0,MODE_EMA,PRICE_CLOSE,1);
   // "Vegas" channel median
   double MedVegas=NormalizeDouble((Ma144_1+Ma169_1)/2,Digits); 
   // calculate Fibo levels values using "Vegas" method
   Fb1=MedVegas-377*Point;     Fb12=MedVegas+377*Point;
   Fb2=MedVegas-233*Point;     Fb11=MedVegas+233*Point;
   Fb3=MedVegas-144*Point;     Fb10=MedVegas+144*Point;
   Fb4=MedVegas-89*Point;      Fb9=MedVegas+89*Point;
   Fb5=MedVegas-55*Point;      Fb8=MedVegas+55*Point;
   Fb6=MedVegas-34*Point;      Fb7=MedVegas+34*Point;
   }
//+------------------------------------------------------------------+

当计算买入头寸的止损时,利润是第一个柱 High[1] 的最高价和开仓水平 OrderOpenPrice() 之间的差值。 止损水平被定义为跟第一个柱 Low[1](图 4)的最小值“最接近”的斐波那契水平。

图 4. 买入头寸的止损计算

当计算卖出头寸的止损时,利润是开仓水平 OrderOpenPrice() 和第一个柱 High[1] 的最高价之间的差值(图 5)

图 5. 卖出头寸的 止损计算

对于买入头寸,止损值是基于斐波那契水平。 根据第一个蜡烛图的最低值,它呈现为单独的函数。

函数代码显示如下:

//+---------------------------------------------------------------------+
//| Function (table) for specifying Stop Loss values for BUY position   |
//| by Fibo levels according to the lowest value of the first candle    |
//+---------------------------------------------------------------------+
 void StopLevelFiboBuy()
   {
   if(Low[1]>Fb12)                                newSL_B=Fb12-100*Point;
   if(Low[1]<=Fb12 && Low[1]>(Fb12+Fb11)/2)       newSL_B=(Fb12+Fb11)/2;
   if(Low[1]<=(Fb12+Fb11)/2 && Low[1]>Fb11)       newSL_B=Fb11;
   if(Low[1]<=Fb11 && Low[1]>(Fb11+Fb10)/2)       newSL_B=(Fb11+Fb10)/2;
   if(Low[1]<=(Fb10+Fb11)/2 && Low[1]>Fb10)       newSL_B=Fb10;
   if(Low[1]<=Fb10 && Low[1]>(Fb10+Fb9)/2)        newSL_B=Fb9;
   if(Low[1]<=(Fb10+Fb9)/2 && Low[1]>Fb9)         newSL_B=Fb8;
   if(Low[1]<=Fb9  && Low[1]>Fb8)                 newSL_B=Fb7;
   if(Low[1]<=Fb8  && Low[1]>Fb7)                 newSL_B=(Fb7+MedVegas)/2;
   if(Low[1]<=Fb7  && Low[1]>MedVegas)            newSL_B=Fb6;
   if(Low[1]<=MedVegas && Low[1]>(MedVegas+Fb6)/2)newSL_B=Fb6;
   if(Low[1]<=(MedVegas+Fb6)/2 && Low[1]>Fb6)     newSL_B=Fb5;
   if(Low[1]<=Fb6  && Low[1]>Fb5)                 newSL_B=Fb4;
   if(Low[1]<=Fb5  && Low[1]>Fb4)                 newSL_B=(Fb3+Fb4)/2;
   if(Low[1]<=Fb4  && Low[1]>Fb3)                 newSL_B=Fb3;
   if(Low[1]<=Fb3  && Low[1]>(Fb3+Fb2)/2)         newSL_B=(Fb3+Fb2)/2;
   if(Low[1]<=(Fb3+Fb2)/2  && Low[1]>Fb2)         newSL_B=Fb2;
   if(Low[1]<=Fb2  && Low[1]>(Fb2+Fb1)/2)         newSL_B=(Fb1+Fb2)/2;
   if(Low[1]<=(Fb2+Fb1)/2 && Low[1]>Fb1)          newSL_B=Fb1;
   if(Low[1]<=Fb1)                                newSL_B=Fb1-100*Point;
   }
//+------------------------------------------------------------------+

下面的代码描述了根据第一个 StopLevelFiboSell() 函数蜡烛图的最大值按照斐波那契水平得到的卖出头寸的止损值表:

//+----------------------------------------------------------------------+
//| Function (table) for specifying Stop Loss values for SELL position   |
//| by Fibo levels according to the highest value of the first candle    |
//+----------------------------------------------------------------------+
 void StopLevelFiboSell()
   {
   if(High[1]<=Fb12 && High[1]>(Fb12+Fb11)/2)        newSL_S=Fb12+100*Point;
   if(High[1]<=Fb12 && High[1]>Fb11)                 newSL_S=Fb12;
   if(High[1]<=Fb11 && High[1]>Fb11+Fb10)            newSL_S=Fb11;
   if(High[1]<=Fb10 && High[1]>(Fb10+Fb9)/2)         newSL_S=(Fb11+Fb10)/2;
   if(High[1]<=Fb9  && High[1]>Fb8)                  newSL_S=(Fb10+Fb9)/2;
   if(High[1]<=Fb8  && High[1]>Fb7)                  newSL_S=Fb9;
   if(High[1]<=Fb7  && High[1]>MedVegas)             newSL_S=Fb8;
   if(High[1]<=MedVegas && High[1]>MedVegas)         newSL_S=Fb7;
   if(High[1]<=(MedVegas+Fb6)/2 && High[1]>Fb6)      newSL_S=MedVegas;
   if(High[1]<=Fb6  && High[1]>Fb5)                  newSL_S=MedVegas;
   if(High[1]<=Fb5  && High[1]>Fb4)                  newSL_S=Fb6;
   if(High[1]<=Fb4  && High[1]>Fb3)                  newSL_S=Fb5;
   if(High[1]<=Fb3  && High[1]>Fb2)                  newSL_S=Fb4;
   if(High[1]<=Fb2  && High[1]>(Fb2+Fb1)/2)          newSL_S=(Fb2+Fb3)/2;
   if(High[1]<(Fb2+Fb1)/2   && High[1]>Fb1)          newSL_S=Fb2;
   if(High[1]<Fb1)                                   newSL_S=(Fb2+Fb1)/2;
   }
//+------------------------------------------------------------------+

最好将斐波那契水平计算函数 LevelFibo 添加到上述的两个依赖函数。 在随附的演示文件中已经这样做了。

现在,考虑这两个函数的组合或在集中于这些水平上的止损水平的识别函数中启用 LevelFibo() 水平计算。 因为这些函数协同工作,所以该组合是合理的。 因此,在跟踪时函数调用的数量将会降低——只会留下一个,而不是两个。

组合之后,它们呈现如下:

//+----------------------------------------------------------------------+
//| Function (table) for specifying Stop Loss values for BUY position    |
//| by Fibo levels according to the lowest value of the first candle     |
//+----------------------------------------------------------------------+
   void StoplevelFiboBuy()
   {
   double Fb1,Fb2,Fb3,Fb4,Fb5,Fb6,Fb7,Fb8,Fb9,Fb10,Fb11,Fb12,Fb13;
   double Ma144_1 = iMA(NULL,0,144,0,MODE_EMA,PRICE_CLOSE,1);
   double Ma169_1 = iMA(NULL,0,169,0,MODE_EMA,PRICE_CLOSE,1);
   double MedVegas=NormalizeDouble((Ma144_1+Ma169_1)/2,Digits); 
   Fb1=MedVegas-377*Point;     Fb12=MedVegas+377*Point;
   Fb2=MedVegas-233*Point;     Fb11=MedVegas+233*Point;
   Fb3=MedVegas-144*Point;     Fb10=MedVegas+144*Point;
   Fb4=MedVegas-89*Point;      Fb9=MedVegas+89*Point;
   Fb5=MedVegas-55*Point;      Fb8=MedVegas+55*Point;
   Fb6=MedVegas-34*Point;      Fb7=MedVegas+34*Point;
   if(Low[1]>Fb12)                                newSL_B=Fb12-100*Point;
   if(Low[1]<=Fb12 && Low[1]>(Fb12+Fb11)/2)       newSL_B=(Fb12+Fb11)/2;
   if(Low[1]<=(Fb12+Fb11)/2 && Low[1]>Fb11)       newSL_B=Fb11;
   if(Low[1]<=Fb11 && Low[1]>(Fb11+Fb10)/2)       newSL_B=(Fb11+Fb10)/2;
   if(Low[1]<=(Fb10+Fb11)/2 && Low[1]>Fb10)       newSL_B=Fb10;
   if(Low[1]<=Fb10 && Low[1]>(Fb10+Fb9)/2)        newSL_B=Fb9;
   if(Low[1]<=(Fb10+Fb9)/2 && Low[1]>Fb9)         newSL_B=Fb8;
   if(Low[1]<=Fb9  && Low[1]>Fb8)                 newSL_B=Fb7;
   if(Low[1]<=Fb8  && Low[1]>Fb7)                 newSL_B=(Fb7+MedVegas)/2;
   if(Low[1]<=Fb7  && Low[1]>MedVegas)            newSL_B=Fb6;
   if(Low[1]<=MedVegas && Low[1]>(MedVegas+Fb6)/2)newSL_B=Fb6;
   if(Low[1]<=(MedVegas+Fb6)/2 && Low[1]>Fb6)     newSL_B=Fb5;
   if(Low[1]<=Fb6  && Low[1]>Fb5)                 newSL_B=Fb4;
   if(Low[1]<=Fb5  && Low[1]>Fb4)                 newSL_B=(Fb3+Fb4)/2;
   if(Low[1]<=Fb4  && Low[1]>Fb3)                 newSL_B=Fb3;
   if(Low[1]<=Fb3  && Low[1]>(Fb3+Fb2)/2)         newSL_B=(Fb3+Fb2)/2;
   if(Low[1]<=(Fb3+Fb2)/2  && Low[1]>Fb2)         newSL_B=Fb2;
   if(Low[1]<=Fb2  && Low[1]>(Fb2+Fb1)/2)         newSL_B=(Fb1+Fb2)/2;
   if(Low[1]<=(Fb2+Fb1)/2 && Low[1]>Fb1)          newSL_B=Fb1;
   if(Low[1]<=Fb1)                                newSL_B=Fb1-100*Point;
   }
// ----------------------------------------------------------------------+

仓位跟踪的主要命令代码表现为具有操作序列的 Expert Advisor 片段,该序列用于根据当前柱的价格值执行上述的函数。 在已经选择了适当的未结订单后,开始逐步跟踪。

下面显示了跟踪代码的一小段:

//+------------------------------------------------------------------+
//| TRAILING OPEN POSITIONS                                          |
//+------------------------------------------------------------------+
for(int i=OrdersTotal()-1; i>=0; i--)
  {
   if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
     {Print("Order selection error = ",GetLastError());}
   if(OrderSymbol()==Symbol())
     {
      if(OrderType()==OP_BUY)
        {
         if(OrderMagicNumber()==Magic)
           {
            // ----------------------------------------------------------------------+
            if((High[1]-OrderOpenPrice())>=SL_B*Point && OrderLots()==0.2)Close_B_lot();
            // ----------------------------------------------------------------------+
            if((High[1]-OrderOpenPrice())/Point>=100 && OrderLots()==0.1 && OrderStopLoss()<OrderOpenPrice())
              {
               Print(" 1 - StopLoss shift");
               if(!OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()+2*Point,OrderTakeProfit(),0,Aqua))
                 {
                  Print(" at Modif.ord.# ",OrderTicket()," Error # ",GetLastError());
                 }
               return;
              }
            // ----------------------------------------------------------------------+
            if((High[1]-OrderOpenPrice())>=120*Point && OrderOpenPrice()>Ma144_1-144*Point)
              {
               StoplevelFiboBuy();
               newSL_B=newSL_B+21*Point;
               if((Bid-newSL_B)/Point<StopLevel)newSL_B=Bid-StopLevel*Point;
               if(newSL_B>OrderStopLoss() && (Bid-newSL_B)/Point>StopLevel)
                 {
                  Print("2nd shift of StopLoss ");
                  Modyf_B_lot();
                 }
              }
            // ----------------------------------------------------------------------+
            if((High[1]-OrderOpenPrice())>=200*Point && (High[1]-OrderOpenPrice())<=250*Point)
              {
               StoplevelFiboBuy();
               if((Bid-newSL_B)/Point<StopLevel)newSL_B=Bid-StopLevel*Point;
               if(newSL_B>OrderStopLoss() && (Bid-newSL_B)/Point>StopLevel)
                 {
                  Print(" 3rd shift by level order # ",OrderTicket());
                  Modyf_B_lot();
                 }
              }
            // ----------------------------------------------------------------------+
            if((High[1]-OrderOpenPrice())>=250*Point && OrderOpenPrice()>Ma144_1-144*Point)
              {
               StoplevelFiboBuy();
               newSL_B=newSL_B+10*Point;
               if((Bid-newSL_B)/Point<StopLevel) newSL_B=Bid-StopLevel*Point;
               if(newSL_B>OrderStopLoss() && (Bid-newSL_B)/Point>StopLevel)
                 {
                  Print(" 4th shift by level order # ",OrderTicket());
                  Modyf_B_lot();
                 }
              }
            // ----------------------------------------------------------------------+
            if((High[1]-OrderOpenPrice())>=300*Point && (High[1]-OrderOpenPrice())<=350*Point)
              {
               StoplevelFiboBuy();
               newSL_B=newSL_B+20*Point;
               if((Bid-newSL_B)/Point<StopLevel) newSL_B=Bid-StopLevel*Point;
               if(newSL_B>OrderStopLoss() && (Bid-newSL_B)/Point>StopLevel)
                 {
                  Print(" 5th shift by level order # ",OrderTicket());
                  Modyf_B_lot();
                 }
              }
            // ----------------------------------------------------------------------+
            ...
           }
        }
     }
  }

在随附的 Expert Advisor 演示版本中,逐步跟踪序列包含了 8 个步骤。

下面是显示 Expert Advisor 演示版进行买入头寸跟踪操作步骤的截屏。 因为形成了“三个蜡烛合并”形态,所以进行了建仓。 此外,“倒锤子”图形位于合并的蜡烛中间。 这种现象强化了打开买入头寸的信号强度。

图 6. 跟踪买入头寸的示例

“Vegas”指标应该用于查看斐波那契线,如同在光亮的截屏上一样。 可以在 MQL4 网站进行查看。 https://www.mql5.com/en/code/7148

来自“暗”屏幕的小幅拉伸的相同截屏:

图 7. 来自监测屏的截屏(买入演示版本)

图 8. 跟踪卖出头寸的示例

为了显示 Expert Advisor 演示版的操作,应该使用临时测试参数,如下图 9-10 所示:

图 9. Demo_trail_Buy.mql Expert Advisor 测试参数

图 10. Demo_trail_Sell.mql Expert Advisor 测试参数

注意: 本文随附了 Expert Advisor 演示版的文件,作为跟踪买入和卖出头寸的迷你控制程序。 这里开仓的手数翻倍。 但当止损移动到保本水平,且对未来价格走势正确有信心,是可以增加头寸的。



总结

所提供的订单跟踪示例显示,聚焦于斐波那契动态水平的止损订单移动法可以产生积极的结果。 所描述的方法建议用于实际交易中。

动态斐波那契水平识别函数: