//+------------------------------------------------------------------+ //| GrailExpertMAV1.0.mq4 | //| Copyright © 2006, systrad5 | //| 17/09/06 | //| Feedback or comments welcome at systrad5@yahoo.com | //+------------------------------------------------------------------+ // You may get profitable experts in backtests if orders are // filled and exited in the same bar. This is usually an error due // to the limitations of backtesting on data with longer timeframes // than the trading strategy. // Backtest results will always be unreliable if an order is // filled and exited on the same bar unless the entry is on the // open or the exit on the close. This is because it is impossible // to tell the price action within the bar. A backtest will make an // estimation of what happened during the bar. At times the // estimation may result in a fill at a price that is estimated to // occur before the exit but in realty occured after. This can // result in fills at impossible prices, especially when the market // moves quickly in one direction. Some strategies will // inadvertently exploit these impossible prices to produce // impossible results. // You can end up with an expert that appears to be extremely // profitable in backtests but will lose a bundle in real trading // (well I think it will), as the attached expert will. Try it on // EURUSD 1H timeframe. // The only way to have reliable backtests off bar data is to // either enter on the open or exit on the close. It is certain // when these two points happened so the order of the price action // will always be correct. It also makes it certain that the expert // does not inadvertenlty open and close an order on the same bar // (such as with a Stop Loss Exit). // As you can guess I wouldn't recommend this expert be used for // real.... #define MAGICGRAIL 20050917 //---- input parameters extern double TakeProfit = 20.0; extern double StopLoss = 50.0; extern double Lots = 0.1; extern int HLPeriod = 6; extern int MAPeriod = 14; extern int MASlope = 2; extern int TgtThreshold = 5; //---- Globals & Buffers double Threshold, HEntry = 0, LEntry = 0, PrevHigh, PrevLow, Spread; double MA1,MA2; int MADir; datetime prevtime = 0; //Used to determine opening bar //+------------------------------------------------------------------+ //| Start function | //+------------------------------------------------------------------+ void start() { int Dir; Threshold = TgtThreshold * Point; //---- Calc Buffers if(prevtime == Time[0]) { // IntraBar Tick // Determine if H[0] or L[0] over previous if(Low[0] < PrevLow) { LEntry = Low[0] + Threshold + (TakeProfit * Point); Spread = PrevHigh - Low[0]; if (Spread < (2 * Threshold) + (TakeProfit * Point)) LEntry = 0; } //---- if(High[0] > PrevHigh) { HEntry = High[0] - Threshold - (TakeProfit * Point); Spread = High[0] - PrevLow; if(Spread < (2 * Threshold) + (TakeProfit * Point)) HEntry = 0; } // Check to see if price has broken entry barrier Dir = 0; //---- if(Ask < HEntry && HEntry != 0 && MADir ==1) Dir = 1; //---- if(Bid > LEntry && LEntry != 0 && MADir ==-1) Dir = -1; } else { // Calc MA MA1 = iMA(NULL, 0, MAPeriod, 0, MODE_EMA, PRICE_TYPICAL, 1); MA2 = iMA(NULL, 0, MAPeriod, 0, MODE_EMA, PRICE_TYPICAL, 2); if(MA1 > MA2 + (MASlope*Point)) MADir = 1; else { if (MA1 < MA2 - (MASlope*Point)) MADir = -1; else MADir = 0; } // Find High & Low of previous x Bars PrevHigh = High[Highest(NULL, 0, MODE_HIGH, HLPeriod, 1)]; PrevLow = Low[Lowest(NULL, 0, MODE_LOW, HLPeriod, 1)]; if(HEntry + Threshold + (TakeProfit * Point) > PrevHigh) HEntry = 0; if(LEntry - Threshold - (TakeProfit * Point) < PrevLow) LEntry = 0; } //---- calculate open orders by current symbol if(CalculateCurrentOrders(Symbol()) == 0) CheckForOpen(Dir); else { HEntry = 0; LEntry = 0; } //----- reset time prevtime = Time[0]; //---- } //+------------------------------------------------------------------+ //| Calculate open positions | //+------------------------------------------------------------------+ int CalculateCurrentOrders(string symbol) { int buys = 0, sells = 0; //---- for(int i = 0; i < OrdersTotal(); i++) { if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false) break; if(OrderSymbol() == Symbol() && OrderMagicNumber() == MAGICGRAIL) { if(OrderType() == OP_BUY) buys++; if(OrderType() == OP_SELL) sells++; } } //---- return orders volume if(buys > 0) return(buys); else return(-sells); } //+------------------------------------------------------------------+ //| Check for open order conditions | //+------------------------------------------------------------------+ void CheckForOpen(int Dir) { int ticket; //---- sell conditions if(Dir == -1) { ticket = OrderSend(Symbol(), OP_SELL, Lots, Bid, 0, Bid + StopLoss*Point, Bid - TakeProfit*Point, "Grail 1.0: Sell", MAGICGRAIL, 0, Red); if(ticket < 1) Print("Error opening SELL order : ", GetLastError()); return; } //---- buy conditions if(Dir == 1) { ticket = OrderSend(Symbol(), OP_BUY, Lots, Ask, 0, Ask - StopLoss*Point, Ask + TakeProfit*Point, "Grail 1.0: Buy", MAGICGRAIL, 0, Blue); if(ticket<1) Print("Error opening BUY order : ", GetLastError()); return; } //---- } //+------------------------------------------------------------------+
Sample
Analysis
Market Information Used:
Series array that contains open time of each bar
Series array that contains the lowest prices of each bar
Series array that contains the highest prices of each bar
Indicator Curves created:
Indicators Used:
Moving average indicator
Custom Indicators Used:
Order Management characteristics:
Checks for the total of open orders
Other Features: