//+------------------------------------------------------------------+ //| ea-test-trail.mq4 | //| Copyright © 2009, Dario Borghino | //| http://www.wysinnwyg.com/ | //+------------------------------------------------------------------+ #property copyright "Copyright © 2009, Dario Borghino" #property link "http://www.wysinnwyg.com/" #include #include #define MAX_SLIPPAGE 1 #define TRAILING_STOP 7 #define VOLUME 0.01 #define SMA_PERIOD 8 #define EMA_PERIOD 6 #define NUM_TICKS_FOR_TREND 20 #define STDDEV_PERIOD 20 #define MIN_STDDEV 0.0002 // global vars int ticket, orderValStatus; // orderValStatus = 1 -> long, -1 -> short active trade (only one trade at a time) double price, val, sl, minMax; int init() { Alert("EA-test-trail started."); minMax = -1; orderValStatus = 0; sl = 0; return(0); } int start() { val = updateVal(0); if(OrdersTotal() > 0) { // is there already an open position? if(val*orderValStatus < 0) // does the open position have to be closed? closeTrade(ticket, orderValStatus, "MA crossover"); // close else // trailing stop/stop loss checkStopLoss(); } else { // no open trades if(sl != 0) { // out by stop loss OrderSelect(ticket, SELECT_BY_TICKET); Alert("Position closed by stop loss (P/L: ", OrderProfit(),")"); sl = 0; } if(canOpenTrade()) ticket = openTrade(val); } return(0); } bool closeTrade(int ticket, int orderValStatus, string reason) { if(orderValStatus > 0) price = Bid; else price = Ask; if(!OrderClose(ticket, VOLUME, price, MAX_SLIPPAGE, Green)) Alert("ATTENTION: trade closing failed: ", ErrorDescription(GetLastError())); else { OrderSelect(ticket, SELECT_BY_TICKET); Alert("Position closed for ", reason, " (P/L: ", OrderProfit(), ")"); minMax = -1; // for trailing stop sl = 0; } } int openTrade(double val) { int ticket; if(val > 0) { ticket = OrderSend("EURUSD", OP_BUY, VOLUME, Ask, MAX_SLIPPAGE, 0, 0, NULL, 0, 0, Yellow); price = Ask; // for trailing stop } else { ticket = OrderSend("EURUSD", OP_SELL, VOLUME, Bid, MAX_SLIPPAGE, 0, 0, NULL, 0, 0, Yellow); price = Bid; // for trailing stop } if(ticket == -1) // error Alert("Error opening trade: ", ErrorDescription(GetLastError())); else if(val > 0) { Alert("Opening long trade (ID = ", ticket,", Ask price: ", Ask, ")"); orderValStatus = 1; } else { Alert("Opening short trade (ID = ", ticket,", Bid price: ", Bid, ")"); orderValStatus = -1; sl = Bid; // fictitious } return (ticket); } void waitFirstOccasion(double val) { double val2 = 0; Alert("Waiting for first signal..."); while(val*val2 >= 0) { Sleep(10); RefreshRates(); val2 = updateVal(1); val = updateVal(0); } } double updateVal(int shift) { return (iMA(NULL, 1, EMA_PERIOD, 0, MODE_EMA, PRICE_CLOSE, shift) - iMA(NULL, 1, SMA_PERIOD, 0, MODE_SMA, PRICE_CLOSE, shift)); } bool canOpenTrade() { int i = 0; double val2, std; Alert("Testing the market..."); while(i < NUM_TICKS_FOR_TREND) { // only if the trend doesn't change for at least N ticks Sleep(5); if(RefreshRates() == True) { val = updateVal(0); val2 = updateVal(1); i++; if(val*val2 < 0) { if(i > 5) Alert("Unstable market (i = ", i, "/", NUM_TICKS_FOR_TREND,")"); i = 0; } } } std = iStdDev("EURUSD", 1, STDDEV_PERIOD, 0, 0, 0, 0); if(std >= MIN_STDDEV) return(True); else { Alert("Can\'t open trade, stddev(", STDDEV_PERIOD,") is only ", std); return(False); } } void checkStopLoss() { bool err = True; if(OrderSelect(ticket, SELECT_BY_TICKET) == False) Alert("Order selection failed: ", ErrorDescription(GetLastError())); else if(OrderProfit() > 0.5 && OrderStopLoss() == 0) err = OrderModify(ticket, price, price+2*Point*10*orderValStatus, 0, 0); else if(OrderProfit() > 0.8 && OrderStopLoss()*orderValStatus <= price+2*Point*10*orderValStatus) err = OrderModify(ticket, price, price+4*Point*10*orderValStatus, 0, 0); else if(OrderProfit() > 1.1 && OrderStopLoss()*orderValStatus <= price+4*Point*10*orderValStatus) err = OrderModify(ticket, price, price+6*Point*10*orderValStatus, 0, 0); if(OrderProfit() > 1.4) { // TRAILING STOP triggered if(orderValStatus == 1) { // long position // trova massimo da apertura trade minMax = MathMax(minMax, Bid); if(minMax-Bid >= Point*TRAILING_STOP*10) // chiudi trade! closeTrade(ticket, orderValStatus, "trailing stop"); } else { // short position // trova min da apertura trade if(minMax == -1) minMax = Ask; minMax = MathMin(minMax, Ask); if(Ask-minMax >= Point*TRAILING_STOP*10) // chiudi trade! closeTrade(ticket, orderValStatus, "trailing stop"); } } }