23 January 2014

TP, TS czy FTS - zarządzanie pozycjami

Jest kilka sposobów realizacji zysków z otwartych zakładów. Take Profit (TP) to bezpieczna metoda, która umożliwia złożenie reklamacji w przypadku błędu brokera. Trailing Stop (TS) umożliwia przesuwanie poziomu Stop Loss (SL) wraz ze wzrostem zysków z zakładu - jest realizowana na wiele sposobów (popularna wersja jest zaimplementowana w menu MT4). Fast Trailing Stop (FTS) to metoda którą stosuję w algorytmach skalpujących - podczas testów sprawdzała się lepiej niż TP (jednak wtedy poziom zamykania transakcji nie był większy od SL). Chciałem aby kolejne doświadczenie z algorytmami porównało trzy metody zarządzania zakładami. Napisałem trzy proste algorytmy ocierające się o skalpowanie, w których SL = 40 pipsów (5 cyfr), a TP oraz stop kroczący wynosi 2 x SL (80 pipsów). W każdym z algorytmów zawarłem zakłady z TP, zakład z własną metodą ruchomego SL (jest to inna metoda niż tradycyjny TS) oraz szybki trailing stop. Wszystkie roboty posiadają system zarządzania wielkością pozycji opisany w poprzednim poście. Algorytmy uruchomiłem u nowego brokera Advanced Markets Ltd. Pierwszy robot to zrównoważony "starszy Pan" czekający na okazje - zapewne najwolniej wyczyści konto ale ominie wiele okazji do zarobienia. Drugi robot jest agresywny i systematyczny jak "rzymski legionista", czeka na swoją okazję powielając zarówno zyski jak i błędy. Trzeci to "drapieżca" dużo zarabia i bardzo dużo traci. Oczywiście wszystkie będą miały swoje wzloty i upadki ale powinny porównać TP, TS i FTS dość dobrze przed wyczerpaniem środków na koncie.
1. "starszy Pan" wygląda tak:

//+------------------------------------------------------------------+
//|Test TP, TS, FTS (option 1) (5 digits).mq4
//|Copyright 2014, FiveWithFour@gmail.com
//|http://www.FiveWithFour.blogspot.com
//+------------------------------------------------------------------+
#property copyright "FiveWithFour@gmail.com"
#property link      "http://www.FiveWithFour.blogspot.com"

bool bTP, bTS, bFTS;
bool bBUY = false;
bool bSELL = false;
bool bBUY_1 = true;
bool bSELL_1 = true;

double dHeikenAshi_M1   = 0; 
double dHeikenAshi_M5   = 0;
double dHeikenAshi_M15  = 0;  
double dHeikenAshi_M30  = 0;

double dFreeMargin = 0;
double dTickValue = 0;
double dSpread = 0;
double dRiskValue = 0.03;
double dRiskInPips = 40;
double dLot = 0;
double dLots = 0;

int start()
   {
   int i = 0;
   
   bTP = false;
   bTS = false;
   bFTS = false;
   
   dFreeMargin = AccountFreeMargin();
   dTickValue = (MarketInfo(Symbol(), MODE_TICKVALUE) * 0.1);
   dSpread = MarketInfo(Symbol(), MODE_SPREAD);

   dLot = ((dFreeMargin * dRiskValue) * dTickValue) / (dRiskInPips + dSpread);
   dLots = (dLot - (dLot * 0.3)) / 3;
      
   dHeikenAshi_M1   = fnCheckHAS(PERIOD_M1); 
   dHeikenAshi_M5   = fnCheckHAS(PERIOD_M5);
   dHeikenAshi_M15  = fnCheckHAS(PERIOD_M15);
   dHeikenAshi_M30  = fnCheckHAS(PERIOD_M30);
   
   if ((dHeikenAshi_M1 == 10) && (dHeikenAshi_M5 == 10) && (dHeikenAshi_M15 == 10) && (dHeikenAshi_M30 == 10))
      {
      bBUY = true;
      bSELL = false;
      }
   if ((dHeikenAshi_M1 == 20) && (dHeikenAshi_M5 == 20) && (dHeikenAshi_M15 == 20) && (dHeikenAshi_M30 == 20))
      {
      bSELL = true;
      bBUY = false;
      }    
   
   while(OrderSelect(i,SELECT_BY_POS))
      {
      switch(OrderMagicNumber())
         {
         case 10001:
            {
            bTP = true;
            break;
            }
         case 10002:
            {
            bTP = true;
            break;
            }
         case 20001:
            {
            bTS = true;
            if ((OrderOpenPrice() + 2*dRiskInPips*Point) <= Bid)
               if ((OrderStopLoss() + 2*dRiskInPips*Point) <= Bid)
                  OrderModify(OrderTicket(),OrderOpenPrice(),OrderStopLoss()+10*Point,0,0,CLR_NONE);
            break;
            }
         case 20002:
            {
            bTS = true;
            if ((OrderOpenPrice() - 2*dRiskInPips*Point) >= Ask)
               if ((OrderStopLoss() - 2*dRiskInPips*Point) >= Ask)
                  OrderModify(OrderTicket(),OrderOpenPrice(),OrderStopLoss()-10*Point,0,0,CLR_NONE);
            break;
            }
         case 30001:
            {
            bFTS = true;
            if ((OrderOpenPrice() + 2*dRiskInPips*Point) <= Bid)
               OrderModify(OrderTicket(),OrderOpenPrice(),OrderStopLoss()+10*Point,0,0,CLR_NONE);
            break;
            }
         case 30002:
            {
            bFTS = true;
            if ((OrderOpenPrice() - 2*dRiskInPips*Point) >= Ask)
               OrderModify(OrderTicket(),OrderOpenPrice(),OrderStopLoss()-10*Point,0,0,CLR_NONE);            
            break;
            }
         }
      i++;
      }
               
   if ((!bTS) && (!bFTS) && (!bTP))
      {
      if ((bBUY) && (bBUY_1))
         {
         if (OrderSend(Symbol(), OP_BUY, NormalizeDouble(dLots, 2), Ask, 3, Ask-dRiskInPips*Point, Ask+2*dRiskInPips*Point, "TP mode", 10001, 0, CLR_NONE) > 0)
            bTP = true;
         if (OrderSend(Symbol(), OP_BUY, NormalizeDouble(dLots, 2), Ask, 3, Ask-dRiskInPips*Point, 0, "TS mode", 20001, 0, CLR_NONE) > 0)
            bTS = true;
         if (OrderSend(Symbol(), OP_BUY, NormalizeDouble(dLots, 2), Ask, 3, Ask-dRiskInPips*Point, 0, "FTS mode", 30001, 0, CLR_NONE) > 0)
            bFTS = true;
         bBUY_1 = false;
         bSELL_1 = true;
         }
      if ((bSELL) && (bSELL_1))
         {
         if (OrderSend(Symbol(), OP_SELL, NormalizeDouble(dLots, 2), Bid, 3, Bid+dRiskInPips*Point, Bid-2*dRiskInPips*Point, "TP mode", 10002, 0, CLR_NONE) > 0)
            bTP = true;
         if (OrderSend(Symbol(), OP_SELL, NormalizeDouble(dLots, 2), Bid, 3, Bid+dRiskInPips*Point, 0, "TS mode", 20002, 0, CLR_NONE) > 0)
            bTS = true;
         if (OrderSend(Symbol(), OP_SELL, NormalizeDouble(dLots, 2), Bid, 3, Bid+dRiskInPips*Point, 0, "FTS mode", 30002, 0, CLR_NONE) > 0)
            bFTS = true;
         bSELL_1 = false;
         bBUY_1 = true;
         }
      }
   
   
   return(0);
   }

// ------------------------ *** Function Heiken Ashi *** ------------------------   
double fnCheckHAS(int iTimeframe)
   {
   if (iCustom(Symbol(),iTimeframe,"Heiken Ashi",2,0) < iCustom(Symbol(),iTimeframe,"Heiken Ashi",3,0) &&
       iCustom(Symbol(),iTimeframe,"Heiken Ashi",1,0) > iCustom(Symbol(),iTimeframe,"Heiken Ashi",0,0))
         return(10);
   if (iCustom(Symbol(),iTimeframe,"Heiken Ashi",2,0) > iCustom(Symbol(),iTimeframe,"Heiken Ashi",3,0) &&
       iCustom(Symbol(),iTimeframe,"Heiken Ashi",1,0) < iCustom(Symbol(),iTimeframe,"Heiken Ashi",0,0))
         return(20);
   return(0);
   }

2. "rzymski legionista"

//+------------------------------------------------------------------+
//|Test TP, TS, FTS (option 2) (5 digits).mq4
//|Copyright 2014, FiveWithFour@gmail.com
//|http://www.FiveWithFour.blogspot.com
//+------------------------------------------------------------------+
#property copyright "FiveWithFour@gmail.com"
#property link      "http://www.FiveWithFour.blogspot.com"

bool bTP, bTS, bFTS;
bool bBUY = false;
bool bSELL = false;
bool bBUY_1 = true;
bool bSELL_1 = true;

double dHeikenAshi_M1   = 0; 
double dHeikenAshi_M5   = 0;
double dHeikenAshi_M15  = 0;  
double dHeikenAshi_M30  = 0;

double dFreeMargin = 0;
double dTickValue = 0;
double dSpread = 0;
double dRiskValue = 0.03;
double dRiskInPips = 40;
double dLot = 0;
double dLots = 0;

int start()
   {
   int i = 0;
   
   bTP = false;
   bTS = false;
   bFTS = false;
   
   dFreeMargin = AccountFreeMargin();
   dTickValue = (MarketInfo(Symbol(), MODE_TICKVALUE) * 0.1);
   dSpread = MarketInfo(Symbol(), MODE_SPREAD);

   dLot = ((dFreeMargin * dRiskValue) * dTickValue) / (dRiskInPips + dSpread);
   dLots = (dLot - (dLot * 0.3)) / 3;   
   
   dHeikenAshi_M1   = fnCheckHAS(PERIOD_M1); 
   dHeikenAshi_M5   = fnCheckHAS(PERIOD_M5);
   dHeikenAshi_M15  = fnCheckHAS(PERIOD_M15);
   dHeikenAshi_M30  = fnCheckHAS(PERIOD_M30);
   
   if ((dHeikenAshi_M5 == 10) && (dHeikenAshi_M15 == 10) && (dHeikenAshi_M30 == 10))
      {
      bBUY = true;
      bSELL = false;
      }
   if ((dHeikenAshi_M5 == 20) && (dHeikenAshi_M15 == 20) && (dHeikenAshi_M30 == 20))
      {
      bSELL = true;
      bBUY = false;
      }
   
   while(OrderSelect(i,SELECT_BY_POS))
      {
      switch(OrderMagicNumber())
         {
         case 10001:
            {
            bTP = true;
            break;
            }
         case 10002:
            {
            bTP = true;
            break;
            }
         case 20001:
            {
            bTS = true;
            if ((OrderOpenPrice() + 2*dRiskInPips*Point) <= Bid)
               if ((OrderStopLoss() + 2*dRiskInPips*Point) <= Bid)
                  OrderModify(OrderTicket(),OrderOpenPrice(),OrderStopLoss()+10*Point,0,0,CLR_NONE);
            break;
            }
         case 20002:
            {
            bTS = true;
            if ((OrderOpenPrice() - 2*dRiskInPips*Point) >= Ask)
               if ((OrderStopLoss() - 2*dRiskInPips*Point) >= Ask)
                  OrderModify(OrderTicket(),OrderOpenPrice(),OrderStopLoss()-10*Point,0,0,CLR_NONE);
            break;
            }
         case 30001:
            {
            bFTS = true;
            if ((OrderOpenPrice() + 2*dRiskInPips*Point) <= Bid)
               OrderModify(OrderTicket(),OrderOpenPrice(),OrderStopLoss()+10*Point,0,0,CLR_NONE);
            break;
            }
         case 30002:
            {
            bFTS = true;
            if ((OrderOpenPrice() - 2*dRiskInPips*Point) >= Ask)
               OrderModify(OrderTicket(),OrderOpenPrice(),OrderStopLoss()-10*Point,0,0,CLR_NONE);            
            break;
            }
         }
      i++;
      }
               
   if ((!bTS) && (!bFTS) && (!bTP))
      {
      if ((bBUY) && (dHeikenAshi_M1 == 10))
         {
         if (OrderSend(Symbol(), OP_BUY, NormalizeDouble(dLots, 2), Ask, 3, Ask-dRiskInPips*Point, Ask+2*dRiskInPips*Point, "TP mode", 10001, 0, CLR_NONE) > 0)
            bTP = true;
         if (OrderSend(Symbol(), OP_BUY, NormalizeDouble(dLots, 2), Ask, 3, Ask-dRiskInPips*Point, 0, "TS mode", 20001, 0, CLR_NONE) > 0)
            bTS = true;
         if (OrderSend(Symbol(), OP_BUY, NormalizeDouble(dLots, 2), Ask, 3, Ask-dRiskInPips*Point, 0, "FTS mode", 30001, 0, CLR_NONE) > 0)
            bFTS = true;
         }
      if ((bSELL) && (dHeikenAshi_M1 == 20))
         {
         if (OrderSend(Symbol(), OP_SELL, NormalizeDouble(dLots, 2), Bid, 3, Bid+dRiskInPips*Point, Bid-2*dRiskInPips*Point, "TP mode", 10002, 0, CLR_NONE) > 0)
            bTP = true;
         if (OrderSend(Symbol(), OP_SELL, NormalizeDouble(dLots, 2), Bid, 3, Bid+dRiskInPips*Point, 0, "TS mode", 20002, 0, CLR_NONE) > 0)
            bTS = true;
         if (OrderSend(Symbol(), OP_SELL, NormalizeDouble(dLots, 2), Bid, 3, Bid+dRiskInPips*Point, 0, "FTS mode", 30002, 0, CLR_NONE) > 0)
            bFTS = true;
         }
      }
   return(0);
   }

// ------------------------ *** Function Heiken Ashi *** ------------------------   
double fnCheckHAS(int iTimeframe)
   {
   if (iCustom(Symbol(),iTimeframe,"Heiken Ashi",2,0) < iCustom(Symbol(),iTimeframe,"Heiken Ashi",3,0) &&
       iCustom(Symbol(),iTimeframe,"Heiken Ashi",1,0) > iCustom(Symbol(),iTimeframe,"Heiken Ashi",0,0))
         return(10);
   if (iCustom(Symbol(),iTimeframe,"Heiken Ashi",2,0) > iCustom(Symbol(),iTimeframe,"Heiken Ashi",3,0) &&
       iCustom(Symbol(),iTimeframe,"Heiken Ashi",1,0) < iCustom(Symbol(),iTimeframe,"Heiken Ashi",0,0))
         return(20);
   return(0);
   }

3. "predator"

//+------------------------------------------------------------------+
//|Test TP, TS, FTS (option 3) (5 digits).mq4
//|Copyright 2014, FiveWithFour@gmail.com
//|http://www.FiveWithFour.blogspot.com
//+------------------------------------------------------------------+
#property copyright "FiveWithFour@gmail.com"
#property link      "http://www.FiveWithFour.blogspot.com"

bool bTP, bTS, bFTS;
bool bBUY = false;
bool bSELL = false;
bool bBUY_1 = true;
bool bSELL_1 = true;

double dHeikenAshi_M1   = 0; 
double dHeikenAshi_M5   = 0;
double dHeikenAshi_M15  = 0;  
double dHeikenAshi_M30  = 0;

double dFreeMargin = 0;
double dTickValue = 0;
double dSpread = 0;
double dRiskValue = 0.03;
double dRiskInPips = 40;
double dLot = 0;
double dLots = 0;

int start()
   {
   int i = 0;
   
   bTP = false;
   bTS = false;
   bFTS = false;
   
   dFreeMargin = AccountFreeMargin();
   dTickValue = (MarketInfo(Symbol(), MODE_TICKVALUE) * 0.1);
   dSpread = MarketInfo(Symbol(), MODE_SPREAD);

   dLot = ((dFreeMargin * dRiskValue) * dTickValue) / (dRiskInPips + dSpread);
   dLots = (dLot - (dLot * 0.3)) / 3;   
   
   dHeikenAshi_M1   = fnCheckHAS(PERIOD_M1); 
   dHeikenAshi_M5   = fnCheckHAS(PERIOD_M5);
   dHeikenAshi_M15  = fnCheckHAS(PERIOD_M15);
   dHeikenAshi_M30  = fnCheckHAS(PERIOD_M30);
   
   if ((dHeikenAshi_M5 == 10) && (dHeikenAshi_M15 == 10) && (dHeikenAshi_M30 == 10))
      {
      bBUY = true;
      bSELL = false;
      }
   if ((dHeikenAshi_M5 == 20) && (dHeikenAshi_M15 == 20) && (dHeikenAshi_M30 == 20))
      {
      bSELL = true;
      bBUY = false;
      }
   
   while(OrderSelect(i,SELECT_BY_POS))
      {
      switch(OrderMagicNumber())
         {
         case 10001:
            {
            bTP = true;
            break;
            }
         case 10002:
            {
            bTP = true;
            break;
            }
         case 20001:
            {
            bTS = true;
            if ((OrderOpenPrice() + 2*dRiskInPips*Point) <= Bid)
               if ((OrderStopLoss() + 2*dRiskInPips*Point) <= Bid)
                  OrderModify(OrderTicket(),OrderOpenPrice(),OrderStopLoss()+10*Point,0,0,CLR_NONE);
            break;
            }
         case 20002:
            {
            bTS = true;
            if ((OrderOpenPrice() - 2*dRiskInPips*Point) >= Ask)
               if ((OrderStopLoss() - 2*dRiskInPips*Point) >= Ask)
                  OrderModify(OrderTicket(),OrderOpenPrice(),OrderStopLoss()-(10*Point),0,0,CLR_NONE);
            break;
            }
         case 30001:
            {
            bFTS = true;
            if ((OrderOpenPrice() + 2*dRiskInPips*Point) <= Bid)
               OrderModify(OrderTicket(),OrderOpenPrice(),OrderStopLoss()+10*Point,0,0,CLR_NONE);
            break;
            }
         case 30002:
            {
            bFTS = true;
            if ((OrderOpenPrice() - 2*dRiskInPips*Point) >= Ask)
               OrderModify(OrderTicket(),OrderOpenPrice(),OrderStopLoss()-10*Point,0,0,CLR_NONE);            
            break;
            }
         }
      i++;
      }
               
      if ((bBUY) && (dHeikenAshi_M1 == 10))
         {
         if (!bTP)
            if (OrderSend(Symbol(), OP_BUY, NormalizeDouble(dLots, 2), Ask, 3, Ask-dRiskInPips*Point, Ask+2*dRiskInPips*Point, "TP mode", 10001, 0, CLR_NONE) > 0)
               bTP = true;
         if (!bTS)
            if (OrderSend(Symbol(), OP_BUY, NormalizeDouble(dLots, 2), Ask, 3, Ask-dRiskInPips*Point, 0, "TS mode", 20001, 0, CLR_NONE) > 0)
               bTS = true;
         if (!bFTS)
            if (OrderSend(Symbol(), OP_BUY, NormalizeDouble(dLots, 2), Ask, 3, Ask-dRiskInPips*Point, 0, "FTS mode", 30001, 0, CLR_NONE) > 0)
               bFTS= true;
         }
      if ((bSELL) && (dHeikenAshi_M1 == 20))
         {
         if (!bTP)
            if (OrderSend(Symbol(), OP_SELL, NormalizeDouble(dLots, 2), Bid, 3, Bid+dRiskInPips*Point, Bid-2*dRiskInPips*Point, "TP mode", 10002, 0, CLR_NONE) > 0)
               bTP = true;
         if (!bTS)
            if (OrderSend(Symbol(), OP_SELL, NormalizeDouble(dLots, 2), Bid, 3, Bid+dRiskInPips*Point, 0, "TS mode", 20002, 0, CLR_NONE) > 0)
               bTS = true;
         if (!bFTS)
            if (OrderSend(Symbol(), OP_SELL, NormalizeDouble(dLots, 2), Bid, 3, Bid+dRiskInPips*Point, 0, "FTS mode", 30002, 0, CLR_NONE) > 0)
               bFTS = true;
         }  
   
   return(0);
   }

// ------------------------ *** Function Heiken Ashi *** ------------------------   
double fnCheckHAS(int iTimeframe)
   {
   if (iCustom(Symbol(),iTimeframe,"Heiken Ashi",2,0) < iCustom(Symbol(),iTimeframe,"Heiken Ashi",3,0) &&
       iCustom(Symbol(),iTimeframe,"Heiken Ashi",1,0) > iCustom(Symbol(),iTimeframe,"Heiken Ashi",0,0))
         return(10);
   if (iCustom(Symbol(),iTimeframe,"Heiken Ashi",2,0) > iCustom(Symbol(),iTimeframe,"Heiken Ashi",3,0) &&
       iCustom(Symbol(),iTimeframe,"Heiken Ashi",1,0) < iCustom(Symbol(),iTimeframe,"Heiken Ashi",0,0))
         return(20);
   return(0);
   }


Wszystkie algorytmy oparte są na jednym wskaźniku i podobnej logice. Powinny działać około miesiąca co pozwoli określić w jakich godzinach mogą grać aby tracić jak najmniej. Rezultaty i porównanie przez magic numbers jak zwykle na MyFxBook.