//+--------+ //|DollarCostAverage //+--------+ #property copyright "Ron Thompson" #property link "http://www.lightpatch.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 // EA SPECIFIC extern int LSMAPeriod = 57; // user input extern double MinFreeMarginPct = 25.0; extern double Lots = 0.1; extern int slope = 6; extern double ProfitMade = 32; extern double LossLimit = 0; extern bool CloseOnReverse = true; extern bool KillLogging = true; // Trade control 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 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 int bartick=0; // number of times bars have moved int i; //objects //EA specific int lsmaDirection=0; // used for verbose error logging #include <stdlib.mqh> //+-------------+ //| Custom init | //|-------------+ // Called ONCE when EA is added to chart or recompiled int init() { if( IsTesting() ) LL2SL=50; 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() { // 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; // direction control bool BUYme=false; bool SELLme=false; //safety counter int loopcount=0; // LSMA slope adjustment int slopeADJ; // 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; if(OrdersPerSymbol>0) { slopeADJ=slope; } else { slopeADJ=0; } // bar counting if(bartime!=Time[0]) { bartime=Time[0]; double lsma2=LSMA(LSMAPeriod, 2); double lsma1=LSMA(LSMAPeriod, 1); if( lsma1>(lsma2+(slopeADJ*Point)) ) { // did we change directions (1=up 0=dn) if(CloseOnReverse && lsmaDirection==0) { CloseEverything(); lsmaDirection=1; } BUYme=true; } if( lsma1<(lsma2-(slopeADJ*Point)) ) { // did we change directions (1=up 0=dn) if(CloseOnReverse && lsmaDirection==1) { CloseEverything(); lsmaDirection=0; } SELLme=true; } TradeAllowed=true; } //ENTRY LONG (buy, Ask) if( TradeAllowed && BUYme) { OpenBuy(); } //ENTRY SHORT (sell, Bid) if( TradeAllowed && SELLme) { 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=(Bid-OrderOpenPrice()) ; // Did we make a profit //====================== if(ProfitMade>0 && CurrentProfit>=(ProfitMade*Point)) { CloseBuy("PROFIT"); } // Did we take a loss //==================== if(LossLimit>0 && CurrentProfit<=(LossLimit*(-1)*Point)) { CloseBuy("LOSS"); } } // if BUY if(OrderType()==OP_SELL) { CurrentProfit=(OrderOpenPrice()-Ask); // Did we make a profit //====================== if( ProfitMade>0 && CurrentProfit>=(ProfitMade*Point) ) { CloseSell("PROFIT"); } // Did we take a loss //==================== if( LossLimit>0 && CurrentProfit<=(LossLimit*(-1)*Point) ) { CloseSell("LOSS"); } } //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); } } //ENTRY LONG (buy, Ask) void OpenBuy() { int gle=0; int ticket=0; double SL=0; double TP=0; int loopcount=0; while(true) { if( AccountFreeMargin()< (AccountBalance()*(MinFreeMarginPct/100)) ) { logwrite(TradeComment,"Your BUY equity is too low to trade"); break; } 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); gle=GetLastError(); if(gle==0) { logwrite(TradeComment,"BUY Ticket="+ticket+" Ask="+Ask+" Lots="+Lots+" SL="+SL+" TP="+TP); TradeAllowed=false; break; } else { logwrite(TradeComment,"-----ERROR----- opening BUY order: Lots="+Lots+" SL="+SL+" TP="+TP+" Bid="+Bid+" Ask="+Ask+" ticket="+ticket+" Err="+gle+" "+ErrorDescription(gle)); RefreshRates(); Sleep(500); loopcount++; if(loopcount>maxloop) break; } }//while }//BUYme //ENTRY SHORT (sell, Bid) void OpenSell() { int gle=0; int ticket=0; double SL=0; double TP=0; int loopcount=0; while(true) { if( AccountFreeMargin()< (AccountBalance()*(MinFreeMarginPct/100)) ) { logwrite(TradeComment,"Your SELL equity is too low to trade"); break; } 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); gle=GetLastError(); if(gle==0) { logwrite(TradeComment,"SELL Ticket="+ticket+" Bid="+Bid+" Lots="+Lots+" SL="+SL+" TP="+TP); TradeAllowed=false; break; } else { logwrite(TradeComment,"-----ERROR----- opening SELL order: Lots="+Lots+" SL="+SL+" TP="+TP+" Bid="+Bid+" Ask="+Ask+" ticket="+ticket+" Err="+gle+" "+ErrorDescription(gle)); RefreshRates(); Sleep(500); loopcount++; if(loopcount>maxloop) break; } }//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(),Bid,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="+Bid+ bTK + bSL + bTP + bPM + bLL); RefreshRates(); Sleep(500); } loopcount++; if(loopcount>maxloop) break; }//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(),Ask,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="+Ask+ sTK + sSL + sTP + sPM + sLL); RefreshRates(); Sleep(500); } loopcount++; if(loopcount>maxloop) break; }//while } 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; 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; //Close pending orders case OP_BUYLIMIT : case OP_BUYSTOP : case OP_SELLLIMIT: case OP_SELLSTOP :result = OrderDelete( OrderTicket() ); } 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