//+------------------------------------------------------------------+ //| Simple S&R.mq4 | //| Copyright © 2008, LEGRUPO | //| http://www.legrupo.com | //| Version: 1.3 | //| 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.2 => Added Money Management feature; | //| 1.3 => Added HMA filter to stop big drawndown | //| 1.4 | //| 1.5 => Tinashe B Chipomho (tinashechipomho@gmail.com) | //| Refactored Indicator code, added first strategy (hedging) | //| Code is broken down into reusable units | //| Fixed issues with 1.4 | //| Controls orders from previous day | //| | //| | //| | //| | //| | //| | //+------------------------------------------------------------------+ #property copyright "Copyright © 2007, LEGRUPO" #property link "http://www.legrupo.com" #include <WinUser32.mqh> #include <stderror.mqh> #include <stdlib.mqh> #include <Logging.mqh> #include <MoneyManagement.mqh> #include <Trading.mqh> #include <FiboPivotPoints.mqh> //define various trading strategies //these strategies are there to minimize the drawdown. //various suggestions have been put forward by the team. #define STRATEGY_NONE 0 #define STRATEGY_HEDGING 1 #define STRATEGY_MEGA_TREND 2 extern string _ = "Risk/Profit Management "; extern double Trading.Risk = 10.0; // risk in percentage % (10% of risk in this case) extern double Trading.LotSize = 0.1; extern int Trading.Slippage = 3; extern int Trading.StopLoss = 100; extern int Trading.FlexPips = 8; //if the price reach within this range of the prescribed take profit //we can close the position. extern string __ = "Money Management "; extern bool MoneyManagement.Enabled = false; extern string ___ = "Account Information "; extern bool Account.Type.IsMicro = false; extern string ____ = "Trailing Stop Management "; extern int TrailingStopMode = 0; extern bool TimeSpecific = false; extern string _____ = "Strategy Types: Which strategy to do you want to use? 0 means none "; extern int StrategyIndex = 1; extern string ______ = "Simple Hedging Strategy: Adjust if your strategy index is 1"; extern double Strategy.Hedging.LotSize = 0; extern double Strategy.Hedging.TrailingStop = 15; extern double Strategy.Hedging.Slippage = 1; extern double Strategy.Hedging.TrailingMode = 1; /* extern string _HMA = " HMA Indicator Settings "; string HMA_Name = "Mega trend"; extern int HMA_Period = 33; extern int HMA_Mode = 3; */ int ExpertID=1844; int MagicNumber = 1844; //magic number string BASEFILENAME = "Fxi_Alpha_EA"; string BuyComment = "Simple R & S BUY"; string SellComment = "Simple R & S SELL"; bool StartOfDayProcessed = false; //+------------------------------------------------------------------+ //| expert initialization function | //+------------------------------------------------------------------+ int init(){ //create magic number MagicNumber = MakeMagicNumber(); //set up logging filename and logging level. SetLogFilename(BASEFILENAME+"."+Symbol()+".log"); SetLogLevel(LOG_DEBUG); //we need to use the debug for now //when its production ready we swicth to LOG_ERROR or LOG_FATAL LogDebug("Starting "+BASEFILENAME); return(0); } //+------------------------------------------------------------------+ //| expert deinitialization function | //+------------------------------------------------------------------+ int deinit(){ return(0); } //+------------------------------------------------------------------+ //| expert start function | //+------------------------------------------------------------------+ int start(){ //---- double prices[]; GetCurrentFiboPivotPoints(prices); double pivot = prices[FIBO_LEVEL_PIVOT]; double r3 = prices[FIBO_LEVEL_R3]; double r2 = prices[FIBO_LEVEL_R2]; double r1 = prices[FIBO_LEVEL_R1]; double s1 = prices[FIBO_LEVEL_S1]; double s2 = prices[FIBO_LEVEL_S2]; double s3 = prices[FIBO_LEVEL_S3]; if (prices[0]==0.0){ } if (prices[0]==0.0){ LogWarn("There was an error getting the Pivot prices."); return (-1); } if(MoneyManagement.Enabled) { Trading.LotSize = DefineLotSize(Trading.Risk,Trading.LotSize,Account.Type.IsMicro); //Adjust the lot size total } //Print("Pivot="+pivot+", S1="+s1+", S2="+s2+", S3="+s3+", R1="+r1+", R2="+r2+", R3="+r3); double takeprofit = 0; int ticket = -1; //default ticket number. double stoploss = Trading.StopLoss * Point; //default stop loss level. double servers_min_stop = MarketInfo(Symbol(), MODE_STOPLEVEL) * MarketInfo(Symbol(), MODE_POINT); datetime TimeToEndOfDay = StrToTime(TimeToStr(TimeCurrent(),TIME_DATE)+" 23:55"); //the last 5mintues of the trading hour of the day are purely for //cleaning up pending orders and getting ready for the new day. //any other time let do business. datetime StartOfDay1 = StrToTime(TimeToStr(TimeCurrent(),TIME_DATE)+" 00:01"); datetime StartOfDay2 = StrToTime(TimeToStr(TimeCurrent(),TIME_DATE)+" 00:30"); if (TimeCurrent()<=TimeToEndOfDay){ //if we dont have a sell order at R3 place one. if ( HasSellOrder(r3,MagicNumber,Trading.Slippage)!= true) { //open a sell order at r3 takeprofit = s1+MathMin(Trading.FlexPips*Point, servers_min_stop); stoploss = r3+MathMax(Trading.StopLoss * Point,servers_min_stop); ticket = PlaceResistanceOrder(r3,pivot, Trading.LotSize, stoploss, takeprofit ,TimeToEndOfDay); } //if we dont have a sell order at R2 place one. if ( HasSellOrder(r2,MagicNumber,Trading.Slippage)!= true) { //open a sell order at r2 takeprofit = s1+MathMin(Trading.FlexPips*Point, servers_min_stop); stoploss = r3+MathMax(Trading.StopLoss * Point,servers_min_stop); ticket = PlaceResistanceOrder(r2,pivot, Trading.LotSize, stoploss, takeprofit ,TimeToEndOfDay); } //if we dont have a sell order at R1 place one. if ( HasSellOrder(r1,MagicNumber,Trading.Slippage)!= true) { //open a sell order at r1 takeprofit = s1+MathMin(Trading.FlexPips*Point, servers_min_stop); stoploss = r3+MathMax(Trading.StopLoss * Point,servers_min_stop); ticket = PlaceResistanceOrder(r1,pivot, Trading.LotSize, stoploss, takeprofit ,TimeToEndOfDay); } //if we dont have a sell order at S3 place one. if ( HasBuyOrder(s3,MagicNumber,Trading.Slippage)!= true) { //open a buy order at s3 takeprofit = r1-MathMax(Trading.FlexPips*Point, servers_min_stop); stoploss = s3-MathMax(Trading.StopLoss * Point,servers_min_stop); ticket = PlaceSupportOrder(s3,pivot, Trading.LotSize, stoploss, takeprofit ,TimeToEndOfDay); } //if we dont have a sell order at S2 place one. if ( HasBuyOrder(s2,MagicNumber,Trading.Slippage)!= true) { //open a buy order at s2 takeprofit = r1-MathMax(Trading.FlexPips*Point, servers_min_stop); stoploss = s2-MathMax(Trading.StopLoss * Point,servers_min_stop); ticket = PlaceSupportOrder(s2,pivot, Trading.LotSize, stoploss, takeprofit ,TimeToEndOfDay); } //if we dont have a sell order at S1 place one. if ( HasBuyOrder(s1,MagicNumber,Trading.Slippage)!= true) { //open a sell order at s1 takeprofit = r1-MathMax(Trading.FlexPips*Point, servers_min_stop); stoploss = s1-MathMax(Trading.StopLoss*Point, servers_min_stop); ticket = PlaceSupportOrder(s1,pivot, Trading.LotSize, stoploss, takeprofit ,TimeToEndOfDay); } //now correct the OrderTakeProfit for left over orders, even if it means making a loss. //implement various strategies. ImplementStrategy(StrategyIndex, prices); } //we want to execute previous orders only during the start of the //day or when we haven't already done so. if (((TimeCurrent()>StartOfDay1) && (TimeCurrent()<StartOfDay2))|| (!StartOfDayProcessed) ){ StartOfDayProcessed = true; AdjustPreviousOrders(prices); } //TrackOrders(TrailingStopMode, MagicNumber, Symbol()); return(0); } /** * Now implement the Trading strategy defined by index. * */ void ImplementStrategy(int index, double prices[]){ switch (index){ case STRATEGY_HEDGING: SimpleHedging(prices); return; case STRATEGY_MEGA_TREND: MegaTrend(prices); return; default: return; } } /** * Yesterday or Last week's orders are a pain in the neck. * we need to close them as quickly as possible. If at all we get chance * to close them at BE we can do it. **/ void AdjustPreviousOrders(double prices[]){ int total = OrdersTotal()-1; int today = TimeDayOfWeek(Time[0]), orderDay=-1; double buytakeprofit=0,selltakeprofit=0; double servers_min_stop = MarketInfo(Symbol(), MODE_STOPLEVEL) * MarketInfo(Symbol(), MODE_POINT); //move the takeprofit to s1 even if it means a losing t/p selltakeprofit = MathMin(Ask,prices[FIBO_LEVEL_S1]); //move the takeprofit to s1 even if it means a losing t/p buytakeprofit = MathMax(Bid,prices[FIBO_LEVEL_R1]); for(;total>=0; total--){ if (OrderSelect(total,SELECT_BY_POS,MODE_TRADES)!=true) continue; if (OrderSymbol()!= Symbol()) continue; if (OrderMagicNumber()!= MagicNumber) continue; if ((OrderType()!=OP_BUY) && (OrderType()!=OP_SELL)) continue; //process only yesterday's or last week's orders. orderDay = TimeDayOfWeek(OrderOpenTime()); if ( (orderDay < today) || ((today==1) && ((orderDay==5)||(orderDay==6)) ) ){ //we can close it at break even if its possible. //if (OrderProfit()==0.0){ // LogInfo("Closing yesterday/last week order at break even."); // PartiallyClose(OrderType(),OrderTicket(),OrderLots(), OrderOpenPrice(), OrderTakeProfit(),Slippage); //} if ((OrderType()==OP_BUY) && (OrderTakeProfit()!=buytakeprofit) ){ //also make sure the takeprofit is valid. //if its not an invalid stop error can be generated. LogInfo("A buy order from yesterday or last week is present: OrderTicket="+OrderTicket()+", OrderProfit="+OrderProfit()+", OrderType="+OrderType2String(OrderType())+", OrderOpenPrice="+OrderOpenPrice()); LogInfo("Buy Order, new takeprofit calculated to be "+ buytakeprofit+" and the current price is "+ Bid); if (!ModifyOrder(OrderTicket(), OrderOpenPrice(),OrderStopLoss(),buytakeprofit, 0,CLR_NONE)) LogError("Failed to modify an old order. "+ ErrorDescription(GetLastError())); } else if ((OrderType()==OP_SELL) && (OrderTakeProfit()!=selltakeprofit)){ //also make sure the takeprofit is valid. //if its not an invalid stop error can be generated. LogInfo("A sell order from yesterday or last week is present: OrderTicket="+OrderTicket()+", OrderProfit="+OrderProfit()+", OrderType="+OrderType2String(OrderType())+", OrderOpenPrice="+OrderOpenPrice()); LogInfo("Sell Order, new takeprofit calculated to be "+ selltakeprofit+" and the current price is "+ Ask); if (!ModifyOrder(OrderTicket(), OrderOpenPrice(),OrderStopLoss(),selltakeprofit, 0,CLR_NONE)) LogError("Failed to modify an old order. "+ ErrorDescription(GetLastError())); } } } } /** * In this function place only buy orders. */ int PlaceSupportOrder(double price, double pivot, double lots, double stoploss, double takeprofit, datetime expiration){ LogDebug(""); LogDebug("PlaceSupportOrder():Start"); int ticket = -1; RefreshRates(); double servers_min_stop = MarketInfo(Symbol(), MODE_STOPLEVEL) * MarketInfo(Symbol(), MODE_POINT); int cmd = OP_BUYLIMIT; //if the price is within + or - Slippage*Point simply buy. if ( (((Trading.Slippage*Point) + Ask) >= price) && ((Ask-(Trading.Slippage*Point) ) <= price) ){ cmd = OP_BUY; LogInfo("Support Order at "+price+" is placed at market price."); LogInfo("SupportOrder: "+ OrderType2String(cmd)+" Price["+Ask+"] Pivot["+pivot+"] StopLoss["+stoploss+"] TakeProfit["+takeprofit+"] Expiration["+TimeToStr(expiration,TIME_DATE|TIME_MINUTES)+"]"); ticket = CreateOrder(cmd, lots, NormalizeDouble(Ask,Digits), NormalizeDouble(stoploss,Digits), NormalizeDouble(takeprofit,Digits), BuyComment, MagicNumber, Trading.Slippage,expiration); } else if (MathAbs(Ask-price) > servers_min_stop){ //if the price is too close to the stoplevel there is //nothing much we can do if (Ask < price) cmd = OP_BUYSTOP; LogInfo("SupportOrder: "+ OrderType2String(cmd)+" Price["+price+"] Pivot["+pivot+"] StopLoss["+stoploss+"] TakeProfit["+takeprofit+"] Expiration["+TimeToStr(expiration,TIME_DATE|TIME_MINUTES)+"]"); ticket = CreateOrder(cmd, lots, NormalizeDouble(price,Digits), NormalizeDouble(stoploss,Digits), NormalizeDouble(takeprofit,Digits), BuyComment, MagicNumber, Trading.Slippage,expiration); } LogDebug("PlaceSupportOrder():End"); LogDebug(""); return (ticket); } /** * In this function place only sell 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); int cmd = OP_SELLLIMIT; if ( (((Trading.Slippage*Point) + Bid) >= price) && ((Bid-(Trading.Slippage*Point) ) <= price) ){ LogInfo("Opening a sell order at market price."); LogInfo("ResistanceOrder: "+ OrderType2String(cmd)+" Price["+price+"] Pivot["+pivot+"] StopLoss["+stoploss+"] TakeProfit["+takeprofit+"] Expiration["+TimeToStr(expiration,TIME_DATE|TIME_MINUTES)+"]"); ticket = CreateOrder(cmd, lots, NormalizeDouble(Ask,Digits), NormalizeDouble(stoploss,Digits), NormalizeDouble(takeprofit,Digits), SellComment, MagicNumber, Trading.Slippage,expiration); } else if (MathAbs(Bid-price) > servers_min_stop){ //if the price is too close to the stoplevel there is //nothing much we can do if (Bid > price) cmd = OP_SELLSTOP; LogInfo("ResistanceOrder: "+ OrderType2String(cmd)+" Price["+price+"] Pivot["+pivot+"] StopLoss["+stoploss+"] TakeProfit["+takeprofit+"] Expiration["+TimeToStr(expiration,TIME_DATE|TIME_MINUTES)+"]"); ticket = CreateOrder(cmd, lots, NormalizeDouble(price,Digits), NormalizeDouble(stoploss,Digits), NormalizeDouble(takeprofit,Digits), SellComment, MagicNumber, Trading.Slippage,expiration); } return (ticket); } //+------------------------------------------------------------------+ //| Make Magic Number | //+------------------------------------------------------------------+ int MakeMagicNumber(){ 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; return(ExpertID+SymbolCode+PeriodCode); } double CountOpenLots(int type){ int total = OrdersTotal()-1; double lots = 0.0; for(;total>=0;total--){ if (OrderSelect(total,SELECT_BY_POS,MODE_TRADES)!=true) continue; if (OrderSymbol()!= Symbol()) continue; if (OrderMagicNumber()!= MagicNumber) continue; if (OrderType()!=type) continue; lots = lots + OrderLots(); } return (lots); } /** ============================= STRATEGIES ================================= **/ //Simple hedging strategy. void SimpleHedging(double prices[]){ //if the prices breaks the R3 and S3 barrier we need to be ready and place some buy order sell stop orders. //with a very tight stop loss int mn = MagicNumber+STRATEGY_HEDGING; double r3 = prices[FIBO_LEVEL_R3]; double s3 = prices[FIBO_LEVEL_S3]; string HedgeBuyComment ="(Hedge) "+BuyComment; string HedgeSellComment ="(Hedge) "+SellComment; int ticket = -1; double buylots = Strategy.Hedging.LotSize; double selllots = Strategy.Hedging.LotSize; if (buylots <=0.0){ //hedge all open buy positions. buylots = CountOpenLots(OP_SELL); } if (selllots <=0.0){ //hedge all open buy positions. selllots = CountOpenLots(OP_BUY); } //if the lot size is zero or less, the user wants to cover all the open sell or buy positions if ( (Ask >= r3 ) && (Ask <= (r3+(Strategy.Hedging.Slippage*Point)) ) ){ //we should place a buy order at this Resistance level 3 //if one is not already there. if ((!HasBuyOrder(r3,mn,Strategy.Hedging.Slippage)) && (!HasClosedBuyOrder(r3,mn,Strategy.Hedging.Slippage)) ){ LogDebug("Price reached near the R3 level, R3="+r3+", Price="+Ask); LogInfo("Opening a buy order at R3, Lots="+buylots+", Price="+Ask+", StopLoss="+ prices[FIBO_LEVEL_R2]+""); ticket = CreateOrder(OP_BUY,buylots,Ask, prices[FIBO_LEVEL_R2], 0, HedgeBuyComment,mn,Strategy.Hedging.Slippage,0); if (ticket<=0) LogError("Failed to open buy order (Hedge). "+ ErrorDescription(GetLastError())); } } if ( (Bid >= s3 ) && (Bid <= (s3+(Strategy.Hedging.Slippage*Point)) ) ){ //we should place a buy order at this Resistance level 3 //if one is not already there. if (!HasSellOrder(s3,mn,Strategy.Hedging.Slippage) && (!HasClosedSellOrder(s3,mn,Strategy.Hedging.Slippage)) ){ LogDebug("Price reached near the S3 level, S3="+s3+", Price="+Bid); LogInfo("Opening a buy order at S3, Lots="+selllots+", Price="+Bid+", StopLoss="+ prices[FIBO_LEVEL_S2]+""); ticket = CreateOrder(OP_SELL,selllots,Bid, prices[FIBO_LEVEL_S2], 0, HedgeSellComment,mn,Strategy.Hedging.Slippage,0); if (ticket<=0) LogError("Failed to open sell order (Hedge). " + ErrorDescription(GetLastError())); } } double params []; ArrayResize(params,1); params[0]=Strategy.Hedging.TrailingStop; TrackOrders(Strategy.Hedging.TrailingMode, mn, Symbol(),params); } //___________________________________________________________________________________________// //use mega trend indicator values void MegaTrend(double prices[]){ LogWarn("Mega trend Strategy is not yet implemented."); }
Sample
Analysis
Market Information Used:
Series array that contains open time of each bar
Indicator Curves created:
Indicators Used:
Custom Indicators Used:
Order Management characteristics:
Checks for the total of open orders
Other Features: