//+------------------------------------------------------------------+ //| Multi-purpose trade manager.mq4 | //| Copyright © 2008, Steve Hopwood | //| http://www.hopwood3.freeserve.co.uk | //+------------------------------------------------------------------+ #property copyright "Copyright © 2008, Steve Hopwood" #property link "http://www.hopwood3.freeserve.co.uk" #include #include #define NL "\n" /* The Start function calls the MonitorTrades function. This cycles through the list of open orders, checking to see which management style the user has chosen - by ticket number, magic number, comment or all trades, regardelss of anything else etc. If an appropriate management style choice is found, the ManageTrade function is called. This in turn calls functions that checks for action depending on the choice of facilities - breakeven, jumping stop etc. The ea offers the option to close 50% of a profitable trade at a target set by the user (PartCloseOrder). It offers a hedge-trade facility for when a trade starts to go wrong. Start then calls GlobalOrderClosure. If enabled, this routine closes all open orders at a $profit or % of account balance. Start then calls ShirtProtection, a routine that closes all open trades at a upl loss point chosen by the user. "Losing your shirt" is a slang expression to describe losing everything - money, home etc. Start then call MonitorBasketTrades, a routine that calls all the funtions required to monitor trading basketes from systems such as T101 and ES. The order of program run is: Start calls MonitorTrades (calls ManageTrade that calls all the functions that actually do the work) then GlobalOrderClosure, then ShirtProtection, then MonitorBasketTrades. Functions list: int start() void MonitorTrades() void ManageTrade() void ShirtProtection() void BreakEvenStopLoss() void JumpingStopLoss() bool CheckForHiddenStopLossHit(int type, int iPipsAboveVisual, double stop ) bool PartCloseTradeFunction() void TryPartCloseAgain() void SetAGlobalTicketVariable() int GetNextAvailableVariableNumber() void TrailingStopLoss() void InstantTrailingStopLoss() void HiLoTrailingStopLoss() added by Robert double ValidStopLoss() added by Robert void HiddenStopLoss() void HiddenTakeProfit() void GlobalOrderClosure() bool ExtractPartCloseVariables() void PartCloseOrder() bool CheckForExistingHedge() void HedgeTrade() void DeleteOrphanHedgeGVs() void DetermineTrendDirection(string symbol) void MonitorBasketTrades() void CloseBasketTrades() void CalculateBasketPL() bool ShouldBasketCloseAtSL() void BasketTrailingStopManipulation() bool ConfirmBasketClosure() double getPipValue(double ord,int dir) void checkStops(int pips,int ticket) void moveStops(int ticket,int stopDiff) void takeProfit(int pips, int ticket) void CheckBasketTradesExpiry() void BasketJumpingStopManipulation() bool ShouldBasketCloseAtAutocalcTP() double AutoPercentageBasketTp() void InsertStopLoss() void InsertTakeProfit() void TightenStopLoss() */ // Added by Robert for those who do not want the comments. extern bool ShowComments = true; // Added by Robert for those who do not want the journal messages. extern bool PrintToJournal = true; // User can choose a variety of trade managment triggers. // These are for use on a chart that controls the currency of that chart extern string ManagementStyle="You can select more than one option"; extern bool ManageByMagicNumber=false; extern int MagicNumber=274693; extern bool ManageByTradeComment=false; extern string TradeComment = "Fib"; extern bool ManageByTickeNumber=false; extern int TicketNumber; extern string OverRide="ManageThisPairOnly will override all previous"; extern string OverRide2="or can be used in combination with 1 of above"; extern bool ManageThisPairOnly=false; extern bool ManageSpecifiedPairs=false;//############## ADDED BY CACUS extern string PairsToManage="AUDJPY,AUDUSD,CHFJPY,EURCHF,EURGBP,EURJPY,EURUSD,GBPCHF,GBPJPY,GBPUSD,NZDJPY,NZDUSD,USDCHF,USDJPY";//############## ADDED BY CACUS // This allows the ea to manage all existing trades extern string OverRide1="ManageAllTrades will override all others"; extern bool ManageAllTrades=false; // Now give user a variety of facilities extern string bl1="---------------------------------------------------------------------"; extern string ManagementFacilities="Select the management facilities you want"; extern string slf="----Stop Loss & Take Profit Manipulation----"; extern bool DoNotOverload5DigitCriminals=true; extern string BE="Break even settings"; extern bool BreakEven=false; extern int BreakEvenPips=30; extern int BreakEvenProfit=2; extern bool HideBreakEvenStop=false; extern int PipsAwayFromVisualBE=100; extern string JSL="Jumping stop loss settings"; extern bool JumpingStop=false; extern int JumpingStopPips=300; extern bool AddBEP=false; extern bool JumpAfterBreakevenOnly=false; extern bool HideJumpingStop=false; extern int PipsAwayFromVisualJS=100; extern string pcbe="PartClose settings can be used in"; extern string pcbe1="conjunction with Breakeven settings"; extern bool PartCloseEnabled=false; extern double Close_Lots = 0.02; extern double Preserve_Lots=0.02; extern string TSL="Trailing stop loss settings"; extern bool TrailingStop=false; extern int TrailingStopPips=500; extern bool HideTrailingStop=false; extern int PipsAwayFromVisualTS=100; extern bool TrailAfterBreakevenOnly=false; extern bool StopTrailAtPipsProfit=false; extern int StopTrailPips=0; extern string ITSL="Instant trailing stop loss settings"; extern bool InstantTrailingStop=false; extern int InstantTrailingStopPips=30; extern int FiveDigitIncrement=0; extern bool StopInstantTrailAfterBreakEven=false; extern bool StopInstantTrailAtPipsProfit=false; extern int StopInstantTrailPips=0; // Added by Robert Hill extern string HLTSL="HiLo trailing stop loss settings"; extern bool HiLoTrailingStop=false; extern bool HiLoTrailAfterBreakevenOnly=false; extern int HiLoBarsBack=5; extern string hsl1="Hidden stop loss settings"; extern bool HideStopLossEnabled=false; extern int HiddenStopLossPips=200; extern string TSF="Tightening stop feature"; extern bool UseTigheningStop=false; extern int TrailAt50Percent=300; extern int TrailAt80Percent=200; extern string MSLA="Add a missing Stop Loss"; extern bool AddMissingStopLoss=false; extern int MissingStopLossPips=200; extern string MTPA="Add a missing Take Profit"; extern bool AddMissingTakeProfit=false; extern int MissingTakeProfitPips=200; extern string htp="Hidden take profit settings"; extern bool HideTakeProfitEnabled=false; extern int HiddenTakeProfitPips=200; extern string bl2="---------------------------------------------------------------------"; extern string GOC="----Global order closure settings----"; extern bool GlobalOrderClosureEnabled=false; extern bool IncludePendingOrdersInClosure=false; extern bool ProfitInDollars=false; extern double DollarProfit=100000; extern bool ProfitAsPercentageOfBalance=false; extern double PercentageProfit=10000; extern string bl9="---------------------------------------------------------------------"; extern string bin1="----Basket trade settings----"; extern string bin2="Set ManageByMagicNumber or"; extern string bin3="ManageByTradeComment to true"; extern string bin4=" to use these features"; extern bool ManageBasketTrades=false; extern string bin5="Basket take profit settings"; extern bool BasketClosureTP=false; extern bool BasketTPinDollars=false; extern double BasketDollarTP=100000; extern bool BasketTPasPercent=false; extern double BasketTpPercentage=1; extern bool AutoCalcBasketTPasPercent=false; extern double FourToSevenTradesPercent=1; extern double EightToTwelveTradesPercent=2; extern double ThirteenPlusTradesPercent=3; extern string bin6="Basket stop loss settings"; extern bool BasketClosureSL=false; extern bool BasketSLinDollars=false; extern double BasketDollarSL=100000; extern bool BasketSLasPercent=false; extern double BasketSLPercentage=1; extern string bin13="Basket jumping stop settings"; extern bool BasketJumpingStop=false; extern double BasketJumpingStopProfit=1; extern bool BasketAddBEP=false; extern double BasketBreakEvenProfit=0.1; extern bool DisableBasketJumpStopAfterBE=false; extern string bin7="Basket trailing stop settings"; extern bool BasketTrailingStop=false; extern double BasketTsAtProfit=1; extern double BasketTrailPercent=75; extern string bin8="Immediate basket closure setting. Use with care"; extern bool BasketCloseImmediately=false; extern string bin9="Trade expiry settings"; extern bool TradesWillExpire=false; extern int TradesWillExpireMins=210; extern string bl3="---------------------------------------------------------------------"; extern string hs="----Hedge settings----"; extern bool HedgeEnabled=false; extern int HedgeAtLossPips=0; extern double HedgeLotsPercent=50; extern int HedgingIncrementPips=0; extern int HedgeTradeStopLoss=0; extern int HedgeTradeTakeProfit=0; extern bool CloseAtBreakEven=false; extern bool HedgingTheHedgeIsAllowed=false; extern string Ins14="Trend filter choices"; extern bool UseEnvelopeTrendFilter=false; extern int LookBackBars=3; extern bool UseAdxTrendFilter=false; extern int AdxPeriod=14; extern bool UseCandleDirection=false; extern int LookBackCandleHours = 3; extern string bl5="---------------------------------------------------------------------"; extern string sps="----Shirt-protection settings----"; extern string spsi="Close all open trades at this $ loss"; extern bool ShirtProtectionEnabled=false; extern double MaxLoss=-10000000; extern bool IncludePendingInClosure=false; extern string bl6="---------------------------------------------------------------------"; extern string OtherStuff="----Other stuff----"; extern bool ShowAlerts=true; double LockedProfit=-1; int cnt=0; //loop counter double bid, ask; // For storing the Bid\Ask so that one instance of the ea can manage all trades, if required double point, digits; // Saves the Point and Digits of an order // Variables for part-close reoutine double TargetAsPrice, TargetAsPips; bool TrendUp=true; bool TrendDown=true; bool CloseBasket=false; string ScreenMessage; double BasketProfit; bool sl; int nextTP; string TicketName = "GlobalVariableTicketNo";// For storing ticket numbers in global vars for picking up failed part-closes bool GlobalVariablesExist=false; int NoOfBasketTrades;//Holds the no of basket trades open. Set in CalculateBasketPL() int TrailingStopPipsStore;//Saves the trailing stop pips setting in int init() int OldHourlyBars;//Used to tell the manager it is a new day and prompt it to go looking for orphaned hedge gv's //############## ADDED BY CACUS string String; int PairsQty; string suffix; string ManagePair[20]; //############## ADDED BY CACUS //############## ADDED BY CACUS int PairsQty() { int i = 0; int j; int qty=0; while(i > -1) { i = StringFind(String, ",",j); if (i > -1) { qty ++; j = i+1; } } return(qty); } //############## ADDED BY CACUS //+------------------------------------------------------------------+ //| expert initialization function | //+------------------------------------------------------------------+ int init() { //---- //############## ADDED BY CACUS String=PairsToManage; if (StringSubstr(String, StringLen(String)-1) != ",") String = StringConcatenate(String,","); //############## ADDED BY CACUS TrailingStopPipsStore=TrailingStopPips; //Make sure the basket sl is a negativ number if (BasketDollarSL > 0) BasketDollarSL = -BasketDollarSL; return(0); } //+------------------------------------------------------------------+ //| expert deinitialization function | //+------------------------------------------------------------------+ int deinit() { //---- Comment(""); return(0); } //+------------------------------------------------------------------+ //| expert start function | //+------------------------------------------------------------------+ int start() { //---- //############## ADDED BY CACUS suffix = StringSubstr(Symbol(),6,4); int qty=PairsQty(); int i = 0;int j = 0; for (int k = 0; k < qty; k ++) { i = StringFind(String, ",",j); if (i > -1) { ManagePair[k] = StringSubstr(String, j,i-j); ManagePair[k] = StringTrimLeft(ManagePair[k]); ManagePair[k] = StringTrimRight(ManagePair[k]); ManagePair[k] = StringConcatenate(ManagePair[k], suffix); j = i+1; } } /*Print("PairsQty: ",qty); // Just to check.... for (int s=1;s<=qty;s++){ Print("Pair ",s,": ", ManagePair[s-1]); } */ //############## ADDED BY CACUS //At the start of each new hour, delete orphaned hedge global variables if (OldHourlyBars != iBars(Symbol(), PERIOD_H1) ) { if (GlobalVariablesTotal() > 0) DeleteOrphanHedgeGVs(); OldHourlyBars = iBars(Symbol(), PERIOD_D1); }//if (OldHourlyBars != iBars(Symbol(), PERIOD_H1) ) // Stop if there is nothing to do if (OrdersTotal()==0) { if (ShowComments) Comment("No trades to manage. I am bored witless."); return(0); } MonitorTrades(); // Stop loss adjusting, part closure etc if (GlobalOrderClosureEnabled) GlobalOrderClosure(); // Whole position closing at set profit level // Account protection in event of catastrophe if (ShirtProtectionEnabled) ShirtProtection(); // Basket trading if (ManageBasketTrades) MonitorBasketTrades(); //---- return(0); } //+------------------------------------------------------------------+ void MonitorTrades() { bool ManageTrade; // tell the program when there is a trade to manage string ScreenMessage; for (cnt=OrdersTotal() - 1; cnt >= 0; cnt--) { if (OrderSelect(cnt, SELECT_BY_POS) ) { ManageTrade=false; ScreenMessage = "Managing by: "; // Set up bid and ask so the program can use them to calculate jumping stops, be's etc bid = MarketInfo(OrderSymbol(), MODE_BID); ask = MarketInfo(OrderSymbol(), MODE_ASK); point = MarketInfo(OrderSymbol(), MODE_POINT); digits = MarketInfo(OrderSymbol(), MODE_DIGITS); // Test whether this individual trade needs managing // MagicNumber if (ManageByMagicNumber && OrderMagicNumber()==MagicNumber) { ManageTrade=true; ScreenMessage=StringConcatenate(ScreenMessage, "Magic Number=", MagicNumber,"; "); } if (ManageByMagicNumber && !OrderMagicNumber()==MagicNumber) { ScreenMessage=StringConcatenate(ScreenMessage, "Magic Number=", MagicNumber,"; "); } // TradeComment if (ManageByTradeComment && OrderComment()==TradeComment) { ManageTrade=true; ScreenMessage=StringConcatenate(ScreenMessage, "Trade Comment=",TradeComment,"; "); } if (ManageByTradeComment && !OrderComment()==TradeComment) { ScreenMessage=StringConcatenate(ScreenMessage, "Trade Comment=",TradeComment,"; "); } // ManageByTickeNumber if (ManageByTickeNumber && OrderTicket()==TicketNumber) { ManageTrade=true; ScreenMessage=StringConcatenate(ScreenMessage, "Ticket Number=", TicketNumber, "; "); } if (ManageByTickeNumber && !OrderTicket()==TicketNumber) { ScreenMessage=StringConcatenate(ScreenMessage, "Ticket Number=", TicketNumber, "; "); } if (ManageThisPairOnly && OrderSymbol()==Symbol()) { ManageTrade=true; ScreenMessage="Managing this pair only"; } if (ManageThisPairOnly && !OrderSymbol()==Symbol()) { ManageTrade=false; ScreenMessage="Managing this pair only"; } //############## ADDED BY CACUS if (ManageSpecifiedPairs) { for (int d=0;d