NewMartingale-CodeBase

Author: Abraão Moreira
Price Data Components
Series array that contains close prices for each barSeries array that contains open prices of each bar
Miscellaneous
It opens Message Boxes to the user
0 Views
0 Downloads
0 Favorites
NewMartingale-CodeBase
ÿþ//+------------------------------------------------------------------+

//|                                                   Martingale.mq5 |

//|                                                   Abraão Moreira |

//|                                                abraaomoreira.com |

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

#property copyright "Abraão Moreira"

#property link      "abraaomoreira.com"

#property version   "3.4"



#include <Trade/Trade.mqh>



CTrade trade;



enum options {

  yes = 1,

  no = 0,

};



input double TP = 100;                      //TP (points)

input double SL = 100;                      //SL (points)

input double settedVolume = 1;              //Volume

input bool trailingStopSwitch = true;       //Trailing stop

input bool breakevenSwitch = true;          //Breakeven

input bool martingaleSwitch = true;         //Martingale

input bool manualFirstSwitch = true;        //Manual first operation

input bool againstTrendSwitch = false;      //Automatic orders against trend

input int maxMartingales = 5;               //Martingales in a row

input double martingaleFactor = 2;          //Martingale factor

input double maxLoss = 1000;                //Monetary max daily loss

input double maxProfit = 1000;              //Monetary max daily profit



input options operationalTimeControl = yes; //Enable operational time control (if you set "No", ignore next two fields)

input string begin = "09:00";               //Time to Start sending orders

input string finish = "17:30";              //Time to Stop sending orders and close all open positions



string today;



int contMartingales = 0;



double pastClose = iClose(NULL, 0, 1);



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

//| Expert initialization function                                   |

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

int OnInit() {

  MessageBox("Please, check the configurations applied to the current stock, a wrong config can impede EA works!!! \n\n Thanks for download, enjoy.",

              NULL,

              MB_ICONINFORMATION);

  today = TimeToString(TimeLocal(), TIME_DATE);



  VolumesOk(settedVolume);

  InTimeInterval(begin, finish, operationalTimeControl, true);

  return(INIT_SUCCEEDED);

}

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

//| Expert deinitialization function                                 |

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

void OnDeinit(const int reason) {



}

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

//| Expert tick function                                             |

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

void OnTick() {

  double bid, ask;

  ulong lastTicket, pastTicket;

  uint dealsTotal;

  string orderControl;



  PositionSelect(_Symbol);

  lastTicket = PositionGetInteger(POSITION_TICKET);



  HistorySelect(StringToTime(today), TimeLocal());

  dealsTotal = HistoryDealsTotal();

  pastTicket = HistoryDealGetTicket(dealsTotal-1);



  TimeLimit(finish, INT_MAX, operationalTimeControl);

  ProfitReached(maxProfit, StringToTime(today), TimeLocal());

  LossReached(maxLoss, StringToTime(today), TimeLocal());



  orderControl = OperationStrategy();



  ask = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits);

  bid = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits);



  if(manualFirstSwitch) {

    if(breakevenSwitch && trailingStopSwitch)

      TrailingStop(!trailingStopSwitch, lastTicket, SL, SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE));

    else

      TrailingStop(trailingStopSwitch, lastTicket, SL, SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE));

    Breakeven(breakevenSwitch, lastTicket, SL, SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE));



    if(contMartingales <= maxMartingales &&

        HistoryDealGetDouble(pastTicket, DEAL_PROFIT) < 0 &&

        OrderSendRequirements()) {

      if(orderControl == "BUY")

        Martingale(martingaleSwitch, martingaleFactor, orderControl, ask, SL, TP);

      if(orderControl == "SELL")

        Martingale(martingaleSwitch, martingaleFactor, orderControl, bid, SL, TP);

      contMartingales++;

    }



  } else {

    if(PositionGetInteger(POSITION_REASON) == POSITION_REASON_EXPERT) {

      if(breakevenSwitch && trailingStopSwitch)

        TrailingStop(!trailingStopSwitch, lastTicket, SL, SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE));

      else

        TrailingStop(trailingStopSwitch, lastTicket, SL, SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE));

      Breakeven(breakevenSwitch, lastTicket, SL, SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE));

    }



    if(contMartingales < maxMartingales &&

        HistoryDealGetDouble(pastTicket, DEAL_PROFIT) <= 0 &&

        OrderSendRequirements()) {

      if(orderControl == "BUY")

        Martingale(martingaleSwitch, martingaleFactor, orderControl, ask, SL, TP);

      if(orderControl == "SELL")

        Martingale(martingaleSwitch, martingaleFactor, orderControl, bid, SL, TP);

      contMartingales++;

    } else

      AutomaticOrder(orderControl);

  }



  if(HistoryDealGetDouble(pastTicket, DEAL_PROFIT) > 0)

    contMartingales = 0;

}



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

//|  Determine order type function                                   |

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

string OperationStrategy() {

  if(againstTrendSwitch) {

    if(iClose(NULL, 0, 1) < iOpen(NULL, 0, 1))

      return "BUY";

    if(iClose(NULL, 0, 1) > iOpen(NULL, 0, 1))

      return "SELL";

  } else {

    if(iClose(NULL, 0, 1) < iOpen(NULL, 0, 1))

      return "SELL";

    if(iClose(NULL, 0, 1) > iOpen(NULL, 0, 1))

      return "BUY";

  }

  return "-";

}



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

//|  Automatic order send function                                   |

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

void AutomaticOrder(string orderControl) {

  double ask, bid;



  ask = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits);

  bid = NormalizeDouble(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits);



  if(orderControl == "BUY" &&

      OrderSendRequirements()) {

    trade.Buy(settedVolume, NULL, ask, ask - SL*_Point, ask + TP*_Point);

  }

  if(orderControl == "SELL" &&

      OrderSendRequirements()) {

    trade.Sell(settedVolume, NULL, bid, bid + SL*_Point, bid - TP*_Point);

  }

}



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

//|  New candle sense function                                       |

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

bool NewCandle() {

  if(pastClose != iClose(NULL, 0, 1)) {

    pastClose = iClose(NULL, 0, 1);

    return true;

  }

  pastClose = iClose(NULL, 0, 1);

  return false;

}



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

//|  Order send requirements function                                |

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

bool OrderSendRequirements() {

  if(VolumesOk(settedVolume) &&

      InTimeInterval(begin, finish, operationalTimeControl, false) &&

      NewCandle() &&

      !ProfitReached(maxProfit, StringToTime(today), TimeLocal()) &&

      !LossReached(maxLoss, StringToTime(today), TimeLocal()) &&

      !PositionSelect(_Symbol))

    return true;

  return false;

}



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

//|  Time interval check function                                    |

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

bool InTimeInterval(string begin_, 

                     string finish_, 

                     bool control, 

                     bool showMessage) {

  if(!control)

    return true;

  

  if(begin_ <= TimeToString(TimeLocal(), TIME_MINUTES) &&

      TimeToString(TimeLocal(), TIME_MINUTES) <= finish_)

    return true;



  if(showMessage)

    MessageBox("Out of operational time interval setted. \n\n" +

               begin_ + " - " + finish_

               + "\n\nPlease, change the configurations!");

  return false;

}



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

//|  Time limit check and close positions function                   |

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

void TimeLimit(string finish_, 

                int deviation, 

                bool control) {

  if((TimeToString(TimeLocal(), TIME_MINUTES) >= finish_) && control) {

    CloseAllPositions(deviation);

  }

}



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

//|  Days of the week operations are enable function                 |

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

bool IsOperationDay(int &daysOn[]) {

  MqlDateTime strTimeLocal;

  TimeToStruct(TimeLocal(), strTimeLocal);

  for(int i = 0; i < ArraySize(daysOn); i++)

    if(strTimeLocal.day_of_week == daysOn[i])

      return true;

  return false;

}



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

//|  Profit limit reached function                                   |

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

bool ProfitReached(double profitMax_PR, 

                    datetime initDate_PR, 

                    datetime finishDate_PR) {

  double acum = AcumulatedProfit(initDate_PR, finishDate_PR);

  if(AcumulatedProfit(initDate_PR, finishDate_PR) >= profitMax_PR) {

    CloseAllPositions(INT_MAX);

    MessageBox("Diary monetary profit reached: \n" + (string)profitMax_PR);

    return true;

  }

  return false;

}



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

//|  Loss limit reached function                                     |

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

bool LossReached(double lossMax_LR, 

                  datetime initDate, 

                  datetime finishDate) {

  if(AcumulatedProfit(initDate, finishDate) <= (lossMax_LR * -1)) {

    CloseAllPositions(INT_MAX);

    MessageBox("Diary monetary loss reached: \n" + (string)lossMax_LR);

    return true;

  }

  return false;

}



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

//|  Acumulated profit function                                     |

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

double AcumulatedProfit(datetime initDate_AP, 

                         datetime finishDate_AP) {

  double profitAcum = 0;



  HistorySelect(initDate_AP, finishDate_AP);

  for(int i = 1; i <= HistoryDealsTotal(); i++) {

    ulong ticket = HistoryDealGetTicket(i);

    profitAcum += HistoryDealGetDouble(ticket, DEAL_PROFIT);

  }

  return profitAcum;

}



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

//|  Close all positions function                                    |

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

void CloseAllPositions(int deviation) {

  CTrade trade_TL;

  ulong ticket = 0;

  if(PositionSelect(_Symbol)) {

    for(int i = 0; i < PositionsTotal(); i++) {

      ticket = PositionGetTicket(i);

      trade_TL.PositionClose(ticket, deviation);

    }

  }

}



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

//|  Trainling stop function                                         |

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

void TrailingStop (bool control,

                   ulong ticket,

                   double stopLoss,

                   double step) {

  CTrade trade_TS;

  double newSL = 0;



  if(PositionSelectByTicket(ticket) &&

      PositionGetDouble(POSITION_PROFIT) > 0 &&

      control) {

    if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) {

      newSL = PositionGetDouble(POSITION_PRICE_CURRENT) - stopLoss;

      if(newSL > PositionGetDouble(POSITION_SL))

        trade_TS.PositionModify(ticket, newSL, PositionGetDouble(POSITION_TP));

    }

    if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) {

      newSL = PositionGetDouble(POSITION_PRICE_CURRENT) + stopLoss;

      if(newSL < PositionGetDouble(POSITION_SL))

        trade_TS.PositionModify(ticket, newSL, PositionGetDouble(POSITION_TP));

    }

  }

}



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

//|  Breakeven function                                              |

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

void Breakeven (bool control,

                ulong ticket,

                double stopLoss,

                double step) {

  bool trailingControl = true;

  if(control &&

      PositionSelectByTicket(ticket)) {

    if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) {

      if(PositionGetDouble(POSITION_SL) >= PositionGetDouble(POSITION_PRICE_OPEN))

        trailingControl = false;

    } else {

      if(PositionGetDouble(POSITION_SL) <= PositionGetDouble(POSITION_PRICE_OPEN))

        trailingControl = false;

    }

    TrailingStop(trailingControl, ticket, stopLoss, step);

  }

}



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

//|  Martingale function                                             |

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

double Martingale (bool control,

                   double factor,

                   string type,

                   double operationPrice,

                   double stopLoss,

                   double takeProfit) {

  CTrade trade_M;

  ulong ticket;

  uint total = 0;

  double lastVolume = 0, newVolume = 0;

  

  if(control){

    HistorySelect(0, TimeLocal());

    total = HistoryDealsTotal();

  

    ticket = HistoryDealGetTicket(total-1);

    lastVolume = HistoryDealGetDouble(ticket, DEAL_VOLUME);

  

    HistoryDealGetInteger(ticket, DEAL_TYPE);

    newVolume = lastVolume * factor;

    if(type == "BUY")

      trade_M.Buy(newVolume,

                  _Symbol,

                  operationPrice,

                  operationPrice - stopLoss*_Point,

                  operationPrice + takeProfit*_Point);

    if(type == "SELL")

      trade_M.Sell(newVolume,

                   _Symbol,

                   operationPrice,

                   operationPrice + stopLoss*_Point,

                   operationPrice - takeProfit*_Point);

  }

  return newVolume;

}



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

//|  Volume check                                                    |

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

bool VolumesOk(double volume) {

  double min_volume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);

  double max_volume = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);

  double volume_step = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);



  if(volume < min_volume) {

    MessageBox("Volume is less than the minimal to this symbol! \n" + "Minimal volume: " + (string)min_volume + "\n \n Please, try again with different value.");

    return false;

  }



  if(volume > max_volume) {

    MessageBox("Volume is greater than the maximal to this symbol! \n" + "Maximal volume: " + (string)max_volume + "\n \n Please, try again with different value.");

    return false;

  }

  int ratio = (int)MathRound(volume/volume_step);

  if(MathAbs(ratio*volume_step - volume) > 0.0000001) {

    MessageBox("Volume is not a multiple of the minimal step to this symbol!\n" + "Minimal step: " + (string)volume_step + "\n \n Please, try again with different value.");

    return false;

  }



  return true;

}

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

Comments