//+------------------------------------------------------------------+
//|                                                  Blessing 2 v5.2 |
//|                              Copyright © 2007-2009, MQLCoder.com |
//|                                                 jta@jtatoday.com |
//|                                             http://www.irxfx.com |
//|                                         fifthelement80@gmail.com |
//|                *** Addition Stochastic Indicator option by epmfx |
//|                      *** AutoCal Timeframe and Period by Bobster | 
//|                          *** Rewritten by TradingSystemForex.com |
//|    In no event will authors be liable for any damages whatsoever |
//|                                             Use at your own risk |
//+------------------------------------------------------------------+

#property copyright "Copyright FiFtHeLeMeNt/J Talon LLC © 2007-2009."
#property link "http://www.mqlcoder.com"

extern int magic=1234;             // magic number
extern string comment="Blessing";  // comment to display in the trades

extern string moneymanagement="Money Management";

extern int initialbalance=5000;    // initial account balance
extern int accounttype=1;          // used in money management feature only, 1=standard, 10=micro
extern double lots=0.01;           // starting lots if money management is off
extern bool mm=true;               // money management
extern int risk=1;                 // risk percentage of the account for each trade
extern double lotadjustment=1.0;   // adjusts mm base lot for large accounts
extern double multiplier=1.1;      // multiplier on each level
extern double multiplier2=2;       // second multiplier on each level
extern double lotinc=0;            // lot increment on each level, very dangerous
extern int lotdigits=2;            // 2 for micro lots, 1 for mini
extern bool equityprotection=true; // close all orders when negative float is excessive
extern double floatpercent=15;     // percent of portion for max Float level

extern string ordersmanagement="Order Management";

extern bool autogrid=true;         // auto calculation of takeProfit and grid size;
extern int atrtimeframe=1440;      // auto tp grid timeframe
extern int atrperiod=21;           // auto tp grid period
extern double atrfactor1=2;
extern double atrfactor2=2;
extern double atrfactor3=4;
extern double autogridadjust=1.0;  // widens/squishes grid on increments/decrements of .1
extern int pipstep1=25;            // set 1 grid size
extern int pipstep2=50;            // level 2 grid size
extern int pipstep3=100;           // level 3 grid size
extern int takeprofit1=50;         // set 1 take profit
extern int takeprofit2=100;        // level 2 take profit
extern int takeprofit3=200;        // level 3 take profit
extern int timegrid=2400;          // time grid in seconds, to avoid opening of lots of levels in fast market
extern int maxlevels1=4;           // level 1 max levels
extern int maxlevels2=4;           // level 2 max levels
extern int maxlevels=99;           // level 2 max levels (stops placing orders when reaches maxlvl2)
extern int closelevel=12;          // close all level, when reaches this level, doesn't wait for TP to be hit
int roundnumber=5;                 // used to offset entry to round numbers , for example if you set d=5,
                                   // it will place its sell order on 1.5795 instead of 1.5780

extern string entrylogics="Entry Logics";

extern bool bollinger=true;        // bollinger bands filter
extern int bbtimeframe=0;
extern int bbperiod=15;
extern double deviation=2.0;
extern double bbdistance=13;
extern int bbmethod=0;
extern int bbprice=1;
extern int bbshift=0;
extern int closeshift=0;
extern bool stochastics=true;
extern int stochtimeframe=0;
extern int kperiod=20;             // stochastic parameters
extern int dperiod=2;
extern int slowing=2;
extern int stochmethod=3;
extern int stochprice=1;
extern int overbought=80;
extern int oversold=20;
extern int stochshift=1;
extern bool volume=false;
extern double maxvolume=250;
extern int slippage=999;           // tolerance of order slips/requotes for closing

// Internal Parameters Set

bool openedorders=false;
double slip=0;
double riskbalance,riskequity,initialmultirisk,dd,maxdd,maxddpercent;
int decimal=1,trading=1;
int round,count;

// Expert initialization function

int init(){
   if(Digits==3 || Digits==5)decimal=10;
   return(0);
}

// Expert deinitialization function

int deinit(){
   return(0);
}

// Expert start function

int start(){
   int i;
   int countbuy=0,countsell=0,countbuylimit=0,countselllimit=0,countbuystop=0,countsellstop=0;
   double countbuylot=0,countselllot=0,profit=0;
   double ma,stddev,bbup,bbulevel,bbdn,bbdlevel,floatingpoint,lots2;
   double lastopenprice,lastopenlots,lastopentp,lastopentime,pipstep,tp,entry;

   // Calculate Total Profits and Total Orders

   for(i=0;i<OrdersTotal();i++){
      OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
      if((OrderMagicNumber()==magic) && (OrderSymbol()==Symbol()) && (OrderType()==OP_BUY)){
         countbuy++;
         profit=profit+OrderProfit();
         countbuylot=countbuylot+OrderLots();
      }
      if((OrderMagicNumber()==magic) && (OrderSymbol()==Symbol()) && (OrderType()==OP_SELL)){
         countsell++;
         profit=profit+OrderProfit();
         countselllot=countselllot+OrderLots();
      }
      if((OrderMagicNumber()==magic) && (OrderSymbol()==Symbol()) && (OrderType()==OP_BUYLIMIT))countbuylimit++;
      if((OrderMagicNumber()==magic) && (OrderSymbol()==Symbol()) && (OrderType()==OP_SELLLIMIT))countselllimit++;
      if((OrderMagicNumber()==magic) && (OrderSymbol()==Symbol()) && (OrderType()==OP_BUYSTOP))countbuystop++;
      if((OrderMagicNumber()==magic) && (OrderSymbol()==Symbol()) && (OrderType()==OP_SELLSTOP))countsellstop++;
   }

   // Account Protection

   riskbalance=NormalizeDouble(AccountBalance()/risk,2);
   riskequity=NormalizeDouble(riskbalance+profit,2);
   if(equityprotection){if(riskbalance-riskequity>=(riskbalance*floatpercent/100))exitalltrades(Red,"Equity Stop Loss Reached");}

   // Trading with EA Criteria

   initialmultirisk=initialbalance/risk;
   if(riskbalance<initialmultirisk){return(0);}

   // Money Management and Lot size coding
   
   if(mm){
      double contracts,factor,lotsize;
      contracts=(AccountBalance()/10000)/risk;
      factor=multiplier+MathPow(multiplier,2)+MathPow(multiplier,3)+MathPow(multiplier,4)+MathPow(multiplier,5)+MathPow(multiplier,6);
      lotsize=lotadjustment*accounttype*(contracts/(1.0+factor));

      // Determine Lot size boundries from minimum to maximum

      lots=NormalizeDouble(lotsize,lotdigits);

      if(lotsize<0.01)lots=0.01;
      if(lotsize>100/MathPow(multiplier,6) && accounttype==1)lots=NormalizeDouble(100/MathPow(multiplier,6),lotdigits);
      if(lotsize>50/MathPow(multiplier,6) && accounttype==10)lots=NormalizeDouble(50/MathPow(multiplier,6),lotdigits);
   }

   // ATR to autocalculate the Grid 

   double grid,atr;
   double atrvalue=iATR(NULL,atrtimeframe,atrperiod,0); // Bobster added external variables; default is 1440, 21
   if(autogrid==true){
      if(Digits==2 || Digits==3)atr=atrvalue*100;
      if(Digits==4 || Digits==5)atr=atrvalue*10000;
      grid=atr*atrfactor1/10;
      pipstep1=grid;
      takeprofit1=grid+pipstep1;
      pipstep2=takeprofit1;
      takeprofit2=(grid+pipstep1)*atrfactor2;
      pipstep3=takeprofit2;
      takeprofit3=(grid+pipstep1)*atrfactor3;
   }

   double Balance=AccountBalance();
   double Equity=AccountEquity();
   dd=Balance-Equity;

   if(dd>maxdd)maxdd=dd;

   maxddpercent=(maxdd/Balance)*100;

   // Blessing Code  

   if(countsell==0 && countbuy==0 && countbuystop==0 && countbuylimit==0 && countsellstop==0 && countselllimit==0)openedorders=false;
     
   slip=NormalizeDouble((slippage*decimal),0);
  
   if(((countbuy>=closelevel || countsell>=closelevel) && profit>0) || openedorders){
      openedorders=true;
      for(i=0;i<OrdersTotal();i++){
         OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
         if((OrderMagicNumber()==magic) && (OrderSymbol()==Symbol()) && (OrderType()==OP_BUY || OrderType()==OP_SELL))OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),slip,Lime);
         if((OrderMagicNumber()==magic) && (OrderSymbol()==Symbol()) && (OrderType()==OP_BUYLIMIT || OrderType()==OP_SELLLIMIT || OrderType()==OP_BUYSTOP || OrderType()==OP_SELLSTOP))
         OrderDelete(OrderTicket(),White);
      }
      return;
   }
   round=roundnumber;
   if(decimal==10)round=roundnumber*10;
   pipstep=pipstep1;
   tp=takeprofit1;

   if(countbuy>=maxlevels1 || countsell>=maxlevels1){pipstep=pipstep2;tp=takeprofit2;}
   if(countbuy>=maxlevels2+maxlevels1 || countsell>=maxlevels2+maxlevels1){pipstep=pipstep3;tp=takeprofit3;}

   // Broker Decimal Selection

   if(decimal==10){pipstep*=10;tp*=10;}

   // Adjust Grid and Normalize Values

   pipstep=NormalizeDouble(pipstep*autogridadjust,0);
   tp=NormalizeDouble(tp*autogridadjust,0);

   // Bollinger Band trade Long/Short

   if(bollinger){
      ma=iMA(Symbol(),bbtimeframe,bbperiod,0,bbmethod,bbprice,bbshift);
	   stddev=iStdDev(Symbol(),bbtimeframe,bbperiod,0,bbmethod,bbprice,bbshift);   
      bbup=ma+(deviation*stddev);
      bbdn=ma-(deviation*stddev);
      bbulevel=(bbup+(bbdistance*Point));
      bbdlevel=(bbdn-(bbdistance*Point));
   }
   
   // Trade Selection Logic

   if((countbuy==0) && (countsell==0)){
      for(i=0;i<OrdersTotal();i++){
         OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
         if((OrderMagicNumber()==magic) && (OrderSymbol()==Symbol()) && (OrderLots()>lots))OrderDelete(OrderTicket());
      }
      if((bollinger==false || (bollinger && Close[closeshift]<bbdlevel))
         && (stochastics==false || (stochastics && iStochastic(NULL,stochtimeframe,kperiod,dperiod,slowing,stochmethod,stochprice,0,stochshift)<oversold
         && iStochastic(NULL,stochtimeframe,kperiod,dperiod,slowing,stochmethod,stochprice,1,stochshift)<oversold))
         && (volume==false || (volume && Volume[0]<maxvolume && Volume[1]<maxvolume))){
         if(countbuystop==0){if(tp>=10)OrderSend(Symbol(),OP_BUY,lots,Ask,0,0,Ask+tp*Point,comment,magic,0,Blue);return;}
      }
      if((bollinger==false || (bollinger && Close[closeshift]>bbulevel))
         && (stochastics==false || (stochastics && iStochastic(NULL,stochtimeframe,kperiod,dperiod,slowing,stochmethod,stochprice,0,stochshift)>overbought
         && iStochastic(NULL,stochtimeframe,kperiod,dperiod,slowing,stochmethod,stochprice,1,stochshift)>overbought))
         && (volume==false || (volume && Volume[0]<maxvolume && Volume[1]<maxvolume))){
         if(countsellstop==0){if(tp>=10)OrderSend(Symbol(),OP_SELL,lots,Bid,0,0,Bid-tp*Point,comment,magic,0,Red);return;}
      }
   }
   if(countbuy>0 || countsell>0){
      for(i=0;i<OrdersTotal();i++){
         OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
         if((OrderMagicNumber()==magic) && (OrderSymbol()==Symbol()) && (OrderType()!=OP_SELL) && (OrderType()!=OP_BUY) && OrderLots()==lots)OrderDelete(OrderTicket());
      }
   }
   if(countbuy>0){
      for(i=0;i<OrdersTotal();i++){
         OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
         if((OrderMagicNumber()!=magic) || (OrderType()!=OP_BUY) || (OrderSymbol()!=Symbol())){continue;}
         lastopenprice=OrderOpenPrice();lastopenlots=OrderLots();lastopentp=OrderTakeProfit();lastopentime=OrderOpenTime();
      }
      if((TimeCurrent()-timegrid>lastopentime) && (countbuy<maxlevels)){
         if(lastopenprice>Ask)entry=NormalizeDouble(lastopenprice-(MathRound((lastopenprice-Ask)/Point/pipstep)+1)*pipstep*Point,Digits);
         else entry=NormalizeDouble(lastopenprice-pipstep*Point,Digits);
         if(lastopenlots<=0.01)lots2=NormalizeDouble(lastopenlots*multiplier2+lotinc,lotdigits);else lots2=NormalizeDouble(lastopenlots*multiplier+lotinc,lotdigits);
         if(countbuylimit==0){OrderSend(Symbol(),OP_BUYLIMIT,lots2,entry,0,0,entry+tp*Point,comment,magic);return;}
         if(countbuylimit==1){
            for(i=0;i<OrdersTotal();i++){
               OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
               if(OrderType()==OP_BUYLIMIT && OrderMagicNumber()==magic && (OrderSymbol()==Symbol()) && entry-OrderOpenPrice()>pipstep/2*Point){
                  OrderModify(OrderTicket(),entry,0,entry+tp*Point,0);
               }
            }
         }
      }
      for(i=0;i<OrdersTotal();i++){ // Sync TPs
         OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
         if((OrderMagicNumber()!= magic) || (OrderType()!=OP_BUY) || (MathAbs(OrderTakeProfit()-lastopentp)<Point) || (OrderSymbol()!=Symbol())){continue;}
         OrderModify(OrderTicket(),OrderOpenPrice(),0,lastopentp,0,Blue);
         return;
      }
   }
   if(countsell>0){
      for(i=0;i<OrdersTotal();i++){
         OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
         if((OrderMagicNumber()!=magic) || (OrderType()!=OP_SELL) || (OrderSymbol()!=Symbol())){continue;}
         lastopenprice=OrderOpenPrice();lastopenlots=OrderLots();lastopentp=OrderTakeProfit();lastopentime=OrderOpenTime();
      }

      if((TimeCurrent()-timegrid>lastopentime) && (countsell<maxlevels)){
         if(Bid>lastopenprice)entry=NormalizeDouble(lastopenprice+(MathRound((-lastopenprice+Bid)/Point/pipstep)+1)*pipstep*Point,Digits);
         else entry=NormalizeDouble(lastopenprice+pipstep*Point,Digits);
         if(lastopenlots<=0.01)lots2=NormalizeDouble(lastopenlots*multiplier2+lotinc,lotdigits);else lots2=NormalizeDouble(lastopenlots*multiplier+lotinc,lotdigits);
         if(countselllimit==0){OrderSend(Symbol(),OP_SELLLIMIT,lots2,entry,0,0,entry-tp*Point,comment,magic);return;}
         if(countselllimit==1){
            for(i=0;i<OrdersTotal();i++){
               OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
               if(OrderType()==OP_SELLLIMIT && OrderMagicNumber()==magic && (OrderSymbol()==Symbol()) && OrderOpenPrice()-entry>pipstep/2*Point){
               OrderModify(OrderTicket(),entry,0,entry-tp*Point,0);
            }
         }
      }
   }
   for(i=0;i<OrdersTotal();i++){ // Sync TPs
      OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
      if((OrderMagicNumber()!=magic) || (OrderType()!=OP_SELL) || (MathAbs(OrderTakeProfit()-lastopentp)<Point) || (OrderSymbol()!=Symbol())){continue;}
         OrderModify(OrderTicket(),OrderOpenPrice(),0,lastopentp,0,Red);
         return;
      }
    }

   return(0);
}

void exitalltrades(color clr,string reason){
   slip=NormalizeDouble((slippage*decimal),0);
   bool success;
   for(int cnt=OrdersTotal()-1;cnt>=0;cnt--){
      OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES);
      if(OrderSymbol()==Symbol() && OrderMagicNumber()==magic){
         OrderDelete(OrderTicket(),clr);
         success=OrderClose(OrderTicket(),OrderLots(),OrderClosePrice(),slip,clr);
      }
   }
}