//+-------------------+ //|Stoch Martingale | //+-------------------+ #property copyright "Ron Thompson" #property link "http://www.ForexMT4.com/" // Modified Les King // This EA is NEVER to be SOLD individually // This EA is NEVER to be INCLUDED as part of a collection that is SOLD // EA SPECIFIC extern int SchoK = 18 ; extern int SchoD = 4 ; extern int SchoS = 4 ; extern double PipsperStep = 25.0 ; extern double LotMultiplier = 1.5 ; // user input extern double Lots = 0.05 ; extern double ProfitMade = 40 ; extern double LossLimit = 0 ; extern int LotResolution = 2 ; extern bool KillLogging = true ; // Trade control double lotsi; // used for Martingale loss recovery double myPoint; // support for 3/5 decimal places int Slippage=2; // how many pips of slippage can you tolorate bool TradeAllowed=true; // used to manage trades int loopcount; // count of order attempts int maxloop=25; // maximum number of attempts to handle errors int LL2SL=10; // LossLimit to StopLoss server spread int maxOrders; // statistic for maximum numbers or orders open at one time extern double maxLots= 0.7; // Largest lot size ever opened int MagicNumber = 153591; // allows multiple experts to trade on same account string TradeComment = "_sm01a.txt"; // where to log information double MinLotMultiplier; // Bar handling datetime bartime=0; // used to determine when a bar has moved //EA specific string currDirection="NONE"; string currOU80; string prevOU80; string currOU20; string prevOU20; // used for verbose error logging #include //+-------------+ //| Custom init | //|-------------+ // Called ONCE when EA is added to chart or recompiled int init() { // get normalized Point based on Broker decimal places myPoint = SetPoint(); // used for Martingale lotsi=Lots; if(IsTesting()) LL2SL=100; if(IsTesting()) maxloop=2; logwrite(TradeComment,"Init Complete"); Comment(" "); } //+----------------+ //| Custom DE-init | //+----------------+ // Called ONCE when EA is removed from chart int deinit() { // always indicate deinit statistics logwrite(TradeComment,"MAX number of orders "+maxOrders); logwrite(TradeComment,"Max Lots is "+maxLots); logwrite(TradeComment,"DE-Init Complete"); Comment(" "); } //+-----------+ //| Main | //+-----------+ // Called EACH TICK and each Bar[] int start() { int cnt=0; int gle=0; int ticket=0; int OrdersPerSymbol=0; // stoploss and takeprofit and close control double SL=0; double TP=0; double CurrentProfit=0; double CurrentPips=0; // direction control bool BUYme=false; bool SELLme=false; double MaCurrent; double MaPrevious; //safety counter int loopcount=0; // bar counting if(bartime!=Time[0]) { bartime=Time[0]; //You can trade every new bar TradeAllowed=true; } if (MarketInfo(Symbol(),MODE_MINLOT) == 0.01) { MinLotMultiplier = 100; } if (MarketInfo(Symbol(),MODE_MINLOT) == 0.05) { MinLotMultiplier = 20; } if (MarketInfo(Symbol(),MODE_MINLOT) == 0.1) { MinLotMultiplier = 10; } //+-----------------------------+ //| Insert your indicator here | //| And set either BUYme or | //| SELLme true to place orders | //+-----------------------------+ OrdersPerSymbol=0; CurrentPips=0; for(cnt=OrdersTotal();cnt>=0;cnt--) { OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES); if( OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber) { OrdersPerSymbol++; if(OrdersPerSymbol>maxOrders) maxOrders=OrdersPerSymbol; // add up pips if(OrderType()==OP_BUY ) CurrentPips=CurrentPips+(( Close[0]-OrderOpenPrice() )/myPoint); if(OrderType()==OP_SELL ) CurrentPips=CurrentPips+(( (Close[0]-OrderOpenPrice()) * (-1) )/myPoint); } } double Smain = iStochastic(Symbol(),0,SchoK,SchoD,SchoS,MODE_SMA,0,MODE_MAIN ,1); double Ssgnl = iStochastic(Symbol(),0,SchoK,SchoD,SchoS,MODE_SMA,0,MODE_SIGNAL,1); if(Smain>80 && Ssgnl>80) currOU80="OVER" ; if(Smain<80 && Ssgnl<80) currOU80="UNDER"; if(Smain>20 && Ssgnl>20) currOU20="OVER" ; if(Smain<20 && Ssgnl<20) currOU20="UNDER"; if(prevOU20=="UNDER" && currOU20=="OVER") { BUYme=true; if(currDirection=="NONE") currDirection="LONG"; } if(prevOU80=="OVER" && currOU80=="UNDER") { SELLme=true; if(currDirection=="NONE") currDirection="SHORT"; } prevOU80=currOU80; prevOU20=currOU20; if(CurrentPips<0) { // calculate new lot size based on pips down and step and multiplier lotsi=MathFloor(NormalizeDouble(Lots* ((MathAbs(CurrentPips)/PipsperStep)*LotMultiplier), LotResolution )*MinLotMultiplier)/MinLotMultiplier; if( lotsi>MarketInfo(Symbol(), MODE_MAXLOT) ) lotsi=MarketInfo(Symbol(), MODE_MAXLOT); } else { lotsi=Lots; } // Not sure if this is a bug but why increase maxlots when it is exceeded // if(lotsi>maxLots) maxLots=lotsi; if(lotsi > maxLots) lotsi = maxLots; if (lotsi < Lots) lotsi = Lots; // Correct for possible 0 lots //+------------+ //| End Insert | //+------------+ //ENTRY LONG (buy, Ask) if( TradeAllowed && BUYme && currDirection=="LONG") { OpenBuy(); } //ENTRY SHORT (sell, Bid) if( TradeAllowed && SELLme && currDirection=="SHORT") { OpenSell(); } // // Order Management // for(cnt=OrdersTotal();cnt>=0;cnt--) { OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES); if( OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber ) { if(OrderType()==OP_BUY) { CurrentProfit=(NormalizeDouble(Bid,Digits)-OrderOpenPrice()) ; // Did we make a profit //====================== if(ProfitMade>0 && CurrentProfit>=(ProfitMade*myPoint)) { CloseEverything(); lotsi=Lots; currDirection="NONE"; } // Did we take a loss //==================== if(LossLimit>0 && CurrentProfit<=(LossLimit*(-1)*myPoint)) { CloseBuy("LOSS"); } } // if BUY if(OrderType()==OP_SELL) { CurrentProfit=(OrderOpenPrice()-NormalizeDouble(Ask,Digits)); // Did we make a profit //====================== if( ProfitMade>0 && CurrentProfit>=(ProfitMade*myPoint) ) { CloseEverything(); lotsi=Lots; currDirection="NONE"; } // Did we take a loss //==================== if( LossLimit>0 && CurrentProfit<=(LossLimit*(-1)*myPoint) ) { CloseSell("LOSS"); } } //if SELL } // if(OrderSymbol) } // for } // start() //========================================================================================================= //========================================================================================================= //========================================================================================================= //========================================================================================================= //========================================================================================================= //========================================================================================================= //========================================================================================================= //========================================================================================================= //+-----------------+ //| CloseEverything | //+-----------------+ // Closes all OPEN and PENDING orders int CloseEverything() { int i; for(i=OrdersTotal();i>=0;i--) { OrderSelect(i, SELECT_BY_POS); if(OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber) { if(OrderType()==OP_BUY) CloseBuy ("CloseEverything"); if(OrderType()==OP_SELL) CloseSell("CloseEverything"); if(OrderType()==OP_BUYLIMIT) OrderDelete( OrderTicket() ); if(OrderType()==OP_SELLLIMIT) OrderDelete( OrderTicket() ); if(OrderType()==OP_BUYSTOP) OrderDelete( OrderTicket() ); if(OrderType()==OP_SELLSTOP) OrderDelete( OrderTicket() ); } Sleep(1000); } //for } // closeeverything // log data to a file name passed in // print everything regardless of log setting void logwrite (string filename, string mydata) { int myhandle; string gregorian=TimeToStr(CurTime(),TIME_DATE|TIME_SECONDS); Print(mydata+" "+gregorian); // don't log anything if testing or if user doesn't want it if(IsTesting()) return(0); if(KillLogging) return(0); myhandle=FileOpen(Symbol()+"_"+filename, FILE_CSV|FILE_WRITE|FILE_READ, ";"); if(myhandle>0) { FileSeek(myhandle,0,SEEK_END); FileWrite(myhandle, mydata+" "+gregorian); FileClose(myhandle); } } //ENTRY LONG (buy, Ask) void OpenBuy() { int gle=0; int ticket=0; double SL=0; double TP=0; int loopcount; // PLACE order is independent of MODIFY order. // This is mandatory for ECNs and acceptable for retail brokers loopcount=0; while(true) { // place order - NO TP OR SL ticket=OrderSend(Symbol(),OP_BUY,lotsi,NormalizeDouble(Ask,Digits),Slippage,0,0,TradeComment,MagicNumber,White); gle=GetLastError(); if(gle==0) { // logwrite(TradeComment,"BUY PLACED Ticket="+ticket+" Ask="+Ask+" Lots="+lotsi); TradeAllowed=false; break; } else { logwrite(TradeComment,"-----ERROR----- Placing BUY order: Lots="+lotsi+" Bid="+NormalizeDouble(Bid,Digits)+" Ask="+NormalizeDouble(Ask,Digits)+" ticket="+ticket+" Err="+gle+" "+ErrorDescription(gle)); RefreshRates(); Sleep(500); // give up after loopcount tries loopcount++; if(loopcount>maxloop) { logwrite(TradeComment,"-----ERROR----- Giving up on placing BUY order"); return(gle); } } }//while - place order // modify the order for users TP & SL loopcount=0; while(true) { // don't set TP and SL both to zero, they're already there if(LossLimit==0 && ProfitMade==0) break; if(LossLimit ==0) SL=0; if(ProfitMade ==0) TP=0; if(LossLimit >0) { SL=NormalizeDouble(Ask,Digits)-((LossLimit+LL2SL)*myPoint ); SL = NormalizeDouble(SL, Digits); } if(ProfitMade >0) { TP=NormalizeDouble(Ask,Digits)+((ProfitMade+LL2SL)*myPoint ); TP = NormalizeDouble(TP, Digits); } OrderModify(ticket,OrderOpenPrice(),SL,TP,0,White); gle=GetLastError(); if(gle==0) { // logwrite(TradeComment,"BUY MODIFIED Ticket="+ticket+" Ask="+Ask+" Lots="+lotsi+" SL="+SL+" TP="+TP); break; } else { logwrite(TradeComment,"-----ERROR----- Modifying BUY order: Lots="+lotsi+" SL="+SL+" TP="+TP+" Bid="+NormalizeDouble(Bid,Digits)+" Ask="+NormalizeDouble(Ask,Digits)+" ticket="+ticket+" Err="+gle+" "+ErrorDescription(gle)); RefreshRates(); Sleep(500); loopcount++; if(loopcount>maxloop) { logwrite(TradeComment,"-----ERROR----- Giving up on modifying BUY order"); return(gle); } } }//while - modify order }//BUYme //ENTRY SHORT (sell, Bid) void OpenSell() { int gle=0; int ticket=0; double SL=0; double TP=0; int loopcount; // PLACE order is independent of MODIFY order. // This is mandatory for ECNs and acceptable for retail brokers loopcount=0; while(true) { ticket=OrderSend(Symbol(),OP_SELL,lotsi,NormalizeDouble(Bid,Digits),Slippage,0,0,TradeComment,MagicNumber,Red); gle=GetLastError(); if(gle==0) { // logwrite(TradeComment,"SELL PLACED Ticket="+ticket+" Bid="+Bid+" Lots="+lotsi); TradeAllowed=false; break; } else { logwrite(TradeComment,"-----ERROR----- placing SELL order: Lots="+lotsi+" SL="+SL+" TP="+TP+" Bid="+NormalizeDouble(Bid,Digits)+" Ask="+NormalizeDouble(Ask,Digits)+" ticket="+ticket+" Err="+gle+" "+ErrorDescription(gle)); RefreshRates(); Sleep(500); loopcount++; if(loopcount>maxloop) { logwrite(TradeComment,"-----ERROR----- Giving up on placing SELL order"); return(gle); } } }//while // modify the order for users TP & SL loopcount=0; while(true) { // don't set TP and SL both to zero, they're already there if(LossLimit==0 && ProfitMade==0) break; if(LossLimit ==0) SL=0; if(ProfitMade ==0) TP=0; if(LossLimit >0) { SL=NormalizeDouble(Bid,Digits)+((LossLimit+LL2SL)*myPoint ); SL = NormalizeDouble (SL, Digits); } if(ProfitMade >0) { TP=NormalizeDouble(Bid,Digits)-((ProfitMade+LL2SL)*myPoint ); TP = NormalizeDouble(TP, Digits); } OrderModify(ticket,OrderOpenPrice(),SL,TP,0,Red); gle=GetLastError(); if(gle==0) { // logwrite(TradeComment,"SELL MODIFIED Ticket="+ticket+" Bid="+Bid+" Lots="+lotsi+" SL="+SL+" TP="+TP); TradeAllowed=false; break; } else { logwrite(TradeComment,"-----ERROR----- modifying SELL order: Lots="+lotsi+" SL="+SL+" TP="+TP+" Bid="+NormalizeDouble(Bid,Digits)+" Ask="+NormalizeDouble(Ask,Digits)+" ticket="+ticket+" Err="+gle+" "+ErrorDescription(gle)); RefreshRates(); Sleep(500); loopcount++; if(loopcount>maxloop) { logwrite(TradeComment,"-----ERROR----- Giving up on placing SELL order"); return(gle); } } }//while }//SELLme void CloseBuy (string myInfo) { int gle; int cnt; int OrdersPerSymbol; int loopcount=0; string bTK=" Ticket="+OrderTicket(); string bSL=" SL="+OrderStopLoss(); string bTP=" TP="+OrderTakeProfit(); string bPM; string bLL; string bER; bPM=" PM="+ProfitMade; bLL=" LL="+LossLimit; while(true) { OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(Bid,Digits),Slippage,White); gle=GetLastError(); bER=" error="+gle+" "+ErrorDescription(gle); if(gle==0) { // logwrite(TradeComment,"CLOSE BUY "+myInfo+ bTK + bSL + bTP + bPM + bLL); break; } else { logwrite(TradeComment,"-----ERROR----- CLOSE BUY "+myInfo+ bER +" Bid="+NormalizeDouble(Bid,Digits)+ bTK + bSL + bTP + bPM + bLL); RefreshRates(); Sleep(500); } loopcount++; if(loopcount>maxloop) { logwrite(TradeComment,"-----ERROR----- Giving up on closing SELL order"); return(gle); } }//while } void CloseSell (string myInfo) { int gle; int cnt; int OrdersPerSymbol; int loopcount=0; string sTK=" Ticket="+OrderTicket(); string sSL=" SL="+OrderStopLoss(); string sTP=" TP="+OrderTakeProfit(); string sPM; string sLL; string sER; sPM=" PM="+ProfitMade; sLL=" LL="+LossLimit; while(true) { OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(Ask,Digits),Slippage,Red); gle=GetLastError(); sER=" error="+gle+" "+ErrorDescription(gle); if(gle==0) { // logwrite(TradeComment,"CLOSE SELL "+myInfo + sTK + sSL + sTP + sPM + sLL); break; } else { logwrite(TradeComment,"-----ERROR----- CLOSE SELL "+myInfo+ sER +" Ask="+NormalizeDouble(Ask,Digits)+ sTK + sSL + sTP + sPM + sLL); RefreshRates(); Sleep(500); } loopcount++; if(loopcount>maxloop) { logwrite(TradeComment,"-----ERROR----- Giving up on closing SELL order"); return(gle); } }//while } // Function to correct the value of Point // for brokers that add an extra digit to price // Courtesy of Robert Hill double SetPoint() { double mPoint; if (Digits < 4) mPoint = 0.01; else mPoint = 0.0001; return(mPoint); }