//+------------------------------------------------------------------+ //| | //| 3pSAR_EA.mq4 - Ver 1.0 | //| | //| Description of EA //| Time Frame //| M1, M15 and H1 //| Indicator //| parabolic SAR changed to 0.01 and 0.1 //| Entry Strategy //| When H1 and M15 are in the same direction then every time that M1 changes in that direction, //| enter a trade at the completion of the candle. //| Exit Strategy //| At this stage apply a default Trailing Stop of 15 pips. //| The TS must be enabled the minute it is applied, and not wait to trail at Break Even, to negate the need for a SL. //+------------------------------------------------------------------+ #property copyright "Robert Hill" #property link "None" #include #include // This makes code easier to read extern string Expert_Name = "3pSar_EA_v1.0"; extern int MagicNumberBase = 10000; //+---------------------------------------------------+ //|Money Management | //+---------------------------------------------------+ extern double Lots=0.1; //+---------------------------------------------------+ //|Indicator Variables | //| Change these to try your own system | //| or add more if you like | //+---------------------------------------------------+ extern string ps1 = "--pSAR inputs--"; extern int pSAR_Step = 0.01; extern double pSAR_Max = 0.1; extern int pSAR1_TimeFrame = 60; extern int pSAR2_TimeFrame = 15; extern int pSAR3_TimeFrame = 1; //+---------------------------------------------------+ //|Profit controls | //+---------------------------------------------------+ extern string st6 = "--Profit Controls--"; extern double StopLoss=15; extern double TakeProfit=0; extern int Slippage=3; extern int MaxTrades = 1; //+---------------------------------------------------+ //|General controls | //+---------------------------------------------------+ int MagicNumber=0; string setup; int TradesInThisSymbol = 0; datetime timeprev = 0; //+---------------------------------------------------+ //| Indicator values for signals and filters | //| Add or Change to test your system | //+---------------------------------------------------+ //+------------------------------------------------------------------+ //| Calculate MagicNumber, setup comment and assign RSI Period | //| | //+------------------------------------------------------------------+ int init() { MagicNumber = MagicNumberBase + func_Symbol2Val(Symbol())*100 + func_TimeFrame_Const2Val(Period()); setup=Expert_Name + Symbol() + "_" + func_TimeFrame_Val2String(func_TimeFrame_Const2Val(Period())); return(0); } int deinit() { return(0); } //+------------------------------------------------------------------+ //| CheckExitCondition | //| //| BUY //| The exit comes one of two ways. //| Most common 8 MA go through the yellow mid keltner band, //| but occasionally the 2 MA will go through first. //| But which ever goes through first it should be the exit. //| //| SELL //| //+------------------------------------------------------------------+ int CheckExitCondition(int cmd) { return (false); } //+------------------------------------------------------------------+ //| CheckEntryCondition | //| | //| Indicators used | //| pSAR | //| When H1 and M15 are in the same direction then //| every time that M1 changes in that direction, //| enter a trade at the completion of the candle. //+------------------------------------------------------------------+ bool CheckEntryCondition(int cmd) { double pSAR_H1, pSAR_M15, pSAR_M1, pSAR_M1Prev; pSAR_H1 = iSAR(Symbol(), pSAR1_TimeFrame, pSAR_Step, pSAR_Max, 1); pSAR_M15 = iSAR(Symbol(), pSAR2_TimeFrame, pSAR_Step, pSAR_Max, 1); pSAR_M1 = iSAR(Symbol(), pSAR3_TimeFrame, pSAR_Step, pSAR_Max, 1); pSAR_M1Prev = iSAR(Symbol(), pSAR3_TimeFrame, pSAR_Step, pSAR_Max, 2); switch (cmd) { case OP_BUY : if (pSAR_H1 < Bid) { if (pSAR_M15 < Bid) { if (pSAR_M1 < Bid && pSAR_M1Prev > Bid) return (true); } } break; case OP_SELL : if (pSAR_H1 > Bid) { if (pSAR_M15 > Bid) { if (pSAR_M1 > Bid && pSAR_M1Prev < Bid) return (true); } } } return (false); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Start | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ int start() { // Only run once per completed bar if(timeprev==Time[0]) return(0); timeprev = Time[0]; //+------------------------------------------------------------------+ //| Check for Open Position | //+------------------------------------------------------------------+ HandleOpenPositions(); // Check if any open positions were not closed TradesInThisSymbol = CheckOpenPositions(); // Only allow 1 trade per Symbol if(TradesInThisSymbol >= MaxTrades) { return(0);} //+------------------------------------------------------------------+ //| Friday No trade zone | //+------------------------------------------------------------------+ if (CheckEntryCondition(OP_BUY)==true) { OpenBuyOrder(Lots, StopLoss,TakeProfit, Slippage, setup, MagicNumber, Green); return(0); } if (CheckEntryCondition(OP_SELL)==true) { OpenSellOrder(Lots, StopLoss,TakeProfit, Slippage, setup, MagicNumber, Red); } return(0); } //+------------------------------------------------------------------+ //| OpenBuyOrder | //| If Stop Loss or TakeProfit are used the values are calculated | //| for each trade | //+------------------------------------------------------------------+ int OpenBuyOrder(double mLots, double mStopLoss, double mTakeProfit, int mSlippage, string mComment, int mMagic, color mColor) { int err,ticket; double myStopLoss = 0, myTakeProfit = 0; RefreshRates(); myStopLoss = StopLong(Bid,mStopLoss); myTakeProfit = TakeLong(Bid,mTakeProfit); // Normalize all price / stoploss / takeprofit to the proper # of digits. if (Digits > 0) { myStopLoss = NormalizeDouble( myStopLoss, Digits); myTakeProfit = NormalizeDouble( myTakeProfit, Digits); } ticket=OrderSend(Symbol(),OP_BUY,mLots,Ask,mSlippage,myStopLoss,myTakeProfit,mComment,mMagic,0,mColor); if (ticket > 0) { if (OrderSelect( ticket,SELECT_BY_TICKET, MODE_TRADES) ) { Print("BUY order opened : ", OrderOpenPrice( )); // PlaySound("Alert.wav"); } } else { err = GetLastError(); Print("Error opening BUY order [" + setup + "]: (" + err + ") " + ErrorDescription(err)); } return(ticket); } //+------------------------------------------------------------------+ //| OpenSellOrder | //| If Stop Loss or TakeProfit are used the values are calculated | //| for each trade | //+------------------------------------------------------------------+ int OpenSellOrder(double mLots, double mStopLoss, double mTakeProfit, int mSlippage, string mComment, int mMagic, color mColor) { int err, ticket; double myBid, myAsk, myStopLoss = 0, myTakeProfit = 0; myStopLoss = StopShort(Ask,mStopLoss); myTakeProfit = TakeShort(Ask,mTakeProfit); // Normalize all price / stoploss / takeprofit to the proper # of digits. if (Digits > 0) { myStopLoss = NormalizeDouble( myStopLoss, Digits); myTakeProfit = NormalizeDouble( myTakeProfit, Digits); } ticket=OrderSend(Symbol(),OP_SELL,mLots,Bid,mSlippage,myStopLoss,myTakeProfit,mComment,mMagic,0,mColor); if (ticket > 0) { if (OrderSelect( ticket,SELECT_BY_TICKET, MODE_TRADES) ) { Print("Sell order opened : ", OrderOpenPrice()); // PlaySound("Alert.wav"); } } else { err = GetLastError(); Print("Error opening Sell order [" + mComment + "]: (" + err + ") " + ErrorDescription(err)); } return(ticket); } double StopLong(double price,int stop) { if(stop==0) return(0); else return(price-(stop*Point)); } double StopShort(double price,int stop) { if(stop==0) return(0); else return(price+(stop*Point)); } double TakeLong(double price,int take) { if(take==0) return(0); else return(price+(take*Point)); } double TakeShort(double price,int take) { if(take==0) return(0); else return(price-(take*Point)); } //+------------------------------------------------------------------+ //| Handle Open Positions | //| Check if any open positions need to be closed or modified | //+------------------------------------------------------------------+ int HandleOpenPositions() { int cnt, ticket, ExitRule; double ol; for(cnt=OrdersTotal()-1;cnt>=0;cnt--) { OrderSelect (cnt, SELECT_BY_POS, MODE_TRADES); if ( OrderSymbol() != Symbol()) continue; if ( OrderMagicNumber() != MagicNumber) continue; ticket = OrderTicket(); ol = OrderLots(); if(OrderType() == OP_BUY) { if (CheckExitCondition(OP_BUY) == true) { CloseOrder(ticket,ol,OP_BUY); } else { HandleTrailingStop(OP_BUY,ticket,OrderOpenPrice(),OrderStopLoss(),OrderTakeProfit()); } } if(OrderType() == OP_SELL) { if (CheckExitCondition(OP_SELL) == true) { CloseOrder(ticket,ol,OP_SELL); } else { HandleTrailingStop(OP_SELL,ticket,OrderOpenPrice(),OrderStopLoss(),OrderTakeProfit()); } } } } //+------------------------------------------------------------------+ //| Check Open Position Controls | //+------------------------------------------------------------------+ int CheckOpenPositions() { int cnt, total; int NumTrades; NumTrades = 0; total=OrdersTotal(); for(cnt=OrdersTotal()-1;cnt>=0;cnt--) { OrderSelect (cnt, SELECT_BY_POS, MODE_TRADES); if ( OrderSymbol() != Symbol()) continue; if ( OrderMagicNumber() != MagicNumber) continue; if(OrderType() == OP_BUY ) NumTrades++; if(OrderType() == OP_SELL ) NumTrades++; } return (NumTrades); } int CloseOrder(int ticket,double numLots,int cmd) { bool result; int CloseCnt, err; double myPrice; // try to close 3 Times CloseCnt = 0; while (CloseCnt < 3) { if (cmd == OP_BUY) myPrice = Bid; if (cmd == OP_SELL) myPrice = Ask; if (Digits > 0) myPrice = NormalizeDouble( myPrice, Digits); if ( OrderClose(ticket,numLots,myPrice,Slippage,Violet) == true) CloseCnt = 3; else { err=GetLastError(); if (err > 0) { Print(" Error closing order : (", err , ") " + ErrorDescription(err)); Sleep(5000); RefreshRates(); } CloseCnt++; } } return(0); } //+------------------------------------------------------------------+ //| HandleTrailingStop | //| Type 1 moves the stoploss without delay. | //| Type 2 waits for price to move the amount of the trailStop | //| before moving stop loss then moves like type 1 | //| Type 3 uses up to 3 levels for trailing stop | //| Level 1 Move stop to 1st level | //| Level 2 Move stop to 2nd level | //| Level 3 Trail like type 1 by fixed amount other than 1 | //| Type 4 Move stop to breakeven + Lockin, no trail | //| Type 5 uses steps for 1, every step pip move moves stop 1 pip | //| Type 6 Uses EMA to set trailing stop | //+------------------------------------------------------------------+ void HandleTrailingStop(int type, int ticket, double op, double os, double tp) { /* switch (TrailingStopType) { case 1 : */ Immediate_TrailingStop (type, ticket, op, os, tp); // break; /* case 2 : Delayed_TrailingStop (type, ticket, op, os, tp); break; case 3 : ThreeLevel_TrailingStop (type, ticket, op, os, tp); break; case 4 : BreakEven_TrailingStop (type, ticket, op, os, tp); break; case 5 : eTrailingStop (type, ticket, op, os, tp); break; case 6 : MA_TrailingStop (type, ticket, op, os, tp); break; case 7 : pSAR_TrailingStop (type, ticket, op, os, tp); break; } */ } //+------------------------------------------------------------------+ //| Immediate_TrailingStop.mq4 | //| Copyright © 2006, Forex-TSD.com | //| Written by MrPip,robydoby314@yahoo.com | //| | //| Moves the stoploss without delay. | //+------------------------------------------------------------------+ void Immediate_TrailingStop(int type, int ticket, double op, double os, double tp) { double pt, pp, BuyStop, SellStop; pp = MarketInfo(Symbol(), MODE_POINT); if (type==OP_BUY) { pt = StopLoss * pp; if(Bid-os > pt) { BuyStop = Bid - pt; if (Digits > 0) BuyStop = NormalizeDouble( BuyStop, Digits); BuyStop = ValidStopLoss(OP_BUY,Bid, BuyStop); if (os < BuyStop) ModifyOrder(ticket,op,BuyStop,tp,LightGreen); return; } } if (type==OP_SELL) { pt = StopLoss * pp; if(os - Ask > pt) { SellStop = Ask + pt; if (Digits > 0) SellStop = NormalizeDouble( SellStop, Digits); SellStop = ValidStopLoss(OP_SELL, Ask, SellStop); if (os > SellStop) ModifyOrder(ticket,op,SellStop,tp,DarkOrange); return; } } } int ModifyOrder(int ord_ticket,double op, double price,double tp, color mColor) { int CloseCnt, err; CloseCnt=0; while (CloseCnt < 3) { if (OrderModify(ord_ticket,op,price,tp,0,mColor)== true) { CloseCnt = 3; } else { err=GetLastError(); Print(CloseCnt," Error modifying order : (", err , ") " + ErrorDescription(err)); Sleep(5000); if (err>0) CloseCnt++; } } } double ValidStopLoss(int type, double price, double SL) { double mySL; double minstop, pp; pp = MarketInfo(Symbol(), MODE_POINT); minstop = MarketInfo(Symbol(),MODE_STOPLEVEL); mySL = SL; if (type == OP_BUY) { if((price - mySL) < minstop*pp) mySL = price - minstop*pp; } if (type == OP_SELL) { if((mySL-price) < minstop*pp) mySL = price + minstop*pp; } return(NormalizeDouble(mySL,MarketInfo(Symbol(), MODE_DIGITS))); } int func_Symbol2Val(string symbol) { string mySymbol = StringSubstr(symbol,0,6); if(mySymbol=="AUDCAD") return(1); if(mySymbol=="AUDJPY") return(2); if(mySymbol=="AUDNZD") return(3); if(mySymbol=="AUDUSD") return(4); if(mySymbol=="CHFJPY") return(5); if(mySymbol=="EURAUD") return(6); if(mySymbol=="EURCAD") return(7); if(mySymbol=="EURCHF") return(8); if(mySymbol=="EURGBP") return(9); if(mySymbol=="EURJPY") return(10); if(mySymbol=="EURUSD") return(11); if(mySymbol=="GBPCHF") return(12); if(mySymbol=="GBPJPY") return(13); if(mySymbol=="GBPUSD") return(14); if(mySymbol=="NZDJPY") return(15); if(mySymbol=="NZDUSD") return(16); if(mySymbol=="USDCAD") return(17); if(mySymbol=="USDCHF") return(18); if(mySymbol=="USDJPY") return(19); Comment("unexpected Symbol"); return(999); } //+------------------------------------------------------------------+ //| Time frame interval appropriation function | //+------------------------------------------------------------------+ int func_TimeFrame_Const2Val(int Constant ) { switch(Constant) { case 1: // M1 return(1); case 5: // M5 return(2); case 15: return(3); case 30: return(4); case 60: return(5); case 240: return(6); case 1440: return(7); case 10080: return(8); case 43200: return(9); } } //+------------------------------------------------------------------+ //| Time frame string appropriation function | //+------------------------------------------------------------------+ string func_TimeFrame_Val2String(int Value ) { switch(Value) { case 1: // M1 return("PERIOD_M1"); case 2: // M1 return("PERIOD_M5"); case 3: return("PERIOD_M15"); case 4: return("PERIOD_M30"); case 5: return("PERIOD_H1"); case 6: return("PERIOD_H4"); case 7: return("PERIOD_D1"); case 8: return("PERIOD_W1"); case 9: return("PERIOD_MN1"); default: return("undefined " + Value); } } //+------------------------------------------------------------------+