[ea]DollarCostAverage_Ron_MT4_v01b





//+--------+
//|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

BackTest : USDJPY on H1

From 2009-11-01 to 2009-11-30 Profit Factor:0.18 Total Net Profit:-5531.40

BackTest : USDCHF on H1

From 2009-12-01 to 2010-01-01 Profit Factor:4.87 Total Net Profit:1698.47

BackTest : EURUSD on H1

From 2009-12-01 to 2010-01-17 Profit Factor:2.50 Total Net Profit:2228.76

BackTest : USDCAD on H1

From 2009-12-01 to 2010-01-01 Profit Factor:1.93 Total Net Profit:1127.84

BackTest : EURUSD on H1

From 2009-08-01 to 2009-10-01 Profit Factor:3.31 Total Net Profit:3515.68

BackTest : GBPUSD on H1

From 2010-01-01 to 2010-02-27 Profit Factor:0.65 Total Net Profit:-2849.84

BackTest : USDCAD on H1

From 2009-01-01 to 2010-01-01 Profit Factor:0.30 Total Net Profit:-10246.29

BackTest : EURUSD on H1

From 2010-03-01 to 2010-03-27 Profit Factor:0.91 Total Net Profit:-214.25

BackTest : GBPUSD on H1

From 2010-01-01 to 2010-04-16 Profit Factor:0.08 Total Net Profit:-9854.53

BackTest : EURUSD on H1

From 2010-04-01 to 2010-04-30 Profit Factor:1.63 Total Net Profit:955.64

BackTest : EURUSD on H1

From 2010-05-01 to 2010-05-31 Profit Factor:0.52 Total Net Profit:-2545.52

BackTest : EURUSD on H1

From 2010-06-01 to 2010-06-30 Profit Factor:1.18 Total Net Profit:392.44

Request Backtest for [ea]DollarCostAverage_Ron_MT4_v01b


From : (yyyy/mm/dd) To: (yyyy/mm/dd)

Pair: Period: