/*-----------------------------+ | | | Shared by www.Aptrafx.com | | | +------------------------------*/ //+------------------------------------------------------------------+ //| Utils.mq4 | //| Copyright © 2006, Paul Hampton-Smith | //| | //+------------------------------------------------------------------+ #property copyright "Copyright © 2006, Paul Hampton-Smith" #property link "" #property library // Store this file in experts\libraries and compile // Needs utils.mqh in experts\include // Incorporate into EA's with command #include <utls.mqh> #include <stdlib.mqh> int nRetries = 5; int nRetryDelay = 1000; bool NewBar() { static int lastBars; if (lastBars != Bars) { lastBars = Bars; return(true); } else { return(false); } } int OpenOrders(int nSystemID = 0) { int nCount = 0; for ( int nPosition=0 ; nPosition<OrdersTotal() ; nPosition++ ) { OrderSelect(nPosition, SELECT_BY_POS, MODE_TRADES); if ( OrderSymbol()==Symbol() && // same symbol ( OrderType() == OP_BUY || OrderType() == OP_SELL ) && (OrderMagicNumber() == nSystemID || nSystemID == 0) ) // same system { nCount++; } } return(nCount); } int OpenStopOrders(int nSystemID = 0) { int nCount = 0; for ( int nPosition=0 ; nPosition<OrdersTotal() ; nPosition++ ) { OrderSelect(nPosition, SELECT_BY_POS, MODE_TRADES); if ( OrderSymbol()==Symbol() && // same symbol ( OrderType() == OP_BUYSTOP || OrderType() == OP_SELLSTOP ) && (OrderMagicNumber() == nSystemID || nSystemID == 0) ) // same system { nCount++; } } return(nCount); } void DeleteStopOrders(int nSystemID = 0) { // note the shift of nPosition++ to lower in the for loop because it is not needed if an order has been deleted for ( int nPosition=0 ; nPosition<OrdersTotal() ; ) { OrderSelect(nPosition, SELECT_BY_POS, MODE_TRADES); if ( OrderSymbol()==Symbol() && // same symbol ( OrderType() == OP_BUYSTOP || OrderType() == OP_SELLSTOP ) && (OrderMagicNumber() == nSystemID || nSystemID == 0) ) // same system { SecureOrderDelete(OrderTicket()); } else { nPosition++; } } } int FindOrder(int cmd, int nSystemID) { for ( int nPosition=0 ; nPosition<OrdersTotal() ; nPosition++ ) { OrderSelect(nPosition, SELECT_BY_POS, MODE_TRADES); if ( OrderSymbol()==Symbol() && // same symbol ( OrderType() == cmd) && OrderMagicNumber() == nSystemID) // same system { return(OrderTicket()); } } } string DayOfWeekToString(int nDayOfWeek) { switch(nDayOfWeek) { case 0: return("Sunday"); case 1: return("Monday"); case 2: return("Tuesday"); case 3: return("Wednesday"); case 4: return("Thursday"); case 5: return("Friday"); case 6: return("Saturday"); default: Alert("Invalid day of week ",nDayOfWeek," in function DayOfWeekToString"); } return(""); } double ATRTrailingStop(int nOrderType, int nATRlen, double dblATRmult) { double dblATR = iATR(OrderSymbol(),0,nATRlen,0); double dblStop, dblTightestStop; switch(nOrderType) { case OP_BUY: dblStop = Bid - dblATRmult * dblATR; // can't be any closer than tightest stop allowed on the market dblTightestStop = Bid - MarketInfo(Symbol(),MODE_STOPLEVEL) * Point; if ( dblStop > dblTightestStop ) dblStop = dblTightestStop; break; case OP_SELL: dblStop = Ask + dblATRmult * dblATR; // can't be any closer than tightest stop allowed on the market dblTightestStop = Ask + MarketInfo(Symbol(),MODE_STOPLEVEL) * Point; if ( dblStop < dblTightestStop ) dblStop = dblTightestStop; break; default: Alert("Invalid nOrdertype ",nOrderType," in function ATRTrailingStop"); } return(dblStop); } double MEMATrailingStop(int nOrderType, int nATRlen, double dblATRmult, double dblAccel) { double dblATR = iATR(OrderSymbol(),0,nATRlen,0); double dblStopLoss = OrderStopLoss(); double dblNewStopLoss, dblTightestStop; double tmp; switch(nOrderType) { case OP_BUY: // can't be any closer than tightest stop allowed on the market dblTightestStop = Bid - MarketInfo(Symbol(),MODE_STOPLEVEL) * Point; tmp = High[0] - dblATRmult*dblATR - dblStopLoss; if (tmp > 0.0) { dblNewStopLoss = dblStopLoss + dblAccel*tmp; } if ( dblNewStopLoss > dblTightestStop ) dblNewStopLoss = dblTightestStop; break; case OP_SELL: // can't be any closer than tightest stop allowed on the market dblTightestStop = Ask + MarketInfo(Symbol(),MODE_STOPLEVEL) * Point; tmp = Low[0] + dblATRmult*dblATR - dblStopLoss; if (tmp < 0.0) { dblNewStopLoss = dblStopLoss + dblAccel*tmp; } if ( dblNewStopLoss < dblTightestStop ) dblNewStopLoss = dblTightestStop; break; default: Alert("Invalid nOrdertype ",nOrderType," in function ATRTrailingStop"); } return(dblNewStopLoss); } int CompletedOrdersSince(datetime dt, int nSystemID) { int nCount = 0; for ( int nPosition=0 ; nPosition<HistoryTotal() ; nPosition++ ) { OrderSelect(nPosition, SELECT_BY_POS, MODE_HISTORY); if ( OrderSymbol()==Symbol() && // same symbol OrderMagicNumber() == nSystemID && // same system ( OrderType() == OP_BUY || OrderType() == OP_SELL ) && OrderCloseTime() >= dt) { nCount++; } } return(nCount); } string TimeString(int hour, int minute) { // used to create "05" instead of "5" if (minute<0 || minute>59 || hour<0 || hour>23) Alert("Incorrect parameters ",hour,":",minute," in TimeString"); string strHourPad; if (hour >= 0 && hour <= 9) strHourPad = "0"; else strHourPad = ""; string strMinutePad; if (minute >= 0 && minute <= 9) strMinutePad = "0"; else strMinutePad = ""; return(StringConcatenate(strHourPad,hour,":",strMinutePad,minute)); } double LastClosedOrderProfit(int nOrderType, int nSystemID) { int nCount = 0; for ( int nPosition=HistoryTotal() ; nPosition>=0 ; nPosition-- ) { OrderSelect(nPosition, SELECT_BY_POS, MODE_HISTORY); if ( OrderSymbol()==Symbol() && // same symbol OrderMagicNumber() == nSystemID && // same system ( OrderType() == OP_BUY || OrderType() == OP_SELL ) ) { return(OrderProfit()); } } return(0.0); } double HighLowTrailingStop(bool bLong, int nLookBack) { double dblStop, dblTightestStop; if (bLong) { // Lowest low, minus one point to stay away from support lines dblStop = Low[ Lowest(OrderSymbol(),0,MODE_LOW,nLookBack) ] - Point; // can't be any closer than tightest stop dblTightestStop = Bid - MarketInfo(Symbol(),MODE_STOPLEVEL) * Point; if ( dblStop > dblTightestStop ) dblStop = dblTightestStop; } else { // short // Highest high, plus one point to stay away from support lines dblStop = High[ Highest(OrderSymbol(),0,MODE_HIGH,nLookBack) ] + Point; // can't be any closer than tightest stop dblTightestStop = Ask + MarketInfo(Symbol(),MODE_STOPLEVEL) * Point; if ( dblStop < dblTightestStop ) dblStop = dblTightestStop; } return(dblStop); } void CloseAllAtEndOfWeek(int nSystemID = 0) { // exit all if time is 17:00 UTC Fridays if ( !(TimeDayOfWeek(Time[0]) == 5 && TimeHour(Time[0]) == 17) ) return; for ( int nPosition=0 ; nPosition<OrdersTotal() ; ) { OrderSelect(nPosition, SELECT_BY_POS, MODE_TRADES); if ( OrderSymbol()==Symbol() && // same symbol (OrderMagicNumber() == nSystemID || nSystemID == 0) && // same system ( OrderType() == OP_BUY || OrderType() == OP_SELL ) ) { Print("End of week close ", TimeToStr(Time[0])); switch(OrderType()) { case OP_BUY: OrderClose(OrderTicket(), OrderLots(), Bid, 0, Purple); return; case OP_SELL: OrderClose(OrderTicket(), OrderLots(), Ask, 0, Purple); return; case OP_BUYSTOP: OrderDelete(OrderTicket()); return; case OP_SELLSTOP: OrderDelete(OrderTicket()); return; } // switch } else { nPosition++; } } } datetime WeeklyExpirationTime(int nExitDay, int nExitHour, int nExitMinute) { datetime dtNow = CurTime(); datetime dtMidnightToday = (dtNow/86400)*86400; int nDaysToExit = nExitDay - TimeDayOfWeek(dtNow); datetime dtExitTime = dtMidnightToday + nDaysToExit*86400 + nExitHour*3600 + nExitMinute*60; return(dtExitTime); } void AdjustTrailingStops(int nTrailingStop, int nSystemID = 0) { for ( int nPosition=0 ; nPosition<OrdersTotal() ; nPosition++ ) { OrderSelect(nPosition, SELECT_BY_POS, MODE_TRADES); if ( OrderSymbol()==Symbol() && (OrderMagicNumber() == 0 || OrderMagicNumber() == nSystemID) ) // same symbol and system { switch(OrderType()) { case OP_BUY: // adjust long trailing stop up if possible if (Bid - nTrailingStop*Point > OrderStopLoss() ) { OrderModify(OrderTicket(),OrderOpenPrice(),Ask - nTrailingStop*Point,OrderTakeProfit(),0,Green); } break; case OP_SELL: // adjust short trailing stop down if possible if (Ask + nTrailingStop*Point < OrderStopLoss() || OrderStopLoss() == 0.0 ) { OrderModify(OrderTicket(),OrderOpenPrice(),Bid + nTrailingStop*Point,OrderTakeProfit(),0,Red); } } // switch } } } bool OrderOfTypeExists(int nOrderType, int nSystemID = 0) { for ( int nPosition=0 ; nPosition<OrdersTotal() ; nPosition++ ) { OrderSelect(nPosition, SELECT_BY_POS, MODE_TRADES); if ( OrderSymbol()==Symbol() && (OrderMagicNumber() == 0 || OrderMagicNumber() == nSystemID) && OrderType() == nOrderType ) // same symbol, system & type { return(true); } } } datetime ServerTime(datetime UTC) { // Uses global variable UTCtoServerTimeInMinutes to convert UTC to server time. // this enables different instances of MT4 using different brokers to // run EAs with idential time settings if (!GlobalVariableCheck("UTCtoServerTimeInMinutes")) { Alert("Please set global variable UTCtoServerTimeInMinutes"); return(0); } return(UTC+60*GlobalVariableGet("UTCtoServerTimeInMinutes")); } void CloseOrdersAfterDuration(int nSeconds, int nSystemID = 0) { for ( int nPosition=0 ; nPosition<OrdersTotal() ; ) { OrderSelect(nPosition, SELECT_BY_POS, MODE_TRADES); if ( OrderSymbol()==Symbol() && (OrderMagicNumber() == nSystemID || nSystemID == 0) && Time[0] > OrderOpenTime() + nSeconds) { switch (OrderType()) { case OP_BUY: SecureOrderClose(OrderTicket(), OrderLots(), Bid, 5, Purple); break; case OP_SELL: SecureOrderClose(OrderTicket(), OrderLots(), Ask, 5, Purple); break; } } else { nPosition++; } } } void CloseOrdersAtTime(datetime dt, int nSystemID = 0) { // note the shift of nPosition++ to lower in the for loop because it is not needed if an order has been closed for ( int nPosition=0 ; nPosition<OrdersTotal() ; ) { OrderSelect(nPosition, SELECT_BY_POS, MODE_TRADES); if ( OrderSymbol()==Symbol() && (OrderMagicNumber() == nSystemID || nSystemID == 0) && CurTime() > dt) { switch (OrderType()) { case OP_BUY: SecureOrderClose(OrderTicket(), OrderLots(), Bid, 5, Purple); break; case OP_SELL: SecureOrderClose(OrderTicket(), OrderLots(), Ask, 5, Purple); break; } } else { nPosition++; } } } void DeleteStopOrdersAtTime(datetime dt, int nSystemID = 0) { // note the shift of nPosition++ to lower in the for loop because it is not needed if an order has been deleted for ( int nPosition=0 ; nPosition<OrdersTotal() ; ) { SecureOrderSelect(nPosition, SELECT_BY_POS); if ( OrderSymbol()==Symbol() && (OrderMagicNumber() == nSystemID || nSystemID == 0) && CurTime() > dt && (OrderType() == OP_BUYSTOP || OrderType() == OP_SELLSTOP)) { SecureOrderDelete(OrderTicket()); } else { nPosition++; } } } int SecureOrderSend( string symbol, int cmd, double volume, double price, int slippage, double stoploss, double takeprofit, string comment, int magic=0, datetime expiration=0, color arrow_color=CLR_NONE) { if (cmd == OP_SELL || cmd == OP_SELLLIMIT || cmd == OP_BUY || cmd == OP_BUYLIMIT) { Alert(CmdToStr(cmd)," not implemented yet in SecureOrderSend"); return(-1); } for (int nTry = 0 ; nTry < nRetries ; nTry++) { double dblMinStopDistance = MarketInfo(Symbol(),MODE_STOPLEVEL)*Point; if (cmd == OP_BUYSTOP) { price = MathMax(Ask+dblMinStopDistance+Point,price); if (stoploss == 0) stoploss = price-dblMinStopDistance-Point; else stoploss = MathMin(price-dblMinStopDistance-Point, stoploss); } else if (cmd == OP_SELLSTOP) { if (price == 0) price = Bid-dblMinStopDistance-Point; else price = MathMin(Bid-dblMinStopDistance-Point,price); stoploss = MathMax(price+dblMinStopDistance+Point, stoploss); } price = NormalizeDouble(price,Digits); stoploss = NormalizeDouble(stoploss,Digits); takeprofit = NormalizeDouble(takeprofit,Digits); int nTicket = OrderSend( symbol, cmd, volume, price, slippage, stoploss, takeprofit, comment, magic, expiration, arrow_color); int nLastError = GetLastError(); Print(ErrorDescription(nLastError)," for SecureOrderSend(",CmdToStr(cmd),"): Ask ",Ask," Bid ",Bid," MinStop ",dblMinStopDistance," price ", price," stoploss ",stoploss," takeprofit ", takeprofit); if (nLastError == 0) return(nTicket); Sleep(nRetryDelay); } return(-1); } bool SecureOrderClose( int ticket, double lots, double price, int slippage, color Color=CLR_NONE) { for (int nTry = 0 ; nTry < nRetries ; nTry++) { OrderClose(ticket, lots, price, slippage, Color); int nLastError = GetLastError(); Print(ErrorDescription(nLastError)," for SecureOrderClose. price ",price); if (nLastError == 0) return(true); Sleep(nRetryDelay); } return(false); } bool SecureOrderDelete(int ticket) { for (int nTry = 0 ; nTry < nRetries ; nTry++) { OrderDelete(ticket); int nLastError = GetLastError(); Print(ErrorDescription(nLastError)," for SecureOrderDelete"); if (nLastError == 0) return(true); Sleep(nRetryDelay); } return(false); } bool SecureOrderSelect( int index, int select, int pool=MODE_TRADES) { for (int nTry = 0 ; nTry < nRetries ; nTry++) { OrderSelect( index, select, pool); int nLastError = GetLastError(); if (nLastError == 0 && OrderTicket() != 0) return(true); else Print(ErrorDescription(nLastError)," for SecureOrderSelect"); } return(false); } string CmdToStr(int cmd) { switch(cmd) { case OP_BUY: return("OP_BUY"); case OP_SELL: return("OP_SELL"); case OP_BUYSTOP: return("OP_BUYSTOP"); case OP_SELLSTOP: return("OP_SELLSTOP"); case OP_BUYLIMIT: return("OP_BUYLIMIT"); case OP_SELLLIMIT: return("OP_SELLLIMIT"); default: return("OP_UNKNOWN"); } } double ClosestStopLoss(int cmd, double dblPrice) { double dblMinStopDistance = MarketInfo(Symbol(),MODE_STOPLEVEL)*Point; switch(cmd) { case OP_BUY: case OP_BUYLIMIT: case OP_BUYSTOP: return(NormalizeDouble(dblPrice-dblMinStopDistance,Digits)); case OP_SELL: case OP_SELLLIMIT: case OP_SELLSTOP: return(NormalizeDouble(dblPrice+dblMinStopDistance,Digits)); default: Alert("Invalid cmd ",cmd," in MinStopLoss"); } } double ClosestBuySellStopPrice(int cmd) { double dblMinStopDistance = MarketInfo(Symbol(),MODE_STOPLEVEL)*Point; switch(cmd) { case OP_BUYSTOP: return(Ask+dblMinStopDistance); case OP_SELLSTOP: return(Bid-dblMinStopDistance); default: Alert("Invalid cmd ",CmdToStr(cmd)," in ClosestBuySellStopPrice"); } return(0); } void CloseAfterPeak(int nTrailingStop, int nSlippage, int nSystemID = 0, datetime AfterTime = 0) { // client side stoploss. If internet connection is broken this will fail! // Ensure that initial stop is also set to control risk static double dblMinAsk = 999; static double dblMaxBid = 0; for ( int nPosition=0 ; nPosition<OrdersTotal() ; nPosition++ ) { OrderSelect(nPosition, SELECT_BY_POS, MODE_TRADES); if ( OrderSymbol()==Symbol() && (OrderMagicNumber() == 0 || OrderMagicNumber() == nSystemID) ) // same symbol and system { if (AfterTime == 0 || CurTime() > AfterTime) { dblMaxBid = MathMax(dblMaxBid, Bid); dblMinAsk = MathMin(dblMinAsk, Ask); switch(OrderType()) { case OP_BUY: if (Bid <= dblMaxBid - nTrailingStop*Point) { Print("Close Buy order after peak of ",dblMaxBid," Bid ",Bid," TrailingStop ", nTrailingStop); if (SecureOrderClose( OrderTicket(), OrderLots(), Bid, nSlippage, Turquoise)) dblMaxBid = 0; } break; case OP_SELL: if (Ask >= dblMinAsk + nTrailingStop*Point) { Print("Close Sell order after peak of ",dblMinAsk," Ask ",Ask," TrailingStop ", nTrailingStop); if (SecureOrderClose( OrderTicket(), OrderLots(), Ask, nSlippage, Coral)) dblMinAsk = 999; } break; } } } } }
Sample
Analysis
Market Information Used:
Series array that contains the highest prices of each bar
Series array that contains the lowest prices of each bar
Series array that contains open time of each bar
Indicator Curves created:
Indicators Used:
Indicator of the average true range
Custom Indicators Used:
Order Management characteristics:
Checks for the total of open orders
It Closes Orders by itself
It can change open orders parameters, due to possible stepping strategy
It automatically opens orders when conditions are reached
Other Features:
It issuies visual alerts to the screen