Superbot strategy [Si Splice M15 0]

Author: superbot.pro
Price Data Components
Series array that contains open time of each barSeries array that contains open prices of each barSeries array that contains the highest prices of each barSeries array that contains the lowest prices of each barSeries array that contains close prices for each bar
Indicators Used
Bollinger bands indicator
0 Views
0 Downloads
0 Favorites
Superbot strategy [Si Splice M15 0]
ÿþ//+------------------------------------------------------------------+

//|                                                         Strategy |

//|                                     Copyright 2022, superbot.pro |

//|                                         https://www.superbot.pro |

//+------------------------------------------------------------------+

#property copyright "superbot.pro"

#property version   "3.10"

#property strict

static input string propertiesOpen = "------------"; // PARAMETERS FOR OPEN POSITION:

static input double tradeLot = 1.000;// Lots

input  int          stopLoss   = 500; // Stop Loss (pips)

input  int          takeProfit = 0;// Take Profit (pips)

input  int          indPeriodOpen = 20; // Bollinger Bands period

input  double       indDeviationOpen = 2.00; // Bollinger Bands deviation

static input int    magicNumber = 0; // Magic number

#define TRADE_RETRY_COUNT 4

#define TRADE_RETRY_WAIT  100

#define OP_FLAT           -1

#define OP_BUY            ORDER_TYPE_BUY

#define OP_SELL           ORDER_TYPE_SELL

int sessionFridayOpen           = 36900;

int sessionFridayClose          = 84600;

bool ignoreSaturdaySunday;

bool sessionCloseAtSessionClose;

bool sessionCloseAtFridayClose;

bool longExit, shortExit, openBreakLong, openBreakShort;

bool filtersLong, filtersShort, indlong_1, indshort_1;

bool indlong_2, indshort_2, indlong_3, indshort_3;

bool openBreakPlusShort, openBreakPlusLong, enableLong, enableShort;

double posType       = OP_FLAT;

ulong  posTicket     = 0;

double posLots       = 0;

double posStopLoss   = 0;

double posTakeProfit = 0;

datetime barTime;

int      digits;

double   pip;

double   stopLevel, dnLevelOpen, upLevelOpen, crossData0Long, crossData0Short,crossData1Long,crossData1Short;

bool isTrailingStop = true;

ENUM_ORDER_TYPE_FILLING orderFillingType;

int BBHandlerOpen;

int OnInit() {

   barTime          = Time(0);

   digits           = (int) SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);

   pip              = GetPipValue(digits);

   stopLevel        = (int) SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL);

   orderFillingType = GetOrderFillingType();

   isTrailingStop   = isTrailingStop && stopLoss > 0;

   TesterHideIndicators(false);

   BBHandlerOpen = iBands(NULL, PERIOD_CURRENT, indPeriodOpen, 0, indDeviationOpen, PRICE_CLOSE);

   const ENUM_INIT_RETCODE initRetcode = ValidateInit();

   return (initRetcode);

}

//+------------------------------------------------------------------+

//|                                                                  |

//+------------------------------------------------------------------+

void OnTick() {

   datetime time = Time(0);

   if(time > barTime) {

      barTime = time;

      OnBar();

   }

}

//+------------------------------------------------------------------+

//|                                                                  |

//+------------------------------------------------------------------+

void OnBar() {

   UpdatePosition();

   if(posType != OP_FLAT) {

      ManageClose();

      UpdatePosition();

   }

   if(posType != OP_FLAT && isTrailingStop) {

      double trailingStop = GetTrailingStop();

      ManageTrailingStop(trailingStop);

      UpdatePosition();

   }

   if(IsOutOfSession()) return;

   if(posType == OP_FLAT) {

      ManageOpen();

      UpdatePosition();

   }

}

//+------------------------------------------------------------------+

//|                                                                  |

//+------------------------------------------------------------------+

void UpdatePosition() {

   posType   = OP_FLAT;

   posTicket = 0;

   posLots   = 0;

   int posTotal = PositionsTotal();

   for(int posIndex = 0; posIndex < posTotal; posIndex++) {

      const ulong ticket = PositionGetTicket(posIndex);

      if(PositionSelectByTicket(ticket) && PositionGetString(POSITION_SYMBOL) == _Symbol && PositionGetInteger(POSITION_MAGIC) == magicNumber)  {

         posType       = (int) PositionGetInteger(POSITION_TYPE);

         posLots       = NormalizeDouble(PositionGetDouble(POSITION_VOLUME), 2);

         posTicket     = ticket;

         posStopLoss   = NormalizeDouble(PositionGetDouble(POSITION_SL), digits);

         posTakeProfit = NormalizeDouble(PositionGetDouble(POSITION_TP), digits);

         break;

      }

   }

}

//+------------------------------------------------------------------+

//|                                                                  |

//+------------------------------------------------------------------+

void ManageOpen() {

   double BB_buffer0[];

   CopyBuffer(BBHandlerOpen, 1, 1, 2, BB_buffer0);

   double BB_buffer1[];

   CopyBuffer(BBHandlerOpen, 2, 1, 2, BB_buffer1);

   double BBOpenUpBand0 = BB_buffer0[1];

   double BBOpenDnBand0 = BB_buffer1[1];

   double BBOpenUpBand1 = BB_buffer0[0];

   double BBOpenDnBand1 = BB_buffer1[0];

   upLevelOpen = BBOpenUpBand0;

   dnLevelOpen = BBOpenDnBand0;

   crossData0Long = crossData0Short = Open(0);

   crossData1Long = crossData1Short = Open(1);

   openBreakPlusLong = openBreakPlusShort = true;

   openBreakLong = (crossData0Long > upLevelOpen) && (openBreakPlusLong);

   openBreakShort = (crossData0Short < dnLevelOpen) && (openBreakPlusShort);

   enableLong = enableShort = true;

   indlong_1 = indshort_1 = true;

   indlong_2 = indshort_2 = true;

   indlong_3 = indshort_3 = true;

   filtersLong = indlong_1 && indlong_2 && indlong_3;

   filtersShort = indshort_1 && indshort_2 && indshort_3;

   const bool canOpenLong  = openBreakLong;

   const bool canOpenShort = openBreakShort;

   if(canOpenLong && canOpenShort) return;

   if(canOpenLong && enableLong && filtersLong) OpenPosition(OP_BUY);

   else if(canOpenShort && enableShort && filtersShort) OpenPosition(OP_SELL);

}

//+------------------------------------------------------------------+

//|                                                                  |

//+------------------------------------------------------------------+

void ManageClose() {

   longExit = shortExit = false;

   if(posType == OP_BUY && longExit)

      ClosePosition();

   else if(posType == OP_SELL && shortExit)

      ClosePosition();

}

//+------------------------------------------------------------------+

//|                                                                  |

//+------------------------------------------------------------------+

void OpenPosition(int command) {

   const double stopLossFinale   = GetStopLossPrice(command);

   const double takeProfitFinale = GetTakeProfitPrice(command);

   ManageOrderSend(command,tradeLot,stopLossFinale,takeProfitFinale,0);

}

//+------------------------------------------------------------------+

//|                                                                  |

//+------------------------------------------------------------------+

void ClosePosition() {

   const int command = posType == OP_BUY ? OP_SELL : OP_BUY;

   ManageOrderSend(command,posLots,0,0,posTicket);

}

//+------------------------------------------------------------------+

//|                                                                  |

//+------------------------------------------------------------------+

void ManageOrderSend(int command,double lots,double stopLossFinale,double takeProfitFinale,ulong ticket) {

   for(int attempt = 0; attempt < TRADE_RETRY_COUNT; attempt++) {

      if(IsTradeContextFree()) {

         ResetLastError();

         MqlTick         tick;

         SymbolInfoTick(_Symbol,tick);

         MqlTradeRequest request;

         ZeroMemory(request);

         MqlTradeResult  result;

         ZeroMemory(result);

         request.action       = TRADE_ACTION_DEAL;

         request.symbol       = _Symbol;

         request.volume       = lots;

         request.type         = command == OP_BUY ? ORDER_TYPE_BUY : ORDER_TYPE_SELL;

         request.price        = command == OP_BUY ? ND(tick.ask) : ND(tick.bid);

         request.type_filling = orderFillingType;

         request.deviation    = 10;

         request.sl           = ND(stopLossFinale);

         request.tp           = ND(takeProfitFinale);

         request.magic        = magicNumber;

         request.position     = ticket;

         request.comment      = IntegerToString(magicNumber);

         bool isOrderCheck = CheckOrder(request);

         bool isOrderSend  = false;

         if(isOrderCheck) {

            isOrderSend = OrderSend(request,result);

         }

         if(isOrderCheck && isOrderSend && result.retcode == TRADE_RETCODE_DONE) return;

      }

      Sleep(TRADE_RETRY_WAIT);

      Print("Order Send retry no: " + IntegerToString(attempt + 2));

   }

}

//+------------------------------------------------------------------+

//|                                                                  |

//+------------------------------------------------------------------+

void ModifyPosition(double stopLossFinale,double takeProfitFinale,ulong ticket) {

   for(int attempt = 0; attempt < TRADE_RETRY_COUNT; attempt++) {

      if(IsTradeContextFree()) {

         ResetLastError();

         MqlTick         tick;

         SymbolInfoTick(_Symbol,tick);

         MqlTradeRequest request;

         ZeroMemory(request);

         MqlTradeResult  result;

         ZeroMemory(result);

         request.action   = TRADE_ACTION_SLTP;

         request.symbol   = _Symbol;

         request.sl       = ND(stopLossFinale);

         request.tp       = ND(takeProfitFinale);

         request.magic    = magicNumber;

         request.position = ticket;

         request.comment  = IntegerToString(magicNumber);

         bool isOrderCheck = CheckOrder(request);

         bool isOrderSend  = false;

         if(isOrderCheck) {

            isOrderSend = OrderSend(request,result);

         }

         if(isOrderCheck && isOrderSend && result.retcode == TRADE_RETCODE_DONE) return;

      }

      Sleep(TRADE_RETRY_WAIT);

      Print("Order Send retry no: " + IntegerToString(attempt + 2));

   }

}

//+------------------------------------------------------------------+

//|                                                                  |

//+------------------------------------------------------------------+

bool CheckOrder(MqlTradeRequest &request) {

   MqlTradeCheckResult check;

   ZeroMemory(check);

   const bool isOrderCheck = OrderCheck(request,check);

   if(isOrderCheck) return (true);

   if(check.retcode == TRADE_RETCODE_INVALID_FILL) {

      switch(orderFillingType)        {

      case  ORDER_FILLING_FOK:

         orderFillingType = ORDER_FILLING_IOC;

         break;

      case  ORDER_FILLING_IOC:

         orderFillingType = ORDER_FILLING_RETURN;

         break;

      case  ORDER_FILLING_RETURN:

         orderFillingType = ORDER_FILLING_FOK;

         break;

      }

      request.type_filling = orderFillingType;

      const bool isNewCheck = CheckOrder(request);

      return (isNewCheck);

   }

   Print("Error with OrderCheck: " + check.comment);

   return (false);

}

//+------------------------------------------------------------------+

//|                                                                  |

//+------------------------------------------------------------------+

double GetStopLossPrice(int command) {

   if(stopLoss == 0) return (0);

   MqlTick tick;

   SymbolInfoTick(_Symbol,tick);

   const double delta    = MathMax(pip * stopLoss, _Point * stopLevel);

   const double price    = command == OP_BUY ? tick.bid : tick.ask;

   const double stopLossFinale = command == OP_BUY ? price - delta : price + delta;

   const double normalizedStopLoss = NormalizeDouble(stopLossFinale, _Digits);

   return (normalizedStopLoss);

}

//+------------------------------------------------------------------+

//|                                                                  |

//+------------------------------------------------------------------+

double GetTrailingStop() {

   MqlTick tick;

   SymbolInfoTick(_Symbol,tick);

   const double stopLevelPoints = _Point * stopLevel;

   const double stopLossPoints  = pip * stopLoss;

   if(posType == OP_BUY) {

      const double stopLossPrice = High(1) - stopLossPoints;

      if(posStopLoss < stopLossPrice - pip) {

         if(stopLossPrice < tick.bid) {

            const double fixedStopLossPrice = (stopLossPrice >= tick.bid - stopLevelPoints) ? tick.bid - stopLevelPoints  : stopLossPrice;

            return (fixedStopLossPrice);

         } else {

            return (tick.bid);

         }

      }

   } else if(posType == OP_SELL) {

      const double stopLossPrice = Low(1) + stopLossPoints;

      if(posStopLoss > stopLossPrice + pip) {

         if(stopLossPrice > tick.ask) {

            if(stopLossPrice <= tick.ask + stopLevelPoints) return (tick.ask + stopLevelPoints);

            else return (stopLossPrice);

         } else {

            return (tick.ask);

         }

      }

   }

   return (posStopLoss);

}

//+------------------------------------------------------------------+

//|                                                                  |

//+------------------------------------------------------------------+

void ManageTrailingStop(double trailingStop) {

   MqlTick tick;

   SymbolInfoTick(_Symbol,tick);

   if(posType == OP_BUY && MathAbs(trailingStop - tick.bid) < _Point) {

      ClosePosition();

   } else if(posType == OP_SELL && MathAbs(trailingStop - tick.ask) < _Point) {

      ClosePosition();

   } else if(MathAbs(trailingStop - posStopLoss) > _Point) {

      posStopLoss = NormalizeDouble(trailingStop,digits);

      ModifyPosition(posStopLoss,posTakeProfit,posTicket);

   }

}

//+------------------------------------------------------------------+

//|                                                                  |

//+------------------------------------------------------------------+

double GetTakeProfitPrice(int command) {

   if(takeProfit == 0) return (0);

   MqlTick tick;

   SymbolInfoTick(_Symbol,tick);

   const double delta      = MathMax(pip * takeProfit, _Point * stopLevel);

   const double price      = command == OP_BUY ? tick.bid : tick.ask;

   const double takeProfitFinale = command == OP_BUY ? price + delta : price - delta;

   const double normalizedTakeProfit = NormalizeDouble(takeProfitFinale, _Digits);

   return (normalizedTakeProfit);

}

//+------------------------------------------------------------------+

//|                                                                  |

//+------------------------------------------------------------------+

datetime Time(int bar) {

   datetime buffer[];

   ArrayResize(buffer,1);

   const int result = CopyTime(_Symbol,_Period,bar,1,buffer);

   return (result == 1 ? buffer[0] : 0);

}

//+------------------------------------------------------------------+

//|                                                                  |

//+------------------------------------------------------------------+

double Open(int bar) {

   double buffer[];

   ArrayResize(buffer,1);

   const int result = CopyOpen(_Symbol,_Period,bar,1,buffer);

   return (result == 1 ? buffer[0] : 0);

}

//+------------------------------------------------------------------+

//|                                                                  |

//+------------------------------------------------------------------+

double High(int bar)  {

   double buffer[];

   ArrayResize(buffer,1);

   const int result = CopyHigh(_Symbol,_Period,bar,1,buffer);

   return (result == 1 ? buffer[0] : 0);

}

//+------------------------------------------------------------------+

//|                                                                  |

//+------------------------------------------------------------------+

double Low(int bar)  {

   double buffer[];

   ArrayResize(buffer,1);

   const int result = CopyLow(_Symbol,_Period,bar,1,buffer);

   return (result == 1 ? buffer[0] : 0);

}

//+------------------------------------------------------------------+

//|                                                                  |

//+------------------------------------------------------------------+

double Close(int bar) {

   double buffer[];

   ArrayResize(buffer,1);

   const int result = CopyClose(_Symbol,_Period,bar,1,buffer);

   return (result == 1 ? buffer[0] : 0);

}

//+------------------------------------------------------------------+

//|                                                                  |

//+------------------------------------------------------------------+

double GetPipValue(int digit) {

   if(digit == 6) return (0.000001);

   if(digit == 5) return (0.00001);

   if(digit == 4) return (0.0001);

   if(digit == 3) return (0.001);

   if(digit == 2) return (0.01);

   if(digit == 1) return (0.1);

   return (1);

}

//+------------------------------------------------------------------+

//|                                                                  |

//+------------------------------------------------------------------+

bool IsTradeContextFree()  {

   if(MQL5InfoInteger(MQL5_TRADE_ALLOWED)) return (true);

   uint startWait = GetTickCount();

   Print("Trade context is busy! Waiting...");

   while(true) {

      if(IsStopped()) return (false);

      uint diff = GetTickCount() - startWait;

      if(diff > 30 * 1000) {

         Print("The waiting limit exceeded!");

         return (false);

      }

      if(MQL5InfoInteger(MQL5_TRADE_ALLOWED)) return (true);

      Sleep(TRADE_RETRY_WAIT);

   }

   return (true);

}

//+------------------------------------------------------------------+

//|                                                                  |

//+------------------------------------------------------------------+

bool IsOutOfSession() {

   if(isTrailingStop) {

      double trailingStop = GetTrailingStop();

      ManageTrailingStop(trailingStop);

      UpdatePosition();

   }

   MqlDateTime time0;

   TimeToStruct(Time(0),time0);

   const int weekDay           = time0.day_of_week;

   const long timeFromMidnight = Time(0) % 86400;

   const int periodLength      = PeriodSeconds(_Period);

   if(weekDay == 0 || weekDay == 6) {

      ignoreSaturdaySunday = true;

      if(ignoreSaturdaySunday) return (true);

   }

   const int lastBarFix = sessionCloseAtFridayClose || sessionCloseAtSessionClose ? periodLength : 0;

   const bool skipTrade = timeFromMidnight < sessionFridayOpen || timeFromMidnight + lastBarFix > sessionFridayClose;

   return (skipTrade);

}

//+------------------------------------------------------------------+

//|                                                                  |

//+------------------------------------------------------------------+

double ND(double x) {

   int symbolDigits = 0;

   double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);

   double symbolPoint = SymbolInfoDouble(_Symbol, SYMBOL_POINT);

   if(tickSize == 0.000001) symbolDigits = 6;

   if(tickSize == 0.00001) symbolDigits = 5;

   if(tickSize == 0.0001) symbolDigits = 4;

   if(tickSize == 0.001) symbolDigits = 3;

   if(tickSize == 0.01) symbolDigits = 2;

   if(tickSize == 0.1) symbolDigits = 1;

   if(tickSize >= 1) {

      return(MathRound(x / tickSize) * tickSize);

   } else {

      return(NormalizeDouble(x, tickSize == symbolPoint ? _Digits : symbolDigits));

   }

}

//+------------------------------------------------------------------+

//|                                                                  |

//+------------------------------------------------------------------+

ENUM_ORDER_TYPE_FILLING GetOrderFillingType() {

   const int oftIndex = (int) SymbolInfoInteger(_Symbol,SYMBOL_FILLING_MODE);

   const ENUM_ORDER_TYPE_FILLING fillType = (ENUM_ORDER_TYPE_FILLING)(oftIndex > 0 ? oftIndex - 1 : oftIndex);

   return (fillType);

}

//+------------------------------------------------------------------+

//|                                                                  |

//+------------------------------------------------------------------+

ENUM_INIT_RETCODE ValidateInit()  {

   return (INIT_SUCCEEDED);

}



//+------------------------------------------------------------------+

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 ---