//+------------------------------------------------------------------+
//|                                           Another Martingale.mq4 |
//|                              Copyright © 2009, Totom Sukopratomo |
//|                                     mailto:forexengine@gmail.com |
//+------------------------------------------------------------------+

//+------------------------------------------------------------------+
//| be my referall by register in my link and get free managed account 
//| for $50000 deposit in standard or $1000 in micro with 
//| 5% per month profit 
//| here is the link:
//| standard: http://fxind.com?agent=200514
//| micro:    http://fxind.com?agent=123621
//+------------------------------------------------------------------+

#property copyright "Copyright © 2009, Totom Sukopratomo"
#property link      "mailto:forexengine@gmail.com"

//*------USER INPUT-----*
extern int MagicNumber=1;               // use for identifing order 
extern double StartLot=0.1;             // basic lot
extern int StopLoss=30;                 // stop loss
extern int TakeProfit=30;               // take profit
extern int TrailingStop=0;              // to moving out stoploss into
                                        // profit direction. adding
                                        // number bigger than 0 will
                                        // activated this fuction
extern bool MoveToBreakEvent=false;     // to moving stoploss into
                                        // opening price so there
                                        // a losses can neutralize
                                        // when market moves again us
extern int LockedPips=1;                // small amount of pips profit
                                        // expected to be earn when
                                        // market moves again us after
                                        // move to break event funtion
                                        // is triggered out
extern int RSIPeriod=9;                 // amount of bar to calculate
                                        // rsi price 
extern int UpperLevel=70;               // a level to determine market
                                        // is overbought if price is touch
                                        // it
extern int LowerLevel=30;               // same as above but for 
                                        // oversold comdition
extern bool Martingale=true;            // false to deactivated this feature
extern double Multiplier=2.5;           // previous lotsize will multiplied
                                        // with this value to get lotsize
                                        // of next order if EA getting loss
extern int DeepLevel=10;                // how many continue losses
                                        // will be covered by martingale
                                        // function
extern int StartHour=0;                 // time for EA start trading
extern int EndHour=20;                  // time for EA stop trading 
       double pt,                       // custom point
       stoplevel,                       // stop level
       minlot,                          // minimal lot
       maxlot;                          // maximal lot
//+------------------------------------------------------------------+
//| order counting                                                   |
//+------------------------------------------------------------------+
int ordercount()                        // we counting our order here
{
   int total=0;                         // total of our order 
   int i;                               // pos of our order 
   for(i=0; i<OrdersTotal(); i++)       // looping to count our order 
                                        // from pos 0 until last pos
   {
       OrderSelect(i,SELECT_BY_POS,MODE_TRADES);  // is it right our order?
       if(OrderSymbol()!=Symbol() ||    // if symbol of order didn't match 
       OrderMagicNumber()!=MagicNumber) // with current chart symbol 
       continue;                        // or the magic numb of order 
                                        // didn't match with our magic
                                        // number, don't count it
       total++;                         // count if all criteria matched
   }
   return(total);                       // this function returned total of
                                        // our opened order 
}
//+------------------------------------------------------------------+
//| check for losses                                                 |
//+------------------------------------------------------------------+  
bool checkforlosses()                   // we check our last closed order 
{                                       // from losses here 
   int losses=0;                        // total of losses
   int i;                               // pos of our order 
   for(i=0; i<OrdersHistoryTotal(); i++) // looping to check all of our
   {                                     // order history from pos 0 until
                                        // last pos
       OrderSelect(i,SELECT_BY_POS,MODE_HISTORY); // is it right our order?
       if(OrderSymbol()!=Symbol() ||    // if symbol of order didn't match 
       OrderMagicNumber()!=MagicNumber) // with current chart symbol 
       continue;                        // or the magic numb of order 
                                        // didn't match with our magic
                                        // number, it is not our's, just don't check it
       if(OrderProfit()<0) losses++;    // so we count it as a losses 'cause negative profit
       else                losses=0;    // otherwise we leave it as is 
   }
   if(losses>0)  return(true);          // if last of our order is in losses
                                        // true "value" will returned from this function
   return(false);                       // when there is no losses false will returned
}
//+------------------------------------------------------------------+
//| last lot                                                         |
//+------------------------------------------------------------------+ 
double lastlot()                        // we will find last lot size 
{                                       // order with this function
  double lot=0;                         // lot size
  int i;                                // pos of our order 
  for(i=0; i<OrdersHistoryTotal(); i++) // looping to check all of our
   {                                     // order history from pos 0 until
                                        // last pos
       OrderSelect(i,SELECT_BY_POS,MODE_HISTORY); // is it right our order?
       if(OrderSymbol()!=Symbol() ||    // if symbol of order didn't match 
       OrderMagicNumber()!=MagicNumber) // with current chart symbol 
       continue;                        // or the magic numb of order 
                                        // didn't match with our magic
                                        // number, it is not our's
       lot=OrderLots();                 // last lot
  }
  return(lot);                          // last lot size returned
}
//+------------------------------------------------------------------+
//| my lot                                                           |
//+------------------------------------------------------------------+ 
double mylot()                          // we calculate for next lot here
{                                       // when a loss occured or not 
  int prec=0;                           // precision value 
  double lot,                           // lot size
         minlot,                        // minimal size of lot
         maxlot,                        // maximal size of lot
         maxlotX;                       // maximal size of martingale lot 
  minlot=MarketInfo(Symbol(),MODE_MINLOT); // get brokers minimal lot size
  maxlot=MarketInfo(Symbol(),MODE_MAXLOT); // get brokers maximal lot size
  if(minlot==0.01) prec=2;              // get precision value
  if(minlot==0.1)  prec=1;              // get precision value
  maxlotX=NormalizeDouble(StartLot*MathPow(Multiplier,DeepLevel), prec); //get max.
                                        // martingale lotsize
  if(Martingale)                        // if martingale activated
  {
     if(checkforlosses())               // if last order is in losses
     {
        lot=NormalizeDouble(lastlot()*Multiplier,prec); // martingale lot
     }
     else
     {
        lot=StartLot;                   // normal lot
     }
  }  
  else
  {
     lot=StartLot;                      // normal lot
  }
  
  if(lot>maxlot)  return(StartLot);     // if lot size is bigger than broker rules,
                                        // we change it into StartLot value
  if(lot>maxlotX) return(StartLot);     // if lot size is bigger than martingale level,
                                        // we change it into StartLot value 
  if(lot<minlot)  return(minlot);       // if lot size smaller than minlot, we change
                                        // into monlot value
  return(lot);                          // lot size returned
}
//+------------------------------------------------------------------+
//| get signal                                                       |
//+------------------------------------------------------------------+
string getsignal()                      // we calculate trading signal here
{
   double rsi=iRSI(Symbol(),0,RSIPeriod,0,0);  // we use RSI to get signal
   if(rsi<LowerLevel) return("buy");    // buy signal returned when
                                        // oversold detected
   if(rsi>UpperLevel) return("sell");   // sell signal returned when
                                        // overbought detected
   return("wait and see");              // no signal returned
} 
//+------------------------------------------------------------------+
//| send order                                                       |
//+------------------------------------------------------------------+     
int sendorder(int cmd,double lots,double prc,double sl,double tp,color warna)
{
   return(OrderSend(Symbol(),cmd,lots,prc,2,sl,tp,"",MagicNumber,0,warna));
}  
//+------------------------------------------------------------------+
//| trailing stop                                                    |
//+------------------------------------------------------------------+   
void trailingstop()                     // we check our opened order to see 
{                                       // posibility to move its stoploss 
   double stoplevel=MarketInfo(Symbol(),MODE_STOPLEVEL); // stoplevel 
   for(int i=OrdersTotal()-1; i>=0; i--) // lets scan all order and position
   {
      OrderSelect(i,SELECT_BY_POS,MODE_TRADES); // is this our order?
      if(OrderSymbol()!=Symbol() ||     // if symbol of order didn't match 
      OrderMagicNumber()!=MagicNumber)  // with current chart symbol 
      continue;                         // or the magic numb of order 
                                        // didn't match with our magic
                                        // number, it is not our's
      if(OrderType()==OP_BUY)           // order type need to be identified 
      {                                 // in order price selection (bid or ask)    
         if(
         MathAbs(OrderTakeProfit()-OrderStopLoss())<=2*stoplevel*pt
           )  break;                    // we calculate range between SL & TP
                                        // to avoid posible error
         if(
         Bid>=OrderStopLoss()+(StopLoss+TrailingStop)*pt
           )                            // common price calculation
         {
             OrderModify(               // moving stoploss
             OrderTicket(),
             OrderOpenPrice(),
             OrderStopLoss()+
             TrailingStop*pt,
             OrderTakeProfit(),
             CLR_NONE);
         }
      }
      if(OrderType()==OP_SELL)
      {
         if(
         MathAbs(OrderTakeProfit()-OrderStopLoss())<=2*stoplevel*pt
           )  break;
         if(
         Ask<=OrderStopLoss()-(StopLoss+TrailingStop)*pt
           )                            // common price calculation
         {
             OrderModify(               // moving stoploss
             OrderTicket(),
             OrderOpenPrice(),
             OrderStopLoss()-
             TrailingStop*pt,
             OrderTakeProfit(),
             CLR_NONE);
         }
      }
   }
}
//+------------------------------------------------------------------+
//| move to break event                                              |
//+------------------------------------------------------------------+   
void breakevent()                       // we check our opened order to see 
{                                       // posibility to move its stoploss 
   double stoplevel=MarketInfo(Symbol(),MODE_STOPLEVEL); // stoplevel 
   for(int i=OrdersTotal()-1; i>=0; i--) // lets scan all order and position
   {
      OrderSelect(i,SELECT_BY_POS,MODE_TRADES); // is this our order?
      if(OrderSymbol()!=Symbol() ||     // if symbol of order didn't match 
      OrderMagicNumber()!=MagicNumber)  // with current chart symbol 
      continue;                         // or the magic numb of order 
                                        // didn't match with our magic
                                        // number, it is not our's
      if(OrderType()==OP_BUY)           // order type need to be identified 
      {                                 // in order price selection (bid or ask)    
         if(
         OrderStopLoss()>=OrderOpenPrice()  // common calculation
           )  break;                    
                                        
         if(
         Bid>=OrderOpenPrice()+(stoplevel+LockedPips)*pt
           )                            // common price calculation
         {
             OrderModify(               // moving stoploss
             OrderTicket(),
             OrderOpenPrice(),
             OrderOpenPrice()+
             LockedPips*pt,
             OrderTakeProfit(),
             CLR_NONE);
         }
      }
      if(OrderType()==OP_SELL)
      {
         if(
         OrderStopLoss()<=OrderOpenPrice()  // common calculation
           )  break;
         if(
         Ask<=OrderOpenPrice()-(stoplevel+LockedPips)*pt
           )                            // common price calculation
         {
             OrderModify(               // moving stoploss
             OrderTicket(),
             OrderOpenPrice(),
             OrderOpenPrice()-
             LockedPips*pt,
             OrderTakeProfit(),
             CLR_NONE);
         }
      }
   }
}
//+------------------------------------------------------------------+
//| order management                                                 |
//+------------------------------------------------------------------+
int ordermanagement()                   // we manage our orders here
{
   if(ordercount()==0)                  // when there is no opened orders 
   {
      if(getsignal()=="buy")            // when buy signal is appeared
      {
        if(sendorder(OP_BUY,mylot(),    // we send our buy order into
           Ask,Ask-StopLoss*pt,         // broker's server then we out
           Ask+TakeProfit*pt,           // from this cycle to avoid
           Blue)>0) return(0);          // errors possibility
      }
      if(getsignal()=="sell")           // same procces as buy signal
      {
        if(sendorder(OP_SELL,mylot(),
           Bid,Bid+StopLoss*pt,
           Bid-TakeProfit*pt,
           Red)>0) return(0);
      }
   }
   if(TrailingStop>0) trailingstop(); // we calling trailing stop function
                                      // if TrailingStop value bigger than 0
   if(MoveToBreakEvent) breakevent(); // we calling breakevent function here
   return(0);
}
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//----
    if(Digits==3 || Digits==5) pt=10*Point;  // when use at broker with 5 digits 
    else                       pt=Point;     // pricing, this function is useful 
    double stoplevel;                        // minimal pips for stop
    stoplevel=MarketInfo(Symbol(),MODE_STOPLEVEL);  // get broker's stoplevel
    if(StopLoss<=stoplevel) StopLoss=stoplevel;   // we compare our StopLoss with
                                             // stoplevel and adjust it when error occured
    if(TakeProfit<=stoplevel) TakeProfit=stoplevel;  // we compared our TakeProfit
                                             // as we compared our StopLoss
//----                                        
    return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
    Comment('');
//----
    return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
    if(Hour()<StartHour)              // when time to trade is not coming yet
    {                                 // let user now
       Comment("\nTrade time is not coming yet..");  // and
       return(0);                     // we just stop here
    }
    if(Hour()>EndHour)                // when time to trade is over
    {                                 // let user know
       Comment("\nTrade time is over...");  // and
       return(0);                     // we just stop here
    }
//----
    Comment("");                      // no comment needed
    ordermanagement();                // we calling order management funtion here
//----
    return(0);                        // we out of our cycle when everything done 
  }
//+------------------------------------------------------------------+