//+-------------------------------------------------------------------+ //| Spider.mq4 | //| Copyright © 2009, Steve Hopwood | //| http://www.hopwood3.freeserve.co.uk | //+-------------------------------------------------------------------+ #property copyright "Copyright © 2009, Steve Hopwood" #property link "http://www.hopwood3.freeserve.co.uk" #include #include #define NL "\n" #define up "Up" #define down "Down" #define none "None" #define buy "Buy" #define both "Both" /* Matt Kennel has provided the code for bool O_R_CheckForHistory(int ticket). Cheers Matt, You are a star. Code for adding debugging Sleep Alert("G"); int x = 0; while (x == 0) Sleep(100); FUNCTIONS LIST int init() int start() ----Trading---- void LookForTradingOpportunities() double CalculateLotSize() bool IsTradingAllowed() bool SendSingleTrade(int type, string comment, double lotsize, double price, double stop, double take) bool DoesTradeExist() bool CloseTrade(int ticket) void LookForTradeClosure() bool CheckTradingTimes() void CloseAllTrades() ----Hanover module. The functions---- bool HanoverFilter() void SetUpArrays() void CleanUpInputString() int CalculateParamsPassed() void ReadHanover() int LoadRSvalues() double ReadStrength(string curr, string tf, int shift) ----Balance/swap filters module---- void TradeDirectionBySwap() bool IsThisPairTradable() bool BalancedPair(int type) ----Matt's Order Reliable library code bool O_R_CheckForHistory(int ticket) Cheers Matt, You are a star. void O_R_Sleep(double mean_time, double max_time) ----Indicator readings---- void ReadIndicatorValues() void GetVq() double GetAa(int tf, int price, int period, int mashift, int method, int buffer, int shift) double GetAtr() ----Balance/swap filters module---- void TradeDirectionBySwap() bool IsThisPairTradable() bool BalancedPair(int type) ----Trade management module---- void TradeManagementModule() void BreakEvenStopLoss() bool CheckForHiddenStopLossHit(int type, int iPipsAboveVisual, double stop ) void JumpingStopLoss() void HiddenTakeProfit() void HiddenStopLoss() void TrailingStopLoss() */ extern string gen="----General inputs----"; extern double Lot=0.01; extern bool StopTrading=false; extern bool TradeLong=true; extern bool TradeShort=true; extern int MagicNumber=325; extern string TradeComment="Spider"; extern bool CriminalIsECN=false; extern double MaxSpread=40; extern string te="----Trade exit inputs----"; extern int FirstTradeTakeProfit=90; extern int SubsequentTakeProfit=30; extern int StopLoss=30; extern string vq="----VQ inputs----"; extern int VqTimeFrame = 0; extern int VqLength=8; extern int VqMethod = 3; extern int VqSmoothing = 1; extern int VqFilter = 5; extern string mi="====Martingale inputs----"; extern bool UseMartingale=true; extern double MartingaleLotMultiplier=2; extern double MaxLotsAllowed=0.32; extern string amc="----Available Margin checks----"; extern string sco="Scoobs"; extern bool UseScoobsMarginCheck=false; extern string fk="ForexKiwi"; extern bool UseForexKiwi=true; extern int FkMinimumMarginPercent=1500; extern string tt="----Trading hours----"; extern string Trade_Hours= "Set Morning & Evening Hours"; extern string Trade_Hoursi= "Use 24 hour, local time clock"; extern string Trade_Hours_M= "Morning Hours 0-12"; extern int start_hourm = 0; extern int end_hourm = 12; extern string Trade_Hours_E= "Evening Hours 12-24"; extern int start_houre = 12; extern int end_houre = 24; extern string tmm="----Trade management module----"; extern bool AlsoManageMartingaleTrades=false; extern string BE="Break even settings"; extern bool BreakEven=false; extern int BreakEvenPips=25; extern int BreakEvenProfit=10; extern bool HideBreakEvenStop=false; extern int PipsAwayFromVisualBE=5; extern string cts="----Candlestick trailing stop----"; extern bool UseCandlestickTrailingStop=false; extern string JSL="Jumping stop loss settings"; extern bool JumpingStop=true; extern int JumpingStopPips=30; extern bool AddBEP=true; extern bool JumpAfterBreakevenOnly=false; extern bool HideJumpingStop=false; extern int PipsAwayFromVisualJS=10; extern string TSL="Trailing stop loss settings"; extern bool TrailingStop=false; extern int TrailingStopPips=50; extern bool HideTrailingStop=false; extern int PipsAwayFromVisualTS=10; extern bool TrailAfterBreakevenOnly=false; extern bool StopTrailAtPipsProfit=false; extern int StopTrailPips=0; extern string hsl1="Hidden stop loss settings"; extern bool HideStopLossEnabled=false; extern int HiddenStopLossPips=20; extern string htp="Hidden take profit settings"; extern bool HideTakeProfitEnabled=false; extern int HiddenTakeProfitPips=20; extern string mis="----Odds and ends----"; extern bool ShowManagementAlerts=true; extern int DisplayGapSize=30; //Matt's O-R stuff int O_R_Setting_max_retries = 10; double O_R_Setting_sleep_time = 4.0; /* seconds */ double O_R_Setting_sleep_max = 15.0; /* seconds */ //Trading variables int TicketNo, OpenTrades; bool CanTradeThisPair;//Will be false when this pair fails the currency can only trade twice filter, or the balanced trade filter bool BuyOpen, SellOpen; //VQ double VqUp, VqDown;//Vq up/down singal arrows //Trend detection string trend; //Margin status display bool EnoughMargin; string MarginMessage; //Misc string Gap, ScreenMessage; int OldBars; int OldCstBars;//For candlestick ts string PipDescription=" pips"; bool ForceTradeClosure; void DisplayUserFeedback() { if (IsTesting() && !IsVisualMode()) return; ScreenMessage = ""; ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL); ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Updates for this EA are to be found at http://www.stevehopwoodforex.com", NL); ScreenMessage = StringConcatenate(ScreenMessage, Gap, TimeToStr(TimeLocal(), TIME_DATE|TIME_MINUTES|TIME_SECONDS), NL ); /* //Code for time to bar-end display from Candle Time by Nick Bilak double i; int m,s,k; m=Time[0]+Period()*60-CurTime(); i=m/60.0; s=m%60; m=(m-m%60)/60; ScreenMessage = StringConcatenate(ScreenMessage,Gap, m + " minutes " + s + " seconds left to bar end", NL); */ ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL); ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Lot size: ", Lot, " (Criminal's minimum lot size: ", MarketInfo(Symbol(), MODE_MINLOT), ")", NL); if (UseMartingale) ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Using Martingale. Multiplier is ", MartingaleLotMultiplier, NL); ScreenMessage = StringConcatenate(ScreenMessage,Gap, "First trade take profit: ", FirstTradeTakeProfit, PipDescription, NL); ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Subsequent trades take profit: ", SubsequentTakeProfit, PipDescription, NL); ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Stop loss: ", StopLoss, PipDescription, NL); ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Magic number: ", MagicNumber, NL); ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Trade comment: ", TradeComment, NL); if (CriminalIsECN) ScreenMessage = StringConcatenate(ScreenMessage,Gap, "CriminalIsECN = true", NL); else ScreenMessage = StringConcatenate(ScreenMessage,Gap, "CriminalIsECN = false", NL); ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Criminal's minimum lot size: ", MarketInfo(Symbol(), MODE_MINLOT), NL, NL ); ScreenMessage = StringConcatenate(ScreenMessage,Gap, "MaxSpread = ", MaxSpread, ": Spread = ", MarketInfo(Symbol(), MODE_SPREAD), NL, NL ); ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Trading hours", NL); if (start_hourm == 0 && end_hourm == 12 && start_houre && end_houre == 24) ScreenMessage = StringConcatenate(ScreenMessage,Gap, " 24H trading", NL); else { ScreenMessage = StringConcatenate(ScreenMessage,Gap, " start_hourm: ", DoubleToStr(start_hourm, 2), ": end_hourm: ", DoubleToStr(end_hourm, 2), NL); ScreenMessage = StringConcatenate(ScreenMessage,Gap, " start_houre: ", DoubleToStr(start_houre, 2), ": end_houre: ", DoubleToStr(end_houre, 2), NL); }//else ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL); ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Most recent VQ signal: ", trend, NL); ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL); if (BreakEven) { ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Breakeven is set to ", BreakEvenPips, PipDescription); ScreenMessage = StringConcatenate(ScreenMessage,": BreakEvenProfit = ", BreakEvenProfit, PipDescription); ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL); }//if (BreakEven) if (UseCandlestickTrailingStop) { ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Using candlestick trailing stop", NL); }//if (UseCandlestickTrailingStop) if (JumpingStop) { ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Jumping stop is set to ", JumpingStopPips, PipDescription); if (AddBEP) ScreenMessage = StringConcatenate(ScreenMessage,": BreakEvenProfit = ", BreakEvenProfit, PipDescription); if (JumpAfterBreakevenOnly) ScreenMessage = StringConcatenate(ScreenMessage, ": JumpAfterBreakevenOnly = true"); ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL); }//if (JumpingStop) if (TrailingStop) { ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Trailing stop is set to ", TrailingStopPips, PipDescription); if (TrailAfterBreakevenOnly) ScreenMessage = StringConcatenate(ScreenMessage, ": TrailAfterBreakevenOnly = true"); ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL); }//if (TrailingStop) if (HideStopLossEnabled) { ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Hidden stop loss enabled at ", HiddenStopLossPips, PipDescription, NL); }//if (HideStopLossEnabled) if (HideTakeProfitEnabled) { ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Hidden take profit enabled at ", HiddenTakeProfitPips, PipDescription, NL); }//if (HideTakeProfitEnabled) if (MarginMessage != "") ScreenMessage = StringConcatenate(ScreenMessage,NL, Gap, MarginMessage, NL); Comment(ScreenMessage); }//void DisplayUserFeedback() //+------------------------------------------------------------------+ //| expert initialization function | //+------------------------------------------------------------------+ int init() { //---- //Adapt to x digit criminals int multiplier; if(Digits == 2 || Digits == 4) multiplier = 1; if(Digits == 3 || Digits == 5) multiplier = 10; if(Digits == 6) multiplier = 100; if(Digits == 7) multiplier = 1000; if (multiplier > 1) PipDescription = " points"; FirstTradeTakeProfit*= multiplier; SubsequentTakeProfit*= multiplier; StopLoss*= multiplier; BreakEvenPips*= multiplier; BreakEvenProfit*= multiplier; PipsAwayFromVisualBE*= multiplier; JumpingStopPips*= multiplier; PipsAwayFromVisualJS*= multiplier; TrailingStopPips*= multiplier; PipsAwayFromVisualTS*= multiplier; StopTrailPips*= multiplier; HiddenStopLossPips*= multiplier; HiddenTakeProfitPips*= multiplier; Gap=""; if (DisplayGapSize >0) { for (int cc=0; cc< DisplayGapSize; cc++) { Gap = StringConcatenate(Gap, " "); } }//if (DisplayGapSize >0) //Reset CriminIsECN if crim is IBFX and the punter does not know or, like me, keeps on forgetting string name = TerminalCompany(); int ispart = StringFind(name, "IBFX", 0); if (ispart > -1) CriminalIsECN = true; if (TradeComment == "") TradeComment = " "; OldBars = Bars; ReadIndicatorValues();//For initial display in case user has turned of constant re-display DisplayUserFeedback(); //Call sq's show trades indi //iCustom(NULL, 0, "SQ_showTrades",Magic, 0,0); //---- return(0); } //+------------------------------------------------------------------+ //| expert deinitialization function | //+------------------------------------------------------------------+ int deinit() { //---- Comment(""); //---- return(0); } //////////////////////////////////////////////////////////////////////////////////////////////// //TRADE MANAGEMENT MODULE bool CheckForHiddenStopLossHit(int type, int iPipsAboveVisual, double stop ) { //Reusable code that can be called by any of the stop loss manipulation routines except HiddenStopLoss(). //Checks to see if the market has hit the hidden sl and attempts to close the trade if so. //Returns true if trade closure is successful, else returns false //Check buy trade if (type == OP_BUY) { double sl = NormalizeDouble(stop + (iPipsAboveVisual * Point), Digits); if (Bid <= sl) { while(IsTradeContextBusy()) Sleep(100); bool result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 5, CLR_NONE); if (result) { if (ShowManagementAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()); }//if (result) else { int err=GetLastError(); if (ShowManagementAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err)); Print("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err)); }//else }//if (Bid <= sl) }//if (type = OP_BUY) //Check buy trade if (type == OP_SELL) { sl = NormalizeDouble(stop - (iPipsAboveVisual * Point), Digits); if (Ask >= sl) { while(IsTradeContextBusy()) Sleep(100); result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 5, CLR_NONE); if (result) { if (ShowManagementAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()); }//if (result) else { err=GetLastError(); if (ShowManagementAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err)); Print("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err)); }//else }//if (Ask >= sl) }//if (type = OP_SELL) }//End bool CheckForHiddenStopLossHit(int type, int iPipsAboveVisual, double stop ) void BreakEvenStopLoss() // Move stop loss to breakeven { //Check hidden BE for trade closure if (HideBreakEvenStop) { bool TradeClosed = CheckForHiddenStopLossHit(OrderType(), PipsAwayFromVisualBE, OrderStopLoss() ); if (TradeClosed) return;//Trade has closed, so nothing else to do }//if (HideBreakEvenStop) bool result; if (OrderType()==OP_BUY) { if (Bid >= OrderOpenPrice () + (Point*BreakEvenPips) && OrderStopLoss() Preserve_Lots)// Only try to do this if the jump stop worked //{ // bool PartCloseSuccess = PartCloseTradeFunction(); // if (!PartCloseSuccess) SetAGlobalTicketVariable(); //}//if (PartCloseEnabled && OrderLots() > Preserve_Lots) } } if (OrderType()==OP_SELL) { if (Ask <= OrderOpenPrice() - (Point*BreakEvenPips) && (OrderStopLoss()>OrderOpenPrice()|| OrderStopLoss()==0)) { while(IsTradeContextBusy()) Sleep(100); result = OrderModify(OrderTicket(),OrderOpenPrice(),NormalizeDouble(OrderOpenPrice()-(BreakEvenProfit*Point), Digits),OrderTakeProfit(),0,CLR_NONE); if (result && ShowManagementAlerts==true) Alert("Breakeven set on ", OrderSymbol(), " ticket no ", OrderTicket()); Print("Breakeven set on ", OrderSymbol(), " ticket no ", OrderTicket()); if (!result && ShowManagementAlerts) { err=GetLastError(); if (ShowManagementAlerts==true) Alert("Setting of breakeven SL ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err)); Print("Setting of breakeven SL ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err)); }//if !result && ShowManagementAlerts) //if (PartCloseEnabled && OrderLots() > Preserve_Lots)// Only try to do this if the jump stop worked // { // PartCloseSuccess = PartCloseTradeFunction(); // if (!PartCloseSuccess) SetAGlobalTicketVariable(); // }//if (PartCloseEnabled && OrderLots() > Preserve_Lots) } } } // End BreakevenStopLoss sub void JumpingStopLoss() { // Jump sl by pips and at intervals chosen by user . // Also carry out partial closure if the user requires this // Abort the routine if JumpAfterBreakevenOnly is set to true and be sl is not yet set if (JumpAfterBreakevenOnly && OrderType()==OP_BUY) { if(OrderStopLoss()OrderOpenPrice() || OrderStopLoss() == 0 ) return(0); } double sl=OrderStopLoss(); //Stop loss if (OrderType()==OP_BUY) { //Check hidden js for trade closure if (HideJumpingStop) { bool TradeClosed = CheckForHiddenStopLossHit(OP_BUY, PipsAwayFromVisualJS, OrderStopLoss() ); if (TradeClosed) return;//Trade has closed, so nothing else to do }//if (HideJumpingStop) // First check if sl needs setting to breakeven if (sl==0 || sl= OrderOpenPrice() + (JumpingStopPips*Point)) { sl=OrderOpenPrice(); if (AddBEP==true) sl=sl+(BreakEvenProfit*Point); // If user wants to add a profit to the break even while(IsTradeContextBusy()) Sleep(100); bool result = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE); if (result) { if (ShowManagementAlerts==true) Alert("Jumping stop set at breakeven ",sl, " ", OrderSymbol(), " ticket no ", OrderTicket()); Print("Jumping stop set at breakeven: ", OrderSymbol(), ": SL ", sl, ": Ask ", Bid); //if (PartCloseEnabled && OrderLots() > Preserve_Lots)// Only try to do this if the jump stop worked //{ //bool PartCloseSuccess = PartCloseTradeFunction(); //if (!PartCloseSuccess) SetAGlobalTicketVariable(); //}//if (PartCloseEnabled && OrderLots() > Preserve_Lots) }//if (result) if (!result) { int err=GetLastError(); if (ShowManagementAlerts) Alert(OrderSymbol(), "Ticket ", OrderTicket(), " buy trade. Jumping stop function failed to set SL at breakeven, with error(",err,"): ",ErrorDescription(err)); Print(OrderSymbol(), " buy trade. Jumping stop function failed to set SL at breakeven, with error(",err,"): ",ErrorDescription(err)); }//if (!result) return(0); }//if (Ask >= OrderOpenPrice() + (JumpingStopPips*Point)) } //close if (sl==0 || sl= (sl + JumpingStopPips) if (Bid>= sl + ((JumpingStopPips*2)*Point) && sl>= OrderOpenPrice()) { sl=sl+(JumpingStopPips*Point); while(IsTradeContextBusy()) Sleep(100); result = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE); if (result) { if (ShowManagementAlerts==true) Alert("Jumping stop set at ",sl, " ", OrderSymbol(), " ticket no ", OrderTicket()); Print("Jumping stop set: ", OrderSymbol(), ": SL ", sl, ": Ask ", Ask); //if (PartCloseEnabled && OrderLots() > Preserve_Lots)// Only try to do this if the jump stop worked //{ //PartCloseSuccess = PartCloseTradeFunction(); //if (!PartCloseSuccess) SetAGlobalTicketVariable(); //}//if (PartCloseEnabled && OrderLots() > Preserve_Lots) }//if (result) if (!result) { err=GetLastError(); if (ShowManagementAlerts) Alert(OrderSymbol(), " buy trade. Jumping stop function failed with error(",err,"): ",ErrorDescription(err)); Print(OrderSymbol(), " buy trade. Jumping stop function failed with error(",err,"): ",ErrorDescription(err)); }//if (!result) }// if (Bid>= sl + (JumpingStopPips*Point) && sl>= OrderOpenPrice()) }//if (OrderType()==OP_BUY) if (OrderType()==OP_SELL) { //Check hidden js for trade closure if (HideJumpingStop) { TradeClosed = CheckForHiddenStopLossHit(OP_SELL, PipsAwayFromVisualJS, OrderStopLoss() ); if (TradeClosed) return;//Trade has closed, so nothing else to do }//if (HideJumpingStop) // First check if sl needs setting to breakeven if (sl==0 || sl>OrderOpenPrice()) { if (Ask <= OrderOpenPrice() - (JumpingStopPips*Point)) { sl = OrderOpenPrice(); if (AddBEP==true) sl=sl-(BreakEvenProfit*Point); // If user wants to add a profit to the break even while(IsTradeContextBusy()) Sleep(100); result = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE); if (result) { //if (PartCloseEnabled && OrderLots() > Preserve_Lots)// Only try to do this if the jump stop worked //{ // PartCloseSuccess = PartCloseTradeFunction(); //if (!PartCloseSuccess) SetAGlobalTicketVariable(); //}//if (PartCloseEnabled && OrderLots() > Preserve_Lots) }//if (result) if (!result) { err=GetLastError(); if (ShowManagementAlerts) Alert(OrderSymbol(), " sell trade. Jumping stop function failed to set SL at breakeven, with error(",err,"): ",ErrorDescription(err)); Print(OrderSymbol(), " sell trade. Jumping stop function failed to set SL at breakeven, with error(",err,"): ",ErrorDescription(err)); }//if (!result) return(0); }//if (Ask <= OrderOpenPrice() - (JumpingStopPips*Point)) } // if (sl==0 || sl>OrderOpenPrice() // Decrement sl by sl - JumpingStopPips. // This will happen when market price <= (sl - JumpingStopPips) if (Bid<= sl - ((JumpingStopPips*2)*Point) && sl<= OrderOpenPrice()) { sl=sl-(JumpingStopPips*Point); while(IsTradeContextBusy()) Sleep(100); result = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE); if (result) { if (ShowManagementAlerts==true) Alert("Jumping stop set at ",sl, " ", OrderSymbol(), " ticket no ", OrderTicket()); Print("Jumping stop set: ", OrderSymbol(), ": SL ", sl, ": Ask ", Ask); //if (PartCloseEnabled && OrderLots() > Preserve_Lots)// Only try to do this if the jump stop worked //{ // PartCloseSuccess = PartCloseTradeFunction(); //if (!PartCloseSuccess) SetAGlobalTicketVariable(); //}//if (PartCloseEnabled && OrderLots() > Preserve_Lots) }//if (result) if (!result) { err=GetLastError(); if (ShowManagementAlerts) Alert(OrderSymbol(), " sell trade. Jumping stop function failed with error(",err,"): ",ErrorDescription(err)); Print(OrderSymbol(), " sell trade. Jumping stop function failed with error(",err,"): ",ErrorDescription(err)); }//if (!result) }// close if (Bid>= sl + (JumpingStopPips*Point) && sl>= OrderOpenPrice()) }//if (OrderType()==OP_SELL) } //End of JumpingStopLoss sub void HiddenStopLoss() { //Called from ManageTrade if HideStopLossEnabled = true //Should the order close because the stop has been passed? //Buy trade if (OrderType() == OP_BUY) { double sl = NormalizeDouble(OrderOpenPrice() - (HiddenStopLossPips * Point), Digits); if (Bid <= sl) { while(IsTradeContextBusy()) Sleep(100); bool result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 5, CLR_NONE); if (result) { if (ShowManagementAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()); }//if (result) else { int err=GetLastError(); if (ShowManagementAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err)); Print("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err)); }//else }//if (Bid <= sl) }//if (OrderType() == OP_BUY) //Sell trade if (OrderType() == OP_SELL) { sl = NormalizeDouble(OrderOpenPrice() + (HiddenStopLossPips * Point), Digits); if (Ask >= sl) { while(IsTradeContextBusy()) Sleep(100); result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 5, CLR_NONE); if (result) { if (ShowManagementAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()); }//if (result) else { err=GetLastError(); if (ShowManagementAlerts==true) Alert("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err)); Print("Stop loss hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err)); }//else }//if (Ask >= sl) }//if (OrderType() == OP_SELL) }//End void HiddenStopLoss() void HiddenTakeProfit() { //Called from ManageTrade if HideStopLossEnabled = true //Should the order close because the stop has been passed? //Buy trade if (OrderType() == OP_BUY) { double tp = NormalizeDouble(OrderOpenPrice() + (HiddenTakeProfitPips * Point), Digits); if (Bid >= tp) { while(IsTradeContextBusy()) Sleep(100); bool result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 5, CLR_NONE); if (result) { if (ShowManagementAlerts==true) Alert("Take profit hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()); }//if (result) else { int err=GetLastError(); if (ShowManagementAlerts==true) Alert("Take profit hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err)); Print("Take profit hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err)); }//else }//if (Ask >= tp) }//if (OrderType() == OP_BUY) //Sell trade if (OrderType() == OP_SELL) { tp = NormalizeDouble(OrderOpenPrice() - (HiddenTakeProfitPips * Point), Digits); if (Ask <= tp) { while(IsTradeContextBusy()) Sleep(100); result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 5, CLR_NONE); if (result) { if (ShowManagementAlerts==true) Alert("Take profit hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()); }//if (result) else { err=GetLastError(); if (ShowManagementAlerts==true) Alert("Take profit hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err)); Print("Take profit hit. Close of ", OrderSymbol(), " ticket no ", OrderTicket()," failed with error (",err,"): ",ErrorDescription(err)); }//else }//if (Bid <= tp) }//if (OrderType() == OP_SELL) }//End void HiddenTakeProfit() void TrailingStopLoss() { if (TrailAfterBreakevenOnly && OrderType()==OP_BUY) { if(OrderStopLoss()OrderOpenPrice()) return(0); } bool result; double sl=OrderStopLoss(); //Stop loss double BuyStop=0, SellStop=0; if (OrderType()==OP_BUY) { if (HideTrailingStop) { bool TradeClosed = CheckForHiddenStopLossHit(OP_BUY, PipsAwayFromVisualTS, OrderStopLoss() ); if (TradeClosed) return;//Trade has closed, so nothing else to do }//if (HideJumpingStop) if (Bid >= OrderOpenPrice() + (TrailingStopPips*Point)) { if (OrderStopLoss() == 0) sl = OrderOpenPrice(); if (Bid > sl + (TrailingStopPips*Point)) { sl= Bid - (TrailingStopPips*Point); // Exit routine if user has chosen StopTrailAtPipsProfit and // sl is past the profit Point already if (StopTrailAtPipsProfit && sl>= OrderOpenPrice() + (StopTrailPips*Point)) return; while(IsTradeContextBusy()) Sleep(100); result = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE); if (result) { Print("Trailing stop updated: ", OrderSymbol(), ": SL ", sl, ": Ask ", Ask); }//if (result) else { int err=GetLastError(); Print(OrderSymbol(), " order modify failed with error(",err,"): ",ErrorDescription(err)); }//else }//if (Bid > sl + (TrailingStopPips*Point)) }//if (Bid >= OrderOpenPrice() + (TrailingStopPips*Point)) }//if (OrderType()==OP_BUY) if (OrderType()==OP_SELL) { if (Ask <= OrderOpenPrice() - (TrailingStopPips*Point)) { if (HideTrailingStop) { TradeClosed = CheckForHiddenStopLossHit(OP_SELL, PipsAwayFromVisualTS, OrderStopLoss() ); if (TradeClosed) return;//Trade has closed, so nothing else to do }//if (HideJumpingStop) if (OrderStopLoss() == 0) sl = OrderOpenPrice(); if (Ask < sl - (TrailingStopPips*Point)) { sl= Ask + (TrailingStopPips*Point); // Exit routine if user has chosen StopTrailAtPipsProfit and // sl is past the profit Point already if (StopTrailAtPipsProfit && sl<= OrderOpenPrice() - (StopTrailPips*Point)) return; while(IsTradeContextBusy()) Sleep(100); result = OrderModify(OrderTicket(),OrderOpenPrice(),sl,OrderTakeProfit(),0,CLR_NONE); if (result) { Print("Trailing stop updated: ", OrderSymbol(), ": SL ", sl, ": Bid ", Bid); }//if (result) else { err=GetLastError(); Print(OrderSymbol(), " order modify failed with error(",err,"): ",ErrorDescription(err)); }//else }//if (Ask < sl - (TrailingStopPips*Point)) }//if (Ask <= OrderOpenPrice() - (TrailingStopPips*Point)) }//if (OrderType()==OP_SELL) } // End of TrailingStopLoss sub void CandlestickTrailingStop() { //Trails the stop at the hi/lo of the previous candle. //Only tries to do this once per bar, so an invalid stop error will only be generated once. if (OldCstBars == Bars) return; OldCstBars = Bars; bool result = false, modify = false; int err; double stop; if (OrderType() == OP_BUY) { if (Low[1] > OrderStopLoss() && OrderProfit() >= 0) { stop = NormalizeDouble(Low[1], Digits); modify = true; }//if (Close[1] > OrderStopLoss() && OrderProfit() >= 0) }//if (OrderType == OP_BUY) if (OrderType() == OP_SELL) { if ( (High[1] < OrderStopLoss() || OrderStopLoss() == 0) && OrderProfit() >= 0) { stop = NormalizeDouble(High[1], Digits); modify = true; }//if (Close[1] > OrderStopLoss() && OrderProfit() >= 0) }//if (OrderType() == OP_SELL) if (modify) { result = OrderModify(OrderTicket(), OrderOpenPrice(), stop, OrderTakeProfit(), OrderExpiration(), CLR_NONE); if (!result) { err = GetLastError(); if (err != 130) OldBars = 0;//Retry the modify at the next tick unless the error is invalid stops }//if (!result) }//if (modify) }//End void CandlestickTrailingStop() void TradeManagementModule() { // Call the working subroutines one by one. //Candlestick trailing stop if (UseCandlestickTrailingStop) CandlestickTrailingStop(); // Hidden stop loss if (HideStopLossEnabled) HiddenStopLoss(); // Hidden take profit if (HideTakeProfitEnabled) HiddenTakeProfit(); // Breakeven if(BreakEven) BreakEvenStopLoss(); // JumpingStop if(JumpingStop) JumpingStopLoss(); //TrailingStop if(TrailingStop) TrailingStopLoss(); }//void TradeManagementModule() //END TRADE MANAGEMENT MODULE //////////////////////////////////////////////////////////////////////////////////////////////// bool SendSingleTrade(int type, string comment, double lotsize, double price, double stop, double take) { int slippage = 10; if (Digits == 3 || Digits == 5) slippage = 100; color col = Red; if (type == OP_BUY || type == OP_BUYSTOP) col = Green; int expiry = 0; //if (SendPendingTrades) expiry = TimeCurrent() + (PendingExpiryMinutes * 60); if (!CriminalIsECN) int ticket = OrderSend(Symbol(),type, lotsize, price, slippage, stop, take, comment, MagicNumber, expiry, col); //Is a 2 stage criminal if (CriminalIsECN) { bool result; int err; ticket = OrderSend(Symbol(),type, lotsize, price, slippage, 0, 0, comment, MagicNumber, expiry, col); if (ticket > 0) { if (take > 0 && stop > 0) { while(IsTradeContextBusy()) Sleep(100); result = OrderModify(ticket, OrderOpenPrice(), stop, take, OrderExpiration(), CLR_NONE); if (!result) { err=GetLastError(); Print(Symbol(), " SL/TP order modify failed with error(",err,"): ",ErrorDescription(err)); }//if (!result) }//if (take > 0 && stop > 0) if (take != 0 && stop == 0) { while(IsTradeContextBusy()) Sleep(100); result = OrderModify(ticket, OrderOpenPrice(), OrderStopLoss(), take, OrderExpiration(), CLR_NONE); if (!result) { err=GetLastError(); Print(Symbol(), " SL order modify failed with error(",err,"): ",ErrorDescription(err)); }//if (!result) }//if (take == 0 && stop != 0) if (take == 0 && stop != 0) { while(IsTradeContextBusy()) Sleep(100); result = OrderModify(ticket, OrderOpenPrice(), stop, OrderTakeProfit(), OrderExpiration(), CLR_NONE); if (!result) { err=GetLastError(); Print(Symbol(), " SL order modify failed with error(",err,"): ",ErrorDescription(err)); }//if (!result) }//if (take == 0 && stop != 0) }//if (ticket > 0) }//if (CriminalIsECN) //Error trapping for both if (ticket < 0) { string stype; if (type == OP_BUY) stype = "OP_BUY"; if (type == OP_SELL) stype = "OP_SELL"; if (type == OP_BUYLIMIT) stype = "OP_BUYLIMIT"; if (type == OP_SELLLIMIT) stype = "OP_SELLLIMIT"; if (type == OP_BUYSTOP) stype = "OP_BUYSTOP"; if (type == OP_SELLSTOP) stype = "OP_SELLSTOP"; err=GetLastError(); Alert(Symbol(), " ", stype," order send failed with error(",err,"): ",ErrorDescription(err)); Print(Symbol(), " ", stype," order send failed with error(",err,"): ",ErrorDescription(err)); return(false); }//if (ticket < 0) TicketNo = ticket; //Make sure the trade has appeared in the platform's history to avoid duplicate trades. //My mod of Matt's code attempts to overcome the bastard crim's attempts to overcome Matt's code. bool TradeReturnedFromCriminal = false; while (!TradeReturnedFromCriminal) { TradeReturnedFromCriminal = O_R_CheckForHistory(ticket); if (!TradeReturnedFromCriminal) { Alert(Symbol(), " sent trade not in your trade history yet. Turn of this ea NOW."); }//if (!TradeReturnedFromCriminal) }//while (!TradeReturnedFromCriminal) //Got this far, so trade send succeeded return(true); }//End bool SendSingleTrade(int type, string comment, double lotsize, double price, double stop, double take) bool DoesTradeExist() { TicketNo = -1; BuyOpen = false; SellOpen = false; if (OrdersTotal() == 0) return(false); for (int cc = OrdersTotal() - 1; cc >= 0 ; cc--) { if (!OrderSelect(cc,SELECT_BY_POS)) continue; if (OrderMagicNumber()==MagicNumber && OrderSymbol() == Symbol() ) { if (OrderType() == OP_BUY) BuyOpen = true; if (OrderType() == OP_SELL) SellOpen = true; TicketNo = OrderTicket(); return(true); }//if (OrderMagicNumber()==MagicNumber && OrderSymbol() == Symbol() ) }//for (int cc = OrdersTotal() - 1; cc >= 0 ; cc--) return(false); }//End bool DoesTradeExist() bool IsTradingAllowed() { //Returns false if any of the filters should cancel trading, else returns true to allow trading //Maximum spread if (MarketInfo(Symbol(), MODE_SPREAD) > MaxSpread) return(false); return(true); }//End bool IsTradingAllowed() double CalculateLotSize() { //Calculate Martingale lot size if (!UseMartingale) return(Lot); //Find most recent trade if (OrdersHistoryTotal() == 0) return(Lot); double SendLots = Lot; for (int cc = OrdersHistoryTotal() - 1; cc >= 0; cc--) { if (!OrderSelect(cc, SELECT_BY_POS, MODE_HISTORY) ) continue; if (OrderSymbol() != Symbol() ) continue; if (OrderMagicNumber() != MagicNumber) continue; if (OrderProfit() < 0) { double LotStep = MarketInfo(Symbol(),MODE_LOTSTEP); double digit = 0; if (LotStep == 0.1) digit = 1; if (LotStep == 0.01) digit = 2; SendLots = NormalizeDouble(OrderLots() * MartingaleLotMultiplier, digit); }//if (OrderProfit() < 0) break; }//for (int cc = OrdersHistoryTotal() - 1; cc >= 0; cc--) //Check maximum lots allowed filter in the Martingale section if (SendLots > MaxLotsAllowed) SendLots = Lot; return(SendLots); }//End double CalculateLotSize() void LookForTradingOpportunities() { RefreshRates(); double take, stop, price; int type; bool SendTrade; //Calculate lotsize to cater for Martingale double SendLots = CalculateLotSize(); //Check filters if (!IsTradingAllowed() ) return; //Trend //Long if (trend == up) { if (!TradeLong) return; //Initial trade tp if (SendLots == Lot && FirstTradeTakeProfit > 0) take = NormalizeDouble(Ask + (FirstTradeTakeProfit * Point), Digits); //Tp for Martingale trades if (SendLots > Lot && SubsequentTakeProfit > 0) take = NormalizeDouble(Ask + (SubsequentTakeProfit * Point), Digits); if (StopLoss > 0) stop = NormalizeDouble(Ask - (StopLoss * Point), Digits); type = OP_BUY; price = Ask; SendTrade = true; }//if (Ask > 1000000) //Short if (trend == down) { if (!TradeShort) return; if (SendLots == Lot && FirstTradeTakeProfit > 0) take = NormalizeDouble(Bid - (FirstTradeTakeProfit * Point), Digits); //Tp for Martingale trades if (SendLots > Lot && SubsequentTakeProfit > 0) take = NormalizeDouble(Bid - (SubsequentTakeProfit * Point), Digits); if (StopLoss > 0) stop = NormalizeDouble(Bid + (StopLoss * Point), Digits); type = OP_SELL; price = Bid; SendTrade = true; }//if (trend == down) if (SendTrade) { bool result = SendSingleTrade(type, TradeComment, SendLots, price, stop, take); }//if (SendTrade) //Actions when trade send succeeds if (SendTrade && result) { }//if (result) //Actions when trade send fails if (SendTrade && !result) { OldBars = 0; }//if (!result) }//void LookForTradingOpportunities() bool CloseTrade(int ticket) { while(IsTradeContextBusy()) Sleep(100); bool result = OrderClose(ticket, OrderLots(), OrderClosePrice(), 1000, CLR_NONE); //Actions when trade send succeeds if (result) { return(true); }//if (result) //Actions when trade send fails if (!result) { return(false); }//if (!result) }//End bool CloseTrade(ticket) //////////////////////////////////////////////////////////////////////////////////////////////// //Indicator module void GetVq() { trend = none; VqUp = iCustom(NULL, 0, "VQ7", false, VqTimeFrame, VqLength, VqMethod, VqSmoothing, VqFilter, false, false, true, true, false, true, Yellow, Aqua, 10000, 3, 1); if (VqUp != EMPTY_VALUE) trend = up; VqDown = iCustom(NULL, 0, "VQ7", false, VqTimeFrame, VqLength, VqMethod, VqSmoothing, VqFilter, false, false, true, true, false, true, Yellow, Aqua, 10000, 4, 1); if (VqDown != EMPTY_VALUE) trend = down; }//void GetVq() void ReadIndicatorValues() { GetVq(); }//void ReadIndicatorValues() //End Indicator module //////////////////////////////////////////////////////////////////////////////////////////////// void LookForTradeClosure() { //Close the trade if the new candle finds a new signal if (!OrderSelect(TicketNo, SELECT_BY_TICKET) ) return; if (OrderSelect(TicketNo, SELECT_BY_TICKET) && OrderCloseTime() > 0) return; bool CloseTrade; if (OrderType() == OP_BUY) { if (trend == down) CloseTrade = true; }//if (OrderType() == OP_BUY) if (OrderType() == OP_SELL) { if (trend == up) CloseTrade = true; }//if (OrderType() == OP_SELL) if (CloseTrade) { bool result = CloseTrade(TicketNo); //Actions when trade send succeeds if (result) { TicketNo = -1; }//if (result) //Actions when trade send fails if (!result) { OldBars = 0; }//if (!result) }//if (CloseTrade) }//void LookForTradeClosure() bool CheckTradingTimes() { int hour = TimeHour(TimeLocal() ); if (end_hourm < start_hourm) { end_hourm += 24; } if (end_houre < start_houre) { end_houre += 24; } bool ok2Trade = true; ok2Trade = (hour >= start_hourm && hour <= end_hourm) || (hour >= start_houre && hour <= end_houre); // adjust for past-end-of-day cases // eg in AUS, USDJPY trades 09-17 and 22-06 // so, the above check failed, check if it is because of this condition if (!ok2Trade && hour < 12) { hour += 24; ok2Trade = (hour >= start_hourm && hour <= end_hourm) || (hour >= start_houre && hour <= end_houre); // so, if the trading hours are 11pm - 6am and the time is between midnight to 11am, (say, 5am) // the above code will result in comparing 5+24 to see if it is between 23 (11pm) and 30(6+24), which it is... } // check for end of day by looking at *both* end-hours if (hour >= MathMax(end_hourm, end_houre)) { ok2Trade = false; }//if (hour >= MathMax(end_hourm, end_houre)) return(ok2Trade); }//bool CheckTradingTimes() //============================================================================= // O_R_CheckForHistory() // // This function is to work around a very annoying and dangerous bug in MT4: // immediately after you send a trade, the trade may NOT show up in the // order history, even though it exists according to ticket number. // As a result, EA's which count history to check for trade entries // may give many multiple entries, possibly blowing your account! // // This function will take a ticket number and loop until // it is seen in the history. // // RETURN VALUE: // TRUE if successful, FALSE otherwise // // // FEATURES: // * Re-trying under some error conditions, sleeping a random // time defined by an exponential probability distribution. // // * Displays various error messages on the log for debugging. // // ORIGINAL AUTHOR AND DATE: // Matt Kennel, 2010 // //============================================================================= bool O_R_CheckForHistory(int ticket) { //My thanks to Matt for this code. He also has the undying gratitude of all users of my trading robots int lastTicket = OrderTicket(); int cnt = 0; int err = GetLastError(); // so we clear the global variable. err = 0; bool exit_loop = false; bool success=false; while (!exit_loop) { /* loop through open trades */ int total=OrdersTotal(); for(int c = 0; c < total; c++) { if(OrderSelect(c,SELECT_BY_POS,MODE_TRADES) == true) { if (OrderTicket() == ticket) { success = true; exit_loop = true; } } } if (cnt > 3) { /* look through history too, as order may have opened and closed immediately */ total=OrdersHistoryTotal(); for(c = 0; c < total; c++) { if(OrderSelect(c,SELECT_BY_POS,MODE_HISTORY) == true) { if (OrderTicket() == ticket) { success = true; exit_loop = true; } } } } cnt = cnt+1; if (cnt > O_R_Setting_max_retries) { exit_loop = true; } if (!(success || exit_loop)) { Print("Did not find #"+ticket+" in history, sleeping, then doing retry #"+cnt); O_R_Sleep(O_R_Setting_sleep_time, O_R_Setting_sleep_max); } } // Select back the prior ticket num in case caller was using it. if (lastTicket >= 0) { OrderSelect(lastTicket, SELECT_BY_TICKET, MODE_TRADES); } if (!success) { Print("Never found #"+ticket+" in history! crap!"); } return(success); }//End bool O_R_CheckForHistory(int ticket) //============================================================================= // O_R_Sleep() // // This sleeps a random amount of time defined by an exponential // probability distribution. The mean time, in Seconds is given // in 'mean_time'. // This returns immediately if we are backtesting // and does not sleep. // //============================================================================= void O_R_Sleep(double mean_time, double max_time) { if (IsTesting()) { return; // return immediately if backtesting. } double p = (MathRand()+1) / 32768.0; double t = -MathLog(p)*mean_time; t = MathMin(t,max_time); int ms = t*1000; if (ms < 10) { ms=10; } Sleep(ms); }//End void O_R_Sleep(double mean_time, double max_time) //+------------------------------------------------------------------+ //| expert start function | //+------------------------------------------------------------------+ int start() { //---- static bool TradeExists; if (OrdersTotal() == 0) { TicketNo = -1; ForceTradeClosure = false; }//if (OrdersTotal() == 0) /////////////////////////////////////////////////////////////////////////////////////////////// //Find open trades. TradeExists = DoesTradeExist(); if (TradeExists) { if (OrderProfit() > 0) { if (OrderLots() == Lot) TradeManagementModule(); if (OrderLots() > Lot && !AlsoManageMartingaleTrades) TradeManagementModule(); }//if (OrderProfit() > 0) }//if (TradeExists) /////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// //Trading times bool TradeTimeOk = CheckTradingTimes(); if (!TradeTimeOk) { Comment("Outside trading hours\nstart_hourm-end_hourm: ", start_hourm, "-",end_hourm, "\nstart_houre-end_houre: ", start_houre, "-",end_houre); return; }//if (hour < start_hourm) ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// //Available margin filters EnoughMargin = true;//For user display MarginMessage = ""; if (UseScoobsMarginCheck && OpenTrades > 0) { if(AccountMargin() > (AccountFreeMargin()/100)) { MarginMessage = "There is insufficient margin to allow trading. You might want to turn off the UseScoobsMarginCheck input."; DisplayUserFeedback(); //Fix for CloseOnOppositeSignal being missed if (OldBars != Bars) { OldBars = Bars; ReadIndicatorValues(); }//if (OldBars != Bars) return; }//if(AccountMargin() > (AccountFreeMargin()/100)) }//if (UseScoobsMarginCheck) if (UseForexKiwi && AccountMargin() > 0) { double ml = NormalizeDouble(AccountEquity() / AccountMargin() * 100, 2); if (ml < FkMinimumMarginPercent) { MarginMessage = StringConcatenate("There is insufficient margin percent to allow trading. ", DoubleToStr(ml, 2), "%"); DisplayUserFeedback(); //Fix for CloseOnOppositeSignal being missed if (OldBars != Bars) { OldBars = Bars; ReadIndicatorValues(); }//if (OldBars != Bars) return; }//if (ml < FkMinimumMarginPercent) }//if (UseForexKiwi && AccountMargin() > 0) /////////////////////////////////////////////////////////////////////////////////////////////// //Trading if (OldBars != Bars) { OldBars = Bars; ReadIndicatorValues(); if (TradeExists) LookForTradeClosure(); if (TicketNo == -1 && !StopTrading) { LookForTradingOpportunities(); }//if (TicketNo == -1) }//if (OldBars != Bars) /////////////////////////////////////////////////////////////////////////////////////////////// DisplayUserFeedback(); //---- return(0); } //+------------------------------------------------------------------+