This script is designed to automatically trade on the Forex market using the MetaTrader platform. It's like a robot programmed to buy and sell currencies based on a specific strategy. Here's the breakdown of how it works:
1. Initial Setup and Customization:
-
User Inputs: Before the trading begins, the user (you) can customize various settings, such as:
- Lots: The amount of currency to buy or sell in each trade. Think of it as the size of your bet.
- Slippage: A tolerance level for price changes between when the robot decides to trade and when the trade actually happens. It's like saying, "I'm okay if the price moves a little before the trade goes through."
- Fast/Slow Periods & Prices: These control how the script calculates a key indicator called "divergence." Period refers to the number of past price points used to calculate the average value and thus the indication of the current trend. The price is how it�s calculated: opening, closing price, etc
- Divergence Thresholds: These are critical values that determine when the robot thinks it's a good time to buy or sell, based on the "divergence" calculation.
- Profit and Loss Limits: How much profit you want to make on each trade, and how much loss you're willing to tolerate before the robot automatically closes the trade.
- Trailing Stop: A feature that automatically adjusts the stop-loss (loss limit) to lock in profits as the price moves in your favor.
- Break-Even Point: A feature that moves the stop loss to your entry price when enough profit has been reached to avoid losses.
- Trading Hours: Sets the specific hours of the day when the robot is allowed to make trades.
- Basket Profit/Loss: Specifies a total profit or loss level for all open trades. If the total reaches this level, the robot will close all trades.
-
Identification: The script assigns a unique "Magic Number" to its trades. This is important if you have other robots running on the same account, as it allows them to distinguish their own trades. A descriptive comment is included in the script.
2. Core Functionality:
-
Price Monitoring: The robot continuously monitors the price of the currency pair. It also tracks if a new "bar" has formed on the chart, indicating new price data.
-
Order Counting: The robot keeps track of how many buy and sell orders it currently has open for the specific currency pair.
-
Divergence Calculation: This is the heart of the trading strategy. The script uses a mathematical formula to calculate a "divergence" value based on the moving averages of the price.
- It essentially compares two moving averages (fast and slow) to identify potential turning points in the market.
- If the divergence value reaches certain thresholds (set by you), the robot will consider placing a buy or sell order.
-
Trading Decisions: Based on the "divergence" value and the thresholds you set, the robot decides whether to buy (go long) or sell (go short).
- The
DVBuySell
parameter represents the minimum value that the divergence has to be to consider an order. - The
DVStayOut
parameter represents the maximum value that the divergence can reach to consider an order.
- The
-
Order Placement: If the robot decides to trade, it sends an order to the broker to buy or sell the currency.
- The robot considers the amount of slippage that you�ve stablished to avoid prices changes when placing the order
- It will use the lot size you've specified, and set stop-loss and take-profit levels based on your settings.
- The robot also records if the trade was successful or if there was an error.
-
Trade Management: The robot actively manages open trades:
- Profit Targets & Stop-Losses: It constantly checks if the trade has reached your profit target or hit your stop-loss. If so, it closes the trade automatically.
- Trailing Stop: If you've enabled the trailing stop feature, the robot will adjust the stop-loss level as the price moves in your favor, locking in profits.
- Break-Even: If you've enabled the break-even feature, the robot will move the stop-loss level to your entry price when enough profit has been reached.
-
Basket Management: The robot monitors the overall profit or loss of all open trades combined (the "basket"). If the total profit or loss reaches the levels you've set, it will close all open trades.
3. Data Logging:
- File Output: Optionally, the robot can write data to a file. This data includes information like the time of each price bar, a tick counter (how many times the price has changed), and the divergence value. This is helpful for analyzing the robot's performance and refining its settings.
4. Shutting Down:
- Deinitialization: When the robot is removed from the chart or the trading platform is closed, it removes any graphical objects (like labels on the chart) that it created.
In short, this script automates Forex trading by using a "divergence" strategy to identify potential buying and selling opportunities, placing orders, and managing those trades based on your predefined rules and risk tolerance.
//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);
}
Comments