Divergence Trader_v3

Author: Ron Thompson
Profit factor:
0.83

This script is designed to automatically trade on the Forex market based on a "divergence" strategy. Here's how it works:

Overall Goal: The script's main purpose is to find potential buying and selling opportunities by calculating a "divergence" value and then automatically opening, managing, and closing trades based on pre-defined rules.

Initialization: When you add the script to a currency chart, it performs some initial setup. It clears any old visual indicators from the chart and prepares to track key performance metrics like the highest number of open trades, maximum profit, and minimum profit.

Tick-by-Tick Analysis: The script constantly monitors the market. Every time the price changes (each "tick"), it springs into action. It first checks if a new bar has formed on the chart. Think of a "bar" as a single unit of time on the chart (like a 5-minute bar, or an hourly bar). If a new bar has appeared, it resets a flag to allow new trades to be opened.

Trade Management: The script keeps track of how many trades are currently open for the specific currency pair. It also counts the number of Buy and Sell orders separately.

Divergence Calculation: The core of this script lies in the "divergence" calculation. It uses two moving averages of the price, a "fast" one and a "slow" one. The script calculates the difference between these moving averages and uses that value to determine whether the price is likely to go up (buy) or down (sell).

Trading Logic:

  • Buy/Sell Signals: The script checks the calculated "divergence" value against user-defined thresholds (DVBuySell, DVStayOut). If the divergence value is within a certain range, it generates a Buy or Sell signal.
  • Order Placement: If a Buy or Sell signal is generated, and trades are allowed, the script automatically places an order to either buy or sell the currency pair. It takes into account user-defined settings like lot size (the amount of currency to trade), slippage (the acceptable difference between the requested price and the actual execution price), stop-loss (the maximum loss you're willing to risk), and take-profit (the profit target).
  • Order Modification: The script constantly monitors the open trades. It can automatically adjust the stop-loss levels in two ways:
    • Break-Even: If a trade becomes profitable by a certain amount (PLBreakEven), the script moves the stop-loss to the trade's entry price (or slightly above/below to account for spread).
    • Trailing Stop: As the trade continues to be profitable, the script moves the stop-loss level up (for buy orders) or down (for sell orders) to lock in profits.
  • Order Closure: The script automatically closes trades when one of the following conditions is met:
    • The trade reaches the take-profit level.
    • The trade hits the stop-loss level.
    • The overall profit (or loss) of all open trades combined reaches a certain threshold (BasketProfit or BasketLoss).

Data Logging: The script can also optionally save the divergence data to a file for later analysis.

User Input: The script has several customizable settings that you can adjust to fit your trading style and risk tolerance. These include:

  • Lots: The size of the trades.
  • Slippage: The acceptable price difference during order execution.
  • Fast_Period/Slow_Period: The periods used to calculate the moving averages.
  • DVBuySell/DVStayOut: The divergence thresholds for generating buy and sell signals.
  • ProfitMade/LossLimit: The profit target and maximum loss per trade.
  • TrailStop/PLBreakEven: Parameters for the trailing stop and break-even features.
  • StartHour/StopHour: Trading hours.
  • BasketProfit/BasketLoss: Overall profit/loss limits for closing all trades.

Visual Feedback: The script adds visual indicators to the chart, such as letters "B" (Buy), "S" (Sell), "BE" (Break Even), "TS" (Trailing Stop), and "C" (Close) at points where trades are opened, modified, or closed. It also displays the current divergence value on the chart.

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
7 Views
0 Downloads
0 Favorites
Divergence Trader_v3
//+------------------------------------------------------------------+
//|                                               Divergence Trader  |
//|                                                                  |
//|                                                                  |
//+------------------------------------------------------------------+

#property copyright "Ron Thompson"
#property link      "http://www.lightpatch.com/forex"
// 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
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/USD Jul 2025 - Sep 2025
1.40
Total Trades 1006
Won Trades 812
Lost trades 194
Win Rate 80.72 %
Expected payoff 5.60
Gross Profit 19579.90
Gross Loss -13942.30
Total Net Profit 5637.60
-100%
-50%
0%
50%
100%
GBP/CAD Jul 2025 - Sep 2025
0.49
Total Trades 264
Won Trades 86
Lost trades 178
Win Rate 32.58 %
Expected payoff -19.84
Gross Profit 4980.25
Gross Loss -10218.08
Total Net Profit -5237.83
-100%
-50%
0%
50%
100%
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 18945.28
Gross Loss -14917.93
Total Net Profit 4027.35
-100%
-50%
0%
50%
100%
AUD/USD Jul 2025 - Sep 2025
0.69
Total Trades 421
Won Trades 264
Lost trades 157
Win Rate 62.71 %
Expected payoff -9.54
Gross Profit 9050.70
Gross Loss -13068.20
Total Net Profit -4017.50
-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.87
Gross Profit 818.34
Gross Loss -771.59
Total Net Profit 46.75
-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.42
Total Trades 248
Won Trades 117
Lost trades 131
Win Rate 47.18 %
Expected payoff -27.63
Gross Profit 4981.21
Gross Loss -11832.47
Total Net Profit -6851.26
-100%
-50%
0%
50%
100%
NZD/USD Jan 2025 - Jul 2025
0.66
Total Trades 1155
Won Trades 714
Lost trades 441
Win Rate 61.82 %
Expected payoff -8.04
Gross Profit 17626.50
Gross Loss -26909.10
Total Net Profit -9282.60
-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.98
Total Trades 1865
Won Trades 1361
Lost trades 504
Win Rate 72.98 %
Expected payoff -0.40
Gross Profit 34954.36
Gross Loss -35697.68
Total Net Profit -743.32
-100%
-50%
0%
50%
100%

Comments