Divergence Trader_v2

Author: Ron Thompson
Profit factor:
0.88

This script is designed to automatically trade on the Forex market using the MetaTrader platform. It works by looking for a specific pattern called "divergence" between two moving averages, which are ways to smooth out price data over time. Here's a breakdown of how it operates:

1. Initial Setup:

  • User Settings: When you add the script to a currency chart, you can adjust various settings like:

    • Lots: How much of the currency to buy or sell in each trade (trade size).
    • Slippage: The acceptable difference between the requested price and the actual price at which the trade is executed.
    • Fast_Period and Slow_Period: These determine the length of the moving averages it is going to compare.
    • Fast_Price and Slow_Price: Those variables determine the price in each period of the moving average, examples: the price open, the price close, etc.
    • DVBuySell: This variable will determinate if the price should buy or sell, according to the divergence.
    • DVStayOut: The program will not trade if the divergence is between the DVBuySell and the DVStayOut.
    • ProfitMade and LossLimit: How much profit the script should try to make or how much loss it should tolerate on each trade before automatically closing it.
    • TrailStop: A feature that automatically adjusts the stop-loss order (an order to limit potential losses) as the trade becomes more profitable, locking in gains.
    • PLBreakEven: A feature that move the stop-loss to break even when the trade reaches certain pips.
    • StartHour and StopHour: The time of day the script is allowed to make trades.
    • BasketProfit and BasketLoss: The profit or loss level at which the script will close all open trades.
  • Identification: The script uses a unique "Magic Number" to identify its own trades, allowing it to manage them without interfering with trades placed manually or by other scripts.

2. Core Trading Logic (executed on every new price tick):

  • Detecting New Data: The script checks for each new price tick.

  • Calculating Divergence: The most important part! The script calculates "divergence" using two moving averages of different lengths (specified by Fast_Period and Slow_Period). Divergence occurs when the price of the currency pair is moving in one direction, but the moving averages are moving in another. This can indicate a potential change in the price direction.

  • Making Trading Decisions:

    • Buy Signal: If the divergence calculation is above a certain positive threshold (DVBuySell), the script interprets this as a potential buying opportunity (BUYme = true).
    • Sell Signal: If the divergence calculation is below a certain negative threshold (DVBuySell * -1), the script interprets this as a potential selling opportunity (SELLme = true).
    • Trade Execution: If a buy or sell signal is triggered, the script places an order to buy or sell the currency pair. The size of the trade is determined by the Lots setting, and the script includes a Slippage tolerance. It also sets stoploss and takeprofit with the values introduced by the user.
    • Trade Restriction: To prevent enter more than one time, the script is going to check the TradeAllowed parameter.
  • Saving the data on File The script is going to save the data into a CSV file if FileData is selected.

3. Trade Management (executed on every new price tick):

  • Profit/Loss Monitoring: The script continuously monitors the profit or loss of each open trade.
  • Stop-Loss and Take-Profit: The script uses the values introduced by the user to prevent loss or take profits.
  • Trailing Stop: If enabled (TrailStop is not 9999), the script automatically adjusts the stop-loss order to lock in profits as the trade moves in a favorable direction.
  • Break-Even: If enabled (PLBreakEven is not 9999), the script automatically adjusts the stop-loss order to break-even.
  • Closing Trades:
    • Individual Trade Targets: If a trade reaches the ProfitMade target or hits the LossLimit, the script automatically closes the trade.
    • Basket Closure: If the overall profit or loss across ALL open trades reaches the BasketProfit or BasketLoss level, the script closes ALL open trades.

4. Other Functions:

  • init(): Executed once when the script is first loaded. It clears any old chart objects.
  • deinit(): Executed once when the script is removed from the chart. It prints some information like Max Orders, Max Equity, Min Equity, and other data.
  • CloseEverything(): A function that closes ALL open orders immediately. This is used when the BasketProfit or BasketLoss targets are reached.

In Simple Terms:

This script is like a robot trader that watches the Forex market for a specific pattern ("divergence") and automatically buys or sells based on that pattern. It has built-in rules to limit losses, take profits, and even adjust its stop-loss levels as trades become profitable. You can customize the script with different settings to match your risk tolerance and trading goals.

Price Data Components
Orders Execution
Checks for the total of open ordersIt automatically opens orders when conditions are reachedIt can change open orders parameters, due to possible stepping strategyIt Closes Orders by itself
Indicators Used
Moving average indicator
Miscellaneous
Uses files from the file systemIt writes information to fileIt issuies visual alerts to the screen
9 Views
0 Downloads
0 Favorites
Divergence Trader_v2
/*-----------------------------+
|			       |
| Shared by www.Aptrafx.com    |
|			       |
+------------------------------*/

//Divergence Trader//


#property copyright "Ron Thompson"
#property link      "http://www.lightpatch.com/forex"
//compile//
// user input
extern double Lots=0.1;               // how many lots to trade at a time 
extern int    Slippage=2;             // how many pips of slippage can you tolorate
extern int    Fast_Period=7;
extern int    Fast_Price = PRICE_OPEN;
extern int    Slow_Period=88;
extern int    Slow_Price = PRICE_OPEN;
extern double DVBuySell=0.0011;
extern double DVStayOut=0.0079;
extern double ProfitMade=0;           // how much money do you expect to make
extern double LossLimit=0;            // how much loss can you tolorate
extern double TrailStop=9999;         // trailing stop (999=no trailing stop)
extern int    PLBreakEven=9999;       // set break even when this many pips are made (999=off)
extern int    StartHour=0;            // your local time to start making trades
extern int    StopHour=24;            // your local time to stop making trades
extern int    BasketProfit=75;        // if equity reaches this level, close trades
extern int    BasketLoss=9999;        // if equity reaches this negative level, close trades
extern bool   FileData=false;

// naming and numbering
int      MagicNumber  = 200601182020; // allows multiple experts to trade on same account
string   TradeComment = "Divergence_00_";

// Bar handling
datetime bartime=0;                   // used to determine when a bar has moved
int      bartick=0;                   // number of times bars have moved
int      objtick=0;                   // used to draw objects on the chart
int      tickcount=0;

// Trade control
bool TradeAllowed=true;               // used to manage trades

// Min/Max tracking
double maxOrders;
double maxEquity;
double minEquity;
double CECount;
double CEProc;
double CEBuy;
double CESell;



//+-------------+
//| Custom init |
//|-------------+
// Called ONCE when EA is added to chart or recompiled

int init()
  {
   int    i;
   string o;
   
   //remove the old objects 
   for(i=0; i<Bars; i++) 
     {
      o=DoubleToStr(i,0);
      ObjectDelete("myx"+o);
      ObjectDelete("myz"+o);
     }
   objtick=0;

   ObjectDelete("Cmmt");
   ObjectCreate("Cmmt", OBJ_TEXT, 0, Time[20], High[20]+(5*Point()));
   ObjectSetText("Cmmt","Divergence=0.0020",10,"Arial",White);

   Print("Init happened ",CurTime());
   Comment(" ");
  }

//+----------------+
//| Custom DE-init |
//+----------------+
// Called ONCE when EA is removed from chart

int deinit()
  {
   int    i;
   string o;
   //remove the old objects 
   
   for(i=0; i<Bars; i++) 
     {
      o=DoubleToStr(i,0);
      ObjectDelete("myx"+o);
      ObjectDelete("myz"+o);
     }
   objtick=0;
   
   Print("MAX number of orders ",maxOrders);
   Print("MAX equity           ",maxEquity);
   Print("MIN equity           ",minEquity);
   Print("Close Everything     ",CECount);
   Print("Close Proc           ",CEProc);
   Print("Proc Buy             ",CEBuy);
   Print("Proc Sell            ",CESell);
      
   Print("DE-Init happened ",CurTime());
   Comment(" ");
  }


//+-----------+
//| Main      |
//+-----------+
// Called EACH TICK and each Bar[]

int start()
  {

   double p=Point();
   double spread=Ask-Bid;
   
   int      cnt=0;
   int      gle=0;
   int      OrdersPerSymbol=0;
   int      OrdersBUY=0;
   int      OrdersSELL=0;
   
   int      iFileHandle;
  
   // stoploss and takeprofit and close control
   double SL=0;
   double TP=0;
   double CurrentProfit=0;
   double CurrentBasket=0;
   
   // direction control
   bool BUYme=false;
   bool SELLme=false;
   
   // Trade stuff
   double diverge;
      

   // bar counting
   if(bartime!=Time[0]) 
     {
      bartime=Time[0];
      bartick++; 
      objtick++;
      TradeAllowed=true;
     }

   OrdersPerSymbol=0;
   for(cnt=OrdersTotal();cnt>=0;cnt--)
     {
      OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
      if( OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber)
        {
         OrdersPerSymbol++;
         if(OrderType()==OP_BUY) {OrdersBUY++;}
         if(OrderType()==OP_SELL){OrdersSELL++;}
        }
     }
   if(OrdersPerSymbol>maxOrders) maxOrders=OrdersPerSymbol;


   //+-----------------------------+
   //| Insert your indicator here  |
   //| And set either BUYme or     |
   //| SELLme true to place orders |
   //+-----------------------------+
   
   diverge=divergence(Fast_Period,Slow_Period,Fast_Price,Slow_Price,0);
   ObjectDelete("Cmmt");
   ObjectCreate("Cmmt", OBJ_TEXT, 0, Time[0], High[0]+(10*p));
   ObjectSetText("Cmmt","Divergence="+DoubleToStr(diverge,4),10,"Arial",White);
   if( diverge>=DVBuySell        && diverge<=DVStayOut )         BUYme=true;
   if( diverge<=(DVBuySell*(-1)) && diverge>=(DVStayOut*(-1)) ) SELLme=true;
   //if( diverge>=DVBuySell        ) BUYme=true;
   //if( diverge<=(DVBuySell*(-1)) ) SELLme=true;
   
   if(FileData)
     {
      tickcount++;
      iFileHandle = FileOpen("iDivergence", FILE_CSV|FILE_READ|FILE_WRITE, ",");
      FileSeek(iFileHandle, 0, SEEK_END);
      FileWrite(iFileHandle, bartick, " ", tickcount, " ", diverge);
      FileFlush(iFileHandle);
      FileClose(iFileHandle);
     }

   //+------------+
   //| End Insert |
   //+------------+

   //ENTRY LONG (buy, Ask) 
   if(TradeAllowed && BUYme)
      {
       //Ask(buy, long)
      if(LossLimit ==0) SL=0; else SL=Ask-((LossLimit+7)*Point() );
      if(ProfitMade==0) TP=0; else TP=Ask+((ProfitMade+7)*Point() );
      OrderSend(Symbol(),OP_BUY,Lots,Ask,Slippage,SL,TP,TradeComment,MagicNumber,White);
      gle=GetLastError();
      if(gle==0)
        {
         Print("BUY  Ask=",Ask," bartick=",bartick);
         ObjectCreate("myx"+DoubleToStr(objtick,0), OBJ_TEXT, 0, Time[0], High[0]+(5*p));
         ObjectSetText("myx"+DoubleToStr(objtick,0),"B",15,"Arial",Red);
         bartick=0;
         TradeAllowed=false;
        }
         else 
        {
         Print("-----ERROR----- BUY  Ask=",Ask," error=",gle," bartick=",bartick);
        }
     }
        
   //ENTRY SHORT (sell, Bid)
   if(TradeAllowed && SELLme )
     {
      //Bid (sell, short)
      if(LossLimit ==0) SL=0; else SL=Bid+((LossLimit+7)*Point() );
      if(ProfitMade==0) TP=0; else TP=Bid-((ProfitMade+7)*Point() );
      OrderSend(Symbol(),OP_SELL,Lots,Bid,Slippage,SL,TP,TradeComment,MagicNumber,Red);
      gle=GetLastError();
      if(gle==0)
        {
         Print("SELL Bid=",Bid," bartick=",bartick); 
         ObjectCreate("myx"+DoubleToStr(objtick,0), OBJ_TEXT, 0, Time[0], High[0]+(5*p));
         ObjectSetText("myx"+DoubleToStr(objtick,0),"S",15,"Arial",Red);
         bartick=0;
         TradeAllowed=false;
        }
         else 
        {
         Print("-----ERROR----- SELL Bid=",Bid," error=",gle," bartick=",bartick);
        }
     }

     

   //Basket profit or loss
   CurrentBasket=AccountEquity()-AccountBalance();
   
   if(CurrentBasket>maxEquity) maxEquity=CurrentBasket;
   if(CurrentBasket<minEquity) minEquity=CurrentBasket;
   
   // actual basket closure
   if( CurrentBasket>=BasketProfit || CurrentBasket<=(BasketLoss*(-1)) )
     {
      CloseEverything();
      CECount++;
     }

   // CLOSE order if profit target made
   for(cnt=0;cnt<OrdersTotal();cnt++)
     {
      OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
      if( OrderSymbol()==Symbol() && OrderMagicNumber()==MagicNumber )
        {
        
         if(OrderType()==OP_BUY)
           {
            CurrentProfit=Bid-OrderOpenPrice() ;

            // modify for break even
            if (CurrentProfit >= PLBreakEven*p && OrderOpenPrice()>OrderStopLoss())
              {
               SL=OrderOpenPrice()+(spread*2);
               TP=OrderTakeProfit();
               OrderModify(OrderTicket(),OrderOpenPrice(),SL,TP, White);
               gle=GetLastError();
               if(gle==0)
                 {
                  Print("MODIFY BREAKEVEN BUY  Bid=",Bid," bartick=",bartick); 
                  ObjectCreate("myz"+DoubleToStr(objtick,0), OBJ_TEXT, 0, Time[0], Low[0]-(7*p));
                  ObjectSetText("myz"+DoubleToStr(objtick,0),"BE",15,"Arial",White);
                 }
                  else 
                 {
                  Print("-----ERROR----- MODIFY BREAKEVEN BUY  Bid=",Bid," error=",gle," bartick=",bartick);
                 }
              }

            // modify for trailing stop
            if(CurrentProfit >= TrailStop*p )
              {
               SL=Bid-(TrailStop*p);
               TP=OrderTakeProfit();
               OrderModify(OrderTicket(),OrderOpenPrice(),SL,TP, White);
               gle=GetLastError();
               if(gle==0)
                 {
                  Print ("MODIFY TRAILSTOP BUY  StopLoss=",SL,"  bartick=",bartick,"OrderTicket=",OrderTicket()," CurrProfit=",CurrentProfit); 
                  ObjectCreate("myz"+DoubleToStr(objtick,0), OBJ_TEXT, 0, Time[0], Low[0]-(7*p));
                  ObjectSetText("myz"+DoubleToStr(objtick,0),"TS",15,"Arial",White);
                 }
                  else 
                 {
                  Print("-----ERROR----- MODIFY TRAILSTOP BUY  Bid=",Bid," error=",gle," bartick=",bartick);
                 }
              }

            // did we make our desired BUY profit
            // or did we hit the BUY LossLimit
            if((ProfitMade>0 && CurrentProfit>=(ProfitMade*p)) || (LossLimit>0 && CurrentProfit<=((LossLimit*(-1))*p))  )
              {
               OrderClose(OrderTicket(),Lots,Bid,Slippage,White);
               gle=GetLastError();
               if(gle==0)
                 {
                  Print("CLOSE BUY  Bid=",Bid," bartick=",bartick); 
                  ObjectCreate("myz"+DoubleToStr(objtick,0), OBJ_TEXT, 0, Time[0], Low[0]-(7*p));
                  ObjectSetText("myz"+DoubleToStr(objtick,0),"C",15,"Arial",White);
                 }
                  else 
                 {
                  Print("-----ERROR----- CLOSE BUY  Bid=",Bid," error=",gle," bartick=",bartick);
                 }
              }
              
           } // if BUY


         if(OrderType()==OP_SELL)
           {

            CurrentProfit=OrderOpenPrice()-Ask;
            
            // modify for break even
            if (CurrentProfit >= PLBreakEven*p && OrderOpenPrice()<OrderStopLoss())
              {
               SL=OrderOpenPrice()-(spread*2);
               TP=OrderTakeProfit();
               OrderModify(OrderTicket(),OrderOpenPrice(),SL,TP, Red);
               gle=GetLastError();
               if(gle==0)
                 {
                  Print("MODIFY BREAKEVEN SELL Ask=",Ask," bartick=",bartick);
                  ObjectCreate("myz"+DoubleToStr(objtick,0), OBJ_TEXT, 0, Time[0], Low[0]-(7*p));
                  ObjectSetText("myz"+DoubleToStr(objtick,0),"BE",15,"Arial",Red);
                 }
                  else 
                 {
                  Print("-----ERROR----- MODIFY BREAKEVEN SELL Ask=",Ask," error=",gle," bartick=",bartick);
                 }
              }

            // modify for trailing stop
            if(CurrentProfit >= TrailStop*p)
              {
               SL=Ask+(TrailStop*p);
               TP=OrderTakeProfit();
               OrderModify(OrderTicket(),OrderOpenPrice(),SL,TP, Red);
               gle=GetLastError();
               if(gle==0)
                 {
                  Print ("MODIFY TRAILSTOP SELL StopLoss=",SL,"  bartick=",bartick,"OrderTicket=",OrderTicket()," CurrProfit=",CurrentProfit); 
                  ObjectCreate("myz"+DoubleToStr(objtick,0), OBJ_TEXT, 0, Time[0], Low[0]-(7*p));
                  ObjectSetText("myz"+DoubleToStr(objtick,0),"TS",15,"Arial",Red);
                 }
                  else 
                 {
                  Print("-----ERROR----- MODIFY TRAILSTOP SELL Ask=",Ask," error=",gle," bartick=",bartick);
                 }
              }

            // did we make our desired SELL profit?
            if( (ProfitMade>0 && CurrentProfit>=(ProfitMade*p)) || (LossLimit>0 && CurrentProfit<=((LossLimit*(-1))*p))  )
              {
               OrderClose(OrderTicket(),Lots,Ask,Slippage,Red);
               gle=GetLastError();
               if(gle==0)
                 {
                  Print("CLOSE SELL Ask=",Ask," bartick=",bartick);
                  ObjectCreate("myz"+DoubleToStr(objtick,0), OBJ_TEXT, 0, Time[0], Low[0]-(7*p));
                  ObjectSetText("myz"+DoubleToStr(objtick,0),"C",15,"Arial",Red);
                 }
                  else 
                 {
                  Print("-----ERROR----- CLOSE SELL Ask=",Ask," error=",gle," bartick=",bartick);
                 }
                 
              }

           } //if SELL
           
        } // if(OrderSymbol)
        
     } // for

  } // start()



//+-----------------+
//| 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);
         CEBuy++;
         break;
      
         //Close opened short positions
         case OP_SELL     :result = OrderClose(myTkt, myLot, myAsk, Slippage, Red);
         CESell++;
         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);
      CEProc++;

     } //for
  
  } // closeeverything




double divergence(int F_Period, int S_Period, int F_Price, int S_Price, int mypos)
  {

   int i;
   
   double maF1, maF2, maS1, maS2;
   double dv1, dv2;
   
   maF1=iMA(Symbol(),0,F_Period,0,MODE_SMA,F_Price,mypos);
   maS1=iMA(Symbol(),0,S_Period,0,MODE_SMA,S_Price,mypos);
   dv1=(maF1-maS1);

   maF2=iMA(Symbol(),0,F_Period,0,MODE_SMA,F_Price,mypos+1);
   maS2=iMA(Symbol(),0,S_Period,0,MODE_SMA,S_Price,mypos+1);
   dv2=((maF1-maS1)-(maF2-maS2));
     
   return(dv1-dv2);
   
  }

Profitability Reports

GBP/AUD Jul 2025 - Sep 2025
1.27
Total Trades 884
Won Trades 663
Lost trades 221
Win Rate 75.00 %
Expected payoff 4.56
Gross Profit 18928.32
Gross Loss -14901.68
Total Net Profit 4026.64
-100%
-50%
0%
50%
100%
EUR/USD Jul 2025 - Sep 2025
0.00
Total Trades 119
Won Trades 74
Lost trades 45
Win Rate 62.18 %
Expected payoff -11522.61
Gross Profit 1651.50
Gross Loss -1372842.60
Total Net Profit -1371191.10
-100%
-50%
0%
50%
100%
AUD/USD Jul 2025 - Sep 2025
0.41
Total Trades 509
Won Trades 250
Lost trades 259
Win Rate 49.12 %
Expected payoff -13.24
Gross Profit 4759.80
Gross Loss -11500.60
Total Net Profit -6740.80
-100%
-50%
0%
50%
100%
USD/JPY Jan 2025 - Jul 2025
1.06
Total Trades 25
Won Trades 15
Lost trades 10
Win Rate 60.00 %
Expected payoff 1.86
Gross Profit 820.00
Gross Loss -773.53
Total Net Profit 46.47
-100%
-50%
0%
50%
100%
USD/CHF Jan 2025 - Jul 2025
0.68
Total Trades 590
Won Trades 342
Lost trades 248
Win Rate 57.97 %
Expected payoff -8.23
Gross Profit 10092.31
Gross Loss -14945.26
Total Net Profit -4852.95
-100%
-50%
0%
50%
100%
USD/CAD Jan 2025 - Jul 2025
0.44
Total Trades 248
Won Trades 117
Lost trades 131
Win Rate 47.18 %
Expected payoff -27.62
Gross Profit 5285.37
Gross Loss -12135.41
Total Net Profit -6850.04
-100%
-50%
0%
50%
100%
NZD/USD Jan 2025 - Jul 2025
0.42
Total Trades 347
Won Trades 149
Lost trades 198
Win Rate 42.94 %
Expected payoff -18.43
Gross Profit 4590.60
Gross Loss -10986.40
Total Net Profit -6395.80
-100%
-50%
0%
50%
100%
GBP/USD Jan 2025 - Jul 2025
0.43
Total Trades 69
Won Trades 30
Lost trades 39
Win Rate 43.48 %
Expected payoff -123.75
Gross Profit 6488.90
Gross Loss -15027.90
Total Net Profit -8539.00
-100%
-50%
0%
50%
100%
GBP/CAD Jan 2025 - Jul 2025
0.97
Total Trades 1865
Won Trades 1355
Lost trades 510
Win Rate 72.65 %
Expected payoff -0.49
Gross Profit 34841.82
Gross Loss -35751.88
Total Net Profit -910.06
-100%
-50%
0%
50%
100%
GBP/AUD Jan 2025 - Jul 2025
0.60
Total Trades 330
Won Trades 181
Lost trades 149
Win Rate 54.85 %
Expected payoff -19.40
Gross Profit 9435.23
Gross Loss -15835.71
Total Net Profit -6400.48
-100%
-50%
0%
50%
100%

Comments