Stairs_Pack_v2





//+------------------------------------------------------------------+
//|                                                      Stairs.mq4 |
//|                                       Copyright © 2008, Tinytjan |
//|                                                 tinytjan@mail.ru |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2008, Tinytjan"
#property link      "tinytjan@mail.ru"

// magic number needed for filtering orders opened by certain EA
extern int        Magic             =  12345;

extern string     TradeLots_        =  "lots size of opening orders. If 0 it is counted automatically";
extern double     TradeLots         =  0;

extern string     RiskPercentage_   =  "risk for automatic lots size counting";
extern double     RiskPercentage    =  0;

extern string     Slippage_         =  "maximum acceptable slippage for the price";
extern int        Slippage          =  30;

extern string     TimesToRepeat_    =  "maximum loop count for orders opening if failed due to requoting";
extern int        TimesToRepeat     =  3;

extern string     Channel_          =  "Channel size in points";
extern int        Channel           =  50;

extern string     Profit_           =  "Profit in points for all orders of the instrument enough to close";
extern int        Profit            =  290;
extern string     CommonProfit_     =  "Profit in points for all orders of all instruments enough to close";
extern int        CommonProfit      =  700;

extern string     AddLots_          =  "Use lots increasing";
extern int        AddLots           =  1;
extern string     MaxIncrease_      =  "Max increase size = starting lot* MaxIncrease";
extern int        MaxIncrease       =  4;

extern string     StartSleep_       =  "Starting sleeping hour";
extern int        StartSleep        =  18;
extern string     EndSleep_         =  "Last sleeping hour";
extern int        EndSleep          =  6;
extern string     UseSleep_         =  "Use sleeping during sleep hours(no new cycles starting)";
extern int        UseSleep          =  0;

extern string     CPUEconomy_       =  "For trade -- if true Plase the EA to M1 chart. It will process 1 time a minute";
extern int        CPUEconomy        =  0;

string symbol;
double Lots;
datetime LastTime;

string CloseAll = "StairsCloseAll";
string StartLots = "StartLots";

/// \brief Equal to ternar operator 
/// needed = Condition ? IfTrue : IfFalse;
/// \param IfTrue
/// \param IfFalse
/// \return matching value from parameters
double DoubleIf(bool Condition, double IfTrue, double IfFalse)
{
   if (Condition) return (IfTrue);
   else           return (IfFalse);
}

void WaitForContext()
{
   while (IsTradeContextBusy())
   {
      Sleep(100);
   }
}

void OpenBuyStop(int MN, double Price, int Target, int Loss, double Lot)
{
   double TP = DoubleIf(Target > 0, Price + Target*Point, 0);
   double SL = DoubleIf(Loss > 0, Price - Loss*Point, 0);
   
   double LotsToBid = DoubleIf(Lot == 0, GetLotsToBid(RiskPercentage), Lot);
   
   WaitForContext();
   
   OrderSend(Symbol(), OP_BUYSTOP, LotsToBid, Price, Slippage, SL, TP, NULL, MN, 0, Blue);
}

void OpenSellStop(int MN, double Price, int Target, int Loss, double Lot)
{
   Price = Price + Bid - Ask;
   
   double TP = DoubleIf(Target > 0, Price - Target*Point, 0);
   double SL = DoubleIf(Loss > 0, Price + Loss*Point, 0);
   
   double LotsToBid = DoubleIf(Lot == 0, GetLotsToBid(RiskPercentage), Lot);
   
   WaitForContext();
   
   OrderSend(Symbol(), OP_SELLSTOP, LotsToBid, Price, Slippage, SL, TP, NULL, MN, 0, Red);
}

void CloseSells(int MagicNumber, int Slippage)
{
   for(int i = OrdersTotal() - 1; i >= 0; i--)
   {
      // already closed
      if(OrderSelect(i, SELECT_BY_POS) == false) continue;
      // not current symbol
      if(OrderSymbol() != Symbol()) continue;
      // order was opened in another way
      if(OrderMagicNumber() != MagicNumber) continue;
      
      if(OrderType() == OP_SELL)
      {
         int count = 0;
         while (count < TimesToRepeat)
         {
            WaitForContext();
            
            RefreshRates();
            if (OrderClose(OrderTicket(), OrderLots(), Ask, Slippage, Red))
            {
               break;
            }
            count++;
         }
      }
   }
}

void CloseBuys(int MagicNumber, int Slippage)
{
   for(int i = OrdersTotal(); i >= 0; i--)
   {
      // already closed
      if(OrderSelect(i, SELECT_BY_POS) == false) continue;
      // not current symbol
      if(OrderSymbol() != Symbol()) continue;
      // order was opened in another way
      if(OrderMagicNumber() != MagicNumber) continue;
      
      if(OrderType() == OP_BUY)
      {
         int count = 0;
         while (count < TimesToRepeat)
         {
            WaitForContext();
            
            RefreshRates();
            if (OrderClose(OrderTicket(), OrderLots(), Bid, Slippage, Blue))
            {
               break;
            }
            count++;
         }
      }
   }
}

void DeletePending(int MagicNumber = -1)
{
   for(int i = OrdersTotal() - 1; i >= 0; i--)
   {
      // already closed
      if(OrderSelect(i, SELECT_BY_POS) == false) continue;
      // not current symbol
      if(OrderSymbol() != Symbol()) continue;
      // order was opened in another way
      if(OrderMagicNumber() != MagicNumber && MagicNumber != -1) continue;
      
      if(OrderType() != OP_SELL && OrderType() != OP_BUY)
      {
         WaitForContext();
         
         OrderDelete(OrderTicket());
      }
   }
}

bool GetActiveOrders(int MagicNumber = -1)
{
   for(int i = 0; i < OrdersTotal(); i++)
   {
      // already closed
      if(OrderSelect(i, SELECT_BY_POS) == false) continue;
      // not current symbol
      if(OrderSymbol() != Symbol()) continue;
      // order was opened in another way
      if(OrderMagicNumber() != MagicNumber && MagicNumber != -1) continue;
      
      if(OrderType() == OP_SELL || OrderType() == OP_BUY)
      {
         return (true);
      }
   }
   
   return (false);
}

int GetOrdersCount(int MagicNumber = -1, int Type = -1, string symb = "")
{
   int count = 0;
   
   for(int i = 0; i < OrdersTotal(); i++)
   {
      // already closed
      if(OrderSelect(i, SELECT_BY_POS) == false) continue;
      // not current symbol
      if(OrderSymbol() != Symbol() && symb == "") continue;
      // not specified symbol
      if(OrderSymbol() != symb && symb != "" && symb != "all") continue;
      // order was opened in another way
      if(OrderMagicNumber() != MagicNumber && MagicNumber != -1) continue;
      
      if(OrderType() == Type || Type == -1)
      {
         count++;
      }
   }
   
   return (count);
}

double GetLotsToBid(double RiskPercentage)
{
   double margin  = MarketInfo(Symbol(), MODE_MARGINREQUIRED);
   double minLot  = MarketInfo(Symbol(), MODE_MINLOT);
   double maxLot  = MarketInfo(Symbol(), MODE_MAXLOT);
   double step    = MarketInfo(Symbol(), MODE_LOTSTEP);
   double account = AccountFreeMargin();
   
   double percentage = account*RiskPercentage/100;
   
   double lots = MathRound(percentage/margin/step)*step;
   
   if(lots < minLot)
   {
      lots = minLot;
   }
   
   if(lots > maxLot)
   {
      lots = maxLot;
   }

   return (lots);
}

bool IsSleepTime()
{
   if (UseSleep == 0) return (false);
   
   int hour = TimeHour(TimeCurrent());
   return (hour > StartSleep || hour < EndSleep);
}

bool IsStart()
{
   double buyStopPrice = 0;
   double sellStopPrice = 0;

   for(int i = 0; i < OrdersTotal(); i++)
   {
      // already closed
      if(OrderSelect(i, SELECT_BY_POS) == false) continue;
      // not current symbol
      if(OrderSymbol() != Symbol()) continue;
      // order was opened in another way
      if(OrderMagicNumber() != Magic) continue;
      
      if(OrderType() == OP_SELLSTOP)
      {
         sellStopPrice = OrderOpenPrice();
      }

      if(OrderType() == OP_BUYSTOP)
      {
         buyStopPrice = OrderOpenPrice();
      }
   }
   
   if (buyStopPrice == 0 || sellStopPrice == 0)
   {
      return (false);
   }
   
   double distance = (buyStopPrice - sellStopPrice)/Point;
   return (distance < 1.5*Channel && distance > 0.5*Channel);
}

int GetLastOpenedTicket(int MN)
{
   datetime lastTime = 0;
   int lastTicket = -1;
   
   for(int i = 0; i < OrdersTotal(); i++)
   {
      // already closed
      if(OrderSelect(i, SELECT_BY_POS) == false) continue;
      // not current symbol
      if(OrderSymbol() != Symbol()) continue;
      // order was opened in another way
      if(OrderMagicNumber() != MN) continue;
      
      if (OrderOpenTime() > lastTime)
      {
         lastTime = OrderOpenTime();
         lastTicket = OrderTicket();
      }
   }
   
   return (lastTicket);
}

double GetLastLot(int MN)
{
   int ticket = GetLastOpenedTicket(MN);
   if (OrderSelect(ticket, SELECT_BY_TICKET))
   {
      return (OrderLots());
   }
   
   double lots = TradeLots;
   if (TradeLots == 0)
   {
      lots = GetLotsToBid(RiskPercentage);
   }
   
   return (lots);
}

double GetLastPrice(int MN)
{
   int ticket = GetLastOpenedTicket(MN);
   if (OrderSelect(ticket, SELECT_BY_TICKET))
   {
      return (OrderOpenPrice());
   }
   
   return(0);
}

void Check()
{
   string name = Symbol() + StartLots;

   if (!GlobalVariableCheck(CloseAll))
   {
      GlobalVariableSet(CloseAll, EMPTY_VALUE);
   }
   else
   {
      double value = GlobalVariableGet(CloseAll);
      
      if (value == 1)
      {
         if (GetOrdersCount(Magic) > 0)
         {
            CloseSells(Magic, Slippage);
            CloseBuys(Magic, Slippage);
            DeletePending(Magic);
         }
         RefreshRates();
         
         if (GetOrdersCount(Magic, -1, "all") == 0)
         {
            GlobalVariableSet(CloseAll, EMPTY_VALUE);
         }
         else
         {
            return;
         }
      }
   }
   
   int SL = Channel + MathRound((Ask - Bid)/Point);
   
   if (GetOrdersCount(Magic) == 0)
   {
      if (IsSleepTime()) return(0);
      
      double lot = DoubleIf(TradeLots == 0, GetLotsToBid(RiskPercentage), TradeLots);
      
      GlobalVariableSet(name, lot);
      
      int distanse = Channel/2;
      
      OpenBuyStop(Magic, Ask + distanse*Point, 0, SL, lot);
      OpenSellStop(Magic, Ask - distanse*Point, 0, SL, lot);
   }
   
   if (!GetActiveOrders(Magic))
   {
      if (GetOrdersCount(Magic) > 0)
      {
         if (!IsStart())
         {
            // îñòàëèñü îòëîæêè
            // ýòî ñîñòîÿíèå êîíå÷íîå
            // óäàëÿåì 
            DeletePending(Magic);
         }
      }
      return;
   }
   
   if (GetOrdersCount(Magic, OP_BUYSTOP) +  GetOrdersCount(Magic, OP_SELLSTOP) < 2 && GetActiveOrders(Magic))
   {
      // îòëîæêà ñðàáîòàëà, íàäî âûñòàâèòü çàíîâî
      // èëè ïîñòíà÷àëüíîå ñîñòîÿíèå, íàäî ðàññòàâèòü ñåòü.
      
      DeletePending(Magic);

      double lastOpenPrice = GetLastPrice(Magic);
      double lastOpenLots = GetLastLot(Magic);
      double addLot = GlobalVariableGet(name);

      if (AddLots == 1)
      {
         lastOpenLots += addLot;
         
         if (lastOpenLots > addLot*MaxIncrease)
         {
            lastOpenLots = addLot*MaxIncrease;
         }
      }
         
      OpenBuyStop(Magic, lastOpenPrice + Channel*Point, 0, SL, lastOpenLots);
      OpenSellStop(Magic, lastOpenPrice - Channel*Point, 0, SL, lastOpenLots);
   }
   
   double profit = 0;
   
   for(int i = 0; i < OrdersTotal(); i++)
   {
      // already closed
      if (OrderSelect(i, SELECT_BY_POS) == false) continue;
      // not current symbol
      if (OrderSymbol() != symbol) continue;
      // order was opened in another way
      if (OrderMagicNumber() != Magic) continue;
      
      int type = OrderType();
      
      if (type != OP_SELL && type != OP_BUY) continue;
      
      double add = DoubleIf(type == OP_BUY, Bid - OrderOpenPrice(), OrderOpenPrice() - Ask);
      
      profit += add/Point;
   }

   if (profit > Profit)
   {
      CloseSells(Magic, Slippage);
      CloseBuys(Magic, Slippage);
   }

   profit = 0;
   
   for(i = 0; i < OrdersTotal(); i++)
   {
      // already closed
      if (OrderSelect(i, SELECT_BY_POS) == false) continue;
      // order was opened in another way
      if (OrderMagicNumber() != Magic) continue;
      
      type = OrderType();
      
      if (type != OP_SELL && type != OP_BUY) continue;
      
      add = OrderOpenPrice() - MarketInfo(OrderSymbol(), MODE_ASK);
      if (type == OP_BUY) add = MarketInfo(OrderSymbol(), MODE_BID) - OrderOpenPrice();
      
      profit += add/MarketInfo(OrderSymbol(), MODE_POINT);
   }

   if (profit > CommonProfit)
   {
      GlobalVariableSet(CloseAll, 1);
   }
}

int init()
{
   Lots = TradeLots;
   symbol = Symbol();
   LastTime = Time[0];
}

int start()
{
   if (CPUEconomy == 1 && LastTime == Time[0]) return(0);
   
   LastTime = Time[0];
   
   if (!IsTradeAllowed()) return(0);
   
   Check();

   return(0);
}



Sample





Analysis



Market Information Used:

Series array that contains open time of each bar


Indicator Curves created:


Indicators Used:



Custom Indicators Used:

Order Management characteristics:
It automatically opens orders when conditions are reached
Checks for the total of open orders

It Closes Orders by itself

Other Features:

BackTest : EURUSD on H1

From 2009-08-01 to 2009-10-01 Profit Factor:0.00 Total Net Profit:0.00

BackTest : EURUSD on H1

From 2009-12-01 to 2010-01-17 Profit Factor:1.80 Total Net Profit:2875.73

BackTest : EURUSD on H1

From 2010-03-01 to 2010-03-27 Profit Factor:1.35 Total Net Profit:937.56

BackTest : EURUSD on H1

From 2010-04-01 to 2010-04-30 Profit Factor:2.10 Total Net Profit:2240.53

BackTest : EURUSD on H1

From 2010-05-01 to 2010-05-31 Profit Factor:2.56 Total Net Profit:4190.34

BackTest : EURUSD on H1

From 2010-06-01 to 2010-06-30 Profit Factor:1.91 Total Net Profit:2423.11

BackTest : GBPUSD on H1

From 2010-01-01 to 2010-02-27 Profit Factor:0.00 Total Net Profit:0.00

BackTest : GBPUSD on H1

From 2010-01-01 to 2010-04-16 Profit Factor:0.00 Total Net Profit:0.00

BackTest : USDCAD on H1

From 2009-01-01 to 2010-01-01 Profit Factor:0.00 Total Net Profit:0.00

BackTest : USDCAD on H1

From 2009-12-01 to 2010-01-01 Profit Factor:0.00 Total Net Profit:0.00

BackTest : USDCHF on H1

From 2009-12-01 to 2010-01-01 Profit Factor:0.00 Total Net Profit:0.00

BackTest : USDJPY on H1

From 2009-11-01 to 2009-11-30 Profit Factor:0.00 Total Net Profit:0.00

Request Backtest for Stairs_Pack_v2


From : (yyyy/mm/dd) To: (yyyy/mm/dd)

Pair: Period: