//+-------------------------------------------------------------------+ //| Nanningbob V10 auto trading robot by Steve Hopwood.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 <WinUser32.mqh> #include <stdlib.mqh> #define NL "\n" #define up "Up" #define down "Down" #define none "None" #define ranging "Ranging" #define upbutuntradable "Up, but not start of trend" #define downbutuntradable "Down, but not start of trend" #define buy "Buy" #define sell "Sell" #define confused "Confused, and so cannot trade" #define trending "Trending" #define opentrade "There is a trade open" #define stopped "Trading is stopped" #define breakevenlinename "Break even line" #define reentrylinename "Re entry line" #define trendorigin "Trend" #define rangeorigin "Range" //Caterpillar #define buyline "Buy line" #define sellline "Sell line" //From iExposure for Recovery BE calcs #define SYMBOLS_MAX 1024 #define DEALS 0 #define BUY_LOTS 1 #define BUY_PRICE 2 #define SELL_LOTS 3 #define SELL_PRICE 4 #define NET_LOTS 5 #define PROFIT 6 /* Go to http://www.forexfactory.com/showthread.php?t=308304 to read about the trading methodology carolco's grid idea: http://www.forexfactory.com/showthread.php?p=4887703#post4887703 Matt Kennel has provided the code for bool O_R_CheckForHistory(int ticket). Cheers Matt, You are a star. This program uses Global Variables to tell BigBob whether the trade was originally a trend or range trade: - value 0 = trend - value 1 = range The GV 'name' is the chart symbol. BB cleans out the redundant GV's during CountOpenTrades() Navigate around the functions by highlighing them and pressing ctrl + F. YOu have to add the Bookmarks facility to your code editor: - Click View - Click Customise - Scroll down the 'Available' window until you find the bookmarks and click the Insert button to add them to your editor Code for adding debugging Sleep Alert("G"); int x = 0; while (x == 0) Sleep(100); FUNCTIONS LIST int init() int start() ----Trading---- void LookForTrendTradingOpps() void LookForRangeTradingOpps() bool IsTradingAllowed() bool SendSingleTrade(int type, string comment, double lotsize, double price, double stop, double take) bool DoesTradeExist() void CountOpenTrades() bool CloseTrade(int ticket) void LookForTradeClosure() bool CheckTradingTimes() void CloseAllTrades() //Caterpillar void StartCaterpillar() void LookForCatTradingOpportunities() void DeleteOrphanGlobals() //Carolco void StartCarolco() void SendGrid() void DeletePendings() ----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 GetBB() double GetMa(int tf, int period, int mashift, int method, int ap, int shift) double CalculateVolatility(int period, int LookBack) ----Trend detection module---- void TrendDetectionModule() void GetTrendConfirmationCandleDir() ----Balance/swap filters module---- void TradeDirectionBySwap() bool IsThisPairTradable() bool BalancedPair(int type) ----Hanover module. The functions---- bool HanoverFilter(int type) void SetUpArrays() void CleanUpInputString() int CalculateParamsPassed() void ReadHanover() int LoadRSvalues() double ReadStrength(string curr, string tf, int shift) ----Recovery---- void RecoveryModule() void CheckRecoveryTakeProfit() int Analyze() int SymbolsIndex(string SymbolName) void RecoveryCandlesticktrailingStop() void LockInRecoveryProfit() void RecoveryCandlesticktrailingStop() ----Re-entry line---- void AddReEntryLine(double price) void CalculateReEntryLinePips() void ReplaceReEntryLine() ----Trade management module---- void TradeManagementModule() void BreakEvenStopLoss() bool CheckForHiddenStopLossHit(int type, int iPipsAboveVisual, double stop ) void JumpingStopLoss() void HiddenTakeProfit() void HiddenStopLoss() void TrailingStopLoss() //sq's string to array module void CleanUpInputString() Mine int StringFindCount(string str, string str2) void StrPairToStringArray(string str, string &a[], string p_suffix, string delim=",") void StrToStringArray(string str, string &a[], string delim=",") */ //Defined constants from hanover. Thanks David #define AUD 0 #define CAD 1 #define CHF 2 #define EUR 3 #define GBP 4 #define JPY 5 #define NZD 6 #define USD 7 #define M1 0 #define M5 1 #define M15 2 #define M30 3 #define H1 4 #define H4 5 #define D1 6 #define W1 7 #define MN 8 extern string gen="----General inputs----"; extern double Lot=0.02; extern bool StopTrading=false; extern bool TradeLong=true; extern bool TradeShort=true; extern int MagicNumber=0; //extern string TradeComment=""; extern bool CriminalIsECN=true; extern double MaxSpread=120; //Hanover extern string hm="----Hanover module----"; extern bool UseHanover=true; extern string ctf="Tren trading time frames"; //extern string TimeFrames="M1,M5,M15,M30,H1,H4,D1,W1,MN"; extern string TrendTimeFrames="D1"; extern int TrendSlopeConfirmationCandles=0; extern int TrendStrongThreshold=0; extern int TrendWeakThreshold=0; extern string hof="Hanover output file"; extern string OutputFile = "Output---Recent Strength.CSV"; extern int NumPoints=15; ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //Arrays etc string InputString;//All purpose string to pass to CleanUpInputString() to remove unwanted leading/trailing stuff int NoOfTrendTimeFrames;//The number for timeframes inputted into the TimeFrames input string Tf[];//Holds the time frames inputted into the TimeFrames input string StrongWeak[];//Holds the pair that represents the strongest and weakest in each time frame string StrongestCcy[], WeakestCcy[];//Go on, take a guess double StrongVal[], PrevStrongVal[], WeakVal[], PrevWeakVal[];//Another guess? string ConstructedPair[];//Holds the pairs made out of the currencies string Ccy1, Ccy2;//First and second currency in the pair //Variables copied from the Strength Alerts indi. int LoadRSvalues() came from this int dig, tmf, h, i, j, k; string alrt[11]; double RSvalue[8,9,99]; // [currency,timeframe,datapoint#] // currency: 0=AUD, 1=CAD, 2=CHF, 3=EUR, 4=GBP, 5=JPY, 6=NZD, 7=USD // timeframe: 0=M1, 1=M5, 2=M15, 3=M30, 4=H1, 5=H4, 6=D1, 7=W1, 8=MN string ccy[8] = {"AUD","CAD","CHF","EUR","GBP","JPY","NZD","USD"}; string tf[9] = {"M1","M5","M15","M30","H1","H4","D1","W1","MN"}; string arr[11]; int ReadBars;//Bot reads the output file when this != Bars ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// extern string bf="----Trading balance filters----"; extern bool UseZeljko=true; extern bool OnlyTradeCurrencyTwice=true; extern string pts="----Swap filter----"; extern bool CadPairsPositiveOnly=true; extern bool AudPairsPositiveOnly=true; extern bool NzdPairsPositiveOnly=true; //Leave private for now and make external later on should there be a demand. At the mo, I am using the defaults //from 10.0 4H CTR BOTH string bbi="----Bollinger Band inputs----"; int BbPeriod=25; int BbDeviation=2; extern string vs="----Volatility inputs----"; extern int LookBackDays=20; /* extern int LowVolatility=100; extern int MediumVolatility=150; extern int HighVolatility=200; extern int PsychoticallyDeranged=250; */ //Trend detection MA's. Default to Bob's settings extern string tmas="----Trend detection moving averages----"; extern int FastMaTdTF=1440;//Time frame defaults to D1 chart extern int FastMaTdPeriod=2; extern int FastMaTdShift=2;//The MA Shift input extern string tmame="Method: 0=sma; 1=ema; 2=smma; 3=lwma"; extern int FastMaTdMethod=2; extern string tmaap="Applied price: 0=Close; 1=Open; 2=High"; extern string tmaap1="3=Low; 4=Median; 5=Typical; 6=Weighted"; extern int FastMaTdAppliedPrice=4; extern int SlowMaTdTF=1440;//Time frame defaults to D1 chart extern int SlowMaTdPeriod=8; extern int SlowMaTdMethod=2; extern int SlowMaTdShift=2; extern int SlowMaTdAppliedPrice=4; extern string spt="----Specific Trend trading inputs----"; extern bool AllowTrendTrading=true; extern bool OnlyTradeStartOfTrend=true; extern int MinimumTrendTradingVolatility=150; extern int MinTriggerCandlePipsMovement=30; extern int TrendConfirmationCandleTF=15; extern int TrendTakeProfit=0; extern int TrendStopLoss=0; extern string TrendTradeComment="Trend"; extern string cat="----Caterpillar trend trade entry and TS----"; extern bool UseCaterpillar=false; extern int MaxTrades=5; extern int MinPipsBetweenCandles=5;//Min distance between trade open prices extern int CatTimeFrame=60;//Trading/updating tf can be independent of current chart extern color BuyLineColour=Green; extern color SellLineColour=Red; extern string CatTradeComment="Caterpillar"; extern string car="----Carolco pending trade entries----"; extern bool UseCarolco=true; extern double CarolcoGridLot=0.02; extern bool UseCarolcoStopLoss=true; extern int TradesInGrid=5; extern int PipsBetweenTrades=20; extern string CarolcoTradeComment="Carolco grid"; extern string tte="--Trend trade exit strategies--"; extern string mte="1) D1 candlestick median (osthafen's idea)";//Closes a trade when the mid-point of the D1 candle moves to the wrong side of fast ma extern bool UseOsthafen=false;//Set this as the default strategy - something has to be ds //This one offers the use of a MA of the user's choice. Defaults to a rough median of the fast and slow trend ma's extern string drg="2) dragosd1 (median MA)"; extern bool UseDragosd1=false; extern bool UseTouch=false; extern bool UseClose=false; extern int DragMaTdTF=1440;//Time frame defaults to D1 chart extern int DragMaTdPeriod=5; extern int DragMaTdShift=2;//The MA Shift input extern string dmame="Method: 0=sma; 1=ema; 2=smma; 3=lwma"; extern int DragMaTdMethod=2; extern string dmaap="Applied price: 0=Close; 1=Open; 2=High"; extern string dmaap1="3=Low; 4=Median; 5=Typical; 6=Weighted"; extern int DragMaTdAppliedPrice=4; //This one closes a trade on an opposite signal extern string opp="3) Close on opposite signal"; extern bool UseOppositeSignal=true; //Hedging for losing trend trades extern string heg="----Hedging losing trend trades----"; extern bool UseHedging=true; extern int HedgeLotMultiplier=3; extern int HedgeProfitTarget=10; extern string HedgeTradeComment="Hedge"; extern string rpt="----Specific Range trading inputs----"; extern bool AllowRangeTrading=true; extern bool TradeEveryTick=false; extern int MaximumRangeTradingVolatility=150; extern int RangeTakeProfit=0; extern int RangeStopLoss=0; extern bool AllowChangeOfOriginToTrend=false; extern string rec="Recovery"; extern bool UseRecovery=true; extern string RecoveryLevels="2,6"; extern string RangeTradeComment="Range"; //I have removed the ability of users to piss around with Start_Recovery_at_trades. Coders, change this and //you will cause chaos. int Start_Recovery_at_trades=2; //DC extern int ReEntryLinePips=0; extern double ReEntryLineVolMult=1; extern color ReEntryLineColour=Turquoise; extern color BreakEvenLineColour=Blue; extern int RecoveryBreakEvenProfitPips=20; extern string rts="Recovery trailing stop"; extern bool UseRecoveryTrailingStop=false; extern int RecoveryTrailingStopAt=10; extern color RecoveryStopLossLineColour=Red; bool UseHardRecoveryStop=false;//Doesn't work but is part of the code and I cannot be bothered to remove it 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 string BE="Break even settings"; extern bool BreakEven=false; extern int BreakEvenPips=25; extern int BreakEvenProfit=2; 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=100; 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; string TradeOrigin;//Will be 'Range' or 'Trend' //Global Variables string GvName; //Range trading //BB variables so I can merely copy the code from Bob's EA's double Var1;//Upper extreme double Var2;//Upper double Var3;//Lower double Var4;//Lower extreme double Var5;//Moving average int OldRangeTradingBars; int RangeTradingTF=240; //Volatility double Volatility; int D1VolatilityBars; //Caterpillar int OldCatBars; int OnePip=1;//For adding to sl, candle close etc bool CandleTraded;//Only one trade per candle string CsGvName; int OldH1Bars;//For orphan gv removal bool TradeOpen; //Carolco int NoOfPendingBuys, NoOfPendingSells; //Trend detection string trend; double FastTrendMaVal, SlowTrendMaVal;//2 MA trend string TrendConfirmationCandleDir; //Trend trade exit double DragMaVal; //Hedging bool HedgingInProgress; double BasketUpl; //Margin status display bool EnoughMargin; string MarginMessage; //Misc string Gap, ScreenMessage; int OldBars; int OldCstBars;//For candlestick ts string PipDescription=" pips"; bool ForceTradeClosure; int GlobalPipsMultiplier;//For x digit conversions //Recovery int NoOfLevels; string RecoveryLevel[];//Holds the individual Recovery levels as strings - remember to convert to integer when using them int OldRecoverTrailBars; bool RecoveryInProgress, TpMoved; int RecoveryLockProfitsAt=50; int RecoveryLockInPips=10; string ExtSymbols[SYMBOLS_MAX]; int ExtSymbolsTotal=0; double ExtSymbolsSummaries[SYMBOLS_MAX][7]; int ExtLines=-1; string ExtCols[8]={"Symbol", "Deals", "Buy lots", "Buy price", "Sell lots", "Sell price", "Net lots", "Profit"}; int ExtShifts[8]={ 10, 80, 130, 180, 260, 310, 390, 460 }; int ExtVertShift=14; double buy_price=0.0; double sell_price=0.0; void DisplayUserFeedback() { if (IsTesting() && !IsVisualMode()) return; ScreenMessage = ""; ScreenMessage = StringConcatenate(ScreenMessage,Gap, 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, "Volatility: ", Volatility, NL); if (Volatility <= MaximumRangeTradingVolatility) ScreenMessage = StringConcatenate(ScreenMessage, Gap, "Can Range trade.", NL); if (Volatility >= MinimumTrendTradingVolatility) ScreenMessage = StringConcatenate(ScreenMessage, Gap, "Can Trend trade.", NL); ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL); ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Lot size: ", Lot, " (Criminal's minimum lot size: ", MarketInfo(Symbol(), MODE_MINLOT), ")"); ScreenMessage = StringConcatenate(ScreenMessage, ": Magic number: ", MagicNumber, NL); //ScreenMessage = StringConcatenate(ScreenMessage, ": 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, "Buy swap = ", MarketInfo(Symbol(), MODE_SWAPLONG), ": Sell swap = ", MarketInfo(Symbol(), MODE_SWAPSHORT), NL); ScreenMessage = StringConcatenate(ScreenMessage,Gap, "MaxSpread = ", MaxSpread, ": Spread = ", MarketInfo(Symbol(), MODE_SPREAD), 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 //Trend ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL); ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Trend is ", trend, NL); ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Fast MA ", DoubleToStr(FastTrendMaVal, Digits), ": Slow MA ", DoubleToStr(SlowTrendMaVal, Digits), NL); //Trading method information ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL); string tab = " "; //Trending market if (trend != ranging) { ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Trend trading information", NL); ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "Trade confirmation candle direction: ", TrendConfirmationCandleDir, NL); ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "MinTriggerCandlePipsMovement: ", MinTriggerCandlePipsMovement, PipDescription, NL); ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "Take profit: ", TrendTakeProfit, PipDescription, NL); ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "Stop loss: ", TrendStopLoss, PipDescription, NL); if (UseHanover) { ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL); string now, then; for (int cc = 0; cc < ArraySize(Tf); cc++) { double strength1 = ReadStrength(Ccy1, Tf[cc], 0); double strength2 = ReadStrength(Ccy2, Tf[cc], 0); if (TrendSlopeConfirmationCandles > 0) { double prevstrength1 = ReadStrength(Ccy1, Tf[cc], TrendSlopeConfirmationCandles); now = StringConcatenate(": Shift ",TrendSlopeConfirmationCandles, " = ", DoubleToStr(prevstrength1, 2)); double prevstrength2 = ReadStrength(Ccy2, Tf[cc], TrendSlopeConfirmationCandles); then = StringConcatenate(": Shift ", TrendSlopeConfirmationCandles, " = ", DoubleToStr(prevstrength2, 2)); }//if (SlopeCandles[cc] > 0) ScreenMessage = StringConcatenate(ScreenMessage,Gap, "TF ", Tf[cc], ": ", Ccy1, ": Now = ", DoubleToStr(strength1, 2), now, ": ", Ccy2, ": Now = ", DoubleToStr(strength2, 2), then, NL); }//for (int cc = 0; cc < ArraySize(Tf); cc++) if (TrendStrongThreshold > 0 && TrendWeakThreshold > 0) { bool tradeable = false; if (strength1 > TrendStrongThreshold && strength2 < TrendWeakThreshold) { ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Threshold: Can trade this pair long", NL); tradeable = true; }//if (strength1 > TrendStrongThreshold && strength2 < TrendWeakThreshold) if (strength2 > TrendStrongThreshold && strength1 < TrendWeakThreshold) { ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Threshold: Can trade this pair short", NL); tradeable = true; }//if (strength1 > TrendStrongThreshold && strength2 < TrendWeakThreshold) if (!tradeable) ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Threshold: Cannot trade this pair yet", NL); }//if (TrendStrongThreshold > 0 && TrendWeakThreshold > 0) }//if (UseHanover) //Trade entry. //carolco grid ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Trade entry", NL); if (UseCarolco) { ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "Using carolco grid", NL); ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, tab, "TradesInGrid: ", TradesInGrid, NL); ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, tab, "PipsBetweenTrades: ", PipsBetweenTrades, PipDescription, NL); }//if (UseCarolco) //Trade closure techniques ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Trade exit", NL); if (UseOsthafen) ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "Using osthafen to close trend trades", NL); if (UseDragosd1) { ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "Using dragosd1 to close trend trades "); ScreenMessage = StringConcatenate(ScreenMessage, ": MA = ", DoubleToStr(DragMaVal, Digits), NL); }//if (UseDragosd1) //Opposite direction signal if (UseOppositeSignal) { ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "Using opposite trend signal to close trend trades "); }//if (UseOppositeSignal) }//if (trend != ranging) //Ranging market if (trend == ranging) { ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Range trading information", NL); ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "Band upper extreme: ", Var2, NL); ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "Band upper: ", Var1, NL); ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "Band MA: ", DoubleToStr(Var5, Digits), NL); ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "Band lower: ", Var3, NL); ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "Band lower extreme: ", Var4, NL); ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "Take profit: ", RangeTakeProfit, PipDescription, NL); ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "Stop loss: ", RangeStopLoss, PipDescription, NL); if (UseRecovery) { ScreenMessage = StringConcatenate(ScreenMessage,Gap, "Recovery", NL); ScreenMessage = StringConcatenate(ScreenMessage,Gap, tab, "Levels ", RecoveryLevels, ": ReEntryLinePips = ", ReEntryLinePips, PipDescription, NL); }//if (UseRecovery) //extern string RecoveryLevels="2,6"; //extern int Start_Recovery_at_trades=2; //DC //extern int ReEntryLinePips=0; }//if (trend = ranging) ScreenMessage = StringConcatenate(ScreenMessage,Gap, NL); //Open trade if (OpenTrades > 0) ScreenMessage = StringConcatenate(ScreenMessage,Gap, TicketNo, " ", TradeOrigin, NL, NL); if (OpenTrades == 0) ScreenMessage = StringConcatenate(ScreenMessage, 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) //ScreenMessage = StringConcatenate(ScreenMessage,Gap, "BB Upper line: ", DoubleToStr(BbUpper, Digits), NL); //ScreenMessage = StringConcatenate(ScreenMessage,Gap, "BB Middle line: ", DoubleToStr(BbMiddle, Digits), NL); //ScreenMessage = StringConcatenate(ScreenMessage,Gap, "BB Lower line: ", DoubleToStr(BbLower, Digits), NL); if (MarginMessage != "") ScreenMessage = StringConcatenate(ScreenMessage,NL, Gap, MarginMessage, NL); Comment(ScreenMessage); }//void DisplayUserFeedback() //+------------------------------------------------------------------+ //| expert initialization function | //+------------------------------------------------------------------+ int init() { //---- //Adapt to x digit criminals if(Digits == 2 || Digits == 4) GlobalPipsMultiplier = 1; if(Digits == 3 || Digits == 5) GlobalPipsMultiplier = 10; if(Digits == 6) GlobalPipsMultiplier = 100; if(Digits == 7) GlobalPipsMultiplier = 1000; if (GlobalPipsMultiplier > 1) PipDescription = " points"; TrendTakeProfit*= GlobalPipsMultiplier; TrendStopLoss*= GlobalPipsMultiplier; RangeTakeProfit*= GlobalPipsMultiplier; RangeStopLoss*= GlobalPipsMultiplier; MinTriggerCandlePipsMovement*= GlobalPipsMultiplier; OnePip*= GlobalPipsMultiplier; PipsBetweenTrades*= GlobalPipsMultiplier; BreakEvenPips*= GlobalPipsMultiplier; BreakEvenProfit*= GlobalPipsMultiplier; PipsAwayFromVisualBE*= GlobalPipsMultiplier; JumpingStopPips*= GlobalPipsMultiplier; PipsAwayFromVisualJS*= GlobalPipsMultiplier; TrailingStopPips*= GlobalPipsMultiplier; PipsAwayFromVisualTS*= GlobalPipsMultiplier; StopTrailPips*= GlobalPipsMultiplier; HiddenStopLossPips*= GlobalPipsMultiplier; HiddenTakeProfitPips*= GlobalPipsMultiplier; ReEntryLinePips*= GlobalPipsMultiplier; RecoveryTrailingStopAt*= GlobalPipsMultiplier; Gap=""; if (DisplayGapSize >0) { for (int cc=0; cc< DisplayGapSize; cc++) { Gap = StringConcatenate(Gap, " "); } }//if (DisplayGapSize >0) //if (TradeComment == "") TradeComment = " "; if (TrendTradeComment == "") TrendTradeComment = " "; if (HedgeTradeComment == "") HedgeTradeComment = " "; if (RangeTradeComment == "") RangeTradeComment = " "; if (CarolcoTradeComment == "") CarolcoTradeComment = " "; if (CatTradeComment == "") CatTradeComment = " "; //Set up the arrays if (UseHanover) { SetUpArrays(); Ccy1 = StringSubstr(Symbol(), 0, 3); Ccy2 = StringSubstr(Symbol(), 3, 3); ReadBars = iBars(NULL, PERIOD_M1);//Don't need it again when start() triggers ReadHanover(); }//if (UseHanover) //OldBars = Bars; //ReadIndicatorValues();//For initial display in case user has turned of constant re-display DisplayUserFeedback(); OldRangeTradingBars = iBars(NULL, RangeTradingTF); OldCatBars = iBars(NULL, CatTimeFrame);//Caterpillar GvName = Symbol(); TradeOrigin = none; if (GlobalVariableCheck(GvName) ) { int type = GlobalVariableGet(GvName); if (type == 0) TradeOrigin = trendorigin; if (type == 1) TradeOrigin = rangeorigin; }//if (GlobalVariableCheck(GvName) ) //If using cat, draw the initial line ReadIndicatorValues(); if (UseCaterpillar && trend != ranging) { OldCatBars = iBars(NULL, CatTimeFrame); //Initial draw of buy/sell lines CountOpenTrades(); //Ensure a minimum gap in between trades double target; double pipsgap = (OnePip * Point); if (OpenTrades > 0) { pipsgap*= MinPipsBetweenCandles; OrderSelect(TicketNo, SELECT_BY_TICKET); target = OrderOpenPrice(); }//if (OpenTrades > 0) if (!TradeLong) ObjectDelete(buyline); if (!TradeShort) ObjectDelete(sellline); if (trend == up) { if (TradeLong && ObjectFind(buyline) == -1 && BuyOpen) { //Add buyline above order open price if there is a trade open already if (OpenTrades > 0) { if (Bid <= OrderOpenPrice() ) target = NormalizeDouble(OrderOpenPrice() + pipsgap, Digits); if (Bid > OrderOpenPrice() ) target = NormalizeDouble(iHigh(NULL, CatTimeFrame, 0) + pipsgap, Digits); }//if (OpenTrades > 0) else target = NormalizeDouble(iHigh(NULL, CatTimeFrame, 1) + pipsgap, Digits);//No open trade, so look at previous candle ObjectCreate(buyline,OBJ_HLINE,0,TimeCurrent(), target); ObjectSet(buyline,OBJPROP_COLOR,BuyLineColour); ObjectSet(buyline,OBJPROP_STYLE,STYLE_SOLID); }//if (TradeLong) }//if (trend == up) if (trend == down) { if (TradeShort && ObjectFind(sellline) == -1 && SellOpen) { //Add sellline below order open price if there is a trade open already if (OpenTrades > 0) { if (Bid >= OrderOpenPrice() ) target = NormalizeDouble(OrderOpenPrice() - pipsgap, Digits); if (Bid < OrderOpenPrice() ) target = NormalizeDouble(iLow(NULL, CatTimeFrame, 0) - pipsgap, Digits); }//if (OpenTrades > 0) else target = NormalizeDouble(iLow(NULL, CatTimeFrame, 1) - pipsgap, Digits); ObjectCreate(sellline,OBJ_HLINE,0,TimeCurrent(), target); ObjectSet(sellline,OBJPROP_COLOR,SellLineColour); ObjectSet(sellline,OBJPROP_STYLE,STYLE_SOLID); }//if (TradeShort && ObjectFind(sellline) == -1) }//if (trend == down) }//if (UseCaterpillar) //Call sq's show trades indi //iCustom(NULL, 0, "SQ_showTrades",Magic, 0,0); //Set up Recovery levels //Extract the levels inputted by the user // Cleanup first InputString=RecoveryLevels; CleanUpInputString(); NoOfLevels = StringFindCount(InputString,","); ArrayResize(RecoveryLevel, NoOfLevels); string AddChar = ""; StrPairToStringArray(RecoveryLevels, RecoveryLevel, AddChar); /* for (cc = 0; cc < NoOfLevels; cc++) { Alert(RecoveryLevel[cc]); } */ //---- return(0); } //+------------------------------------------------------------------+ //| expert deinitialization function | //+------------------------------------------------------------------+ int deinit() { //---- Comment(""); ObjectDelete(buyline); ObjectDelete(sellline); //---- return(0); } ////////////////////////////////////////////////////////////////////////////////////////////////////// //sq's string to array module void CleanUpInputString() { // Does any tidying up of the user inputs //Remove unwanted spaces InputString = StringTrimLeft(InputString); InputString = StringTrimRight(InputString); //Add final comma if ommitted by user if (StringSubstr(InputString, StringLen(InputString)-1) != ",") InputString = StringConcatenate(InputString,","); }//void CleanUpInputString //+------------------------------------------------------------------+ int StringFindCount(string str, string str2) //+------------------------------------------------------------------+ // Returns the number of occurrences of STR2 in STR // Usage: int x = StringFindCount("ABCDEFGHIJKABACABB","AB") returns x = 3 { int c = 0; for (int i=0; i<StringLen(str); i++) if (StringSubstr(str,i,StringLen(str2)) == str2) c++; return(c); } // End int StringFindCount(string str, string str2) //+------------------------------------------------------------------+ void StrPairToStringArray(string str, string &a[], string p_suffix, string delim=",") //+------------------------------------------------------------------+ { int z1=-1, z2=0; for (int i=0; i<ArraySize(a); i++) { z2 = StringFind(str,delim,z1+1); a[i] = StringSubstr(str,z1+1,z2-z1-1) + p_suffix; a[i] = StringTrimLeft(a[i]); a[i] = StringTrimRight(a[i]); if (z2 >= StringLen(str)-1) break; z1 = z2; } return(0); } /* //+------------------------------------------------------------------+ void StrToStringArray(string str, string &a[], string delim=",") //+------------------------------------------------------------------+ { int z1=-1, z2=0; for (int i=0; i<ArraySize(a); i++) { z2 = StringFind(str,delim,z1+1); a[i] = StringSubstr(str,z1+1,z2-z1-1); if (z2 >= StringLen(str)-1) break; z1 = z2; } return(0); } */ //END sq's string to array module ////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////// //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()<OrderOpenPrice()) { 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) { int 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 //{ // 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()) return(0); } if (JumpAfterBreakevenOnly && OrderType()==OP_SELL) { 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()) { 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); 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<OrderOpenPrice() // Increment 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(), " 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); } if (TrailAfterBreakevenOnly && OrderType()==OP_SELL) { 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 || (type != OP_BUY && type != OP_SELL) ) int ticket = OrderSend(Symbol(),type, lotsize, price, slippage, stop, take, comment, MagicNumber, expiry, col); //Is a 2 stage criminal if (CriminalIsECN && (type == OP_BUY || type == OP_SELL) ) { 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; 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() ) { 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); //Swap filter if (OpenTrades == 0) TradeDirectionBySwap(); //An individual currency can only be traded twice, so check for this CanTradeThisPair = true; if (OnlyTradeCurrencyTwice && OpenTrades == 0) { IsThisPairTradable(); }//if (OnlyTradeCurrencyTwice) if (!CanTradeThisPair) return(false); //Trend specific filters //Minimum candle movement if (trend != ranging) { if (iHigh(NULL, PERIOD_D1, 0) - iLow(NULL, PERIOD_D1, 0) < (MinTriggerCandlePipsMovement * Point) ) return(false); }//if (trend != ranging) return(true); }//End bool IsTradingAllowed() void LookForTrendTradingOpps() { double take, stop, price; int type; bool SendTrade; double SendLots = Lot; //Check filters if (!IsTradingAllowed() ) return; RefreshRates(); //Long if (trend == up && TrendConfirmationCandleDir == up) { if (!TradeLong) return; if (UseHanover && !HanoverFilter(OP_BUY) ) return; if (Bid <= iOpen(NULL, PERIOD_D1, 0)) return;//Must be a rising candle //Balanced pair trade filter. Only apply to pre-recovery trades. //Will remove the comments when I add Recovery //if (OpenTrades + 1 < Start_Recovery_at_trades || !UseRecovery) //{ if (UseZeljko && !BalancedPair(OP_BUY) ) return; //}//if (OpenTrades + 1 < Start_Recovery_at_trades) if (TrendTakeProfit > 0) take = NormalizeDouble(Ask + (TrendTakeProfit * Point), Digits); if (TrendStopLoss > 0) stop = NormalizeDouble(Ask - (TrendStopLoss * Point), Digits); type = OP_BUY; price = Ask; SendTrade = true; }//if (Ttrend == up) //Short if (trend == down && TrendConfirmationCandleDir == down) { if (!TradeShort) return; if (UseHanover && !HanoverFilter(OP_SELL) ) return; if (Bid >= iOpen(NULL, PERIOD_D1, 0)) return;//Must be a falling candle //Balanced pair trade filter. Only apply to pre-recovery trades //Will remove the comments when I add Recovery //if (OpenTrades + 1 < Start_Recovery_at_trades || !UseRecovery) //{ if (UseZeljko && !BalancedPair(OP_SELL) ) return; //}//if (OpenTrades + 1 < Start_Recovery_at_trades) if (TrendTakeProfit > 0) take = NormalizeDouble(Bid - (TrendTakeProfit * Point), Digits); if (TrendStopLoss > 0) stop = NormalizeDouble(Bid + (TrendStopLoss * Point), Digits); type = OP_SELL; price = Bid; SendTrade = true; }//if (Ttrend == down) if (SendTrade) { bool result = SendSingleTrade(type, TrendTradeComment, SendLots, price, stop, take); }//if (SendTrade) //Actions when trade send succeeds if (SendTrade && result) { GlobalVariableSet(GvName, 0); TradeOrigin = trendorigin; }//if (result) //Actions when trade send fails if (SendTrade && !result) { }//if (!result) }//void LookForTrendTradingOpps() void LookForRangeTradingOpps() { //Looks for Range trading opportunities as directed by Bob's crt strategy. //Closes an opposite direction trade. /////////////////////////////////////////////////////////////////////////////////////////////////////// //NOTE TO CODERS: I shoe-horned Recovery into the existing, working structure. This caused me huge //problems. The code is rather messy because LUC called with all his best buddies, and a fix -here- caused // a problem -there- and so on. Even now, I am not certain that this is absolutely correct, so change stuff //at your peril. /////////////////////////////////////////////////////////////////////////////////////////////////////// double take, stop, price, reentryprice, target; int type, count; bool SendTrade, result; double SendLots = Lot; //Using Recovery target = ObjectGet(reentrylinename, OBJPROP_PRICE1); //This idea from Pippo if (UseRecovery && OpenTrades > 0) { if ( (OpenTrades + 1) >= Start_Recovery_at_trades) { RecoveryInProgress = true; }//if ( (OpenTrades + 1) >= Start_Recovery_at_trades) if (RecoveryInProgress) { //The first Recovery level inputed by the user equates to a L2 trade, so OpenTrades can be used //to point to the correct Recovery level if ( (OpenTrades + 1) <= NoOfLevels) { int mult = StrToDouble(RecoveryLevel[OpenTrades - 1] ); SendLots = Lot * mult; }//if (OpenTrades == 2) if ( (OpenTrades + 1) > NoOfLevels) return;//No further trading is possible }//if (RecoveryInProgress) }//if (UseRecovery) //Check filters if (!IsTradingAllowed() ) return; RefreshRates(); /* At the time of coding, there are two BOTH ea's with slightly different conditionals. '10 4H CTR BOTH' is if ( Var5 < Var3 ) Order = SIGNAL_BUY; if ( Var5 > Var1 ) Order = SIGNAL_SELL; '10 4H CTR BOTH B' is if ( Var5 < Var3 && Bid < Var3 ) Order = SIGNAL_BUY; if ( Var5 > Var1 && Bid > Var1 ) Order = SIGNAL_SELL; Using the B version for now */ //Long if (target == 0) target = 1000000;//Dummy value if ( Var5 < Var3 && Bid < Var3 && Bid < target)//B version plus Recovery //if ( Var5 < Var3 && Bid < Var3 && Bid < SlowTrendMaVal)//B version with my mod { //Abort this if there is an open sell and recovery is in progress //if (SellOpen && RecoveryInProgress) return; //Close an opposite direction trade. This might need ammending when Recovery is implemented i.e. //if (SellOpen && !UseRecovery) if (SellOpen && OpenTrades == 1)//Nearly works { if (OrderSelect(TicketNo, SELECT_BY_TICKET) && OrderCloseTime() == 0 && OrderProfit() >= 0) //if (OrderSelect(TicketNo, SELECT_BY_TICKET) && OrderCloseTime() == 0) { result = false; count = 0; while (!result) { result = CloseTrade(TicketNo); if (result) { OpenTrades = 0; SellOpen = false; }//if (result) count++; if (count == 200) { Alert(TicketNo, " BigBob tried and failed to close this trade 200 times. This may need manual intervention."); result = true; }//if (count == 200) }//while (!result) }//if (OrderSelect(TicketNo, SELECT_BY_TICKET) && (OrderCloseTime() == 0) }//if (SellOpen) //Don't want a buy if there is a sell already open if (SellOpen) return; //For Recovery if (OpenTrades > 0 && !UseRecovery) return; if (OpenTrades == 0) SendLots = Lot;//A fix for earlier chaos caused by Recovery lot calcs if (SellOpen && RecoveryInProgress) return;//Stops accidental hedging if (!TradeLong) return; //Balanced pair trade filter. Only apply to pre-recovery trades. //Will remove the comments when I add Recovery //if (OpenTrades + 1 < Start_Recovery_at_trades || !UseRecovery) //{ if (UseZeljko && !BalancedPair(OP_BUY) ) return; //}//if (OpenTrades + 1 < Start_Recovery_at_trades) if (RangeTakeProfit > 0) take = NormalizeDouble(Ask + (RangeTakeProfit * Point), Digits); if (RangeStopLoss > 0) stop = NormalizeDouble(Ask - (RangeStopLoss * Point), Digits); type = OP_BUY; price = Ask; reentryprice = NormalizeDouble(price - (ReEntryLinePips * Point), Digits); SendTrade = true; }//if ( Var5 < Var3 && Bid < Var3 ) //Short if (target == 1000000) target = 0;//Dummy value if ( Var5 > Var1 && Bid > Var1 && Bid > target)//B version plus Recovery //if ( Var5 > Var1 && Bid > Var1 && Bid > SlowTrendMaVal )//B version with my mod { //Abort this if there is an open buy and recovery is in progress //if (BuyOpen && RecoveryInProgress) return; //Close an opposite direction trade. This might need ammending when Recovery is implemented i.e. //if (bUYOpen && !UseRecovery) if (BuyOpen && OpenTrades == 1) { if (OrderSelect(TicketNo, SELECT_BY_TICKET) && OrderCloseTime() == 0 && OrderProfit() >= 0) //if (OrderSelect(TicketNo, SELECT_BY_TICKET) && OrderCloseTime() == 0) { result = false; count = 0; while (!result) { result = CloseTrade(TicketNo); if (result) { OpenTrades = 0; BuyOpen = false; }//if (result) count++; if (count == 200) { Alert(TicketNo, " BigBob tried and failed to close this trade 200 times. This may need manual intervention."); result = true; }//if (count == 200) }//while (!result) }//if (OrderSelect(TicketNo, SELECT_BY_TICKET) && (OrderCloseTime() == 0) }//if (BuyOpen) //Recovery if (OpenTrades > 0 && !UseRecovery) return; if (OpenTrades == 0) SendLots = Lot;//A fix for earlier chaos caused by Recovery lot calcs if (BuyOpen && RecoveryInProgress) return;//Stops accidental hedging //Don't want a sell if there is a buy already open if (BuyOpen) return; if (!TradeShort) return; //Balanced pair trade filter. Only apply to pre-recovery trades //Will remove the comments when I add Recovery //if (OpenTrades + 1 < Start_Recovery_at_trades || !UseRecovery) //{ if (UseZeljko && !BalancedPair(OP_SELL) ) return; //}//if (OpenTrades + 1 < Start_Recovery_at_trades) if (RangeTakeProfit > 0) take = NormalizeDouble(Bid - (RangeTakeProfit * Point), Digits); if (RangeStopLoss > 0) stop = NormalizeDouble(Bid + (RangeStopLoss * Point), Digits); type = OP_SELL; price = Bid; reentryprice = NormalizeDouble(price + (ReEntryLinePips * Point), Digits); SendTrade = true; }//if ( Var5 > Var1 && Bid > Var1 ) if (SendTrade) { result = SendSingleTrade(type, RangeTradeComment, SendLots, price, stop, take); }//if (SendTrade) //Actions when trade send succeeds if (SendTrade && result) { GlobalVariableSet(GvName, 1); TradeOrigin = rangeorigin; AddReEntryLine(reentryprice); }//if (result) //Actions when trade send fails if (SendTrade && !result) { OldRangeTradingBars = 0; }//if (!result) }//End void LookForRangeTradingOpps() bool CloseTrade(int ticket) { while(IsTradeContextBusy()) Sleep(100); bool result = OrderClose(ticket, OrderLots(), OrderClosePrice(), 1000, CLR_NONE); //Actions when trade send succeeds if (result) { OpenTrades--; return(true); }//if (result) //Actions when trade send fails if (!result) { return(false); }//if (!result) }//End bool CloseTrade(ticket) //////////////////////////////////////////////////////////////////////////////////////////////// //Indicator module void GetBB() { //Reads BB figures into BbUpper, BbMiddle, BbLower. //Copied from Bob's 10.0 CRT BOTH EA Var1 = iBands(NULL, RangeTradingTF, 20, 1, 0, PRICE_CLOSE, MODE_UPPER, 0);//PAIR, PERIODH1, MA period, Deviation, shift Var2 = iBands(NULL, RangeTradingTF, 20, 2, 0, PRICE_CLOSE, MODE_UPPER, 0); Var3 = iBands(NULL, RangeTradingTF, 20, 1, 0, PRICE_CLOSE, MODE_LOWER, 0); Var4 = iBands(NULL, RangeTradingTF, 20, 2, 0, PRICE_CLOSE, MODE_LOWER, 0); Var5 = iMA(NULL, RangeTradingTF, 3, 1, MODE_LWMA, PRICE_OPEN, 0); }//void GetBb() double GetMa(int tf, int period, int mashift, int method, int ap, int shift) { return(iMA(NULL, tf, period, mashift, method, ap, shift) ); }//End double GetMa(int tf, int period, int mashift, int method, int ap, int shift) double CalculateVolatility(int period, int LookBack) { //Calculates the volatility of a pair based on an average of their movement over LookBack periods double pips; for (int cc = 1; cc < LookBack; cc++) { pips+= iHigh(NULL, period, cc) - iLow(NULL, period, cc); }//for (int cc = 1; cc < LookBack; cc++) pips/= LookBack;//Average pips movement per day //Alert(pips); //Convert to pips int multiplier; if (Digits == 2) multiplier = 100; if (Digits == 3) multiplier = 100; if (Digits == 4) multiplier = 10000; if (Digits == 5) multiplier = 10000; pips*= multiplier; int rpips = pips;//Convert to a simple integer - all we need return(rpips); }//End double CalculateVolatility(int period, int LookBack) void ReadIndicatorValues() { TrendDetectionModule();//Detect the trend //Reads any indicators associated with range trading if (trend == ranging) { GetBB(); }//if (trend == ranging) /* extern string drg="dragosd1"; extern bool UseDragosd1=true;//Set this as the default strategy - something has to be ds extern int DragMaTdTF=1440;//Time frame defaults to D1 chart extern int DragMaTdPeriod=5; extern int DragMaTdShift=2;//The MA Shift input extern string dmame="Method: 0=sma; 1=ema; 2=smma; 3=lwma"; extern int DragMaTdMethod=2; extern string dmaap="Applied price: 0=Close; 1=Open; 2=High"; extern string dmaap1="3=Low; 4=Median; 5=Typical; 6=Weighted"; extern int DragMaTdAppliedPrice=4; */ //Reads any indicators associated with trend trading if (trend != ranging) { //dragosd1 if (UseDragosd1) { DragMaVal = GetMa(DragMaTdTF, DragMaTdPeriod, DragMaTdShift, DragMaTdMethod, DragMaTdAppliedPrice, 0); }//if (UseDragosd1) }//if (trend != ranging) }//void ReadIndicatorValues() //End Indicator module //////////////////////////////////////////////////////////////////////////////////////////////// void LookForTradeClosure() { //Consult the various trend trade closure strategies bool CloseTrade; bool CloseCarolco = false;//Set to true if carolco gris is being used and there is a successful trade close, to force a pending deletion RefreshRates(); //CountOpenTrades() leaves TicketNo pointing at the last trade in the sequence, which could easily be //a pending if carolco is being used. To solve this, I have enclosed the following code in a loop that //cycles through the list of open trades and examines each one. This increases the processor use, but //I cannot think of another solution. for (int cc = OrdersTotal() - 1; cc >= 0; cc--) { if (OrderSymbol() != Symbol() ) continue; if (OrderMagicNumber() != MagicNumber) continue; if (OrderType() != OP_BUY && OrderType() != OP_SELL) continue;//Ignore pendings for now //Close the trade if the market retreats to the wrong side of either ma from the 'wrong' direction. //Uses the candle median suggested by osthafen to avoid premature trade closure, so median must cross //to the wrong side of the fast ma to cause a trade closure. if (UseOsthafen) { double median = (iHigh(NULL, PERIOD_D1, 0) + iLow(NULL, PERIOD_D1, 0) ) /2;//Save some typing }//if (UseCandleMedian) //The SlowTrendMaVal check is probably redundant. if (OrderType() == OP_BUY) { //osthafen - the default if (UseOsthafen) { if (median < FastTrendMaVal || median < SlowTrendMaVal) CloseTrade = true; }//if (UseCandleMedian) //dragosd1 (median MA) if (UseDragosd1) { if (UseTouch && Bid <= DragMaVal) CloseTrade = true; if (UseClose) { if (iClose(NULL, DragMaTdTF, 1) < DragMaVal) CloseTrade = true; }//if (UseClose) }//if (UseDragosd1) //Opposite direction signal if (UseOppositeSignal) { if (iHigh(NULL, PERIOD_D1, 0) < FastTrendMaVal && iLow(NULL, PERIOD_D1, 0) < FastTrendMaVal) CloseTrade = true; }//if (UseOppositeSignal) }//if (OrderType() == OP_BUY) if (OrderType() == OP_SELL) { //osthafen - the default if (UseOsthafen) { if (median > FastTrendMaVal || median > SlowTrendMaVal) CloseTrade = true; }//if (UseOsthafen) //dragosd1 (median MA) if (UseDragosd1) { if (UseTouch && Bid >= DragMaVal) CloseTrade = true; if (UseClose) { if (iClose(NULL, DragMaTdTF, 1) < DragMaVal) CloseTrade = true; }//if (UseClose) }//if (UseDragosd1) //Opposite direction signal if (UseOppositeSignal) { if (iHigh(NULL, PERIOD_D1, 0) > FastTrendMaVal && iLow(NULL, PERIOD_D1, 0) > FastTrendMaVal) CloseTrade = true; }//if (UseOppositeSignal) }//if (OrderType() == OP_SELL) //Trade closure if (CloseTrade && !UseHedging) { bool result = CloseTrade(TicketNo); //Actions when trade close succeeds if (result) { OpenTrades--; if (OpenTrades <= 0) TradeOrigin = none; GlobalVariableDel(GvName); CloseCarolco = true; }//if (result) //Actions when trade close fails if (!result) { }//if (!result) }//if (CloseTrade) //Hedging instead of closure if (CloseTrade && UseHedging && !HedgingInProgress && OrderProfit() < 0) { double SendLots = OrderLots() * HedgeLotMultiplier; RefreshRates(); if (OrderType() == OP_BUY) { result = SendSingleTrade(OP_SELL, HedgeTradeComment, SendLots, NormalizeDouble(Bid, Digits), 0, 0); if (result) { //Delete outstanding pendings if (UseCarolco && (NoOfPendingBuys > 0 || NoOfPendingSells > 0 ) ) { DeletePendings(); CountOpenTrades();//Forces startcarolco() to do a rerun if any deletions fail. cot resets all the xxxOpen variables. }//if (UseCarolco) return;//Attempt to stop multiple hedge trades being taken }//if (result) }//if (OrderType() == OP_BUY) if (OrderType() == OP_SELL) { result = SendSingleTrade(OP_BUY, HedgeTradeComment, SendLots, NormalizeDouble(Ask, Digits), 0, 0); if (result) { //Delete outstanding pendings if (UseCarolco && (NoOfPendingBuys > 0 || NoOfPendingSells > 0 ) ) { DeletePendings(); CountOpenTrades();//Forces startcarolco() to do a rerun if any deletions fail. cot resets all the xxxOpen variables. }//if (UseCarolco) return;//Attempt to stop multiple hedge trades being taken }//if (result) }//if (OrderType() == OP_SELL) }//if (CloseTrade && UseHedging && !HedgingInProgress) }//for (int cc = OrdersTotal() - 1; cc >= 0; cc--) //Delete carolco grid trades. Probably not needed in light of the previous code. We shall see. if (CloseCarolco) { DeletePendings(); CloseAllTrades(); CountOpenTrades();//Forces startcarolco() to do a rerun if any deletions fail. cot resets all the xxxOpen variables. }//if (CloseCarolco) }//void LookForTradeClosure() void CloseAllTrades() { ForceTradeClosure= false; if (OrdersTotal() == 0) return; for (int cc = OrdersTotal() - 1; cc >= 0; cc--) { if (!OrderSelect(cc, SELECT_BY_POS) ) continue; if (OrderSymbol() == Symbol() ) { while(IsTradeContextBusy()) Sleep(100); if (OrderType() == OP_BUY || OrderType() == OP_SELL) bool result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 1000, CLR_NONE); if (result) cc++; if (!result) ForceTradeClosure= true; }//if (OrderSymbol() == Symbol() ) }//for (int cc = OrdersTotal() - 1; cc >= 0; cc--) }//End void CloseAllTrades() 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() void CountOpenTrades() { OpenTrades = 0; TicketNo = -1; BuyOpen = false; SellOpen = false; TradeOpen = false;//Cat //Carolco NoOfPendingBuys = 0; NoOfPendingSells = 0; //Hedging BasketUpl = 0; if (OrdersTotal() == 0) return; int OrdTot = OrdersTotal();//Makes BB finish the entire loop if a trade closes mid-loop. Not likely, but possible for (int cc = 0; cc <= OrdTot; cc++) { if (!OrderSelect(cc, SELECT_BY_POS) ) continue; if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber) { BasketUpl+= (OrderProfit() + OrderSwap() + OrderCommission() );//For closing a hedged basket at BE OpenTrades++; TicketNo = OrderTicket(); if (OrderType() == OP_BUY) BuyOpen = true; if (OrderType() == OP_SELL) SellOpen = true; TradeOpen = true;//cat //Profitable trade management if (OrderProfit() > 0 && !RecoveryInProgress && !HedgingInProgress) TradeManagementModule(); //carolco if (OrderType() == OP_BUYSTOP) { //BuyTicketNo = OrderTicket(); NoOfPendingBuys++; }//if (OrderType() == OP_BUYSTOP) if (OrderType() == OP_SELLSTOP) { //SellTicketNo = OrderTicket(); NoOfPendingSells++; }//if (OrderType() == OP_SELLSTOP) //Recovery if (ObjectFind(breakevenlinename) > -1 && !HedgingInProgress) { double take = ObjectGet(breakevenlinename, OBJPROP_PRICE1); if (OrderTakeProfit() != take && (OrderType() == OP_BUY || OrderType() == OP_SELL) && !UseRecoveryTrailingStop) { while(IsTradeContextBusy()) Sleep(100); OrderModify(OrderTicket(), OrderOpenPrice(), OrderStopLoss(), take, OrderExpiration(), CLR_NONE); }//if (OrderTakeProfit() != take && (OrderType() == OP_BUY || OrderType() == OP_SELL) ) }//if (ObjectFind(breakevenlinename) > -1) }//if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber) }//for (int cc = 0; cc <= OrdTot; cc++) //Delete rednundat gv if (OpenTrades == 0 && TradeOrigin != none) { TradeOrigin = none; GlobalVariableDel(GvName); }//if (OpenTrades == 0 && TradeOrigin != none) //Hedging HedgingInProgress = false;//Had to be moved here so the management module is not called to hedged trades if (BuyOpen && SellOpen) HedgingInProgress = true; //Recovery RecoveryInProgress = false;//Had to be moved here so the management module is not called to recovery trades if (UseRecovery) { if (OpenTrades >= Start_Recovery_at_trades && TradeOrigin == rangeorigin) RecoveryInProgress = true; }//if (UseRecovery) }//End void CountOpenTrades(); //============================================================================= // 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) /////////////////////////////////////////////////////////////////////////////////////////////////////// //Balance/swap filters module void TradeDirectionBySwap() { //Sets TradeLong & TradeShort according to the positive/negative swap it attracts double LongSwap = MarketInfo(Symbol(), MODE_SWAPLONG); double ShortSwap = MarketInfo(Symbol(), MODE_SWAPSHORT); if (CadPairsPositiveOnly) { if (StringSubstr(Symbol(), 0, 3) == "CAD" || StringSubstr(Symbol(), 0, 3) == "cad" || StringSubstr(Symbol(), 3, 3) == "CAD" || StringSubstr(Symbol(), 3, 3) == "cad" ) { if (LongSwap > 0) TradeLong = true; else TradeLong = false; if (ShortSwap > 0) TradeShort = true; else TradeShort = false; }//if (StringSubstr(Symbol(), 0, 3) == "CAD" || StringSubstr(Symbol(), 0, 3) == "cad" ) }//if (CadPairsPositiveOnly) if (AudPairsPositiveOnly) { if (StringSubstr(Symbol(), 0, 3) == "AUD" || StringSubstr(Symbol(), 0, 3) == "aud" || StringSubstr(Symbol(), 3, 3) == "AUD" || StringSubstr(Symbol(), 3, 3) == "aud" ) { if (LongSwap > 0) TradeLong = true; else TradeLong = false; if (ShortSwap > 0) TradeShort = true; else TradeShort = false; }//if (StringSubstr(Symbol(), 0, 3) == "AUD" || StringSubstr(Symbol(), 0, 3) == "aud" || StringSubstr(Symbol(), 3, 3) == "AUD" || StringSubstr(Symbol(), 3, 3) == "aud" ) }//if (AudPairsPositiveOnly) if (NzdPairsPositiveOnly) { if (StringSubstr(Symbol(), 0, 3) == "NZD" || StringSubstr(Symbol(), 0, 3) == "nzd" || StringSubstr(Symbol(), 3, 3) == "NZD" || StringSubstr(Symbol(), 3, 3) == "nzd" ) { if (LongSwap > 0) TradeLong = true; else TradeLong = false; if (ShortSwap > 0) TradeShort = true; else TradeShort = false; }//if (StringSubstr(Symbol(), 0, 3) == "AUD" || StringSubstr(Symbol(), 0, 3) == "aud" || StringSubstr(Symbol(), 3, 3) == "AUD" || StringSubstr(Symbol(), 3, 3) == "aud" ) }//if (AudPairsPositiveOnly) }//void TradeDirectionBySwap() bool IsThisPairTradable() { //Checks to see if either of the currencies in the pair is already being traded twice. //If not, then return true to show that the pair can be traded, else return false string c1 = StringSubstr(Symbol(), 0, 3);//First currency in the pair string c2 = StringSubstr(Symbol(), 3, 3);//Second currency in the pair int c1open = 0, c2open = 0; CanTradeThisPair = true; for (int cc = OrdersTotal() - 1; cc >= 0; cc--) { if (!OrderSelect(cc, SELECT_BY_POS) ) continue; if (OrderSymbol() != Symbol() ) continue; int index = StringFind(OrderSymbol(), c1); if (index > -1) { c1open++; }//if (index > -1) index = StringFind(OrderSymbol(), c2); if (index > -1) { c2open++; }//if (index > -1) if (c1open == 1 && c2open == 1) { CanTradeThisPair = false; return(false); }//if (c1open == 1 && c2open == 1) }//for (int cc = OrdersTotal() - 1; cc >= 0; cc--) //Got this far, so ok to trade return(true); }//End bool IsThisPairTradable() bool BalancedPair(int type) { //Only allow an individual currency to trade if it is a balanced trade //e.g. UJ Buy open, so only allow Sell xxxJPY. //The passed parameter is the proposed trade, so an existing one must balance that //This code courtesy of Zeljko (zkucera) who has my grateful appreciation. string BuyCcy1, SellCcy1, BuyCcy2, SellCcy2; if (type == OP_BUY || type == OP_BUYSTOP) { BuyCcy1 = StringSubstr(Symbol(), 0, 3); SellCcy1 = StringSubstr(Symbol(), 3, 3); }//if (type == OP_BUY || type == OP_BUYSTOP) else { BuyCcy1 = StringSubstr(Symbol(), 3, 3); SellCcy1 = StringSubstr(Symbol(), 0, 3); }//else for (int cc = OrdersTotal() - 1; cc >= 0; cc--) { if (!OrderSelect(cc, SELECT_BY_POS)) continue; if (OrderSymbol() == Symbol()) continue; if (OrderType() == OP_BUY || OrderType() == OP_BUYSTOP) { BuyCcy2 = StringSubstr(OrderSymbol(), 0, 3); SellCcy2 = StringSubstr(OrderSymbol(), 3, 3); }//if (OrderType() == OP_BUY || OrderType() == OP_BUYSTOP) else { BuyCcy2 = StringSubstr(OrderSymbol(), 3, 3); SellCcy2 = StringSubstr(OrderSymbol(), 0, 3); }//else if (BuyCcy1 == BuyCcy2 || SellCcy1 == SellCcy2) return(false); }//for (int cc = OrdersTotal() - 1; cc >= 0; cc--) //Got this far, so it is ok to send the trade return(true); }//End bool BalancedPair(int type) //End Balance/swap filters module /////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// //Recovery module void RecoveryModule() { //Draw a breakeven line if there is not one in place already. //The bot will adjust the tp's during the CountOpenTrades function. if (ObjectFind(breakevenlinename) > -1) return; //Do not need a breakeven line if Recovery is already at be //if (ObjectFind(breakevenlinename) > -1) return; buy_price = 0; sell_price = 0; CheckRecoveryTakeProfit(); double recovery_profit; if (buy_price > 0) { recovery_profit = buy_price; recovery_profit = NormalizeDouble(buy_price + (RecoveryBreakEvenProfitPips * Point), Digits); }//if (buy_price > 0) if (sell_price > 0) { recovery_profit = sell_price; recovery_profit = NormalizeDouble(sell_price - (RecoveryBreakEvenProfitPips * Point), Digits); }//if (sell_price > 0) ObjectCreate(breakevenlinename,OBJ_HLINE,0,TimeCurrent(), recovery_profit ); ObjectSet(breakevenlinename,OBJPROP_COLOR,BreakEvenLineColour); ObjectSet(breakevenlinename,OBJPROP_STYLE,STYLE_SOLID); ObjectSet(breakevenlinename,OBJPROP_WIDTH,2); }//End void RecoveryModule() void CheckRecoveryTakeProfit() { //This is adapted from the NB iExposure indicator. I do not understand how it works. //There will be redundant code, so anybody wishing to clear it up is most welcome to do so. ExtLines = 0; int i,col,line; ArrayInitialize(ExtSymbolsSummaries,0.0); int total=Analyze(); if(total>0) { line=0; for(i=0; i<ExtSymbolsTotal; i++) { if (ExtSymbols[i] != Symbol() ) continue; if(ExtSymbolsSummaries[i][DEALS]<=0) continue; line++; //---- add line if(line>ExtLines) { int y_dist=ExtVertShift*(line+1)+1; ExtLines++; }//if(line>ExtLines) //---- set line //color price_colour;//Steve mod int digits=MarketInfo(ExtSymbols[i],MODE_DIGITS); double buy_lots=ExtSymbolsSummaries[i][BUY_LOTS]; double sell_lots=ExtSymbolsSummaries[i][SELL_LOTS]; if(buy_lots!=0) buy_price=NormalizeDouble(ExtSymbolsSummaries[i][BUY_PRICE]/buy_lots, Digits); if(sell_lots!=0) sell_price=NormalizeDouble(ExtSymbolsSummaries[i][SELL_PRICE]/sell_lots, Digits); }//for(i=0; i<ExtSymbolsTotal; i++) }//if(total>0) }//End void CheckRecoveryTakeProfit() int Analyze() { double profit; int i,index,type,total=OrdersTotal(); //---- for(i=0; i<total; i++) { if(!OrderSelect(i,SELECT_BY_POS)) continue; type=OrderType(); if(type!=OP_BUY && type!=OP_SELL) continue; index=SymbolsIndex(OrderSymbol()); if(index<0 || index>=SYMBOLS_MAX) continue; //---- ExtSymbolsSummaries[index][DEALS]++; profit=OrderProfit()+OrderCommission()+OrderSwap(); ExtSymbolsSummaries[index][PROFIT]+=profit; if(type==OP_BUY) { ExtSymbolsSummaries[index][BUY_LOTS]+=OrderLots(); ExtSymbolsSummaries[index][BUY_PRICE]+=OrderOpenPrice()*OrderLots(); } else { ExtSymbolsSummaries[index][SELL_LOTS]+=OrderLots(); ExtSymbolsSummaries[index][SELL_PRICE]+=OrderOpenPrice()*OrderLots(); } } //---- total=0; for(i=0; i<ExtSymbolsTotal; i++) { if(ExtSymbolsSummaries[i][DEALS]>0) total++; } //---- return(total); }//int Analyze() //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int SymbolsIndex(string SymbolName) { bool found=false; //---- for(int i=0; i<ExtSymbolsTotal; i++) { if(SymbolName==ExtSymbols[i]) { found=true; break; } } //---- if(found) return(i); if(ExtSymbolsTotal>=SYMBOLS_MAX) return(-1); //---- i=ExtSymbolsTotal; ExtSymbolsTotal++; ExtSymbols[i]=SymbolName; ExtSymbolsSummaries[i][DEALS]=0; ExtSymbolsSummaries[i][BUY_LOTS]=0; ExtSymbolsSummaries[i][BUY_PRICE]=0; ExtSymbolsSummaries[i][SELL_LOTS]=0; ExtSymbolsSummaries[i][SELL_PRICE]=0; ExtSymbolsSummaries[i][NET_LOTS]=0; ExtSymbolsSummaries[i][PROFIT]=0; //---- return(i); }//End int SymbolsIndex(string SymbolName) void AddReEntryLine(double price) { if (ObjectFind(reentrylinename) > -1) ObjectDelete(reentrylinename); if (!ObjectCreate(reentrylinename,OBJ_HLINE,0,TimeCurrent(),price) ) { int err=GetLastError(); Alert("Re-entry line draw failed with error(",err,"): ",ErrorDescription(err)); Print("Re-entry line draw failed with error(",err,"): ",ErrorDescription(err)); return(0); }//if (!ObjectCreate(reentrylinename,OBJ_HLINE,0,TimeCurrent(),price) ) ObjectSet(reentrylinename,OBJPROP_COLOR,ReEntryLineColour); ObjectSet(reentrylinename,OBJPROP_STYLE,STYLE_SOLID); ObjectSet(reentrylinename,OBJPROP_WIDTH,2); }//void AddReEntryLine(int type, double price) void ReplaceReEntryLine() { //Find the most recent trade in the sequence and replace the missing re-entry line for (int cc = OrdersTotal() - 1; cc >= 0; cc--) { if (OrderSelect(cc, SELECT_BY_POS, MODE_TRADES) ) { if (OrderSymbol() == Symbol()) { if (OrderType() == OP_BUY) AddReEntryLine(NormalizeDouble(OrderOpenPrice() - (ReEntryLinePips * Point), Digits) ); if (OrderType() == OP_SELL) AddReEntryLine(NormalizeDouble(OrderOpenPrice() + (ReEntryLinePips * Point), Digits) ); return; }//if (OrderSymbol() == Symbol() && OrderCloseTime() == 0) }//if (OrderSelect(cc, SELECT_BY_POS) ) }//for (cc = OpenTrades; cc >= 0; cc--) }//void ReplaceReEntryLine() void CalculateReEntryLinePips() { if (ReEntryLinePips > 0) return;//User has chosen the value, so nothing else to do ReEntryLinePips = (Volatility * ReEntryLineVolMult) * GlobalPipsMultiplier; }//End void CalculateReEntryLinePips() void RecoveryCandlesticktrailingStop() { //Called from start() //This function will only be called if Recovery is in progress. //* no tp in Recovery trades, just the breakeven line on the chart //* at be +10, the breakeven line becomes the stop loss line //* code a candlestick trail for the stop loss line //* close the Recovery basket when the market retraces to the stop loss line //Find the trade type. Function leaves an open trade selected double target, stop; RefreshRates(); if (BuyOpen) { //Should breakeven line be replaced by trailing stop line. //Irrelevant if be line has been deleted if (ObjectFind(breakevenlinename) > -1) { target = ObjectGet(breakevenlinename, OBJPROP_PRICE1); if (Ask >= target + (RecoveryTrailingStopAt * Point) ) { ObjectDelete(breakevenlinename); ObjectCreate(breakevenlinename, 1,0,TimeCurrent(),target); ObjectSet(breakevenlinename,OBJPROP_COLOR,RecoveryStopLossLineColour); ObjectSet(breakevenlinename,OBJPROP_STYLE,STYLE_SOLID); ObjectSet(breakevenlinename,OBJPROP_WIDTH,2); //return; }//if (Ask >= target + (RecoveryTrailingStopAt * Point) ) }//if (ObjectFind(breakevenlinename) > -1) //Abort the function if be line is wrong colour if (ObjectGet(breakevenlinename, OBJPROP_COLOR) != RecoveryStopLossLineColour) return; //Move the stop at each new candle if (OldRecoverTrailBars != Bars) { target = ObjectGet(breakevenlinename, OBJPROP_PRICE1); if (Low[1] > target) { ObjectMove(breakevenlinename, 0, TimeCurrent(), Low[1]); }//if (Low[1] > target) OldRecoverTrailBars = Bars; //return; }//if (OldRecoverTrailBars != Bars) //Has the market retraced to the recovery stop loss target = ObjectGet(breakevenlinename, OBJPROP_PRICE1); if (Ask <= target) { ForceTradeClosure = true; CloseAllTrades(); ObjectDelete(breakevenlinename); return; }//if (Ask <= target) }//if (OrderType() == OP_BUY) //The most recent trade selected in CountOpenTrades will show the type of trades involved if (SellOpen) { //Should breakeven line be replaced by trailing stop line //Irrelevant if be line has been deleted if (ObjectFind(breakevenlinename) > -1) { target = ObjectGet(breakevenlinename, OBJPROP_PRICE1); if (Bid <= target - (RecoveryTrailingStopAt * Point) ) { ObjectDelete(breakevenlinename); ObjectCreate(breakevenlinename, 1,0,TimeCurrent(),target); ObjectSet(breakevenlinename,OBJPROP_COLOR,RecoveryStopLossLineColour); ObjectSet(breakevenlinename,OBJPROP_STYLE,STYLE_SOLID); ObjectSet(breakevenlinename,OBJPROP_WIDTH,2); //return; }//if (Bid <= target - (RecoveryTrailingStopAt * Point) ) }//if (ObjectFind(breakevenlinename) > -1) //Abort the function if be line is wrong colour if (ObjectGet(breakevenlinename, OBJPROP_COLOR) != RecoveryStopLossLineColour) return; //Move the stop at each new candle if (OldRecoverTrailBars != Bars) { target = ObjectGet(breakevenlinename, OBJPROP_PRICE1); if (High[1] < target) { ObjectMove(breakevenlinename, 0, TimeCurrent(), High[1]); }//if (High[1] < target) OldRecoverTrailBars = Bars; //return; }//if (OldRecoverTrailBars != Bars) //Has the market retraced to the recovery stop loss target = ObjectGet(breakevenlinename, OBJPROP_PRICE1); //Alert("Target = ", target); if (Bid >= target) { ForceTradeClosure = true; CloseAllTrades(); ObjectDelete(breakevenlinename); return; }//if (Bid >= target) }//if (OrderType() == OP_SELL) }//End void RecoveryCandlesticktrailingStop() //End Recovery module /////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// //Trend detection module void TrendDetectionModule() { //Define the trend according to the user's choices. //Only called if UseTrendDetection is set to true - as it should be /* Trend definitions - uptrend: high and low of D1 candle above both MA's - downtrend: high and low of D1 candle below both MA's - ranging: any part of the candle in between the MA's */ //Set the trend according to an open trade. This may change, but for now it makes little sense to me //to have a trades sent from one market type managed the the opposite following a change from trend //to range or vice versa if (TradeOrigin == trendorigin) { //Read the moving averages for display FastTrendMaVal = GetMa(FastMaTdTF, FastMaTdPeriod, FastMaTdShift, FastMaTdMethod, FastMaTdAppliedPrice, 0); SlowTrendMaVal = GetMa(SlowMaTdTF, SlowMaTdPeriod, SlowMaTdShift, SlowMaTdMethod, SlowMaTdAppliedPrice, 0); if (OpenTrades == 0) CountOpenTrades(); if (OpenTrades > 0) { OrderSelect(TicketNo, SELECT_BY_TICKET); if (OrderType() == OP_BUY) { trend = up; return; }//if (OrderType() == OP_BUY) if (OrderType() == OP_SELL) { trend = down; return; }//if (OrderType() == OP_SELL) }//if (OpenTrades > 0) }//if (TradeOrigin == trendorigin) /* if (TradeOrigin == rangeorigin) { trend = ranging; return; }//if (TradeOrigin == trendorigin) */ //No open trade, so no restriction on trend setting trend = ranging;//Default //Read the moving averages FastTrendMaVal = GetMa(FastMaTdTF, FastMaTdPeriod, FastMaTdShift, FastMaTdMethod, FastMaTdAppliedPrice, 0); SlowTrendMaVal = GetMa(SlowMaTdTF, SlowMaTdPeriod, SlowMaTdShift, SlowMaTdMethod, SlowMaTdAppliedPrice, 0); //Calculate the trend //Uptrend if (iHigh(NULL, PERIOD_D1, 0) > FastTrendMaVal && iHigh(NULL, PERIOD_D1, 0) > SlowTrendMaVal && iLow(NULL, PERIOD_D1, 0) > FastTrendMaVal && iLow(NULL, PERIOD_D1, 0) > SlowTrendMaVal) trend = up; //Downtrend if (iHigh(NULL, PERIOD_D1, 0) < FastTrendMaVal && iHigh(NULL, PERIOD_D1, 0) < SlowTrendMaVal && iLow(NULL, PERIOD_D1, 0) < FastTrendMaVal && iLow(NULL, PERIOD_D1, 0) < SlowTrendMaVal) trend = down; //Check that we are entering the market at the start of the trend. We will be at the start of the trend //if either hi or lo of yesterdays candle was within the two MA's if (OnlyTradeStartOfTrend && trend != ranging) { double PrevFastTrendMaVal, PrevSlowTrendMaVal; PrevFastTrendMaVal = GetMa(FastMaTdTF, FastMaTdPeriod, FastMaTdShift, FastMaTdMethod, FastMaTdAppliedPrice, 1); PrevSlowTrendMaVal = GetMa(SlowMaTdTF, SlowMaTdPeriod, SlowMaTdShift, SlowMaTdMethod, SlowMaTdAppliedPrice, 1); if (trend == up) { trend = upbutuntradable; if (iHigh(NULL, PERIOD_D1, 1) < PrevFastTrendMaVal || iHigh(NULL, PERIOD_D1, 1) < PrevSlowTrendMaVal || iLow(NULL, PERIOD_D1, 1) < PrevFastTrendMaVal || iLow(NULL, PERIOD_D1, 1) < PrevSlowTrendMaVal) trend = up; }//if (trend == up) if (trend == down) { trend = downbutuntradable; if (iHigh(NULL, PERIOD_D1, 1) > PrevFastTrendMaVal || iHigh(NULL, PERIOD_D1, 1) > PrevSlowTrendMaVal || iLow(NULL, PERIOD_D1, 1) > PrevFastTrendMaVal || iLow(NULL, PERIOD_D1, 1) > PrevSlowTrendMaVal) trend = down; }//if (trend == down) }//if (OnlyTradeStartOfTrend && trend != ranging) //Allow for conversion of trade origin from range to trend if the market is now trending if (AllowChangeOfOriginToTrend && TradeOrigin == rangeorigin && trend != ranging) { TradeOrigin = trendorigin; GlobalVariableSet(GvName, 0); ObjectDelete(reentrylinename); ObjectDelete(breakevenlinename); }//if (AllowChangeOfOriginToTrend && TradeOrigin == rangeorigin && trend != ranging) }//void TrendDetectionModule() //End Trend detection module /////////////////////////////////////////////////////////////////////////////////////////////////////// void GetTrendConfirmationCandleDir() { //BB uses a shorter-term candle direction filter to confirm that the market is moving in the correct //direction for the trade. This function ascertains the direction of movement of the candle TrendConfirmationCandleDir = none; if (iOpen(NULL, TrendConfirmationCandleTF, 1) > iClose(NULL, TrendConfirmationCandleTF, 1) ) TrendConfirmationCandleDir = down; if (iOpen(NULL, TrendConfirmationCandleTF, 1) < iClose(NULL, TrendConfirmationCandleTF, 1) ) TrendConfirmationCandleDir = up; }//End void GetTrendConfirmationCandleDir() ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// //Caterpillar module void DeleteOrphanGlobals() { //Remove those globals left behind after a trade closes for (int cc = GlobalVariablesTotal() - 1; cc >= 0; cc--) { CsGvName = GlobalVariableName(cc); int tn = StrToDouble(CsGvName); if (tn > 0) { if (!OrderSelect(tn, SELECT_BY_TICKET) || OrderCloseTime() > 0) { GlobalVariableDel(CsGvName); cc++; }//if (!OrderSelect(tn, SELECT_BY_TICKET) || OrderCloseTime() > 0) }//if (tn > 0) }//for (int cc = GlobalVariablesTotal() - 1; cc >= 0; cc--) }//End void DeleteOrphanGlobals() void MoveCaterpillarStopToBreakeven() { //OpenTrades - 1 trade needs to have its stop moved to be at the opening of a new trade //Select OpenTrades - 1 int found = 0; for (int cc = 0; cc <= OrdersTotal() - 1; cc++) { if (!OrderSelect(cc, SELECT_BY_POS) ) continue; if (OrderSymbol() != Symbol() ) continue; if (OrderMagicNumber() != MagicNumber ) continue; //Order must belong to Cat found++; if (found == OpenTrades - 1) break; }//for (int cc = 0; cc <= OrdersTotal() - 1; cc++) double stop = OrderOpenPrice(); bool modify = false; if (OrderType() == OP_BUY && OrderStopLoss() < OrderOpenPrice() ) modify = true; if (OrderType() == OP_SELL && OrderStopLoss() > OrderOpenPrice() ) modify = true; if (modify) { int tries = 0; bool result = false; while (!result) { result = OrderModify(OrderTicket(), OrderOpenPrice(), stop, OrderTakeProfit(), OrderExpiration(), CLR_NONE); if (!result) { tries++; if (tries == 1) Alert(OrderTicket(), " stop loss move to BE failed"); if (tries == 100) { result = true;//Give up Alert(OrderTicket(), " Caterpillar failed to move the sl to breakeven after 100 attempts."); }//if (tries == 100) }//if (!result) }//while (!result) }//if (modify) }//End void MoveCaterpillarStopToBreakeven() void CaterpillarTrailingStop(int TradesToCheck) { //Move trade stops 1 candle to the right when there is a new hi or lo, depending on the trade type //Also deletes redundant gv's if (GlobalVariablesTotal() == 0) return;//Shouldn't happen, but you never know int found, shift, ctime; bool result; double stop; int MaxTradesTicketNo = -1;//This will hold the ticket number of the final trade in the sequence, but which is checked first //Cycle through the Golbal Variables list to look for those with an integer as their name for (int cc = GlobalVariablesTotal() - 1; cc >= 0; cc--) { CsGvName = GlobalVariableName(cc); int tn = StrToDouble(CsGvName); if (tn > 0) { //Delete the gv if the trade has closed if (!OrderSelect(tn, SELECT_BY_TICKET) || OrderCloseTime() > 0) { GlobalVariableDel(CsGvName); cc++; continue; }//if (!OrderSelect(tn, SELECT_BY_TICKET) || OrderCloseTime() > 0) //The trade is still open, so check for ownership if (OrderSymbol() != Symbol() ) continue; if (OrderMagicNumber() != MagicNumber ) continue; //Got this far, so Cat owns the trade and the stop needs moving. //Store the ticket number of the most recent trade in the sequence,for BE stop stuff further down if (MaxTradesTicketNo == -1) MaxTradesTicketNo = OrderTicket(); //Calculate the shift back from current candle to the candle open time of the previous cts move shift = 0; ctime = GlobalVariableGet(CsGvName); while (Time[shift] > ctime && shift < Bars) { shift++; }//while (Time[shift} > ctime) //Point to the next candls shift--; //This is an attempt to stop the final trade in the sequence having its stop moved too early, because //this can result in it being stopped out as soon as it is opened if (shift < 2) continue; if (OrderType() == OP_BUY) { //stop = Low[shift]; stop = iLow(NULL, CatTimeFrame, shift); if (OrderStopLoss() < stop && stop > 0) { while (IsTradeContextBusy() ) Sleep(100); result = OrderModify(tn, OrderOpenPrice(), stop, OrderTakeProfit(), OrderExpiration(), CLR_NONE); GlobalVariableSet(CsGvName, Time[shift]); }//if (OrderStopLoss() < stop) }//if (OrderType() == OP_BUY) if (OrderType() == OP_SELL) { //stop = High[shift]; stop = iHigh(NULL, CatTimeFrame, shift); if (OrderStopLoss() > stop && stop > 0) { while (IsTradeContextBusy() ) Sleep(100); result = OrderModify(tn, OrderOpenPrice(), stop, OrderTakeProfit(), OrderExpiration(), CLR_NONE); GlobalVariableSet(CsGvName, Time[shift]); }//if (OrderStopLoss() > stop) }//if (OrderType() == OP_SELL) found++; if (found >= TradesToCheck) break;//All finished }//if (tn > -1) }//for (int cc = GlobalVariablesTotal() - 1; cc >= 0; cc--) //Attempt to move the stop of the final trade to BE asap, if OpenTrades has reached the max allowed. if (OpenTrades == MaxTrades) { if (OrderSelect(MaxTradesTicketNo, SELECT_BY_TICKET) && OrderCloseTime() == 0) { stop = OrderOpenPrice(); bool modify = false; if (OrderType() == OP_BUY && OrderStopLoss() < OrderOpenPrice() ) { modify = true; }//if (OrderType() == OP_BUY && OrderStopLoss() < OrderOpenPrice() ) if (OrderType() == OP_SELL && OrderStopLoss() > OrderOpenPrice() ) { modify = true; }//if (OrderType() == OP_SELL && OrderStopLoss() > OrderOpenPrice() ) if (modify) { result = OrderModify(MaxTradesTicketNo, OrderOpenPrice(), stop, OrderTakeProfit(), OrderExpiration(), CLR_NONE); }//if (modify) }//if (OrderSelect(MaxTradesTicketNo, SELECT_BY_TICKET) && OrderCloseTime() == 0) }//if (OpenTrades == MaxTrades) }//void CaterpillarTrailingStop() void LookForCatTradingOpportunities() { RefreshRates(); double take, stop, price; int type; bool SendTrade; double spread = MarketInfo(Symbol(), MODE_SPREAD) * Point; //Ensure a minimum gap in between trades double pipsgap = (OnePip * Point); if (OpenTrades > 0) pipsgap*= MinPipsBetweenCandles; double SendLots = Lot; //Check filters if (!IsTradingAllowed() ) return; RefreshRates(); //Long double target; if (TradeLong) { target = ObjectGet(buyline, OBJPROP_PRICE1); if (Bid > target) { //if (TakeProfit > 0) take = NormalizeDouble(Ask + (TakeProfit * Point), Digits); //stop = NormalizeDouble(Low[1] - spread - (OnePip * Point), Digits); //stop = NormalizeDouble(iLow(NULL, CatTimeFrame, 1) - spread - (OnePip * Point), Digits); type = OP_BUY; price = Ask; SendTrade = true; }//if (Bid > target) return; }//if (TradeLong) //Short if (TradeShort) { target = ObjectGet(sellline, OBJPROP_PRICE1); if (Bid < target) { //stop = NormalizeDouble(High[1] + spread + (OnePip * Point), Digits); //stop = NormalizeDouble(iHigh(NULL, CatTimeFrame, 1) + spread + (OnePip * Point), Digits); type = OP_SELL; price = Bid; SendTrade = true; }//if (Bid < target) }//if (TradeShort) if (SendTrade) { bool result = SendSingleTrade(type, CatTradeComment, SendLots, price, stop, take); }//if (SendTrade) //Actions when trade send succeeds if (SendTrade && result) { OpenTrades++; TradeOpen = true; CandleTraded = true; if (OpenTrades > 1) MoveCaterpillarStopToBreakeven();//Move the stop of the previously opened trade to be if (OpenTrades > 2) CaterpillarTrailingStop(OpenTrades - 1);//All trades from OpenTrades - 2 should move their stops 1 candle to the right //Set up a trend origin GV GlobalVariableSet(GvName, 0); TradeOrigin = trendorigin; //Redraw the trade line pipsgap = (OnePip * Point); if (OpenTrades > 0) pipsgap*= MinPipsBetweenCandles; if (type == OP_BUY) { ObjectDelete(buyline); target = NormalizeDouble(price + pipsgap + spread, Digits); ObjectCreate(buyline,OBJ_HLINE,0,TimeCurrent(), target); ObjectSet(buyline,OBJPROP_COLOR,BuyLineColour); ObjectSet(buyline,OBJPROP_STYLE,STYLE_SOLID); }//if (type == OP_BUY) if (type == OP_SELL) { ObjectDelete(sellline); target = NormalizeDouble(price - pipsgap - spread, Digits); ObjectCreate(sellline,OBJ_HLINE,0,TimeCurrent(), target); ObjectSet(sellline,OBJPROP_COLOR,SellLineColour); ObjectSet(sellline,OBJPROP_STYLE,STYLE_SOLID); }//if (type == OP_SELL) }//if (result) //Actions when trade send fails if (SendTrade && !result) { }//if (!result) }//void LookForCatTradingOpportunities() void StartCaterpillar() { //This function is the equivalent of start() in the independent Caterpillar EA. Please read BB's user guide //for details of how Cat works. static bool OldTradeOpen; //Delete orphan Caterpillar gv's if (OldH1Bars != iBars(NULL, PERIOD_H1) ) { OldH1Bars = iBars(NULL, PERIOD_H1); if (GlobalVariablesTotal() > 0) DeleteOrphanGlobals(); }//if (OldH1Bars != iBars(NULL, PERIOD_H1) ) //Trading if (OpenTrades < MaxTrades && !CandleTraded) { LookForCatTradingOpportunities(); }//if (OpenTrades < MaxTrades) /////////////////////////////////////////////////////////////////////////////////////////////// if (OldCatBars != iBars(NULL, CatTimeFrame)) { OldCatBars = iBars(NULL, CatTimeFrame); CandleTraded = false; //Move lines //Ensure a minimum gap in between trades double pipsgap = (OnePip * Point); if (OpenTrades > 0) pipsgap*= MinPipsBetweenCandles; double target; target = ObjectGet(buyline, OBJPROP_PRICE1); //if (TradeLong && NormalizeDouble(High[1] + pipsgap, Digits) > target) if (trend == up && TradeLong && NormalizeDouble(iHigh(NULL, CatTimeFrame, 1) + pipsgap, Digits) > target) { ObjectDelete(buyline); //target = NormalizeDouble(High[1] + pipsgap, Digits); if (UseHanover && !HanoverFilter(OP_BUY) ) return; target = NormalizeDouble(iHigh(NULL, CatTimeFrame, 1) + pipsgap, Digits); ObjectCreate(buyline,OBJ_HLINE,0,TimeCurrent(), target); ObjectSet(buyline,OBJPROP_COLOR,BuyLineColour); ObjectSet(buyline,OBJPROP_STYLE,STYLE_SOLID); if (OpenTrades > 1) CaterpillarTrailingStop(OpenTrades); }//if (TradeLong) target = ObjectGet(sellline, OBJPROP_PRICE1); if (trend == down && TradeShort && NormalizeDouble(iLow(NULL, CatTimeFrame, 1) - pipsgap, Digits) < target) { ObjectDelete(sellline); //target = NormalizeDouble(Low[1] - pipsgap, Digits); if (UseHanover && !HanoverFilter(OP_SELL) ) return; target = NormalizeDouble(iLow(NULL, CatTimeFrame, 1) - pipsgap, Digits); ObjectCreate(sellline,OBJ_HLINE,0,TimeCurrent(), target); ObjectSet(sellline,OBJPROP_COLOR,SellLineColour); ObjectSet(sellline,OBJPROP_STYLE,STYLE_SOLID); if (OpenTrades > 1) CaterpillarTrailingStop(OpenTrades); }//if (TradeShort && ObjectFind(sellline) == -1) }//if (OldCatBars != iBars(NULL, CatTimeFrame)) /////////////////////////////////////////////////////////////////////////////////////////////// }//End void StartCaterpillar() //END Caterp[illar module ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// //Carolco module void DeletePendings() { //Deletes pending grid trades after all filled trades have closed if (OrdersTotal() == 0) return; for (int cc = OrdersTotal() - 1; cc >= 0; cc--) { if (!OrderSelect(cc, SELECT_BY_POS) ) continue; if (OrderType() != OP_BUY && OrderType() != OP_SELL && OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber) { bool result = OrderDelete(OrderTicket() ); if (result) cc++; }//if (OrderType() != OP_BUY && OrderType() != OP_SELL && OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber) }//for (int cc = OrdersTotal() - 1; cc >= 0; cc--) }//End void DeletePendings() void SendGrid() { //Sends the carolco grid trades RefreshRates(); double take, stop, price; int type; bool result; int cc; double spread = MarketInfo(Symbol(), MODE_SPREAD) * Point; //Check filters if (!IsTradingAllowed() ) return; RefreshRates(); //Send market trades. //Long if (trend == up && TradeLong && TrendConfirmationCandleDir == up) { if (UseZeljko && !BalancedPair(OP_BUY) ) return; //First trade without tp and sl result = SendSingleTrade(OP_BUY, CarolcoTradeComment, Lot, NormalizeDouble(Ask, Digits), 0, 0); if (!result) return; Sleep(100); //Second trade with tp RefreshRates(); take = NormalizeDouble(Ask + (PipsBetweenTrades * Point), Digits); result = SendSingleTrade(OP_BUY, CarolcoTradeComment, Lot, NormalizeDouble(Ask, Digits), 0, take); if (result) { GlobalVariableSet(GvName, 0); TradeOrigin = trendorigin; }//if (result) }//if (trend == up && TradeLong) //Short if (trend == down && TradeShort && TrendConfirmationCandleDir == down) { if (UseZeljko && !BalancedPair(OP_SELL) ) return; //First trade without tp and sl result = SendSingleTrade(OP_SELL, CarolcoTradeComment, Lot, NormalizeDouble(Bid, Digits), 0, 0); if (!result) return; Sleep(100); //Second trade with tp RefreshRates(); take = NormalizeDouble(Bid - (PipsBetweenTrades * Point), Digits); result = SendSingleTrade(OP_SELL, CarolcoTradeComment, Lot, NormalizeDouble(Bid, Digits), 0, take); if (result) { GlobalVariableSet(GvName, 0); TradeOrigin = trendorigin; }//if (result) }//if (trend == dowb && TradeShort) //Send peding trade grid //Long double target; if (trend == up && TradeLong && TrendConfirmationCandleDir == up) { price = Ask; for (cc = 1; cc <= TradesInGrid; cc++) { price = NormalizeDouble(price + spread + (PipsBetweenTrades * Point), Digits); take = NormalizeDouble(price + (PipsBetweenTrades * Point), Digits); stop = 0; if (UseCarolcoStopLoss) stop = NormalizeDouble(price - (PipsBetweenTrades * Point), Digits); result = false; while (!result) { result = SendSingleTrade(OP_BUYSTOP, CarolcoTradeComment, CarolcoGridLot, price, stop, take); if (!result) Sleep(100); }//while (!result) Sleep(100); }//for (cc = 1; cc < TradesInGrid; cc++) }//if (TradeLong) //Short if (trend == down && TradeShort && TrendConfirmationCandleDir == down) { price = Bid; for (cc = 1; cc <= TradesInGrid; cc++) { price = NormalizeDouble(price - spread - (PipsBetweenTrades * Point), Digits); take = NormalizeDouble(price - (PipsBetweenTrades * Point), Digits); stop = 0; if (UseCarolcoStopLoss) stop = NormalizeDouble(price + (PipsBetweenTrades * Point), Digits); result = false; while (!result) { result = SendSingleTrade(OP_SELLSTOP, CarolcoTradeComment, CarolcoGridLot, price, stop, take); if (!result) Sleep(100); }//while (!result) Sleep(100); }//for (cc = 1; cc < TradesInGrid; cc++) }//if (TradeShort) }//End void SendGrid() void StartCarolco() { //Equates to start() in a stand-alone ea //Send initial trades if (NoOfPendingBuys == 0 && NoOfPendingSells == 0 && !BuyOpen && !SellOpen) { SendGrid(); }//if (NoOfPendingBuys == 0 && NoOfPendingSells == 0) //Delete pendings after all open trades have closed if (!BuyOpen && !SellOpen && (NoOfPendingBuys > 0 || NoOfPendingSells > 0) ) { DeletePendings(); }//if (!BuyOpen && !SellOpen && (NoOfPendingBuys > 0 || NoOfPendingSells > 0) ) }//void StartCarolco() //End Carolco module ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////// //Hanover module void SetUpArrays() { //Sets up all the arrays required by this program int cc; int Index = 0;//For searching InputString int LastIndex = 0;//Points the the most recent Index //TimeFrames InputString = TrendTimeFrames; CleanUpInputString(); TrendTimeFrames = InputString; NoOfTrendTimeFrames = CalculateParamsPassed(); string NewArray2 = ArrayResize(Tf, NoOfTrendTimeFrames); Index = 0;//For searching InputString LastIndex = 0;//Points the the most recent Index for (cc = 0; cc < NoOfTrendTimeFrames; cc ++) { Index = StringFind(InputString, ",",LastIndex); if (Index > -1) { Tf[cc] = StringSubstr(InputString, LastIndex,Index-LastIndex); Tf[cc] = StringTrimLeft(Tf[cc]); Tf[cc] = StringTrimRight(Tf[cc]); LastIndex = Index+1; }//if (Index > -1) }//for (cc = 0; cc < NoOfTrendTimeFrames; cc ++) //StrongWeak string NewArray3 = ArrayResize(StrongWeak, NoOfTrendTimeFrames); string NewArray4 = ArrayResize(StrongestCcy, NoOfTrendTimeFrames); string NewArray5 = ArrayResize(WeakestCcy, NoOfTrendTimeFrames); double NewArray6 = ArrayResize(StrongVal, NoOfTrendTimeFrames); double NewArray7 = ArrayResize(WeakVal, NoOfTrendTimeFrames); double NewArray8 = ArrayResize(PrevStrongVal, NoOfTrendTimeFrames); double NewArray9 = ArrayResize(PrevWeakVal, NoOfTrendTimeFrames); double NewArray10 = ArrayResize(ConstructedPair, NoOfTrendTimeFrames); }//End void SetUpArrays() int CalculateParamsPassed() { // Calculates the numbers of paramaters passed in LongMagicNumber and TradeComment. int Index = 0;//For searching NoTradePairs int LastIndex;//Points the the most recent Index int NoOfParams = 0; while(Index > -1) { Index = StringFind(InputString, ",",LastIndex); if (Index > -1) { NoOfParams++; LastIndex = Index+1; }//if (Index > -1) }//while(int cc > -1) return(NoOfParams); }//int CalculateParamsPassed() //+------------------------------------------------------------------+ string StringRight(string str, int n=1) //+------------------------------------------------------------------+ // Returns the rightmost N characters of STR, if N is positive // Usage: string x=StringRight("ABCDEFG",2) returns x = "FG" // // Returns all but the leftmost N characters of STR, if N is negative // Usage: string x=StringRight("ABCDEFG",-2) returns x = "CDEFG" { if (n > 0) return(StringSubstr(str,StringLen(str)-n,n)); if (n < 0) return(StringSubstr(str,-n,StringLen(str)-n)); return(""); } string StringUpper(string str) //+------------------------------------------------------------------+ // Converts any lowercase characters in a string to uppercase // Usage: string x=StringUpper("The Quick Brown Fox") returns x = "THE QUICK BROWN FOX" { string outstr = ""; string lower = "abcdefghijklmnopqrstuvwxyz"; string upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; for(int i=0; i<StringLen(str); i++) { int t1 = StringFind(lower,StringSubstr(str,i,1),0); if (t1 >=0) outstr = outstr + StringSubstr(upper,t1,1); else outstr = outstr + StringSubstr(str,i,1); } return(outstr); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ string StringTrim(string str) //+------------------------------------------------------------------+ // Removes all spaces (leading, traing embedded) from a string // Usage: string x=StringUpper("The Quick Brown Fox") returns x = "TheQuickBrownFox" { string outstr = ""; for(int i=0; i<StringLen(str); i++) { if (StringSubstr(str,i,1) != " ") outstr = outstr + StringSubstr(str,i,1); } return(outstr); } //+------------------------------------------------------------------+ int StrToStringArray(string str, string &a[], string delim=",", string init="") { //+------------------------------------------------------------------+ // Breaks down a single string into string array 'a' (elements delimited by 'delim') for (int i=0; i<ArraySize(a); i++) a[i] = init; int z1=-1, z2=0; if (StringRight(str,1) != delim) str = str + delim; for (i=0; i<ArraySize(a); i++) { z2 = StringFind(str,delim,z1+1); a[i] = StringSubstr(str,z1+1,z2-z1-1); if (z2 >= StringLen(str)-1) break; z1 = z2; } return(StringFindCount(str,delim)); } //+------------------------------------------------------------------+ int ArrayLookupString(string str, string a[]) { //+------------------------------------------------------------------+ for (int i=0; i<ArraySize(a); i++) { if (str == a[i]) return(i); } return(-1); } //+------------------------------------------------------------------+ double StrToNumber(string str) { //+------------------------------------------------------------------+ // Usage: strips all non-numeric characters out of a string, to return a numeric (double) value // valid numeric characters are digits 0,1,2,3,4,5,6,7,8,9, decimal point (.) and minus sign (-) int dp = -1; int sgn = 1; double num = 0.0; for (int i=0; i<StringLen(str); i++) { string s = StringSubstr(str,i,1); if (s == "-") sgn = -sgn; else if (s == ".") dp = 0; else if (s >= "0" && s <= "9") { if (dp >= 0) dp++; if (dp > 0) num = num + StrToInteger(s) / MathPow(10,dp); else num = num * 10 + StrToInteger(s); } } return(num*sgn); } int LoadRSvalues() { //This code courtesy of hanover. Many thanks David. You are a star. //Ccy[] holds the individual currency symbol //Tf[] holds the time frames //God knows where we go from here // Initialize array...... for (i=0; i<8; i++) for (j=0; j<9; j++) for (k=0; k<99; k++) RSvalue[i][j][k] = 0; // Read data from Recent Strength export file into RSvalue array....... h = FileOpen(OutputFile,FILE_CSV|FILE_READ,'~'); i=0; j=0; k=0; string prevtf = ""; while (!FileIsEnding(h)) { StrToStringArray(FileReadString(h),arr); if (FileIsEnding(h)) break; if (arr[1] == "TF ") { // get ccy IDs from header record for (i=0; i<8; i++) { ccy[i] = StringUpper(StringTrim(arr[i+3])); }//for (i=0; i<8; i++) continue; }//if (arr[1] == "TF ") string currtf = StringUpper(StringTrimRight(arr[1])); j = ArrayLookupString(currtf,tf); if (j<0) continue; // unknown timeframe - should never happen if (currtf != prevtf) // reset datapoint counter on change of timeframe k = 0; else k++; if (k>=99) continue; // max of 99 data points only for (i=0; i<8; i++) { // load array values for all currencies RSvalue[i][j][k] = StrToNumber(arr[i+3]); }//for (i=0; i<8; i++) prevtf = currtf; }//while (!FileIsEnding(h)) FileClose(h); return(0); }//End int LoadRSvalues() void ReadHanover() { //This function reads the output from the indi output file. LoadRSvalues(); /* Posted by hanover If we use RSvalue[i][j][k], then i = the currency j = the timeframe k = the datapoint#. Point #0 is rightmost point on the RS plot; point #1 is the second point from the right; point #2 is the third point from the right; and so on, up to the number of points being output (set by the NumPoints parameter in RS) Hence, supposing you want to retrieve the value of the third datapoint for USD,H1, then (using the constants defined earlier) you could use the code: double value = RSvalue[_USD][_H1][2]; */ //Find the strongest and weakest currency //Strongest double s, ps;//Strongest and previous strongest value double w, pw;//Weakest and previous weakest value //Currencies for (i = 0; i < ArraySize(StrongVal); i++) { StrongVal[i] = 0;//Initialize the strongest datapoint WeakVal[i] = 100000;//Initialize the weakest datapoint }//for (i = 0; i < ArraySize(StrongVal); i++) for (i = 0; i < ArraySize(ccy); i++) { //Timeframes for (j = 0; j < ArraySize(Tf); j++) { //Data point //Extract the timeframe - uses David's constants int DatapointTf; if (Tf[j] == "M1") DatapointTf = M1; if (Tf[j] == "M5") DatapointTf = M5; if (Tf[j] == "M15") DatapointTf = M15; if (Tf[j] == "M30") DatapointTf = M30; if (Tf[j] == "H1") DatapointTf = H1; if (Tf[j] == "H4") DatapointTf = H4; if (Tf[j] == "D1") DatapointTf = D1; if (Tf[j] == "W1") DatapointTf = W1; if (Tf[j] == "MN") DatapointTf = MN; for (k = 0; k < NumPoints; k++) { //Find the strongest datapoint on the current currency and timeframe if (RSvalue[i, DatapointTf, 0] > StrongVal[j]) { StrongestCcy[j] = ccy[i]; StrongVal[j] = RSvalue[i, DatapointTf, 0]; PrevStrongVal[j] = RSvalue[i, DatapointTf, TrendSlopeConfirmationCandles]; }//if (RSvalue[i, j, k] > StrongVal[cc]) //Find the seakest datapoint on the current currency and timeframe if (RSvalue[i, DatapointTf, 0] < WeakVal[j]) { WeakestCcy[j] = ccy[i]; WeakVal[j] = RSvalue[i, DatapointTf, 0]; PrevWeakVal[j] = RSvalue[i, DatapointTf, TrendSlopeConfirmationCandles]; }//if (RSvalue[i, j, k] > StrongVal[cc]) }//for (k = 0; k <= NumPoints; k++) }//for (j = 0; j < ArraySize(Tf); j++) }//for (i = 0; i < ArraySize(ccy); i++) //Alert("Strongest ", StrongestCcy[0], " ", StrongVal[0], " Weakest ", WeakestCcy[0], " ", WeakVal[0]); }//End void ReadHanover() double ReadStrength(string curr, string tf, int shift) { /* Returns the strength of the individual currency referenced by the parameters: - curr is the currency - tf is the time frame - shift is how far back in time to look */ //Extract the timeframe - uses David's constants int DatapointTf; if (tf == "M1") DatapointTf = M1; if (tf == "M5") DatapointTf = M5; if (tf == "M15") DatapointTf = M15; if (tf == "M30") DatapointTf = M30; if (tf == "H1") DatapointTf = H1; if (tf == "H4") DatapointTf = H4; if (tf == "D1") DatapointTf = D1; if (tf == "W1") DatapointTf = W1; if (tf == "MN") DatapointTf = MN; //Allign the curr param with David's constant int cc; if (curr == "AUD") cc = AUD; if (curr == "CAD") cc = CAD; if (curr == "CHF") cc = CHF; if (curr == "EUR") cc = EUR; if (curr == "GBP") cc = GBP; if (curr == "JPY") cc = JPY; if (curr == "NZD") cc = NZD; if (curr == "USD") cc = USD; return(RSvalue[cc, DatapointTf, shift]); }//End double ReadStrength(string curr, string tf, int shift) bool HanoverFilter(int type) { //Returns true if the filter indicates sufficient strength/weakness in the pair. //Works by running through the tests and returning false if any of them fail. If all pass, the eventually //returns true. //Tests all fail if the two currencies have equal strength values //Read the strength values for (int cc = 0; cc < ArraySize(Tf); cc++) { //First filter. Compare the strength over the chosen time frames double strength1 = ReadStrength(Ccy1, Tf[cc], 0); double strength2 = ReadStrength(Ccy2, Tf[cc], 0); if (TrendSlopeConfirmationCandles > 0) { double prevstrength1 = ReadStrength(Ccy1, Tf[cc], TrendSlopeConfirmationCandles); double prevstrength2 = ReadStrength(Ccy2, Tf[cc], TrendSlopeConfirmationCandles); }//if (SlopeCandles[cc] > 0) //EA is looking to buy. if (type == OP_BUY) { //First currency must be the strongest if (strength1 <= strength2) return(false); //Slope must be rising in the first curr and falling in the second if (TrendSlopeConfirmationCandles > 0) { if (prevstrength1 >= strength1) return(false); if (prevstrength2 <= strength2) return(false); }//if (TrendSlopeConfirmationCandles > 0 //Threshold. First currency must be above TrendStrongThreshold. Second currency must be below WeakThreshopld if (TrendStrongThreshold > 0 && TrendWeakThreshold > 0) { if (strength1 < TrendStrongThreshold || strength2 > TrendWeakThreshold) return(false); }//if (TrendStrongThreshold > 0 && TrendWeakThreshold > 0) }//if (type == OP_BUY) //EA is looking to sell, so first currency must be the weakest if (type == OP_SELL && strength1 >= strength2) return(false); //EA is looking to sell. if (type == OP_SELL) { //First currency must be the weakest if (strength1 >= strength2) return(false); //Slope must be falling in the first curr and rising in the second curr if (TrendSlopeConfirmationCandles > 0) { if (prevstrength1 <= strength1) return(false); if (prevstrength2 >= strength2) return(false); }//if (TrendSlopeConfirmationCandles > 0 //Threshold. First currency must be below TrendWeakThreshold. Second currency must be above StrongThreshopld if (TrendStrongThreshold > 0 && TrendWeakThreshold > 0) { if (strength1 > TrendWeakThreshold || strength2 < TrendStrongThreshold) return(false); }//if (TrendStrongThreshold > 0 && TrendWeakThreshold > 0) }//if (type == OP_SELL) }//for (int cc = 0; cc < ArraySize(Tf); cc++) //Got this far, so all tests have passed. return(true); }//End bool HanoverFilter() //End Hanover module //////////////////////////////////////////////////////////////////////////////////////////////// //+------------------------------------------------------------------+ //| expert start function | //+------------------------------------------------------------------+ int start() { //---- //A little bit of code to turn off functions that I do not want to remove yet in case we turn out to need them int x = 0; //Read a pair's volatility if (D1VolatilityBars != iBars(NULL, PERIOD_D1) ) { D1VolatilityBars = iBars(NULL, PERIOD_D1); Volatility = CalculateVolatility(PERIOD_D1, LookBackDays); CalculateReEntryLinePips();//Range trade Rocovery }//if (D1VolatilityBars != iBars(NULL, PERIOD_D1) //ReadIndicatorValues() contains the call to TrendDetectionModule() ReadIndicatorValues(); //Other stuff associated with trend trading if (trend != ranging) { GetTrendConfirmationCandleDir(); }//if (trend != ranging) static bool TradeExists = false; if (OrdersTotal() == 0) { TicketNo = -1; ForceTradeClosure = false; }//if (OrdersTotal() == 0) if (ForceTradeClosure) { CloseAllTrades(); return; }//if (ForceTradeClosure) if (trend == ranging) ReadIndicatorValues(); /////////////////////////////////////////////////////////////////////////////////////////////// //Find open trades. CountOpenTrades(); if (!BuyOpen && !SellOpen) { GlobalVariableDel(GvName);//Make sure there are no probs from this source TradeOrigin = none; OpenTrades = 0; }//if (!BuyOpen && !SellOpen) //Manage a single open trade's possible closure if (OpenTrades >= 1) { if (OrderSelect(TicketNo, SELECT_BY_TICKET) && OrderCloseTime() == 0) { if (TradeOrigin == trendorigin && !HedgingInProgress) LookForTradeClosure(); }//if (OrderSelect(TicketNo, SELECT_BY_TICKET) || OrderCloseTime() == 0) ) }//if (OpenTrades == 1) //Deal with hedged pair if (HedgingInProgress && BasketUpl >= HedgeProfitTarget) { CloseAllTrades(); return; }//if (HedgingInProgress && BasketUpl >=) //Tidying up if (OpenTrades == 0) { ObjectDelete(breakevenlinename); ObjectDelete(reentrylinename); }//if (OpenTrades == 0) if (x == 1) //Function turned off for now { TradeExists = DoesTradeExist(); if (TradeExists) { if (OrderProfit() > 0) TradeManagementModule(); LookForTradeClosure(); }//if (TradeExists) }//if (x == 1) //Function turned off for now /////////////////////////////////////////////////////////////////////////////////////////////// //Recovery if (UseRecovery && TradeOrigin == rangeorigin) { if (OpenTrades >= Start_Recovery_at_trades) RecoveryInProgress = true; //Replace accidentally deleted be line if (RecoveryInProgress && ObjectFind(breakevenlinename) == -1) { RecoveryModule(); }//if (RecoveryInProgress && ObjectFind(breakevenlinename) == -1) //Recovery trailing sl if (RecoveryInProgress && UseRecoveryTrailingStop) { RecoveryCandlesticktrailingStop(); }//if (RecoveryInProgress && UseRecoveryTrailingStop) }//if (UseRecovery) //Replace deleted reentry line if (RecoveryInProgress && ObjectFind(reentrylinename) == -1) { ReplaceReEntryLine(); }//if (RecoveryInProgress && ObjectFind(reentrylinename) == -1) ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// //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(); 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(); return; }//if (ml < FkMinimumMarginPercent) }//if (UseForexKiwi && AccountMargin() > 0) if (UseHanover) { //Read the indi once a minute if (ReadBars != iBars(NULL, PERIOD_M1) && UseHanover) { ReadBars = iBars(NULL, PERIOD_M1); ReadHanover(); }//if (ReadBars != iBars(NULL, PERIOD_M1) }//if (UseHanover) /////////////////////////////////////////////////////////////////////////////////////////////// //Trading. //Trend trading if (trend != ranging && AllowTrendTrading && Volatility >= MinimumTrendTradingVolatility) { if (!UseCaterpillar && !UseCarolco && !StopTrading && TicketNo == -1) LookForTrendTradingOpps(); if (UseCaterpillar && !StopTrading) StartCaterpillar(); if (UseCarolco && !StopTrading) StartCarolco(); }//if (trend != ranging && AllowTrendTrading && Volatility <= MaximumRangeTradingVolatility) //Fix for carolco initial trade closing and leaving behind pending trades when the hi-lo of the D1 candle has //moved into Ranging if (trend == ranging && UseCarolco) { if (!BuyOpen && !SellOpen && (NoOfPendingBuys > 0 || NoOfPendingSells > 0) ) { DeletePendings(); }//if (!BuyOpen && !SellOpen && (NoOfPendingBuys > 0 || NoOfPendingSells > 0) ) }//if (trend == ranging && UseCarolco) if (TradeEveryTick) OldRangeTradingBars = 0;//Look for trades every tick, not every candle //Range trading opps need checking even though there may a trade already open, else the open trade never gets closed if (trend == ranging && AllowRangeTrading && OldRangeTradingBars != iBars(NULL, RangeTradingTF) && Volatility <= MaximumRangeTradingVolatility) { OldRangeTradingBars = iBars(NULL, RangeTradingTF); LookForRangeTradingOpps(); }//if (trend == ranging && AllowRangeTrading && OldRangeTradingBars != iBars(NULL, RangeTradingTF)) /////////////////////////////////////////////////////////////////////////////////////////////// DisplayUserFeedback(); //---- return(0); } //+------------------------------------------------------------------+
Комментарии к исходному коду форекс советника BigBob.mq4
В целях безопасности и борьбы со спамом в тексте комментариев запрещено размещать html-теги и ссылки. Благодарим за понимание.