//+--------+ //|DollarCostAverage //+--------+ #property copyright "Ron Thompson" #property link "http://www.ForexMT4.com/forex" // This EA is NEVER to be SOLD individually // This EA is NEVER to be INCLUDED as part of a collection that is SOLD // user input extern int LSMAPeriod = 11; extern double Lots = 0.01; extern double slope = 2.0; extern double ProfitMade = 10; extern double LossLimit = 40; extern bool KillLogging = true; // Trade control int Slippage=2; // how many pips of slippage can you tolorate 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 double maxLots; // Largest lot size ever opened int MagicNumber = 142555; // allows multiple experts to trade on same account string TradeComment = "_DCA.txt"; // where to log information // Bar handling datetime bartime=0; // used to determine when a bar has moved //objects int uniq=0; int i; // used for verbose error logging #include <stdlib.mqh> // direction and change detector double lsma0; double lsma1; int ldiff; int currdir; int prevdir; //+-------------+ //| Custom init | //|-------------+ // Called ONCE when EA is added to chart or recompiled int init() { if( IsTesting() ) LL2SL=50; //remove the old objects ObjectsDeleteAll(); // current bar is current bar // prevents trade when placing EA on chart bartime=Time[0]; // draw the indicator for comparison for(i=500; i>=0; i--) { lsma0=NormalizeDouble(LSMA(LSMAPeriod, i),4); lsma1=NormalizeDouble(LSMA(LSMAPeriod, i+1),4); ldiff=((lsma0-lsma1)/Point); ObjectCreate("myx"+DoubleToStr(uniq,0), OBJ_TEXT, 0, Time[i], lsma0 ); ObjectSetText("myx"+DoubleToStr(uniq,0),DoubleToStr(ldiff,0),15,"Arial",White); uniq++; } // set the directions at the end of the loop // based on Bar[0] and Bar[1] if(lsma0>lsma1) { //Rising currdir=2; prevdir=2; } else { //falling currdir=1; prevdir=1; } logwrite(TradeComment,"Account balance="+AccountBalance()+" Lots="+Lots); logwrite(TradeComment,"Init Complete"); Comment(" "); } //+----------------+ //| Custom DE-init | //+----------------+ // Called ONCE when EA is removed from chart int deinit() { ObjectsDeleteAll(); // 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; string cmt; string sDir; string sCA; // stoploss and takeprofit and close control double SL=0; double TP=0; double CurrentProfit=0; // order management string oTK; string oSL; string oTP; string oPM; string oLL; string oER; // keep some statistics OrdersPerSymbol=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; lsma1=NormalizeDouble(LSMA(LSMAPeriod, 1),4); lsma0=NormalizeDouble(LSMA(LSMAPeriod, 0),4); // bar counting if(bartime!=Time[0]) { bartime=Time[0]; Print ("-----Tick!"); //draw number on chart // save previous ldiff value for direction check ldiff=((lsma0-lsma1)/Point); ObjectCreate("myx"+DoubleToStr(uniq,0), OBJ_TEXT, 0, Time[0], lsma0 ); ObjectSetText("myx"+DoubleToStr(uniq,0),DoubleToStr(ldiff,0),15,"Arial",Aqua); uniq++; //default is sideways //and closeall =no change sDir=" Sideways"; sCA=" as bafore"; // Rising //if( lsma0>(lsma1+(slopeADJ*Point)) ) if( lsma0>(lsma1+(slope*Point)) ) { sDir="Rising"; // has the direction changed, including slope currdir=2; if(currdir!=prevdir) { sCA=" was Falling"; CloseEverything(); prevdir=currdir; } if(LossLimit ==0) SL=0; else SL=Ask-((LossLimit+LL2SL)*Point ); if(ProfitMade==0) TP=0; else TP=Ask+((ProfitMade+LL2SL)*Point ); ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,Slippage,SL,TP,TradeComment,MagicNumber,White); logwrite(TradeComment,"BUY Ticket="+ticket+" Ask="+Ask+" Lots="+Lots+" SL="+SL+" TP="+TP); } // Falling //if( lsma0<(lsma1-(slopeADJ*Point)) ) if( lsma0<(lsma1-(slope*Point)) ) { sDir="Falling"; // has the direction changed, including slope currdir=1; if(currdir!=prevdir) { sCA=" was Rising"; CloseEverything(); prevdir=currdir; } if(LossLimit ==0) SL=0; else SL=Bid+((LossLimit+LL2SL)*Point ); if(ProfitMade==0) TP=0; else TP=Bid-((ProfitMade+LL2SL)*Point ); ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,Slippage,SL,TP,TradeComment,MagicNumber,Red); logwrite(TradeComment,"SELL Ticket="+ticket+" Bid="+Bid+" Lots="+Lots+" SL="+SL+" TP="+TP); } cmt="LSMA[0]="+lsma0+" LSMA[1]="+lsma1+" DIFF="+ldiff+" DIRECTION="+sDir+sCA; Comment(cmt); }//bartime // // 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=(Bid-OrderOpenPrice()) ; // Did we make a profit //====================== if(ProfitMade>0 && CurrentProfit>=(ProfitMade*Point)) { oTK=" Ticket="+OrderTicket(); oSL=" SL="+OrderStopLoss(); oTP=" TP="+OrderTakeProfit(); oPM=" PM="+ProfitMade; oLL=" LL="+LossLimit; OrderClose(OrderTicket(),OrderLots(),Bid,Slippage,White); logwrite(TradeComment,"CLOSE BUY PROFIT" + oTK + oSL + oTP + oPM + oLL); } // Did we take a loss //==================== if(LossLimit>0 && CurrentProfit<=(LossLimit*(-1)*Point)) { oTK=" Ticket="+OrderTicket(); oSL=" SL="+OrderStopLoss(); oTP=" TP="+OrderTakeProfit(); oPM=" PM="+ProfitMade; oLL=" LL="+LossLimit; OrderClose(OrderTicket(),OrderLots(),Bid,Slippage,White); logwrite(TradeComment,"CLOSE BUY LOSS" + oTK + oSL + oTP + oPM + oLL); } } // if BUY if(OrderType()==OP_SELL) { CurrentProfit=(OrderOpenPrice()-Ask); // Did we make a profit //====================== if( ProfitMade>0 && CurrentProfit>=(ProfitMade*Point) ) { oTK=" Ticket="+OrderTicket(); oSL=" SL="+OrderStopLoss(); oTP=" TP="+OrderTakeProfit(); oPM=" PM="+ProfitMade; oLL=" LL="+LossLimit; OrderClose(OrderTicket(),OrderLots(),Ask,Slippage,Red); logwrite(TradeComment,"CLOSE SELL PROFIT"+ oTK + oSL + oTP + oPM + oLL); } // Did we take a loss //==================== if( LossLimit>0 && CurrentProfit<=(LossLimit*(-1)*Point) ) { oTK=" Ticket="+OrderTicket(); oSL=" SL="+OrderStopLoss(); oTP=" TP="+OrderTakeProfit(); oPM=" PM="+ProfitMade; oLL=" LL="+LossLimit; OrderClose(OrderTicket(),OrderLots(),Ask,Slippage,Red); logwrite(TradeComment,"CLOSE SELL LOSS"+ oTK + oSL + oTP + oPM + oLL); } } //if SELL } // if(OrderSymbol) } // for } // start() // 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); } } double LSMA(int myLPeriod, int myShift ) { int myI; double myLengthvar; double myTmp; double mySum=0; for(myI = myLPeriod; myI >= 1 ; myI--) { myLengthvar = myLPeriod + 1; myLengthvar /= 3; myTmp = 0; myTmp = ( myI - myLengthvar)*Open[myLPeriod-myI+myShift]; mySum+=myTmp; } return( mySum*6/(myLPeriod*(myLPeriod+1)) ); } //+-----------------+ //| CloseEverything | //+-----------------+ // Closes all OPEN and PENDING orders int CloseEverything() { double myAsk; double myBid; int myTkt; double myLot; int myTyp; int i; bool result = false; // int total=OrdersTotal(); // for(int pos=0;pos<total;pos++) for( i=OrdersTotal(); i>=0; i-- ) { OrderSelect(i, SELECT_BY_POS); myAsk=MarketInfo(OrderSymbol(),MODE_ASK); myBid=MarketInfo(OrderSymbol(),MODE_BID); myTkt=OrderTicket(); myLot=OrderLots(); myTyp=OrderType(); switch( myTyp ) { //Close opened long positions case OP_BUY :result = OrderClose(myTkt, myLot, myBid, Slippage, Red); break; //Close opened short positions case OP_SELL :result = OrderClose(myTkt, myLot, myAsk, Slippage, Red); break; } if(result == false) { Alert("Order " , myTkt , " failed to close. Error:" , GetLastError() ); Print("Order " , myTkt , " failed to close. Error:" , GetLastError() ); Sleep(3000); } Sleep(1000); } //for } // closeeverything
Sample
Analysis
Market Information Used:
Series array that contains open time of each bar
Series array that contains open prices of each bar
Indicator Curves created:
Indicators Used:
Custom Indicators Used:
Order Management characteristics:
Checks for the total of open orders
It automatically opens orders when conditions are reached
It Closes Orders by itself
Other Features:
Uses files from the file system
It writes information to file
It issuies visual alerts to the screen