//+------------------------------------------------------------------+ //| 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 | //| | //| 2.0 => Tinashe B Chipomho (tinashechipomho@gmail.com) | //| Ok we have had our lessions from previous experiences | //| new version to address huge drawdowns. the new hedging | //| strategy requires a big margin we have to take out | //| money management module for a while. | //+------------------------------------------------------------------+ #property copyright "Copyright © 2007, LEGRUPO" #property link "http://www.legrupo.com" //include standard MQL headers. #include #include #include //include custom libraries. #include #include #include #include #include #include #include //define our strategies #define STRATEGY_NONE 0 //simple this one is very aggressive #define STRATEGY_TREND_MANAGER 2 //non-aggressive and is sensitive to market trend. #define STRATEGY_SIMPLE_RSI 4 //not so aggressive and very very sensitive to market direction/trend. //sick of how EAs read and pass parameters? //we now use this java style property file, with full explaination of each //parameter. extern string Configuration.File = "config\\fxialphatrader.properties"; //Global Parameters. int MagicNumber = 2044; //magic number string DailyPivot = "Daily Pivot"; string Expert.Name = "fxialpha"; int Expert.ID=20414; string Expert.Version="v3.0"; datetime PreviousDatetime = 0; bool StartOfDayProcessed = false; int Trading.Precision = 4; //+------------------------------------------------------------------+ //| expert initialization function | //+------------------------------------------------------------------+ int init(){ //create a session Session.Create(); //check for configuration file specific to this currency Symbol //otherwise use the default configuration property file. Configuration.File = Config.GetConfiguration(Symbol(),Expert.Name, Configuration.File); //get the precision (recently brokers have added an extra digit //this is a pain work with only 4 digits and 2 digits for JPY currencies). Trading.Precision = Trading.CheckPrecision(Symbol()); //Override the expert id with the one in the file if its available. if (StrToInteger( Config.GetProperty("Expert.Id",Configuration.File) ) > 0) Expert.ID = StrToInteger( Config.GetProperty("Expert.Id",Configuration.File) ); //create magic number based on symbol and chart period. //and effectively overwrite the existing magic number. MagicNumber = MagicNumber.MakeMagicNumber(Expert.ID); //what strategy are we using? string strategy = "0";//Config.GetProperty("Expert.Params.Strategy",Configuration.File); //ok we are done setting up what needed to be set up. //we log the details. Logging.Info("Starting "+WindowExpertName()+" : MagicNumber="+MagicNumber+", ExpertID="+Expert.ID +" Strategy="+strategy +" Precision="+Trading.Precision); Logging.Info("Server Minimum Stop ="+ (MarketInfo(Symbol(), MODE_STOPLEVEL) * MarketInfo(Symbol(), MODE_POINT))); //for detecting new bars. PreviousDatetime = Time[0]; return(0); } //+------------------------------------------------------------------+ //| expert deinitialization function | //+------------------------------------------------------------------+ int deinit(){ //we done destroy the session. Session.Destroy(); return(0); } //+------------------------------------------------------------------+ //| expert start function | //+------------------------------------------------------------------+ int start(){ //prepare array for prices. double prices[]; //read Fibonacci Prices. GetSupportResistance(prices); //Execute strategy, the value is read on every tick, to allow hot depployment //can be changed at any time without restarting the EA. ExecuteStrategy(prices, StrToInteger(Config.GetProperty("Expert.Params.Strategy",Configuration.File))); //make sure all positions are hedged anyway. Hedging.HedgeAll(MagicNumber,Configuration.File); //hedging is a sign that things have gone bad somewhere, it a fall back. //as soon as the profit is at break even for all hedged positions we need to close //the position and its related hedges. Hedging.CloseAtBreakEven(MagicNumber,Configuration.File); return(0); } /** * Executes the strategy the configured strategy, the default is the simple aggressive strategy. * */ void ExecuteStrategy(double prices[],int strategy){ switch(strategy){ case STRATEGY_TREND_MANAGER: TrendManagerStrategy(prices); break; case STRATEGY_SIMPLE_RSI: SimpleRSIStrategy(prices); break; default: SimpleSupportAndResistance(prices); } } void TrendManagerStrategy(double 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]; string Indicator.Name = "Trend Manager Indicator"; int Indicator.MinimumGap = Trading.GetPips(Configuration.File,"Expert.Indicator.1.MinimumGap"); int Indicator.BuyShift=StrToInteger(Config.GetProperty("Expert.Indicator.1.BuySignalShiftIndex",Configuration.File)); int Indicator.SellShift=StrToInteger(Config.GetProperty("Expert.Indicator.1.SellSignalShiftIndex",Configuration.File)); double buy = iCustom(Symbol(),PERIOD_D1,Indicator.Name,Indicator.MinimumGap,Indicator.BuyShift,0); double sell = iCustom(Symbol(),PERIOD_D1,Indicator.Name,Indicator.MinimumGap,Indicator.SellShift,0); double rsi = iRSI(Symbol(),PERIOD_D1,14,PRICE_TYPICAL,1); double takeprofit=0; double flexpips = Trading.GetPips(Configuration.File, "Trading.FlexPips"); double slippage = Trading.GetPips(Configuration.File, "Trading.Slippage"); double lotsize = StrToDouble(Config.GetProperty("Trading.LotSize",Configuration.File)); int ticket = -1; //default ticket number. double servers_min_stop = MarketInfo(Symbol(), MODE_STOPLEVEL) * MarketInfo(Symbol(), MODE_POINT); datetime TimeToEndOfDay = GetTimeToEndOfDay(); //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 StartTime = GetStartTime(); datetime EndTime = GetEndTime(); if (TimeCurrent()< TimeToEndOfDay){ if ((buy!=0.0) && (rsi>50.0)){ //buy signal do buys onlys including buying at Pivot level??. //delete all pending sell orders. Trading.DeletePending(OP_SELLLIMIT,MagicNumber,Symbol()); //if we dont have a buy order at S3 place one. if (!Trading.HasBuyOrder(s3,MagicNumber,slippage)) { //open a buy order at s3 takeprofit = NormalizeDouble(r1-MathMax(flexpips*Point, servers_min_stop),Trading.Precision); ticket = PlaceSupportOrder(FIBO_LEVEL_S3,prices, takeprofit,lotsize ,TimeToEndOfDay); } //if we dont have a buy order at S2 place one. if (!Trading.HasBuyOrder(s2,MagicNumber,slippage)) { //open a buy order at s2 takeprofit = NormalizeDouble(r1-MathMax(flexpips*Point, servers_min_stop),Trading.Precision); ticket = PlaceSupportOrder(FIBO_LEVEL_S2,prices, takeprofit,lotsize ,TimeToEndOfDay); } //if we dont have a buy order at S1 place one. if (!Trading.HasBuyOrder(s1,MagicNumber,slippage)) { //open a sell order at s1 takeprofit = NormalizeDouble(r1-MathMax(flexpips*Point, servers_min_stop),Trading.Precision); ticket = PlaceSupportOrder(FIBO_LEVEL_S1,prices, takeprofit,lotsize ,TimeToEndOfDay); } //also place an order at pivot level. //if we dont have a buy order at pivot level place one. if (!Trading.HasBuyOrder(pivot,MagicNumber,slippage)) { //open a sell order at s1 //bad idea to buy at pivot level, uncomment the two lines if you want to buy at pivot level. //takeprofit = NormalizeDouble(r1-MathMax(flexpips*Point, servers_min_stop),Trading.Precision); //ticket = PlaceSupportOrder(FIBO_LEVEL_PIVOT,prices, takeprofit,lotsize ,TimeToEndOfDay); } } else if ((sell!=0.0) && (rsi<50.0)){ //sell signal do sells only including selling at pivot level. //also delete pending buy orders Trading.DeletePending(OP_BUYLIMIT,MagicNumber,Symbol()); //if we dont have a sell order at R3 place one. if ( !Trading.HasSellOrder(r3,MagicNumber,slippage)) { //open a sell order at r3 takeprofit = NormalizeDouble(s1+MathMin(flexpips*Point, servers_min_stop),Trading.Precision); ticket = PlaceResistanceOrder(FIBO_LEVEL_R3,prices, takeprofit,lotsize,TimeToEndOfDay); Logging.Trace("Placing a SELL Order at R3. TakeProfit["+takeprofit+"] LotSize["+lotsize+"] Price["+prices[FIBO_LEVEL_R3]+"] Ticket="+ticket); } //if we dont have a sell order at R2 place one. if ( !Trading.HasSellOrder(r2,MagicNumber,slippage) ) { //open a sell order at r2 takeprofit = NormalizeDouble(s1+MathMin(flexpips*Point, servers_min_stop),Trading.Precision); ticket = PlaceResistanceOrder(FIBO_LEVEL_R2,prices, takeprofit,lotsize,TimeToEndOfDay); Logging.Trace("Placing a SELL Order at R2. TakeProfit["+takeprofit+"] LotSize["+lotsize+"] Price["+prices[FIBO_LEVEL_R2]+"] Ticket="+ticket); } //if we dont have a sell order at R1 place one. if ( !Trading.HasSellOrder(r1,MagicNumber,slippage) ) { //open a sell order at r1 takeprofit = NormalizeDouble(s1+MathMin(flexpips*Point, servers_min_stop),Trading.Precision); ticket = PlaceResistanceOrder(FIBO_LEVEL_R1,prices, takeprofit,lotsize,TimeToEndOfDay); Logging.Trace("Placing a SELL Order at R1 TakeProfit["+takeprofit+"] LotSize["+lotsize+"] Price["+prices[FIBO_LEVEL_R1]+"] Ticket="+ticket); } //also place an order at pivot level. //if we dont have a sell order at S1 place one. if (!Trading.HasSellOrder(pivot,MagicNumber,slippage)) { //open a sell order at s1 //takeprofit = NormalizeDouble(s1+MathMin(flexpips*Point, servers_min_stop),Trading.Precision); //ticket = PlaceResistanceOrder(FIBO_LEVEL_PIVOT,prices, takeprofit,lotsize ,TimeToEndOfDay); //Logging.Trace("Placing a SELL Order at Pivot. TakeProfit["+takeprofit+"] LotSize["+lotsize+"] Price["+prices[FIBO_LEVEL_PIVOT]+"] Ticket="+ticket); } } else{ //at this point do nothing //to be updated later. } } } //=================== Simple RSI Strategy ========================= // Using this simple RSI strategy we use RSI(14) on a daily chart. void SimpleRSIStrategy(double prices[]){ } void SimpleSupportAndResistance(double 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]; double takeprofit=0; double flexpips = Trading.GetPips(Configuration.File, "Trading.FlexPips"); int slippage = Trading.GetPips(Configuration.File,"Trading.Slippage"); double lotsize = StrToDouble(Config.GetProperty("Trading.LotSize",Configuration.File)); int ticket = -1; //default ticket number. 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 ( !Trading.HasSellOrder(r3,MagicNumber,slippage)) { //open a sell order at r3 takeprofit = NormalizeDouble(s1+MathMin(flexpips*Point, servers_min_stop),Trading.Precision); ticket = PlaceResistanceOrder(FIBO_LEVEL_R3,prices, takeprofit,lotsize,TimeToEndOfDay); } //if we dont have a sell order at R2 place one. if ( !Trading.HasSellOrder(r2,MagicNumber,slippage) ) { //open a sell order at r2 takeprofit = NormalizeDouble(s1+MathMin(flexpips*Point, servers_min_stop),Trading.Precision); ticket = PlaceResistanceOrder(FIBO_LEVEL_R2,prices, takeprofit,lotsize,TimeToEndOfDay); } //if we dont have a sell order at R1 place one. if ( !Trading.HasSellOrder(r1,MagicNumber,slippage) ) { //open a sell order at r1 takeprofit = NormalizeDouble(s1+MathMin(flexpips*Point, servers_min_stop),Trading.Precision); ticket = PlaceResistanceOrder(FIBO_LEVEL_R1,prices, takeprofit,lotsize,TimeToEndOfDay); } //if we dont have a sell order at S3 place one. if ( Trading.HasBuyOrder(s3,MagicNumber,slippage)!= true) { //open a buy order at s3 takeprofit = NormalizeDouble(r1-MathMax(flexpips*Point, servers_min_stop),Trading.Precision); ticket = PlaceSupportOrder(FIBO_LEVEL_S3,prices, takeprofit,lotsize ,TimeToEndOfDay); } //if we dont have a sell order at S2 place one. if ( Trading.HasBuyOrder(s2,MagicNumber,slippage)!= true) { //open a buy order at s2 takeprofit = NormalizeDouble(r1-MathMax(flexpips*Point, servers_min_stop),Trading.Precision); ticket = PlaceSupportOrder(FIBO_LEVEL_S2,prices, takeprofit,lotsize ,TimeToEndOfDay); } //if we dont have a sell order at S1 place one. if ( Trading.HasBuyOrder(s1,MagicNumber,slippage)!= true) { //open a sell order at s1 takeprofit = NormalizeDouble(r1-MathMax(flexpips*Point, servers_min_stop),Trading.Precision); ticket = PlaceSupportOrder(FIBO_LEVEL_S1,prices, takeprofit,lotsize ,TimeToEndOfDay); } } } /** * In this function place only sell orders. */ int PlaceResistanceOrder(int index, double prices[], double takeprofit, double lots, datetime expiration){ int ticket = -1; int slippage = Trading.GetPips(Configuration.File,"Trading.Slippage"); string SellComment = WindowExpertName()+":"+Config.GetProperty("Trading.SellComment",Configuration.File); double HedgePips = Trading.GetPips(Configuration.File,"Hedging.Pips"); double r3 = prices[FIBO_LEVEL_R3]; double pivot = prices[FIBO_LEVEL_PIVOT]; double price = prices[index]; double stoploss = r3 + (HedgePips * Point); double servers_min_stop = MarketInfo(Symbol(), MODE_STOPLEVEL) * MarketInfo(Symbol(), MODE_POINT); RefreshRates(); int cmd = OP_SELLLIMIT; if ( (((slippage*Point) + Bid) >= price) && ((Bid-(slippage*Point) ) <= price) ){ Logging.Info("Opening a sell order at market price."); Logging.Info("ResistanceOrder: "+ Trading.OrderType2String(cmd)+" Bid["+Bid+"] Price["+price+"] Pivot["+pivot+"] StopLoss["+stoploss+"] TakeProfit["+takeprofit+"] Expiration["+TimeToStr(expiration,TIME_DATE|TIME_MINUTES)+"]"); ticket = Trading.CreateOrder(cmd, lots, NormalizeDouble(Bid,Trading.Precision), NormalizeDouble(stoploss,Trading.Precision), NormalizeDouble(takeprofit,Trading.Precision), SellComment, MagicNumber, 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; Logging.Info("ResistanceOrder: Server Minimum Stop["+servers_min_stop+"] "+ Trading.OrderType2String(cmd)+" Bid["+Bid+"] Price["+price+"] Pivot["+pivot+"] StopLoss["+stoploss+"] TakeProfit["+takeprofit+"] Expiration["+TimeToStr(expiration,TIME_DATE|TIME_MINUTES)+"]"); ticket = Trading.CreateOrder(cmd, lots, NormalizeDouble(price,Trading.Precision), NormalizeDouble(stoploss,Trading.Precision), NormalizeDouble(takeprofit,Trading.Precision), SellComment, MagicNumber, slippage,expiration); } return (ticket); } /** * In this function place only buy orders. */ int PlaceSupportOrder(int index, double prices[], double takeprofit, double lots, datetime expiration){ double HedgePips = Trading.GetPips(Configuration.File,"Hedging.Pips"); double s3 = prices[FIBO_LEVEL_S3]; double pivot = prices[FIBO_LEVEL_PIVOT]; double price = prices[index]; //double hedging_distance = s3 - (StopLossHedgePips* Point); double stoploss = s3 - (HedgePips* Point); //( (MathAbs(price-hedging_distance)) *2); int ticket = -1; int slippage = Trading.GetPips(Configuration.File,"Trading.Slippage"); string BuyComment = WindowExpertName()+":"+Config.GetProperty("Trading.BuyComment",Configuration.File); 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 ( (((slippage*Point) + Ask) >= price) && ((Ask-(slippage*Point) ) <= price) ){ cmd = OP_BUY; Logging.Info("Support Order at "+price+" is placed at market price."); Logging.Info("SupportOrder: "+ Trading.OrderType2String(cmd)+" Ask["+Ask+"] Price["+Ask+"] Pivot["+pivot+"] StopLoss["+stoploss+"] TakeProfit["+takeprofit+"] Expiration["+TimeToStr(expiration,TIME_DATE|TIME_MINUTES)+"]"); ticket = Trading.CreateOrder(cmd, lots, NormalizeDouble(Ask,Trading.Precision), NormalizeDouble(stoploss,Trading.Precision), NormalizeDouble(takeprofit,Trading.Precision), BuyComment, MagicNumber, 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; Logging.Info("SupportOrder: "+ Trading.OrderType2String(cmd)+" Ask["+Ask+"] Price["+price+"] Pivot["+pivot+"] StopLoss["+stoploss+"] TakeProfit["+takeprofit+"] Expiration["+TimeToStr(expiration,TIME_DATE|TIME_MINUTES)+"]"); ticket = Trading.CreateOrder(cmd, lots, NormalizeDouble(price,Trading.Precision), NormalizeDouble(stoploss,Trading.Precision), NormalizeDouble(takeprofit,Trading.Precision), BuyComment, MagicNumber, slippage,expiration); } return (ticket); } void GetSupportResistance(double& prices[]){ ArrayResize(prices,7); ArrayInitialize(prices,0.0); prices[FIBO_LEVEL_R3] = NormalizeDouble(iCustom(Symbol(),PERIOD_D1,DailyPivot,0,1),Trading.Precision); prices[FIBO_LEVEL_R2] = NormalizeDouble(iCustom(Symbol(),PERIOD_D1,DailyPivot,1,1),Trading.Precision); prices[FIBO_LEVEL_R1] = NormalizeDouble(iCustom(Symbol(),PERIOD_D1,DailyPivot,2,1),Trading.Precision); prices[FIBO_LEVEL_PIVOT] = NormalizeDouble(iCustom(Symbol(),PERIOD_D1,DailyPivot,3,1),Trading.Precision); prices[FIBO_LEVEL_S1] = NormalizeDouble(iCustom(Symbol(),PERIOD_D1,DailyPivot,4,1),Trading.Precision); prices[FIBO_LEVEL_S2] = NormalizeDouble(iCustom(Symbol(),PERIOD_D1,DailyPivot,5,1),Trading.Precision); prices[FIBO_LEVEL_S3] = NormalizeDouble(iCustom(Symbol(),PERIOD_D1,DailyPivot,6,1),Trading.Precision); } datetime GetTimeToEndOfDay(){ string eod = StringTrimRight(StringTrimLeft(Config.GetProperty("Expert.Params.Orders.ExpiryTime",Configuration.File))); if (StringLen(eod)<5) eod = "23:55"; return (StrToTime(TimeToStr(TimeCurrent(),TIME_DATE)+" "+eod)); } datetime GetStartTime(){ string st = StringTrimRight(StringTrimLeft(Config.GetProperty("Expert.Params.StartTime",Configuration.File))); if (StringLen(st)<5) st = "00:01"; return (StrToTime(TimeToStr(TimeCurrent(),TIME_DATE)+" "+st)); } datetime GetEndTime(){ string et = StringTrimRight(StringTrimLeft(Config.GetProperty("Expert.Params.EndTime",Configuration.File))); if (StringLen(et)<5) et = "23:55"; return (StrToTime(TimeToStr(TimeCurrent(),TIME_DATE)+" "+et)); }