StepBack0.9.0

Orders Execution
Checks for the total of open ordersIt Closes Orders by itself It automatically opens orders when conditions are reached
Miscellaneous
It issuies visual alerts to the screen
0 Views
0 Downloads
0 Favorites
StepBack0.9.0
ÿþ#property version "0.9.0"

#property strict



enum ENUM_TRADE_DIRECTION

  {

   TRADE_DIRECTION_UNDEFINED,

   TRADE_DIRECTION_UP,

   TRADE_DIRECTION_DOWN

  };



const string NOTIF_LABEL     = "",                      // 5B:0 4;O A>>1I5=89 2 6C@=0;

             OBJECTS_LABEL   = "StepBack ",             // 5B:0 4;O >1J5:B>2

// <5=0 :=>?>:

             START_BUTT_NAME = OBJECTS_LABEL + "Start";

//-------

input int    inpGridStep                  = 300;  // Grid step

input double inpFirstLot                  = 0.01; // First lot

input double inpTrendLotMultiplier        = 2;    // Trend lot multiplier

input double inpCountertrendLotMultiplier = 3;    // Countertrend lot multiplier

input double stepsbackclose               = 1;    // Steps back close 

input int    inpMagic                     = 1;    // Magic



// 0AB@>9:8

double               gridStepInP;

// =D>@<0F8O >1 >@45@0E

bool                 isOrdersInfoActual;

ENUM_TRADE_DIRECTION tradeDirection;

double               lastStepAveragePrice;

int                  purchNumber,

                     salesNumber,

                     stepsNumber;



int OnInit()

  {

   createButtons();

   

   gridStepInP = NormalizeDouble(inpGridStep * _Point, _Digits);

   

   return(INIT_SUCCEEDED);

  }



void OnDeinit(const int reason)

  {

   deleteObjectsByLabel(OBJECTS_LABEL, __LINE__);

  }



void OnChartEvent(const int id, const long& lparam, const double& dparam, const string& sparam)

  {

   isOrdersInfoActual = false;

   

   if(sparam == START_BUTT_NAME)

      onStartButtonClick();

  }



void OnTick()

  {

   isOrdersInfoActual = false;

   

   if(IsTesting())

      onStartButtonClick();

   

   closingByRollback();

   addNewPair();

  }

//--------------------------

bool NewBar()

{

static datetime lastbar;

datetime curbar = Time[0];

if(lastbar!=curbar)

{

lastbar=curbar;

return (true);

}

else

{

return(false);

}

}

  



//-------------------------

void addNewPair()

  {

   updateOrdersInfo();

   

   if(stepsNumber < 1 || purchNumber != salesNumber)

      return;

   

   double trendVolume        = normalizeVolume(inpFirstLot * MathPow(inpTrendLotMultiplier, stepsNumber), __LINE__),

          countertrendVolume = normalizeVolume(inpFirstLot * MathPow(inpCountertrendLotMultiplier, stepsNumber), __LINE__);

   

   double currAveragePrice = NormalizeDouble((Ask + Bid) / 2, _Digits),

          purchVolume      = 0,

          saleVoleme       = 0;

   

   if(stepsNumber > 1)

     {

      if(tradeDirection == TRADE_DIRECTION_UP)

        {

         if(currAveragePrice - lastStepAveragePrice >= gridStepInP)

           {

            purchVolume = normalizeVolume(inpFirstLot * MathPow(inpTrendLotMultiplier, stepsNumber), __LINE__);

            saleVoleme  = normalizeVolume(inpFirstLot * MathPow(inpCountertrendLotMultiplier, stepsNumber), __LINE__);

           }

        }

      

      else if(lastStepAveragePrice - currAveragePrice >= gridStepInP)

        {

         purchVolume = normalizeVolume(inpFirstLot * MathPow(inpCountertrendLotMultiplier, stepsNumber), __LINE__);

         saleVoleme  = normalizeVolume(inpFirstLot * MathPow(inpTrendLotMultiplier, stepsNumber), __LINE__);

        }

     }

   

   else

     {

      if(currAveragePrice - lastStepAveragePrice >= gridStepInP)

        {

         purchVolume = normalizeVolume(inpFirstLot * MathPow(inpTrendLotMultiplier, stepsNumber), __LINE__);

         saleVoleme  = normalizeVolume(inpFirstLot * MathPow(inpCountertrendLotMultiplier, stepsNumber), __LINE__);

        }

      

      else if(lastStepAveragePrice - currAveragePrice >= gridStepInP)

        {

         purchVolume = normalizeVolume(inpFirstLot * MathPow(inpCountertrendLotMultiplier, stepsNumber), __LINE__);

         saleVoleme  = normalizeVolume(inpFirstLot * MathPow(inpTrendLotMultiplier, stepsNumber), __LINE__);

        }

     }

   

   if(purchVolume == 0 || saleVoleme == 0)

      return;

   

   isOrdersInfoActual = false;

   

   if(openMarketOrder(0, purchVolume, INT_MAX, 0, 0, inpMagic, __LINE__, true))

      openMarketOrder(1, saleVoleme, INT_MAX, 0, 0, inpMagic, __LINE__, true);

  }



void closingByRollback()

  {

   updateOrdersInfo();

   

   if(purchNumber != salesNumber)

      return;

   

   if(stepsNumber < 2 || tradeDirection == TRADE_DIRECTION_UNDEFINED)

      return;

   

   double currAveragePrice = NormalizeDouble((Ask + Bid) / 2, _Digits),

          currRollback     = tradeDirection == TRADE_DIRECTION_UP ? lastStepAveragePrice - currAveragePrice : currAveragePrice - lastStepAveragePrice;



  if(currRollback < gridStepInP * stepsbackclose)

      return;



         

   isOrdersInfoActual = false;

   

   closeOrdersByMagic(inpMagic, __LINE__);

  }



void onStartButtonClick()

  {

   if(ObjectGetInteger(0, START_BUTT_NAME, OBJPROP_STATE) == false)

     {

      if(!IsTesting()) // ! OnTick() ?@8 B5AB8@>20=88 MB0 DC=:F8O 2K7K205BAO A :064K< B8:>< 8 ?@>25@O5BAO A>AB>O=85 :=>?:8.

         PrintFormat("%sH81:0 :=>?:8 \"%s\". !B@>:0 %i.", NOTIF_LABEL, START_BUTT_NAME, __LINE__);

      

      return;

     }

   

   updateOrdersInfo();

   

   if(purchNumber + salesNumber != 0)

     {

      ObjectSetInteger(0, START_BUTT_NAME, OBJPROP_STATE, false);

      

      return;

     }

   

   double volume = normalizeVolume(inpFirstLot, __LINE__);

   

   isOrdersInfoActual = false;

   

   ObjectSetInteger(0, START_BUTT_NAME, OBJPROP_STATE, false);

   

   if(openMarketOrder(0, volume, INT_MAX, 0, 0, inpMagic, __LINE__, true))

      openMarketOrder(1, volume, INT_MAX, 0, 0, inpMagic, __LINE__, true);

  }



void updateOrdersInfo()

  {

   if(isOrdersInfoActual)

      return;

   

   // @5<O >B:@KB8O 8 F5=0 >B:@KB8O >@45@>2 H030 0

   datetime firstPurchOpTime  = INT_MAX,

            firstSaleOpTime   = INT_MAX;

   double   firstPurchOpPrice = 0,

            firstSaleOpPrice  = 0;

   // @5<O >B:@KB8O 8 F5=0 >B:@KB8O >@45@>2 ?>A;54=53> H030

   datetime lastPurchOpTime   = 0,

            lastSaleOpTime    = 0;

   double   lastPurchOpPrice  = 0,

            lastSaleOpPrice   = 0;

   //-------

   

   tradeDirection = TRADE_DIRECTION_UNDEFINED;

   purchNumber    = 0;

   salesNumber    = 0;

   

   for(int i = OrdersTotal() - 1; i >= 0; i--)

     if(OrderSelect(i, SELECT_BY_POS) && OrderMagicNumber() == inpMagic && OrderSymbol() == Symbol() && OrderType() < 2)

       {

        if(OrderType() == 0)

          {

           purchNumber++;

           

           // @5<O >B:@KB8O 8 F5=0 >B:@KB8O ?>:C?:8 H030 0

           if(OrderOpenTime() < firstPurchOpTime)

             {

              firstPurchOpTime  = OrderOpenTime();

              firstPurchOpPrice = OrderOpenPrice();

             }

           

           // @5<O >B:@KB8O 8 F5=0 >B:@KB8O ?>:C?:8 ?>A;54=53> H030

           if(OrderOpenTime() > lastPurchOpTime)

             {

              lastPurchOpTime  = OrderOpenTime();

              lastPurchOpPrice = OrderOpenPrice();

             }

          }

        

        else if(OrderType() == 1)

          {

           salesNumber++;

           

           // @5<O >B:@KB8O 8 F5=0 >B:@KB8O ?@>4068 H030 0

           if(OrderOpenTime() < firstSaleOpTime)

             {

              firstSaleOpTime  = OrderOpenTime();

              firstSaleOpPrice = OrderOpenPrice();

             }

           

           // @5<O >B:@KB8O 8 F5=0 >B:@KB8O ?@>4068 ?>A;54=53> H030

           if(OrderOpenTime() > lastSaleOpTime)

             {

              lastSaleOpTime  = OrderOpenTime();

              lastSaleOpPrice = OrderOpenPrice();

             }

          }

        

        else continue;

       }

   

   isOrdersInfoActual = true;

   

   stepsNumber = MathMax(purchNumber, salesNumber);

   

   if(stepsNumber > 0)

      lastStepAveragePrice = NormalizeDouble((lastPurchOpPrice + lastSaleOpPrice) / 2, _Digits);

   

   if(stepsNumber > 1)

     {

      double step0AveragePrice = NormalizeDouble((firstPurchOpPrice + firstSaleOpPrice) / 2, _Digits);

      

      tradeDirection = lastStepAveragePrice > step0AveragePrice ? TRADE_DIRECTION_UP : TRADE_DIRECTION_DOWN;

     }

  }



void createButtons()

  {

   const int BUTTONS_HEIGTH       = 24,

             BUTTONS_WIDTH        = 80,

             BUTTONS_INDENT       = 10,

             BUTTONS_FONT_SIZE    = 10;

   int       right_buttons_x_Dist = BUTTONS_WIDTH + BUTTONS_INDENT,

             left_buttons_x_Dist  = right_buttons_x_Dist * 2,

             yDist                = BUTTONS_HEIGTH + BUTTONS_INDENT;

   

   buttonCreate(START_BUTT_NAME, "Start", BUTTONS_WIDTH, BUTTONS_HEIGTH, BUTTONS_FONT_SIZE, CORNER_RIGHT_LOWER, clrBlack, clrSilver,

   clrSilver, right_buttons_x_Dist, yDist);

  }



bool buttonCreate(string name, string text, int width, int height, int fontSize, ENUM_BASE_CORNER corner,

                  color fontColor, color bgColor, color borderColor, int x_dist, int y_dist)

  {

   if(!objectCreate(name, OBJ_BUTTON, 0, 0))

     return(false);

   

   // #3>; 30@D8:0, >B=>A8B5;L=> :>B>@>3> 1C4CB >?@545;OBLAO :>>@48=0BK

   ObjectSetInteger(0, name, OBJPROP_CORNER, corner);

   // >>@48=0BK :=>?:8

   ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x_dist);

   ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y_dist);

   //  07<5@ :=>?:8

   ObjectSetInteger(0, name, OBJPROP_XSIZE, width); 

   ObjectSetInteger(0, name, OBJPROP_YSIZE, height);

   // "5:AB :=>?:8

   ObjectSetString(0, name, OBJPROP_TEXT, text);

   //  07<5@ H@8DB0

   ObjectSetInteger(0, name, OBJPROP_FONTSIZE, fontSize);

   // &25B B5:AB0

   ObjectSetInteger(0, name, OBJPROP_COLOR, fontColor);

   // &25B D>=0

   ObjectSetInteger(0, name, OBJPROP_BGCOLOR, bgColor);

   // &25B 3@0=8FK

   ObjectSetInteger(0, name, OBJPROP_BORDER_COLOR, borderColor);

   // !>AB>O=85 :=>?:8

   ObjectSetInteger(0, name, OBJPROP_STATE, false);

   // B:;NG8< @568< ?5@5<5I5=85 :=>?:8 <KHLN

   ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false); 

   ObjectSetInteger(0, name, OBJPROP_SELECTED, false); 

   // !:@>5< A> A?8A:0 >1J5:B>2

   ObjectSetInteger(0, name, OBJPROP_HIDDEN, true); 

   

   return(true);

  }



bool objectCreate(string name, ENUM_OBJECT type, datetime time1, double price1, datetime time2 = 0, double price2 = 0, datetime time3 = 0,

                  double price3 = 0, int subWindow = 0)

  {

   ResetLastError();

   

   if(ObjectCreate(name, type, subWindow, time1, price1, time2, price2, time3, price3))

      return(true);

   

   PrintFormat("%s5 C40;>AL A>740BL >1J5:B \"%s\". H81:0 %i", NOTIF_LABEL, name, GetLastError());

   

   return(true);

  }



void deleteObjectsByLabel(string label, int line)

  {

   string name;

   

   for(int i = ObjectsTotal() - 1; i >= 0; i--)

     {

      name = ObjectName(i);

      

      if(StringFind(name, label) != -1)

         objectDelete(name, line);

     }

  }



bool objectDelete(string name, int line)

  {

   ResetLastError();

   

   if(ObjectDelete(name))

      return(true);

   

   PrintFormat("%s5 C40;>AL C40;8BL >1J5:B \"%s\". H81:0 %i, AB@>:0 %i", NOTIF_LABEL, name, GetLastError(), line);

   

   return(false);

  }



double normalizeVolume(double volume, int line)

  {

   double volumeStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP),

          minVolume  = MarketInfo(Symbol(), MODE_MINLOT),

          maxVolume  = MarketInfo(Symbol(), MODE_MAXLOT);

   

   volume = MathRound(volume / volumeStep) * volumeStep;

   

   if(volume < minVolume)

     {

      PrintFormat("%s 0AAG8B0==K9 ;>B %.3f <5=LH5 <8=8<0;L=>3>. C45B 8A?>;L7>20= <8=8<0;L=K9 ;>B (%.2f). !B@>:0 %i", NOTIF_LABEL, volume,

      minVolume, line);

      

      return(minVolume);

     }

   

   if(volume > maxVolume)

     {

      PrintFormat("%s 0AAG8B0==K9 ;>B %.3f 1>;LH5 <0:A8<0;L=>3>. C45B 8A?>;L7>20= <0:A8<0;L=K9 ;>B (%.2f). !B@>:0 %i", NOTIF_LABEL, volume,

      maxVolume, line);

      

      return(maxVolume);

     }

   

   return(volume);

  }



bool closeOrdersByMagic(int magic, int line)

  {

   bool result = true;

   

   for(int i = OrdersTotal() - 1; i >= 0; i--)

     if(OrderSelect(i, SELECT_BY_POS) && OrderMagicNumber() == magic && OrderSymbol() == Symbol() && OrderType() < 2

     && !closeOrder(OrderTicket(), line))

        result = false;

   

   return(result);

  }



bool closeOrder(int ticket, int line, double volume = -1, int maxAttemptsNumber = 3)

  {

   double clsPrice;

   int    attemptsNumber = 0;

   

   while(true)

     {

      attemptsNumber++;

      

      if(attemptsNumber > maxAttemptsNumber)

        {

         Print(NOTIF_LABEL, "5 C40;>AL 70:@KBL >@45@ A ", maxAttemptsNumber, " ?>?KB>:, AB@>:0 ", line);

         

         return(false);

        }

      

      if(!OrderSelect(ticket, SELECT_BY_TICKET))

        {

         Print(NOTIF_LABEL, "@45@ #", ticket, " =5 =0945=. !B@>:0 ", line);

         

         continue;

        }

      

      if(volume == -1)

         volume = OrderLots();

      

      if(isTradeAllowed() < 0)

         return(false);

      

      RefreshRates();

            

      if(OrderType() == 0)

         clsPrice = NormalizeDouble(Bid, Digits);

            

      else clsPrice = NormalizeDouble(Ask, Digits);

            

      if(!OrderClose(OrderTicket(), volume, clsPrice, 99999))

         Print(NOTIF_LABEL, "@8 70:@KB88 >@45@0 ", OrderTicket(), " 2>7=8:;0 >H81:0 ", GetLastError(), ", AB@>:0 ", line);

         

      else break;

      

      Sleep(3000);

     }

   

   return(true);

  }



int openMarketOrder(int type, double lots, int slippage, double sl, double tp, int magic, int line, bool isFixLvlsCalculated, string comment = NULL,

                    int triesNumber = 3)

  {

   int tries = 0;

   

   if(!checkFreeMargin(type, lots, line))

      return(-1);

   

   while(true)

     {

      tries++;

      

      if(tries > triesNumber)

        {

         Print(NOTIF_LABEL, "5 C40;>AL >B:@KBL >@45@ A ", triesNumber, " ?>?KB>:, AB@>:0 ", line);

         

         return(-1);

        }

      

      if(isTradeAllowed() < 0)

         return(-1);

      

      RefreshRates();

      

      double price,

             takeProfit = 0,

             stopLoss   = 0;

      int    tpMultipl,

             slMultipl;

      

      if(type == 0)

        {

         price     = NormalizeDouble(Ask, Digits);

         tpMultipl = 1;

         slMultipl = -1;

        }

      

      else

        {

         price     = NormalizeDouble(Bid, Digits);

         tpMultipl = -1;

         slMultipl = 1;

        }

      

      if(tp != 0)

         takeProfit = NormalizeDouble(isFixLvlsCalculated ? tp : price + tp * tpMultipl * Point, _Digits);

      

      if(sl != 0)

         stopLoss = NormalizeDouble(isFixLvlsCalculated ? sl : price + sl * slMultipl * Point, _Digits);

      

      int ticket = OrderSend(Symbol(), type, lots, price, slippage, stopLoss, takeProfit, comment, magic);

      

      if(ticket != -1)

         return(ticket);

      

      else if(!errorFunc(GetLastError(), line))

         break;

     }

   

   return(-1);

  }



bool errorFunc(int error, int lineNumber)

  {

   switch(error)

     {

      case 135: Print(NOTIF_LABEL, "&5=0 87<5=8;0AL. @>1C5< 5IQ @07..");

         return(true);

         

      case 136: Print(NOTIF_LABEL, "5B F5=. 4Q< =>2K9 B8:..");

         while(RefreshRates()==false)

            Sleep(1);

         return(true);

         

      case 129: Print(NOTIF_LABEL, "5?@028;L=0O F5=0. @>1C5< 5IQ @07..");

         return(true);

         

      case  4: Print(NOTIF_LABEL, "">@3>2K9 A5@25@ 70=OB. @>1C5< 5IQ @07..");

         Sleep(3000);

         return(true);

         

      case 137: Print(NOTIF_LABEL, "@>:5@ 70=OB. @>1C5< 5IQ @07..");

         Sleep(3000);

         return(true);

         

      case 130: Print(NOTIF_LABEL, "5?@028;L=K5 AB>?K. @>1C5< 5IQ @07..");

         return(true);

      

      case 138: Print(NOTIF_LABEL, ">2K5 F5=K. @>1C5< 5IQ @07..");

         return(true);

      

      default: Print(NOTIF_LABEL, ">7=8:;0 >H81:0 ", error, ", AB@>:0 ", lineNumber);

         return(false);

     }

  }



int isTradeAllowed(uint MaxWaiting_sec = 10)

  {

    if(!IsTradeAllowed())

      {

        uint StartWaitingTime = GetTickCount();

        Print(NOTIF_LABEL, "">@3>2K9 ?>B>: 70=OB! 4Q<, ?>:0 >= >A2>1>48BLAO...");

        

        while(true)

          {

            if(IsStopped()) 

              {

                Print(NOTIF_LABEL, "-:A?5@B 1K; >AB0=>2;5= ?>;L7>20B5;5<!"); 

                return(-1); 

              }

            

            if(GetTickCount() - StartWaitingTime > MaxWaiting_sec * 1000)

              {

                Alert(StringConcatenate("@52KH5= ;8<8B >6840=8O (", MaxWaiting_sec, " A5:.)!"));

                return(-2);

              }

              

            if(IsTradeAllowed())

              {

                Print(NOTIF_LABEL, "">@3>2K9 ?>B>: >A2>1>48;AO!");

                return(0);

              }

              

            Sleep(100);

          }

      }

      

    return(1);

  }



bool checkFreeMargin(int cmd, double volume, int line)

  {

   if(AccountFreeMarginCheck(NULL, cmd, volume) > 0)

      return(true);

   

   PrintFormat("%s;O >B:@KB8O >@45@0 >1J5<>< %.3f =54>AB0B>G=> A@54AB2. !B@>:0 %i", NOTIF_LABEL, volume, line);

   

   return(false);

  }

Comments

Markdown supported. Formatting help

Markdown Formatting Guide

Element Markdown Syntax
Heading # H1
## H2
### H3
Bold **bold text**
Italic *italicized text*
Link [title](https://www.example.com)
Image ![alt text](image.jpg)
Code `code`
Code Block ```
code block
```
Quote > blockquote
Unordered List - Item 1
- Item 2
Ordered List 1. First item
2. Second item
Horizontal Rule ---