捕捉趋势

Eryomin Sergey | 17 三月, 2016

警告

本文中包含的信息仅为我的个人见解。作为作者,我不想诱导你使用本文描述的算法进行交易。此外,我必须警告,使用该信息可能导致损失。



简介

本文包含对交易方法的描述 - 即获利交易的成交量积累。我认为只有获利交易才能够积累。文章解释了实施的最佳方式,并包含了帮助正确进行交易的 EA 代码。



算法的概念

获利交易的成交量积累可以让我们从市场变动中最大化获利。但成交量积累必须避免导致风险的增加。本文描述了这种成交量积累的算法之一。

首先,我们需要一个参考点 - 第一个主交易。主交易的交易量应大于每个辅交易的交易量。假设主交易的量为 0.2 手,辅交易的量则为 0.1 手。跟踪止损用于所有的交易,例如,50 个点。当主交易的获利达到 +100 点,止损为 +50。此时,在止损 -50 点的相同方向上打开 0.1 手的交易。如果价格回落,两个交易将被止损订单关闭。获得的利润等于 0.2 手的 50 点和 0.1 手的 - 50 点。总共获利等于 0.1 手的 50 点。这样就在交易量增加时实现了止损保护。

如果交易继续沿着必要的方向移动,当辅交易的获利达到 +50 点时,跟踪止损激活。当主交易的获利达到 200 点,辅交易的获利达到 100 点,将打开另一个辅交易。止损还是等于 -50。诸如此类。

这是一个非常简单的从手数积累良好获利的方法。同时使风险最小化。实际上,这里的风险不过是亏损了主交易的一部分,即第一个辅交易亏损的风险。但这并不是亏损风险,而是没有获得全部利润的风险。

标准的跟踪 止 损在只有获利时才跟踪交易。但如果在获得必要的利润之前对辅交易实施,则可以提高这种手数积累方法的获利性。你可以利用 MQL4 在优化辅订单的打开时如此操作。



实施

为此而编写的 Expert Advisor 基于“方便的剥头皮交易”一文中描述的 EA。本文中,EA 具有复合功能:即作为训练游戏,又是打开交易的工具。在该交易中,删除了游戏的功能。这样 Expert Advisor 在图表上绘制两个箭头 - 向上和向下。删除其中之一是在必要的方向打开交易的信号。例如,删除向下的箭头,则向上的箭头保留在图表上。对于 EA,这是一个买入信号,下一定量的买入止损挂单。

这里,市场订单是主订单。挂单具有辅订单的功能,辅订单比主订单的手数小。为了计算辅交易打开的“频率”及其数量,使用了两个概念。第一个是终极目标,即获利。这对所有订单都一样(主订单和辅订单)。第二个概念是打开挂单的步长。根据终极目标,EA 计算按照从当前价格到获利水平的间隔下单的数量。

例如,如果使获利等于 400 点,打开订单的步长为 100 点(默认),则买入时要打开 4 个订单。第一个是以沽盘价买入的主订单。第二个是以沽盘价+100 点买入的止损辅订单。第三个是以沽盘价+200 点买入的止损辅订单。第四个是以沽盘价+300 点买入的止损辅订单。所有订单的获利等于沽盘价+400 点,即对第一个订单为 400 点,第二个为 300 点,第三个为 200 点,第四个为 100 点。

跟踪 止 损 只有在获得必要的利润时才作用于主交易(默认为 50 点)。对于辅交易,则从打开订单的时刻开始(即可以跟踪止损的亏损区域)。跟踪止损水平对所有交易都相等。此外,跟踪止损水平是对辅交易的止损水平。

如果主订单关闭,会删除剩余的挂单。之后,图表上再次绘制两个箭头。这意味着 EA 准备好再次打开交易。

这一切看起来很冗长,但在实践中很容易实施。我们来分析 EA 代码。

//+------------------------------------------------------------------+
//|                                                   take_trend.mq4 |
//|                                       Copyright © 2008, FXRaider |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2008, FXRaider"
extern int gap=20;            //level at which arrows are placed 
extern int TP=400;            //Take Profit level
extern int SL=0;              //Stop Loss level
extern double Lots1=0.2;      //lot of a main trade
extern double Lots2=0.1;      //lot of auxiliary trades 
extern int slippage=2;        //level of acceptable requote
extern int MagicNumber1=5345; //magic number of the main trade
extern int MagicNumber2=4365; //magic number of auxiliary trades
extern int Open_Step=100;     //step for opening auxiliary trades
 
extern bool UseTrailing = true; //enabling/disabling T-SL
extern int TrailingStop = 50;   //Trailing Stop Loss level
extern int TrailingStep = 1;    //Trailing Stop Loss step
int start()
  {
//------------------------------       
//+----------------------------------------------------------------------------------------------+
//|                              searching open orders for a pair                                |
    int pos_sell=0;
  for (int i_op_sell=OrdersTotal()-1; i_op_sell>=0; i_op_sell--) 
  { 
   if (!OrderSelect(i_op_sell,SELECT_BY_POS,MODE_TRADES)) break; 
   if (Symbol()==OrderSymbol()
   &&OrderMagicNumber()==MagicNumber1   
   &&(OrderType()==OP_SELL))
   {
    pos_sell=1; break;   
   } 
  }
    
    int pos_buy=0;
  for (int i_op_buy=OrdersTotal()-1; i_op_buy>=0; i_op_buy--) 
  { 
   if (!OrderSelect(i_op_buy,SELECT_BY_POS,MODE_TRADES)) break; 
   if (Symbol()==OrderSymbol()
   &&OrderMagicNumber()==MagicNumber1
   &&(OrderType()==OP_BUY))
   {
    pos_buy=1; break;   
   } 
  }    
//|                              searching open orders for a pair                                |
//+----------------------------------------------------------------------------------------------+  
//+------------------------------------------------------------------------------------+
//|                                 working with objects                               |  
 
//+----------------------------------------------------------+
//|                    deleting objects                      | 
  if(iBarShift(NULL,0,ObjectGet("down",OBJPROP_TIME1))>0
     ||ObjectGet("down",OBJPROP_PRICE1)!=Open[0]-gap*Point) 
    {
     ObjectDelete("down"); 
    }  
  if(iBarShift(NULL,0,ObjectGet("up",OBJPROP_TIME1))>0
    ||ObjectGet("up",OBJPROP_PRICE1)!=Open[0]+gap*Point)            
    { 
     ObjectDelete("up"); 
    } 
//|                    deleting objects                      |   
//+----------------------------------------------------------+ 
 
//+----------------------------------------------------------+
//|                   drawing objects                        |   
   if((ObjectFind("down") != 0&&ObjectFind("up") != 0) //if no objects
   &&!pos_sell&&!pos_buy)                              //if no open orders
   {
     ObjectCreate("down", OBJ_ARROW, 0, Time[0], Open[0]-gap*Point); //draw a down arrow
     ObjectSet("down", OBJPROP_STYLE, STYLE_DOT);
     ObjectSet("down", OBJPROP_ARROWCODE, 234);
     ObjectSet("down", OBJPROP_COLOR, Red);
 
     ObjectCreate("up", OBJ_ARROW, 0, Time[0], Open[0]+gap*Point); //draw an up arrow
     ObjectSet("up", OBJPROP_STYLE, STYLE_DOT);
     ObjectSet("up", OBJPROP_ARROWCODE, 233);
     ObjectSet("up", OBJPROP_COLOR, Blue);
   }    
//|                   drawing objects                        |
//+----------------------------------------------------------+   
      
//|                                 working with objects                               |   
//+------------------------------------------------------------------------------------+
 
   
 
 
//+----------------------------------------------------------------------------------------------+ 
//|                                deleting unnecessary orders                                   | 
int cnt_del; 
if(pos_buy==0)
{               
  for (cnt_del=0; cnt_del<OrdersTotal(); cnt_del++) 
  {
    if (!(OrderSelect(cnt_del, SELECT_BY_POS, MODE_TRADES))) continue;     
    if(OrderSymbol()==Symbol())
    {
     if (OrderType()==OP_BUYSTOP && OrderMagicNumber()==MagicNumber2) OrderDelete(OrderTicket()); 
    }
  } 
 } 
 
if(pos_sell==0)
{               
  for (cnt_del=0; cnt_del<OrdersTotal(); cnt_del++) 
  {
    if (!(OrderSelect(cnt_del, SELECT_BY_POS, MODE_TRADES))) continue;     
    if(OrderSymbol()==Symbol())
    { 
    if (OrderType()==OP_SELLSTOP && OrderMagicNumber()==MagicNumber2) OrderDelete(OrderTicket()); 
    }
  } 
 }  
//|                                deleting unnecessary orders                                   |
//+----------------------------------------------------------------------------------------------+  
 
  
//+------------------------------------------------------------------------------------+ 
//|                                   opening trades                                   |
double sl_buy, sl_sell;
 if(!SL)
 { 
  sl_buy=0;
  sl_sell=0;
 }
 else
 {
  sl_buy=Ask-SL*Point;
  sl_sell=Bid+SL*Point;
 }
 int stop_positions=MathFloor(TP/Open_Step-1);
 int i, open_step_2;
  if(
     ObjectGet("up", OBJPROP_PRICE1)==Open[0]+gap*Point
     &&iBarShift(NULL,0,ObjectGet("up",OBJPROP_TIME1))==0
     &&ObjectFind("down") != 0
     &&ObjectFind("up") == 0
     &&!pos_buy  
     )
     {
      OrderSend(Symbol(),OP_BUY, Lots1,Ask,slippage,sl_buy,Ask+TP*Point,"take_trend",MagicNumber1,0,Blue); 
      for(i=stop_positions;i>=0; i--) 
      {
       open_step_2=open_step_2+Open_Step;
       OrderSend(Symbol(),OP_BUYSTOP, Lots2,
       Ask+open_step_2*Point,slippage,
       0,Ask+TP*Point,"take_trend",MagicNumber2,0,Blue);
      }          
     }
  if(
     ObjectGet("down", OBJPROP_PRICE1)==Open[0]-gap*Point
     &&iBarShift(NULL,0,ObjectGet("down",OBJPROP_TIME1))==0
     &&ObjectFind("up") != 0
     &&ObjectFind("down") == 0
     &&!pos_sell
     )
     {
      OrderSend(Symbol(),OP_SELL, Lots1,Bid,slippage,sl_sell,Bid-TP*Point,"take_trend",MagicNumber1,0,Red);
      for(i=stop_positions;i>=0; i--) 
      {
       open_step_2=open_step_2+Open_Step;
       OrderSend(Symbol(),OP_SELLSTOP, Lots2,
       Bid-open_step_2*Point,slippage,
       0,Bid-TP*Point,"take_trend",MagicNumber2,0,Red);
      }        
     }
//|                                   opening trades                                   |  
//+------------------------------------------------------------------------------------+   
 
 
//+-------------------------------------------------------------------------------------------------+ 
//|                                      trail of open orders                                       |
if (UseTrailing)
{ 
  for (int trall=0; trall<OrdersTotal(); trall++) {
    if (!(OrderSelect(trall, SELECT_BY_POS, MODE_TRADES))) continue;
    if (OrderSymbol() != Symbol()) continue;       
 
    if (OrderType() == OP_BUY ) {
      if (Bid-OrderOpenPrice() > TrailingStop*Point || OrderMagicNumber()==MagicNumber2) {
        if (OrderStopLoss() < Bid-(TrailingStop+TrailingStep-1)*Point || OrderStopLoss() == 0) {
          OrderModify(OrderTicket(), OrderOpenPrice(), Bid-TrailingStop*Point, OrderTakeProfit(), 0, Blue);
       }
      }
    }
 
    if (OrderType() == OP_SELL) {
     if (OrderOpenPrice()-Ask > TrailingStop*Point || OrderMagicNumber()==MagicNumber2) {
        if (OrderStopLoss() > Ask+(TrailingStop+TrailingStep-1)*Point || OrderStopLoss() == 0) {
          OrderModify(OrderTicket(), OrderOpenPrice(), Ask+TrailingStop*Point, OrderTakeProfit(), 0, Blue);
        }
     }
    }
  }
 }
//|                                      trail of open orders                                       |
//+-------------------------------------------------------------------------------------------------+
     
   return(0);
  }
//+------------------------------------------------------------------+

代码包含所有必要的注释。

变量:

gap – level, on which arrows are placed;
TP – Take Profit level;
SL – Stop Loss level;
Lots1 – lot of a main trade;
Lots2 – lot of auxiliary trades;
slippage – level of acceptable requote;
MagicNumber1 – magic number of the main trade;
MagicNumber2 – magic number of auxiliary trades;
Open_Step – step for opening auxiliary trades;


UseTrailing – enabling/disabling T-SL;
TrailingStop – Trailing Stop Loss level;
TrailingStep – Trailing Stop Loss step.

在添加 Expert Advisor 到图表后,绘制了两个箭头:

直到下一个蜡烛图出现前,剩下的箭头会保留在图表上。

在删除一个箭头后,EA 立即打开交易。

可以看到,剩下的箭头未显示在截屏上 - 之前已经说过,在下一个蜡烛图出现时它会被删除,直到所有交易关闭后才出现箭头。只要第一个交易的利润达到必要水平,T-SL 开始工作(它始终作用于辅交易)。在本例中,只有第一个交易在回落时关闭。同时,所有其他订单被删除。



总结

最后,我想说的是,应该为每一个货币对单独选择跟踪止损水平、获利和打开辅交易的水平。另需要注意的是,为了有效使用,辅交易的打开水平必须大于 T-SL 水平。在主交易中,建议使用大于辅交易的手数。