//+------------------------------------------------------------------+ //| Simple S&R.mq4 | //| Copyright © 2008, LEGRUPO | //| http://www.legrupo.com | //| Version: 1.1 | //| History: | //| 1.0 => Release version to the public | //| 1.1 => fixes on this releases: | //| 1) StopLoss bug fixed; | //| 2) Now the EA close the open and pending orders on the | //| end of the day, you just need to see when day ends | //| on your broker. InterbankFX is GMT, so it is 0 on them | //| 3) You don't need to manage the MagicNumber anymore | //| 1.3 => 10 Feb 2008 (Tinashe B Chipomho chipomho@xtra.co.nz | //| Improved order handling routines, embedded the indicator | //| making backtesting possible, close half of the position | //| when the pivot point is reached. | //| | //| | //+------------------------------------------------------------------+ #include <WinUser32.mqh> #include <stderror.mqh> #include <stdlib.mqh> #property copyright "Copyright © 2007, LEGRUPO Version 1.6" #property link "http://www.legrupo.com" extern bool TimeSpecific = false; extern int Slippage = 3; extern double Lots = 0.2; extern int ExpertID=1900; extern int TakeProfitRange = 8; extern int StopLoss = 100; extern double FirstHalf = 0.1; int MagicNumber = 10; double Pivot = 0; int CreateMagicNumber(){ int SymbolCode = 0; int PeriodCode = 0; //---- Symbol Code if( StringSubstr(Symbol(),0,6) == "AUDCAD") { SymbolCode = 1000; } else if( StringSubstr(Symbol(),0,6) == "AUDJPY") { SymbolCode = 2000; } else if( StringSubstr(Symbol(),0,6) == "AUDNZD") { SymbolCode = 3000; } else if( StringSubstr(Symbol(),0,6) == "AUDUSD") { SymbolCode = 4000; } else if( StringSubstr(Symbol(),0,6) == "CHFJPY") { SymbolCode = 5000; } else if( StringSubstr(Symbol(),0,6) == "EURAUD") { SymbolCode = 6000; } else if( StringSubstr(Symbol(),0,6) == "EURCAD") { SymbolCode = 7000; } else if( StringSubstr(Symbol(),0,6) == "EURCHF") { SymbolCode = 8000; } else if( StringSubstr(Symbol(),0,6) == "EURGBP") { SymbolCode = 9000; } else if( StringSubstr(Symbol(),0,6) == "EURJPY") { SymbolCode = 1000; } else if( StringSubstr(Symbol(),0,6) == "EURUSD") { SymbolCode = 1100; } else if( StringSubstr(Symbol(),0,6) == "GBPCHF") { SymbolCode = 1200; } else if( StringSubstr(Symbol(),0,6) == "GBPJPY") { SymbolCode = 1300; } else if( StringSubstr(Symbol(),0,6) == "GBPUSD") { SymbolCode = 1400; } else if( StringSubstr(Symbol(),0,6) == "NZDJPY") { SymbolCode = 1500; } else if( StringSubstr(Symbol(),0,6) == "NZDUSD") { SymbolCode = 1600; } else if( StringSubstr(Symbol(),0,6) == "USDCAD") { SymbolCode = 1700; } else if( StringSubstr(Symbol(),0,6) == "USDCHF") { SymbolCode = 1800; } else if( StringSubstr(Symbol(),0,6) == "USDJPY") { SymbolCode = 1900; } //---- Period Code if( TimeSpecific ){ if( Period() == PERIOD_M1 ) { PeriodCode = 10; } else if( Period() == PERIOD_M5 ) { PeriodCode = 20; } else if( Period() == PERIOD_M15 ){ PeriodCode = 30; } else if( Period() == PERIOD_M30 ){ PeriodCode = 40; } else if( Period() == PERIOD_H1 ) { PeriodCode = 50; } else if( Period() == PERIOD_H4 ) { PeriodCode = 60; } else if( Period() == PERIOD_D1 ) { PeriodCode = 70; } else if( Period() == PERIOD_W1) { PeriodCode = 80; } else if( Period() == PERIOD_MN1 ){ PeriodCode = 90; } } else PeriodCode = 0; //---- Calculate MagicNumber return(ExpertID+SymbolCode+PeriodCode); } bool HasBuyOrder(double price){ int total = OrdersTotal(); double min = Slippage * Point; for(int i=0; i<total; i++){ if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true){ if (OrderSymbol()!=Symbol()) continue; if (OrderMagicNumber()!=MagicNumber)continue; if ((OrderType()==OP_BUY) || (OrderType()==OP_BUYLIMIT) || (OrderType()==OP_BUYSTOP)) { if ((OrderOpenPrice()-(Slippage*Point)<=price) && (OrderOpenPrice()+(Slippage*Point)>=price)){ return (true); } } } } return (false); } bool HasSellOrder(double price){ int total = OrdersTotal(); double min = Slippage * Point; for(int i=0; i<total; i++){ if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true){ if (OrderSymbol()!=Symbol()) continue; //if (OrderMagicNumber()!=MagicNumber)continue; if ((OrderType()==OP_SELL) || (OrderType()==OP_SELLLIMIT) || (OrderType()==OP_SELLSTOP)) { if ((OrderOpenPrice()-min<=price) && (OrderOpenPrice()+min>=price)){ return (true); } } } } return (false); } double GetLots(string name){ //use this function to calculate the number of lots to use //if market conditions are favourable we might want to double //the lots. return (Lots); } string OrderType2String(int type){ if (type==OP_BUY) return ("BUY"); else if (type==OP_BUYLIMIT) return ("BUY LIMIT"); else if (type==OP_BUYSTOP) return ("BUY STOP"); else if (type==OP_SELL) return ("SELL"); else if (type==OP_SELLLIMIT) return ("SELL LIMIT"); else if (type==OP_SELLSTOP) return ("SELL STOP"); return ("Unknown Order Type"); } ///////////////////////////////////////////////////////////////////////////////// // int _IsTradeAllowed( int MaxWaiting_sec = 30 ) // // the function checks the trade context status. Return codes: // 1 - trade context is free, trade allowed // 0 - trade context was busy, but became free. Trade is allowed only after // the market info has been refreshed. // -1 - trade context is busy, waiting interrupted by the user (expert was removed from // the chart, terminal was shut down, the chart period and/or symbol was changed, etc.) // -2 - trade context is busy, the waiting limit is reached (MaxWaiting_sec). // Possibly, the expert is not allowed to trade (checkbox "Allow live trading" // in the expert settings). // // MaxWaiting_sec - time (in seconds) within which the function will wait // until the trade context is free (if it is busy). By default,30. ///////////////////////////////////////////////////////////////////////////////// int _IsTradeAllowed(int MaxWaiting_sec = 30){ if (IsTesting()) return (1); // check whether the trade context is free if(!IsTradeAllowed()){ int StartWaitingTime = GetTickCount(); Print("Trade context is busy! Wait until it is free..."); // infinite loop while(true){ // if the expert was terminated by the user, stop operation if(IsStopped()){ Print("The expert was terminated by the user!"); return(-1); } // if the waiting time exceeds the time specified in the // MaxWaiting_sec variable, stop operation, as well if(GetTickCount() - StartWaitingTime > MaxWaiting_sec * 1000){ Print("The waiting limit exceeded (" + MaxWaiting_sec + " ???.)!"); return(-2); } // if the trade context has become free, if(IsTradeAllowed()){ Print("Trade context has become free!"); return(0); } // if no loop breaking condition has been met, "wait" for 0.1 // second and then restart checking Sleep(100); } } else return(1); } int CreateOrder(int cmd, double price, double stoploss, double takeprofit, double lots, double expiration){ int ticket = -1; if (!IsConnected()){ Print("CreateOrder(): Not Connected."); return (-1); } if (IsStopped()){ Print("CreateOrder(): Stopped."); return (-1); } // check whether trade context is free int TradeAllow = _IsTradeAllowed(); if(TradeAllow < 0){ return(-1); } if(TradeAllow == 0){ RefreshRates(); } string comment = "SimpleFiboS&REA : "; Print("Opening "+OrderType2String(cmd) +" Order: Price["+price+"] StopLoss["+stoploss+"] TakeProfit["+takeprofit+"]"); ticket = OrderSend(Symbol(), cmd, lots, price, Slippage, stoploss, takeprofit, comment, MagicNumber, expiration); int err=GetLastError(); if (err!=0){ Print(""+OrderType2String(cmd) +" Failed to create Order: "+ err+" "+ ErrorDescription(err)); } return (ticket); } /** * In this function place only buy orders. */ int PlaceSupportOrder(double price, double pivot, double lots, double stoploss, double takeprofit, datetime expiration){ int ticket = -1; RefreshRates(); double servers_min_stop = MarketInfo(Symbol(), MODE_STOPLEVEL) * MarketInfo(Symbol(), MODE_POINT); //if the price is within + or - Slippage*Point simply buy. if ( (((Slippage*Point) + Ask) >= price) && (((Slippage*Point) - Ask) <= price) ){ Print("Opening a buy order at market price."); } int cmd = OP_BUYLIMIT; //if the price is too close to the stoplevel there is //nothing much we can do if (MathAbs(Ask-price) > servers_min_stop){ if (Ask < price){ cmd = OP_BUYSTOP; } //Print("SupportOrder: "+ OrderType2String(cmd)+" Price["+price+"] Pivot["+pivot+"] StopLoss["+stoploss+"] TakeProfit["+takeprofit+"] Expiration["+TimeToStr(expiration,TIME_DATE|TIME_MINUTES)+"]"); ticket = CreateOrder(cmd, NormalizeDouble(price,Digits), NormalizeDouble(stoploss,Digits), NormalizeDouble(takeprofit,Digits), lots, expiration); } return (ticket); } /** * In this function place only buy orders. */ int PlaceResistanceOrder(double price, double pivot, double lots, double stoploss, double takeprofit, datetime expiration){ int ticket = -1; RefreshRates(); double servers_min_stop = MarketInfo(Symbol(), MODE_STOPLEVEL) * MarketInfo(Symbol(), MODE_POINT); //if the price is within + or - Slippage*Point simply buy. if ( (((Slippage*Point) + Bid) >= price) && (((Slippage*Point) - Bid) <= price) ){ Print("Opening a sell order at market price."); } int cmd = OP_SELLLIMIT; //if the price is too close to the stoplevel there is //nothing much we can do if (MathAbs(Bid-price) > servers_min_stop){ if (Bid > price){ cmd = OP_SELLSTOP; } Print("ResistanceOrder: "+ OrderType2String(cmd)+" Price["+price+"] Pivot["+pivot+"] StopLoss["+stoploss+"] TakeProfit["+takeprofit+"] Expiration["+TimeToStr(expiration,TIME_DATE|TIME_MINUTES)+"]"); ticket = CreateOrder(cmd, NormalizeDouble(price,Digits), NormalizeDouble(stoploss,Digits), NormalizeDouble(takeprofit,Digits), lots, expiration); } return (ticket); } int PartiallyClose(int type,int ticket, double openprice, double takeprofit){ int TradeAllow = _IsTradeAllowed(); double closeprice = 0.0; Print("Moving to break even and partially closing position "); Print(" TradeAllow["+TradeAllow+"] ticket["+ ticket+"] openprice["+openprice+"] takeprofit["+takeprofit+"] type["+type+"] "); if (TradeAllow >= 0){ if(TradeAllow == 0) RefreshRates(); if (OrderModify(ticket,openprice,openprice,takeprofit,0)!=true) Print(OrderType2String(type)+" Failed to modify to break even: "+ ErrorDescription(GetLastError())); TradeAllow = _IsTradeAllowed(); if (TradeAllow==0) RefreshRates(); if (type==OP_BUY) closeprice=Bid; else if (type==OP_SELL) closeprice=Ask; Print(" After modify trade allow "+ TradeAllow); Print(OrderType2String(type)+" : Closing first lot, Ticket["+ticket+"] FirstLots["+FirstHalf+"] Ask["+Ask+"] Bid["+Bid+"] ClosePrice["+closeprice+"]"); if (OrderClose(ticket,FirstHalf,closeprice,Slippage)!=true) Print(OrderType2String(type)+" Failed to partially close an open order: "+ ErrorDescription(GetLastError())); return (0); } return (-1); } int TrackOrders(){ int i=0, ticket=-1; int total = OrdersTotal(); int modify = -1; double pivot = Pivot;//NormalizeDouble(ObjectGet("PIVOT", OBJPROP_PRICE1), Digits); double servers_min_stop = MarketInfo(Symbol(), MODE_STOPLEVEL) * MarketInfo(Symbol(), MODE_POINT); for(i=(total-1);i>=0; i--){ //if we cant select an order ignore it. if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)!=true) continue; //if its not our order just leave it. if (OrderMagicNumber()!=MagicNumber) continue; //dont be nosy and manipulate other people's orders. if (OrderSymbol()!=Symbol()) continue; //orders not yet filled leave them as well. if ((OrderType()!=OP_SELL)&&(OrderType()!= OP_BUY)) continue; //not doing anything to orders that are not yet profitable //let the stoploss take care of it. //TODO: This might be not be acceptable in certain market conditions. if (OrderProfit()<=0) continue; ticket = OrderTicket(); if (OrderType()==OP_SELL){ //sell order if (MathAbs(OrderOpenPrice()-pivot)>=servers_min_stop){ if (pivot>=Ask){ //we have gone past the pivot point, if (((OrderStopLoss()>OrderOpenPrice())|| (OrderStopLoss()==0)) && (FirstHalf>0)) { //the stop loss is still untouched, close the first half and move the //stop loss to break even. modify = PartiallyClose(OrderType(),OrderTicket(),OrderOpenPrice(),OrderTakeProfit()); } } } } else if (OrderType()==OP_BUY){ //buy Order if (MathAbs(OrderOpenPrice()-pivot)>=servers_min_stop){ if (pivot<=Bid){ if (((OrderStopLoss()<OrderOpenPrice())|| (OrderStopLoss()==0) ) && (FirstHalf>0)){ //the stop loss is still untouched, close the first half and move the stop loss to break //even. modify = PartiallyClose(OrderType(),OrderTicket(),OrderOpenPrice(),OrderTakeProfit()); } } } } //TrailingStop(OrderType(),OrderTicket(), OrderOpenPrice(), OrderTakeProfit(), OrderStopLoss()); } } //+------------------------------------------------------------------+ //| expert initialization function | //+------------------------------------------------------------------+ int init(){ MagicNumber = CreateMagicNumber(); return(0); } //+------------------------------------------------------------------+ //| expert deinitialization function | //+------------------------------------------------------------------+ int deinit(){ return(0); } //+------------------------------------------------------------------+ //| expert start function | //+------------------------------------------------------------------+ int start(){ double rates[1][6],yesterday_close,yesterday_high,yesterday_low; ArrayCopyRates(rates, Symbol(), PERIOD_D1); if(DayOfWeek() == 1){ if(TimeDayOfWeek(iTime(Symbol(),PERIOD_D1,1)) == 5){ yesterday_close = rates[1][4]; yesterday_high = rates[1][3]; yesterday_low = rates[1][2]; } else{ for(int d = 5;d>=0;d--){ if(TimeDayOfWeek(iTime(Symbol(),PERIOD_D1,d)) == 5){ yesterday_close = rates[d][4]; yesterday_high = rates[d][3]; yesterday_low = rates[d][2]; } } } } else{ yesterday_close = rates[1][4]; yesterday_high = rates[1][3]; yesterday_low = rates[1][2]; } double R = yesterday_high - yesterday_low;//range double pivot = NormalizeDouble((yesterday_high + yesterday_low + yesterday_close)/3,Digits);// Standard Pivot Pivot=NormalizeDouble(pivot,Digits); double r3 = NormalizeDouble(pivot + (R * 1.000),Digits); double r2 = NormalizeDouble(pivot + (R * 0.618),Digits); double r1 = NormalizeDouble(pivot + (R * 0.382),Digits); double s1 = NormalizeDouble(pivot - (R * 0.382),Digits); double s2 = NormalizeDouble(pivot - (R * 0.618),Digits); double s3 = NormalizeDouble(pivot - (R * 1.000),Digits); double servers_min_stop = MarketInfo(Symbol(), MODE_STOPLEVEL) * MarketInfo(Symbol(), MODE_POINT); //well just use 1min before the end of day. //this is the expiration for our pending orders. datetime TimeToEndOfDay = StrToTime("23:59"); double takeprofit = 0; int ticket = -1; //default ticket number. double stoploss = StopLoss * Point; //default stop loss level. // //well just no order placing in the last minute of the day. if (TimeToStr(TimeCurrent(),TIME_DATE|TIME_MINUTES)!=TimeToStr(TimeToEndOfDay,TIME_DATE|TIME_MINUTES)){ //check if we have orders at various fibo points, if not we need to open //the orders. //start by opening orders from s3,r3 then move to s2,r2 then move to s1,r1 if ( HasSellOrder(r3)!= true) { //open a sell order at r3 takeprofit = s1+MathMin(TakeProfitRange*Point, servers_min_stop); stoploss = r3+MathMax(StopLoss * Point,servers_min_stop); ticket = PlaceResistanceOrder(r3,pivot, GetLots("r3"), stoploss, takeprofit ,TimeToEndOfDay); } if ( HasSellOrder(r2)!= true) { //open a sell order at r2 takeprofit = s1+MathMin(TakeProfitRange*Point, servers_min_stop); stoploss = r3+MathMax(StopLoss * Point,servers_min_stop); ticket = PlaceResistanceOrder(r2,pivot, GetLots("r2"), stoploss, takeprofit ,TimeToEndOfDay); } if ( HasSellOrder(r1)!= true) { //open a sell order at r1 takeprofit = s1+MathMin(TakeProfitRange*Point, servers_min_stop); stoploss = r3+MathMax(StopLoss * Point,servers_min_stop); ticket = PlaceResistanceOrder(r1,pivot, GetLots("r1"), stoploss, takeprofit ,TimeToEndOfDay); } if ( HasBuyOrder(s3)!= true) { //open a buy order at s3 takeprofit = r1-MathMax(TakeProfitRange*Point, servers_min_stop); stoploss = s3-MathMax(StopLoss * Point,servers_min_stop); ticket = PlaceSupportOrder(s3,pivot, GetLots("s3"), stoploss, takeprofit ,TimeToEndOfDay); } if ( HasBuyOrder(s2)!= true) { //open a buy order at s2 takeprofit = r1-MathMax(TakeProfitRange*Point, servers_min_stop); stoploss = s2-MathMax(StopLoss * Point,servers_min_stop); ticket = PlaceSupportOrder(s2,pivot, GetLots("s2"), stoploss, takeprofit ,TimeToEndOfDay); } if ( HasBuyOrder(s1)!= true) { //open a sell order at s1 takeprofit = r1-MathMax(TakeProfitRange*Point, servers_min_stop); stoploss = s1-MathMax(StopLoss * Point,servers_min_stop); ticket = PlaceSupportOrder(s1,pivot, GetLots("s1"), stoploss, takeprofit ,TimeToEndOfDay); } } TrackOrders(); return(0); } //+------------------------------------------------------------------+
Sample
Analysis
Market Information Used:
Indicator Curves created:
Indicators Used:
Custom Indicators Used:
Order Management characteristics:
Checks for the total of open orders
It can change open orders parameters, due to possible stepping strategy
It Closes Orders by itself
Other Features: