//+------------------------------------------------------------------+
//|                                    PowerSM SemiMartingale-EA.mq4 |
//|             Copyright © 2007, Scott Merritt, mer071898@mchsi.com |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, Scott Merritt, modified by RickD"
#property link      "http://www.mql4.info/, http://www.e2e-fx.com"
#include <stdlib.mqh>

// Edit: 17 June 2010, kijkij from ForexFactory

extern int expertId = 183547;
extern int TakeProfit=40;
extern int StopLoss=10;
extern int BreakevenStop = 30;

extern bool TimeEntry=true;
extern string StartTime="7:00";
extern string StopTime="17:00";
extern bool PriceEntry=false;
extern double Price=1.5500;
extern bool FirstLong=false;
extern string LotsProgression="0.1;0.1;0.2;0.3;0.4;0.6;0.8;1.1;1.5;2.0;2.7;3.6;4.7;6.2;8.0;10.2;13.0;16.5;20.8;26.3;33.1;41.6;52.2;65.5;82.5;103.9;130.9;165;207.9;262;330.1;416;524.7;661.1";
extern bool RestartNewCycle = true;

extern int    slippage=3;   	//slippage for market order processing
extern int    OrderTriesNumber=10; //to repeat sending orders when you receive an error or requote

extern string    EAName="PowerSM"; 

bool buysig,sellsig,cycleended;
int tries,long,short,co,plen,lord,mord,lpos;
double Lot,lots[],tlot,lop,lcp,lsl,ltp, Poin;

double lbid = -1;

int counter = 0;

int init() 
{
   int i,j,k;
   string ls;
   while (true) {
   	j=StringFind(LotsProgression,";",i);
   	if (j>0) {
   		ls=StringSubstr(LotsProgression,i,j-i);
   		i=j+1;
   		k++;
   		ArrayResize(lots,k);
   		lots[k-1]=StrToDouble(ls);
   	} else {
   		ls=StringSubstr(LotsProgression,i);
   		k++;
   		ArrayResize(lots,k);
   		lots[k-1]=StrToDouble(ls);
   		break;
   	}
   }

   plen=ArraySize(lots);
   
   //Change 5 and 3 currency decimal digits into 4 and 2
   if (Point == 0.00001) Poin = 0.0001; 
   else if (Point == 0.001) Poin = 0.01; 
   else Poin = Point;
}

void start()  {
   
   //---- check for history and trading
   if(Bars<100 || IsTradeAllowed()==false) return;
   
   if (lbid == -1) lbid = Bid;

   co=CalculateCurrentOrders();
   if (co > 0) counter = 1;
      
   CheckForSignals();
   CheckForOpen();  
   DoBreakEven(BreakevenStop,0);
   
   lbid = Bid;
}


int CalculateCurrentOrders() {
   int ord; string c;
//----
   for(int i=0;i<OrdersTotal();i++) {
      if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
      if(OrderSymbol()==Symbol() && OrderMagicNumber()==expertId) {
         ord++;
         if (OrderType()==OP_BUY) {
            mord=1;
            if (OrderClosePrice()-OrderOpenPrice()>BreakevenStop*Poin) tlot=MathAbs(tlot); else tlot=-MathAbs(tlot);
         }
         if (OrderType()==OP_SELL) {
            mord=-1;
            if (-OrderClosePrice()+OrderOpenPrice()>BreakevenStop*Poin) tlot=MathAbs(tlot); else tlot=-MathAbs(tlot);
         }
         c=StringSubstr(OrderComment(),0,StringFind(OrderComment(),"_",0));
         lpos=StrToInteger(c);
         return(ord);
      }
   }
//---- return orders volume
   return(ord);
}

double GetLastTrade() 
{
   int ord; lord=0;
   string c;
//----
   for(int i=OrdersHistoryTotal()-1;i>=0;i--) 
   {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)) continue;
      if(OrderSymbol()==Symbol() && OrderMagicNumber()==expertId) 
      {
         if (OrderType()==OP_BUY) lord=1;
         if (OrderType()==OP_SELL) lord=-1;
         c=StringSubstr(OrderComment(),0,StringFind(OrderComment(),"_",0));
         lpos=StrToInteger(c);
         
         lop = NormalizeDouble(OrderOpenPrice(), Digits);
         lcp = NormalizeDouble(OrderClosePrice(), Digits);
         lsl = NormalizeDouble(OrderStopLoss(), Digits);
         ltp = NormalizeDouble(OrderTakeProfit(), Digits);
         
         if (OrderProfit()>0) 
          return(OrderLots()); 
         else 
          return(-OrderLots());
      }
   }
   return(0);
}

bool IsEntryTime()
{
  datetime tm0 = TimeCurrent();
  datetime tm1 = StrToTime(TimeToStr(tm0, TIME_DATE) + " " + StartTime);
  datetime tm2 = StrToTime(TimeToStr(tm0, TIME_DATE) + " " + StopTime);

  bool isTm = false; 
  if (tm1 <= tm2) 
    isTm = isTm || (tm1 <= tm0 && tm0 < tm2);
  else
    isTm = isTm || (tm1 <= tm0 || tm0 < tm2);
  
  return (isTm);
}

void CheckForSignals() 
{
  buysig = false;
  sellsig = false;
      
	if (co > 0) return;

  if (TimeEntry)
  {
    bool cond = IsEntryTime();
    if (!cond) return;
  }

  if (PriceEntry)
  { 
    cond = ((Bid >= Price && lbid < Price) || (Bid <= Price && lbid > Price));
    if (!cond) return;
  }
	
	double lastlot = GetLastTrade();
	if (lastlot >= 0)
	{
	  if (counter > 0)
	  {
	    if (!RestartNewCycle) return;
	  }
	
    if (FirstLong) 
      buysig = true; 
    else 
      sellsig = true;
      
    lpos = 0;
    Lot = lots[0];
	}

	else
	{
    lpos++;

    int BE = 0;
    if (lord > 0 && lcp == lop+BE*Poin) lpos--;
    if (lord < 0 && lcp == lop-BE*Poin) lpos--;

    Lot = lots[lpos];
    if (lord > 0) 
      sellsig = true;
    else if (lord < 0) 
      buysig = true;
  }
}

void CheckForOpen() {
   int    res,tr,TP;
   //---- sell conditions
   if(sellsig && co==0)  {
	   Print("sell open ",Lot," ",lpos);
      res = OpenAtMarket(OP_SELL,Lot,TakeProfit,lpos);
	   if (res>0) { tlot=Lot; }
      return;
   }
   //---- buy conditions
   if(buysig && co==0)  {
	   Print("buy open ",Lot," ",lpos);
      res = OpenAtMarket(OP_BUY,Lot,TakeProfit,lpos);
	   if (res>0) { tlot=Lot; }
      return;
   }
}
  
int OpenAtMarket(int mode,double lot,int TP,int pos) {
   int    res,tr,col;
   double openprice,sl,tp;
   tries=0;
   while (res<=0 && tries<OrderTriesNumber) {
      tr=0; while (tr<5 && !IsTradeAllowed()) { tr++; Sleep(2000); }
      RefreshRates();
      if (mode==OP_SELL) {
         openprice=Bid; 
         if (StopLoss>0) sl=openprice+StopLoss*Poin;
         if (TP>0) tp=openprice-TP*Poin;
         col=Red;
      } else {
         openprice=Ask;
         if (StopLoss>0) sl=openprice-StopLoss*Poin;
         if (TP>0) tp=openprice+TP*Poin;
         col=Blue;
      }
      res=OrderSend(Symbol(),mode,lot,openprice,slippage,sl,tp,pos+"_"+EAName+"_"+expertId,expertId,0,col);
      tries++;
   }
   Print("market order:: ",Symbol(),"  ",mode,"  ",lot,"  ",openprice,"  ",sl,"  ",tp,"  ",pos+"_"+EAName+"_"+expertId);
   if (res<=0) Print("error opening order : ",ErrorDescription(GetLastError()));
   return(res);
}


void DoBreakEven(int BP, int BE) {
   bool bres;
   for (int i = 0; i < OrdersTotal(); i++) {
      if ( !OrderSelect (i, SELECT_BY_POS) )  continue;
      if ( OrderSymbol() != Symbol() || OrderMagicNumber() != expertId )  continue;
      if ( OrderType() == OP_BUY ) {
         if (Bid<OrderOpenPrice()+BP*Poin) continue;
         if ( OrderOpenPrice()+BE*Poin-OrderStopLoss()>Poin/10) {
               //Print(BP,"  ",BE," bestop");
               bres=OrderModify (OrderTicket(), OrderOpenPrice(), OrderOpenPrice()+BE*Poin, OrderTakeProfit(), 0, Black);
				   if (!bres) Print("Error Modifying BE BUY order : ",ErrorDescription(GetLastError()));
         }
      }

      if ( OrderType() == OP_SELL ) {
         if (Ask>OrderOpenPrice()-BP*Poin) continue;
         if ( OrderStopLoss()-(OrderOpenPrice()-BE*Poin)>Poin/10) {
               //Print(BP,"  ",BE," bestop");
               bres=OrderModify (OrderTicket(), OrderOpenPrice(), OrderOpenPrice()-BE*Poin, OrderTakeProfit(), 0, Gold);
				   if (!bres) Print("Error Modifying BE SELL order : ",ErrorDescription(GetLastError()));
         }
      }
   }
   return;
}