Bless.FifthE.TK.2.0.1-EA





//+------------------------------------------------------------------+
//|                                          Bless.FifthE.TK.2.0.mq4 |
//|                Open source at Forex-TSD forum, www.forex-tsd.com |
//|                        Ideas proposed by rifo.valas Bless System |
//|                  Coded by FiFtHeLeMeNt, fifthelement80@gmail.com |
//|                        Mofified by tkforextsd, tkemail@yahoo.com |
//+------------------------------------------------------------------+
//
//  History of FifthE's versions:
//    Verion 1.0.0: bless_FiftHeLeMent_noTG_1.0.0.mq4
//       Original FifthE version without MaxTrades
//    Verion 1.0.1: bless_FiftHeLeMent_noTG_1.0.1.mq4
//       FifthE version with MaxTrades
//    Verion 1.0.3: bless_FiftHeLeMent_1.0.3.mq4
//       FifthE version with spread control and LotInc
//
//  History of TK's versions:
//    Based on FifthE's bless_FiftHeLeMent_noTG_1.0.1.mq4
//    Version 1.0.2: bless_FiftHeLeMent_noTG_1.0.2.mq4 
//       Add stoploss at MaxTrades level to protect capital
//    Version 1.0.3: bless_FiftHeLeMent_noTG_1.0.3.mq4 
//       Add EA closing features: CloseImmediately, CloseOnTime, 
//           CloseOnFloatingLoss, CloseOnEquityTarget
//    Version 1.0.4: bless_FiftHeLeMent_noTG_1.0.4.mq4
//       Add selectable multiplier progression
//       Add auto restart after equity target reach
//       Add email alert when margin level low 
//       Add email alert when trade level reach a preset level
//       Add more info in chart comments
//
//  History of unified versions:
//    Version 2.0: Bless.FifthE.TK.2.0.mq4
//      Merge TK's bless_FiFtHeLeMeNt_noTG_1.0.4.mq4 and FifthE's bless_FiftHeLeMent_1.0.3.mq4
//      Unified features: Selectable Multiplier, LotInc, Spread control, MaxTrades stop loss, 
//          x% equity restart, closing order management, email alert
//      New features:
//          Breakeven bail out after BEP_Level reach
//          Opposite direction hedge at MaxTrades
//    Version 2.0.1: Bless.FifthE.TK.2.0.1.mq4
//       Add options for buying and selling management
//
//


#property copyright "Forex-tsd open source"
#property link      "http://www.forex-tsd.com"

#include <stdlib.mqh>

extern string  Expert_Name = "---- Bless.FifthE.TK.2.0.mq4 ----";
extern int     MinGS = 20;          //pips between each level
extern int     TP = 35;             //pips to take profit each trade
extern double  lot = 0.01;          //starting lot size
extern bool    BuySide=true;        // Buy orders will be placed
extern bool    SellSide=true;       // Sell orders will be placed
extern bool    AccountIsMini = true; // Set to true if trading mini account, otherwise set to false
extern int     MaxTrades = 7;       //max level allowed
extern int     RegularSpread = 10;   //max spread rejection, reject trades if spread exceed this value
extern double  Multiplier = 2;      //lots progressive multiplier factor
extern double  LotInc = 0;          //Lot increment on each level
extern int     BEP_Level = 5;       //breakeven bail out level
extern bool    SetMaxTradesSL = False; //Set stop loss at Maxtrades level
extern bool    SetMaxTradesHedge = true; //Set hedge trade at MaxTrades level

extern string  Close_Management = "---- EA Closing Management ----";
extern bool    CloseImmediately = false;

extern string  s1 = "---- Close on time setting ----";
extern bool    CloseOnTime = false;
extern int     CloseHour = 23;      //Time to close, Hour
extern int     CloseMinute = 0;     //Time to close, minutes

extern string  s2 = "---- Close when floating profit/loss no more than MaxFloatPL settings ----";
extern bool    CloseOnFloatPL = false;
extern double  MaxFloatPL = -100.00;    //Max floating profit/loss allowed when closing EA

extern string  s3 = "---- Close when equity hit target settings ----";
extern bool    CloseOnEquityTarget = false;
extern bool    AutoRestartAfterEqTarget = True;
extern double  EquityTargetPercentage = 5.0;    //Percentage equity growth when closing EA

extern string  s4 = "---- Comment settings ----";
extern bool    DisableComments = false;   //turn off comments

extern string  s5 = "---- Email settings ----";
extern bool    TestEmail = false;         //if true send a test email every 5 minutes
extern string  EmailAddress = "youremail@any.com";
extern int     EmailIteration = 3;        //How namy times email send when alert active

extern string  s6 = "---- Alert settings ----";
extern bool    AlertOnLowMargin = false;  //email alert when margin low
extern double  MarginPercentage = 100.0;  //margin low percentage
extern bool    AlertOnTradeLevel = false; //email alert when trade level reach
extern int     AlertTradeLevel = 6;       //trade level to alert


int magic;
double lot2; //lots to open at each level
int LotDigits;
datetime tob,tos; //Time Out Buy & Sell
double SL_Point; //stoploss price at MaxTrades level
double TP_Point; //TP price at each level


bool Halt = false;
double StartBalance, EquityTarget;
double MarginPer;
int CurrentLevel = 0;
int BuyLevel, SellLevel;
int Slippage = 1;
bool HedgeBuy = false;
bool HedgeSell = false;


//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----


   
//----
   return(0);
  }
  
int init()
  {
   if (Symbol() == "AUDCADm" || Symbol() == "AUDCAD") { magic = 211001; }
   if (Symbol() == "AUDJPYm" || Symbol() == "AUDJPY") { magic = 211002; }
   if (Symbol() == "AUDNZDm" || Symbol() == "AUDNZD") { magic = 211003; }
   if (Symbol() == "AUDUSDm" || Symbol() == "AUDUSD") { magic = 211004; }
   if (Symbol() == "CHFJPYm" || Symbol() == "CHFJPY") { magic = 211005; }
   if (Symbol() == "EURAUDm" || Symbol() == "EURAUD") { magic = 211006; }
   if (Symbol() == "EURCADm" || Symbol() == "EURCAD") { magic = 211007; }
   if (Symbol() == "EURCHFm" || Symbol() == "EURCHF") { magic = 211008; }
   if (Symbol() == "EURGBPm" || Symbol() == "EURGBP") { magic = 211009; }
   if (Symbol() == "EURJPYm" || Symbol() == "EURJPY") { magic = 211010; }
   if (Symbol() == "EURUSDm" || Symbol() == "EURUSD") { magic = 211011; }
   if (Symbol() == "GBPCHFm" || Symbol() == "GBPCHF") { magic = 211012; }
   if (Symbol() == "GBPJPYm" || Symbol() == "GBPJPY") { magic = 211013; }
   if (Symbol() == "GBPUSDm" || Symbol() == "GBPUSD") { magic = 211014; }
   if (Symbol() == "NZDJPYm" || Symbol() == "NZDJPY") { magic = 211015; }
   if (Symbol() == "NZDUSDm" || Symbol() == "NZDUSD") { magic = 211016; }
   if (Symbol() == "USDCHFm" || Symbol() == "USDCHF") { magic = 211017; }
   if (Symbol() == "USDJPYm" || Symbol() == "USDJPY") { magic = 211018; }
   if (Symbol() == "USDCADm" || Symbol() == "USDCAD") { magic = 211019; }
   if (magic == 0) { magic = 211999; }
   
   Halt = false;
   LotDigits = 1;
   if (AccountIsMini) { LotDigits = 2; }
   HedgeBuy = false;
   HedgeSell = false;
   return(0);
  }

void OpenBuy()
 {
    int ticket,err;
        if (!GlobalVariableCheck("InTrade")) {
               GlobalVariableSet("InTrade", TimeCurrent());  // set lock indicator
               ticket = OrderSend(Symbol(),OP_BUY,lot2,Ask,Slippage,SL_Point,TP_Point,"EA Order",magic,0,Red);
               GlobalVariableDel("InTrade");   // clear lock indicator
        }
 }

void OpenSell()
 {
    int ticket,err;
        if (!GlobalVariableCheck("InTrade")) {
               GlobalVariableSet("InTrade", TimeCurrent());  // set lock indicator
               ticket = OrderSend(Symbol(),OP_SELL,lot2,Bid,Slippage,SL_Point,TP_Point,"EA Order",magic,0,Red);
               GlobalVariableDel("InTrade");   // clear lock indicator
        }
 }


void ManageBuy() 
 {
   int lasttradetime = 0;
   double lastopenprice=0;
   double maxlots = 0;
   double lasttp=0;
   double lastsl=0;
   int lastordertype=-1;
   int lastorderticket=0;
   int y=0; 

   BuyLevel = 0;
   for (y = 0; y < OrdersTotal(); y++)
   {
      OrderSelect (y, SELECT_BY_POS, MODE_TRADES);
      if ((OrderMagicNumber() != magic) || (OrderType()!=OP_BUY)) { continue; }
      if (OrderOpenTime() >= lasttradetime) { 
        lasttradetime = OrderOpenTime();
        lastopenprice = OrderOpenPrice();
        lastordertype=OrderType();
        lastorderticket=OrderTicket();
        lasttp=OrderTakeProfit();
        lastsl=OrderStopLoss();
      }     
      if (OrderLots() > maxlots) { maxlots = OrderLots(); }
      BuyLevel++;
   }
   
   lot2 = NormalizeDouble(lot*MathPow(Multiplier, BuyLevel)+LotInc, LotDigits);
   
   SL_Point = 0;
   TP_Point = Ask + TP*Point;
   if ((BuyLevel==0) && (((Ask-Bid)/Point)<=RegularSpread) && !Halt ) { 
      OpenBuy(); 
      BuyLevel++; 
      CurrentLevel=BuyLevel;
      return(0); 
   }
   
   if ((lastopenprice-Ask>MinGS*Point) && (BuyLevel==MaxTrades-1) && (SetMaxTradesSL || SetMaxTradesHedge) ) {
      //set stoploss at the last open level
      SL_Point = Ask - MinGS*Point; 
   }

   if ((lastopenprice-Ask>MinGS*Point) && (BuyLevel<MaxTrades) && (((Ask-Bid)/Point)<=RegularSpread) && !Halt && !HedgeBuy ) {
      OpenBuy();
      BuyLevel++;
      CurrentLevel=BuyLevel;
      return(0);
   }

   CurrentLevel=BuyLevel;
   
/////////// TP
/*
   double sumlots=0;
   double sump=0;
   double avgp=0;
   for (y = 0; y < OrdersTotal(); y++)
   {
      OrderSelect (y, SELECT_BY_POS, MODE_TRADES);
      if ((OrderMagicNumber() != magic) || (OrderType()!=OP_BUY)) { continue; }
      sumlots=sumlots+OrderLots();
      sump=OrderOpenPrice()*OrderLots()+sump;
   }
   
   if (sumlots>0) {
     avgp=NormalizeDouble(sump/sumlots,Digits);
     double tpp=NormalizeDouble(TP/10/sumlots*Point+avgp,Digits);
     
     for (y = 0; y < OrdersTotal(); y++)
     {
       OrderSelect (y, SELECT_BY_POS, MODE_TRADES);
       if ((OrderMagicNumber() != magic) || (OrderType()!=OP_BUY) || (OrderTakeProfit()==tpp)) { continue; }
       OrderModify(OrderTicket(),OrderOpenPrice(),OrderStopLoss(),tpp,0,Red);
     }
     
     
   }
 */  

     for (y = OrdersTotal()-1; y >= 0; y--)
     {
       OrderSelect (y, SELECT_BY_POS, MODE_TRADES);
       if ((OrderMagicNumber() != magic) || (OrderType()!=OP_BUY) || (OrderTakeProfit()==lasttp) || (lasttp==0) || HedgeBuy ) { continue; }
       OrderModify(OrderTicket(),OrderOpenPrice(),lastsl,lasttp,0,Red);
     }

   //reverse hedge
   if (BuyLevel==MaxTrades && !HedgeSell && SetMaxTradesHedge) {
      TP_Point = lastsl; 
      SL_Point = lasttp;
      OpenSell();
      HedgeSell = true;
      return(0);
   }

}
    
void ManageSell() 
 {
   int lasttradetime = 0;
   double lastopenprice=0;
   double maxlots = 0;
   double lasttp=0;
   double lastsl=0;
   int lastordertype=-1;
   int lastorderticket=0;
   int y=0; 

   SellLevel = 0;
   for (y = 0; y < OrdersTotal(); y++)
   {
      OrderSelect (y, SELECT_BY_POS, MODE_TRADES);
      if ((OrderMagicNumber() != magic) || (OrderType()!=OP_SELL)) { continue; }
      if (OrderOpenTime() >= lasttradetime) { 
        lasttradetime = OrderOpenTime();
        lastopenprice = OrderOpenPrice();
        lastordertype=OrderType();
        lastorderticket=OrderTicket();
        lasttp=OrderTakeProfit();
        lastsl=OrderStopLoss();
      }     
      if (OrderLots() > maxlots) { maxlots = OrderLots(); }
      SellLevel++;
   }
   
   lot2 = NormalizeDouble(lot*MathPow(Multiplier, SellLevel)+LotInc, LotDigits);
   
   SL_Point = 0;
   TP_Point = Bid-TP*Point;
   if ((SellLevel==0) && (((Ask-Bid)/Point)<=RegularSpread) && !Halt ) { 
      OpenSell(); 
      SellLevel++; 
      if (SellLevel>CurrentLevel) CurrentLevel=SellLevel;
      return(0); 
   }
   
   if ((Bid-lastopenprice>MinGS*Point) && (SellLevel==MaxTrades-1) && (SetMaxTradesSL || SetMaxTradesHedge) ) {
      //set stoploss at the last open level
      SL_Point = Bid + MinGS*Point; 
   }

   if ((Bid-lastopenprice>MinGS*Point) && (lastopenprice>0) && (SellLevel<MaxTrades) && (((Ask-Bid)/Point)<=RegularSpread) && !Halt && !HedgeSell ) {
      OpenSell();
      SellLevel++;
      if (SellLevel>CurrentLevel) CurrentLevel=SellLevel;
      return(0);
   }
   if (SellLevel>CurrentLevel) CurrentLevel=SellLevel;
   
/////////// TP
/*   double sumlots=0;
   double sump=0;
   double avgp=0;
   for (y = 0; y < OrdersTotal(); y++)
   {
      OrderSelect (y, SELECT_BY_POS, MODE_TRADES);
      if ((OrderMagicNumber() != magic) || (OrderType()!=OP_SELL)) { continue; }
      sumlots=sumlots+OrderLots();
      sump=OrderOpenPrice()*OrderLots()+sump;
   }
   
   if (sumlots>0) {
     avgp=NormalizeDouble(sump/sumlots,Digits);
     double tpp=NormalizeDouble(-TP/10/sumlots*Point+avgp,Digits);
     
     for (y = 0; y < OrdersTotal(); y++)
     {
       OrderSelect (y, SELECT_BY_POS, MODE_TRADES);
       if ((OrderMagicNumber() != magic) || (OrderType()!=OP_SELL) || (OrderTakeProfit()==tpp)) { continue; }
       OrderModify(OrderTicket(),OrderOpenPrice(),OrderStopLoss(),tpp,0,Red);
     }
     
     
   }
 */ 
 
      for (y = OrdersTotal()-1; y >= 0; y--)
     {
       OrderSelect (y, SELECT_BY_POS, MODE_TRADES);
       if ((OrderMagicNumber() != magic) || (OrderType()!=OP_SELL) || (OrderTakeProfit()==lasttp) || (lasttp==0) || HedgeSell || HedgeSell ) { continue; }
       OrderModify(OrderTicket(),OrderOpenPrice(),lastsl,lasttp,0,Red);
     }

   //reverse hedge
   if (SellLevel==MaxTrades && !HedgeBuy && SetMaxTradesHedge) {
      TP_Point = lastsl;
      SL_Point = lasttp;
      OpenBuy();
      HedgeBuy = true;
      return(0);
   }
 
 }

  
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
//----
     
      ManageClose();
      
      if (BuySide)
         ManageBuy();
      
      if (SellSide)
         ManageSell();

      if(!IsTesting()) HandleAlerts();
      
      if(!IsTesting()) ChartComment();
      
//----
   return(0);
  }
//+------------------------------------------------------------------+


void CloseAllTrades()
{
   int  total = OrdersTotal();
   for (int y=OrdersTotal()-1; y>=0; y--)  
   {
      OrderSelect(y, SELECT_BY_POS, MODE_TRADES);
      if (OrderMagicNumber() == magic) 
      {
         int type = OrderType();
         bool result = false;
         int  TriesNum = 5;
         int tries=0;
         while (!result && tries < TriesNum) 
         {
            RefreshRates();
            switch(type)
            {
               case OP_BUY : 
                  result = OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_BID),Slippage,Pink);
                  break;
               case OP_SELL: 
                  result = OrderClose(OrderTicket(),OrderLots(),MarketInfo(OrderSymbol(),MODE_ASK),Slippage,Pink);             
            }            
            tries++;
         }
         if (!result) Print("Error closing order : ",ErrorDescription(GetLastError()));  
      }
   }
}


bool LastCloseOnEquityTarget = false;

void ManageClose()
{
   //Breakeven bail out after BEP_Level
   if ((CurrentLevel>=BEP_Level) && (AccountProfit()>=0)) {
      CloseAllTrades();
   }

   //Reverse hedge at Maxtrades level
   if ((BuyLevel<MaxTrades) && HedgeSell) { HedgeSell = false; }
   if ((SellLevel<MaxTrades) && HedgeBuy) { HedgeBuy = false; }

   if (CloseOnEquityTarget && !LastCloseOnEquityTarget) { 
      StartBalance = AccountBalance();
   }
   LastCloseOnEquityTarget = CloseOnEquityTarget;
   
   if (CloseImmediately) 
   {
      CloseAllTrades();
      Halt = true;
   }
   if (CloseOnTime && Hour()==CloseHour && Minute()>=CloseMinute) 
   {
      CloseAllTrades();
      Halt = true;
   }
   if (CloseOnFloatPL && AccountProfit()>=MaxFloatPL)
   {
      CloseAllTrades();
      Halt = true;
   }
   if (CloseOnEquityTarget && !Halt)
   {
      EquityTarget = StartBalance*(1.0 + EquityTargetPercentage/100.0);
      if (AccountEquity()>=EquityTarget )
      {
         CloseAllTrades();
         StartBalance = AccountBalance();
         if (!AutoRestartAfterEqTarget) Halt = true;
      }
   }
   if (!CloseImmediately && !CloseOnTime && !CloseOnFloatPL && !CloseOnEquityTarget )
   {
      if (Halt) StartBalance = AccountBalance();
      Halt = false;
   }
     
}


void ChartComment()
{
   string sComment    = "";
   string sp          = "----------------------------------------\n";
   string Activity    = "-----------Trading Activity-------------\n";
   string CloseManage = "-----------Closing Management-----------\n";
   string AcctStatus  = "-----------Account Status---------------\n";
   string NL          = "\n";
 
   double   spread = MarketInfo(Symbol(),MODE_SPREAD);
   double   SwapLong = MarketInfo(Symbol(),MODE_SWAPLONG);
   double   SwapShort = MarketInfo(Symbol(),MODE_SWAPSHORT);
 
   
   sComment = Activity;
   sComment = sComment + "Current time is " + TimeToStr(TimeCurrent()) + NL;
   if (Halt)
      sComment = sComment + "Trading halt!!! To resume trading set ALL closing conditions to FALSE." + NL;
   else
      sComment = sComment + "Trading is active at level " + CurrentLevel + NL;

   if (CloseImmediately || CloseOnTime || CloseOnFloatPL || CloseOnEquityTarget)
   {
      sComment = sComment + CloseManage;
      if (CloseImmediately)
         sComment = sComment + "Close Immediately!!!!" + NL;
      if (CloseOnTime)
         sComment = sComment + "Close on time is active when " + CloseHour + ":" + CloseMinute + NL;
      if (CloseOnFloatPL)
         sComment = sComment + "Close on floating loss is active when float P/L >= " + DoubleToStr(MaxFloatPL,2) + NL;
      if (CloseOnEquityTarget)
         sComment = sComment + "Close on equity target is active when EquityTarget >= " + DoubleToStr(EquityTarget,2) + NL;
   }

   sComment = sComment + AcctStatus;
   sComment = sComment + "Balance: " + DoubleToStr(AccountBalance(), 2) + ", Equity: " + DoubleToStr(AccountEquity(),2)
               + ", Leverage: " + DoubleToStr(AccountLeverage(),2) + ", Lots: " + DoubleToStr(lot2,2) + NL;
   sComment = sComment + "MinGS: " + MinGS + ", TP: " + TP + ", Buy Level: " + BuyLevel + ", Sell Level: " + SellLevel + ", MaxTrades: " + MaxTrades + NL;
   
   sComment = sComment + "Spread: " + DoubleToStr(spread,1) + ", SWAP Long: " + DoubleToStr(SwapLong,2) + ", SWAP Short: " + DoubleToStr(SwapShort,2) +  NL;

   sComment = sComment + "AccountMargin: " + DoubleToStr(AccountMargin(), 2) + ", Margin%: " + DoubleToStr(MarginPer,2) + "%" + NL;
   sComment = sComment + sp;
      
   if (!DisableComments) Comment(sComment);
   else Comment("");
   
}

//Alert handling variables
bool LastTestEmail = false;
int  TestEmailCnt = 0;
bool LastAlertOnLowMargin = false;
int  AlertOnLowMarginCnt = 0;
bool LastAlertOnTradeLevel = false;
int  AlertOnTradeLevelCnt = 0;
bool TimeToSend;
datetime LastTime;


void HandleAlerts()
{
   string Message = "";
   
   //RefreshRates();
   //Switch on detection
   if (TestEmail && !LastTestEmail) { 
      TestEmailCnt = EmailIteration; 
      LastTime = TimeCurrent(); 
   }
   if (AlertOnLowMargin && !LastAlertOnLowMargin) { 
      AlertOnLowMarginCnt = EmailIteration; 
      LastTime = TimeCurrent(); 
   }
   if (AlertOnTradeLevel && !LastAlertOnTradeLevel) { 
      AlertOnTradeLevelCnt = EmailIteration; 
      LastTime = TimeCurrent(); 
   }

   //Update
   LastTestEmail = TestEmail;
   LastAlertOnLowMargin = AlertOnLowMargin;
   LastAlertOnTradeLevel = AlertOnTradeLevel;
   
   //Handle email alert
   if (TimeCurrent() - LastTime >= 300) { TimeToSend = true; }
   else { TimeToSend = false; }
   
   
  
   
   if (AccountMargin()==0) MarginPer = 100000;
   else MarginPer = AccountEquity()/AccountMargin()*100.0;
     
      AlertOnLowMarginCnt--;
      LastTime = TimeCurrent();
   }
   
   








Sample





Analysis



Market Information Used:



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 can change open orders parameters, due to possible stepping strategy
It Closes Orders by itself

Other Features: