//+------------------------------------------------------------------+ //| TSD_MR_Trade_OsMA_WPR_0_36.mq4 | //| Copyright © 2006 Mindaugas | //| TSD Trade version 0.36 | //| | //| o TSD idea and realization by Bob O'Brien / Barcode | //| o TSD rewritten to MQL4 and enhanced by Mindaugas | //| o Enhanced comments by Mike aka FxMt | //| o Trailing Stop based on ATR by Loren Gordon | //+------------------------------------------------------------------+ #property copyright "Copyright © 2006 Mindaugas" #include <stdlib.mqh> #define DIRECTION_MACD 1 #define DIRECTION_OSMA 2 #define FILTER_WPR 1 #define FILTER_FORCE 2 // Put new trades only on new bar or also on expert initialization. Default is to trade only on new bar. extern bool TradeOnInit = false; // Whether to put new orders or only track old ones. Default is to put new orders. extern bool NewTrades = true; // which indicators to use int DirectionMode = DIRECTION_OSMA, FilterMode = FILTER_WPR; // trading periods int PeriodDirection = PERIOD_W1, PeriodTrade = PERIOD_D1, PeriodTrailing = PERIOD_H4, CandlesTrailing = 0; // currency pairs to trade string pairs[] = { "AUDUSD", "EURCHF", "EURGBP", "EURJPY", "EURUSD", "GBPCHF", "GBPJPY", "GBPUSD", "USDCAD", "USDCHF", "USDJPY" }; // MM and broker parameters double Risk = 0.00, Lots = 0.1; // parameters for MACD and OsMA int DirectionFastEMA = 12, DirectionSlowEMA = 26, DirectionSignal = 9; // parameters for iWPR and iForce indicators int WilliamsP = 24, WilliamsL = -75, WilliamsH = -25; int ForceP = 2; int MagicNumber = 2005072001; bool TrailingStop = true; int TakeProfit = 60, Slippage = 2, TrailingStopStep = 2; string TradeSymbol, CommentHeader, CommentsPairs[]; int Pair = -1, SDigits; double Spread, SPoint, STS, StopLevel; //+------------------------------------------------------------------+ int init() { string DirInd, FilterInd; if ( ! TradeOnInit ) Print ("WARNING!!! Expert will place new orders only on the beginning of the new bar."); if ( IsTesting() ) { if ( ArrayResize(pairs,1) != 0 ) pairs[0] = Symbol(); } else { if ( DirectionMode == DIRECTION_MACD ) DirInd = "MACD"; else if ( DirectionMode == DIRECTION_OSMA ) DirInd = "OsMA"; if ( FilterMode == FILTER_WPR ) FilterInd = "WPR("+WilliamsP+","+WilliamsL+","+WilliamsH+")"; else if ( FilterMode == FILTER_FORCE ) FilterInd = "Force("+ForceP+")"; CommentHeader = ("\nTSD Trade P("+PeriodDirection+","+PeriodTrade+","+PeriodTrailing+","+CandlesTrailing+")"+ " "+DirInd+"("+DirectionFastEMA+","+DirectionSlowEMA+","+DirectionSignal+")"+ " "+FilterInd+"\n"); } ArrayCopy (CommentsPairs, pairs); return(0); } //+------------------------------------------------------------------+ int deinit() { return(0); } //+------------------------------------------------------------------+ int start() { static bool Alerted = false; int TradesThisSymbol, Direction; int i, ticket; bool okSell, okBuy, Deleted; double PriceOpen, Buy_Sl, Buy_Tp, LotMM; string ValueComment; Pair = (Pair+1) % ArraySize(pairs); TradeSymbol = pairs[Pair]; if ( ! PairExists(TradeSymbol) ) { if ( ! Alerted ) Alert ("No data for the pair: ", TradeSymbol, ". Please review and fix pairs variable."); Alerted = true; return(0); } TradesThisSymbol = TotalTradesThisSymbol (TradeSymbol); SPoint = MarketInfo (TradeSymbol, MODE_POINT); Spread = MarketInfo (TradeSymbol, MODE_ASK) - MarketInfo (TradeSymbol, MODE_BID); SDigits = MarketInfo (TradeSymbol, MODE_DIGITS); StopLevel = MarketInfo (TradeSymbol, MODE_STOPLEVEL) * SPoint + 1*SPoint; STS = iATR (TradeSymbol, PeriodTrailing, PeriodDirection*3/PeriodTrailing, 1) + Spread + 1*SPoint; Direction = Direction (TradeSymbol, PeriodDirection, DirectionMode); ValueComment = Filter(TradeSymbol, PeriodTrade, FilterMode, okBuy, okSell); CommentAll (Direction, ValueComment); if ( ! IsTradeAllowed() || MarketInfo(TradeSymbol, MODE_TRADEALLOWED) == 0 ) return(0); /////////////////////////////////////////////////////////////////////////////// // Place new orders and modify pending ones only on the beginning of new bar /////////////////////////////////////////////////////////////////////////////// if ( NewBar() ) { ///////////////////////////////////////////////// // Place new order ///////////////////////////////////////////////// if ( TradesThisSymbol < 1 && NewTrades ) { ticket = 0; LotMM = CalcMM_TSDTrade (Direction); if ( LotMM <= 0 ) return(0); if ( Direction == 1 && okBuy ) { Print ("TSD BuyStop: ", TradeSymbol, " ", LotMM, " ", CalcOpenBuy(), " ", CalcSlBuy(), " ", CalcTpBuy(), ", ", MarketInfo(TradeSymbol, MODE_ASK), " ", ValueComment); ticket = OrderSend (TradeSymbol, OP_BUYSTOP, LotMM, CalcOpenBuy(), Slippage, CalcSlBuy(), CalcTpBuy(), "TSD BuyStop", MagicNumber, 0); } if ( Direction == -1 && okSell ) { Print ("TSD SellStop: ", TradeSymbol, " ", LotMM, " ", CalcOpenSell(), " ", CalcSlSell(), " ", CalcTpSell(), ", ", MarketInfo(TradeSymbol, MODE_BID), " ", ValueComment); ticket = OrderSend (TradeSymbol, OP_SELLSTOP, LotMM, CalcOpenSell(), Slippage, CalcSlSell(), CalcTpSell(), "TSD SellStop", MagicNumber, 0); } OrderError(ticket >= 0); if ( ticket != 0 ) return(0); } // End of TradesThisSymbol < 1 && NewTrades ///////////////////////////////////////////////// // Pending Order Management ///////////////////////////////////////////////// for (i = 0; i < OrdersTotal(); i++) { if ( OrderSelect (i, SELECT_BY_POS) == false ) continue; if ( OrderSymbol() != TradeSymbol || OrderMagicNumber() != MagicNumber) continue; if ( OrderOpenTime() > iTime(TradeSymbol, PeriodTrade, 0) ) continue; if ( OrderType () == OP_BUYSTOP ) { if ( Direction != 1 || ComparePrices (CalcOpenBuy(), OrderOpenPrice()) != 0 || ComparePrices (CalcSlBuy(), OrderStopLoss()) != 0 ) { Print ("TSD delete BuyStop: ", TradeSymbol); Deleted = OrderDelete ( OrderTicket() ); OrderError(Deleted); return(0); } } if ( OrderType () == OP_SELLSTOP ) { if ( Direction != -1 || ComparePrices (CalcOpenSell(), OrderOpenPrice()) != 0 || ComparePrices (CalcSlSell(), OrderStopLoss()) != 0 ) { Print ("TSD delete SellStop: ", TradeSymbol); Deleted = OrderDelete ( OrderTicket() ); OrderError(Deleted); return(0); } } } // End of Pending Order Management } // End of NewBar() ///////////////////////////////////////////////// // Stop Loss Management ///////////////////////////////////////////////// if ( TrailingStop ) { for (i = 0; i < OrdersTotal(); i++) { if ( OrderSelect (i, SELECT_BY_POS) == false ) continue; if ( OrderSymbol() != TradeSymbol || OrderMagicNumber() != MagicNumber) continue; if ( TrailStop (STS) ) return(0); } } return(0); } //+------------------------------------------------------------------+ double CalcOpenBuy () { return (MathMax (iHigh(TradeSymbol, PeriodTrade, 1) + 1*SPoint + Spread, MarketInfo(TradeSymbol, MODE_ASK) + StopLevel)); } double CalcOpenSell () { return (MathMin (iLow(TradeSymbol, PeriodTrade, 1) - 1*SPoint, MarketInfo(TradeSymbol, MODE_BID) - StopLevel)); } double CalcSlBuy () { return (iLow (TradeSymbol, PeriodTrade, 1) - 1*SPoint); } double CalcSlSell () { return (iHigh(TradeSymbol, PeriodTrade, 1) + 1*SPoint + Spread); } double CalcTpBuy () { double PriceOpen = CalcOpenBuy(), SL = CalcSlBuy(); if ( TakeProfit == 0 ) return(0); return (PriceOpen + MathMax( MathMax(TakeProfit*SPoint, STS*3), (PriceOpen - SL)*2) ); } double CalcTpSell () { double PriceOpen = CalcOpenSell(), SL = CalcSlSell(); if ( TakeProfit == 0 ) return(0); return (PriceOpen - MathMax( MathMax(TakeProfit*SPoint, STS*3), (SL - PriceOpen)*2)); } //+------------------------------------------------------------------+ bool TrailStop (double TrailingStop) { double StopLoss; bool Modified; if ( OrderType() == OP_BUY ) { if ( MarketInfo (TradeSymbol, MODE_BID) < OrderOpenPrice()+TrailingStop ) return(false); StopLoss = iLow(TradeSymbol, PeriodTrailing, Lowest (TradeSymbol, PeriodTrailing, MODE_LOW, CandlesTrailing+1, 0)) - 1*SPoint; StopLoss = MathMin (MarketInfo (TradeSymbol, MODE_BID)-TrailingStop, StopLoss); if ( ComparePrices (StopLoss, OrderStopLoss() + TrailingStopStep*SPoint) == 1 ) { Print ("TSD trailstop Buy: ", TradeSymbol, " ", StopLoss, ", ", MarketInfo(TradeSymbol, MODE_ASK)); Modified = OrderModify (OrderTicket(), OrderOpenPrice(), StopLoss, OrderTakeProfit(), 0); OrderError(Modified, false); return(true); } } if ( OrderType() == OP_SELL ) { if ( MarketInfo (TradeSymbol, MODE_ASK) > OrderOpenPrice()-TrailingStop ) return(false); StopLoss = iHigh(TradeSymbol, PeriodTrailing, Highest (TradeSymbol, PeriodTrailing, MODE_HIGH, CandlesTrailing+1, 0)) + 1*SPoint + Spread; StopLoss = MathMax (MarketInfo (TradeSymbol, MODE_ASK)+TrailingStop, StopLoss); if ( ComparePrices (StopLoss, OrderStopLoss() - TrailingStopStep*SPoint) == -1 ) { Print ("TSD trailstop Sell: ", TradeSymbol, " ", StopLoss, ", ", MarketInfo(TradeSymbol, MODE_BID)); Modified = OrderModify (OrderTicket(), OrderOpenPrice(), StopLoss, OrderTakeProfit(), 0); OrderError(Modified, false); return(true); } } return(false); } //+------------------------------------------------------------------+ int Direction (string TradeSymbol, int PeriodDirection, int Mode) { double Previous, Previous2; if (Mode == DIRECTION_MACD ) { Previous = iMACD (TradeSymbol, PeriodDirection, DirectionFastEMA, DirectionSlowEMA, DirectionSignal, PRICE_CLOSE, MODE_MAIN, 1); Previous2 = iMACD (TradeSymbol, PeriodDirection, DirectionFastEMA, DirectionSlowEMA, DirectionSignal, PRICE_CLOSE, MODE_MAIN, 2); } else if (Mode == DIRECTION_OSMA) { Previous = iOsMA (TradeSymbol, PeriodDirection, DirectionFastEMA, DirectionSlowEMA, DirectionSignal, PRICE_CLOSE, 1); Previous2 = iOsMA (TradeSymbol, PeriodDirection, DirectionFastEMA, DirectionSlowEMA, DirectionSignal, PRICE_CLOSE, 2); } if ( Previous > Previous2 ) return(1); if ( Previous < Previous2 ) return(-1); return(0); } //+------------------------------------------------------------------+ string Filter (string TradeSymbol, int PeriodTrade, int Mode, bool &okBuy, bool &okSell) { double Value; okBuy = false; okSell = false; if (Mode == FILTER_WPR) { Value = iWPR(TradeSymbol, PeriodTrade, WilliamsP, 1); if (Value < WilliamsH) okBuy = true; if (Value > WilliamsL) okSell = true; return ("iWPR: " + DoubleToStr(Value, 2)); } else if (Mode == FILTER_FORCE) { Value = iForce (TradeSymbol, PeriodTrade, ForceP, MODE_EMA, PRICE_CLOSE, 1); if (Value < 0) okBuy = true; if (Value > 0) okSell = true; return ("iForce: " + DoubleToStr(Value, 2)); } } //+------------------------------------------------------------------+ double CalcMM_TSDTrade (int Direction) { if ( Direction == 1 ) return ( CalcMM (TradeSymbol, (CalcOpenBuy()-CalcSlBuy())/SPoint) ); else if ( Direction == -1 ) return ( CalcMM (TradeSymbol, (CalcSlSell()-CalcOpenSell())/SPoint) ); } //+------------------------------------------------------------------+ double CalcMM (string TradeSymbol, int StopLoss) { double MinLot = MarketInfo(TradeSymbol, MODE_MINLOT); double LotStep = MarketInfo(TradeSymbol, MODE_LOTSTEP); double LotsToTrade, LotsMM = Lots; if ( Risk > 0 ) { LotsToTrade = AccountBalance() * Risk / (StopLoss * PipCost(TradeSymbol)); for (LotsMM = MinLot; NormalizeDouble(LotsToTrade-LotsMM, 8) >= 0; LotsMM += LotStep ) {} LotsMM = MathMax (MinLot, LotsMM - LotStep); } if ( AccountFreeMargin() < LotsMM * LotMarginSize(TradeSymbol) ) { Alert("Not enough money to open trade. Free Margin = ", AccountFreeMargin(), ". Number of Lots to trade = ", LotsMM); return(-1); } return (LotsMM); } //+------------------------------------------------------------------+ double PipCost (string TradeSymbol) { double Base, Cost; string TS_13, TS_46, TS_4L; TS_13 = StringSubstr (TradeSymbol, 0, 3); TS_46 = StringSubstr (TradeSymbol, 3, 3); TS_4L = StringSubstr (TradeSymbol, 3, StringLen(TradeSymbol)-3); Base = MarketInfo (TradeSymbol, MODE_LOTSIZE) * MarketInfo (TradeSymbol, MODE_POINT); if ( TS_46 == "USD" ) Cost = Base; else if ( TS_13 == "USD" ) Cost = Base / MarketInfo (TradeSymbol, MODE_BID); else if ( PairExists ("USD"+TS_4L) ) Cost = Base / MarketInfo ("USD"+TS_4L, MODE_BID); else Cost = Base * MarketInfo (TS_46+"USD", MODE_BID); return(Cost); } //+------------------------------------------------------------------+ double LotMarginSize (string TradeSymbol) { double Margin, MarginSize = MarketInfo (TradeSymbol, MODE_LOTSIZE) / AccountLeverage(); string TS_13, TS_7L; TS_13 = StringSubstr (TradeSymbol, 0, 3); TS_7L = StringSubstr (TradeSymbol, 6, StringLen(TradeSymbol)-6); if ( TS_13 == "USD" ) Margin = MarginSize; else if ( PairExists (TS_13+"USD"+TS_7L) ) Margin = MarginSize * MarketInfo (TS_13+"USD"+TS_7L, MODE_BID); else Margin = MarginSize / MarketInfo ("USD"+TS_13+TS_7L, MODE_BID); return(Margin); } //+------------------------------------------------------------------+ bool PairExists (string TradeSymbol) { return ( MarketInfo (TradeSymbol, MODE_LOTSIZE) > 0 ); } //+------------------------------------------------------------------+ int TotalTradesThisSymbol (string TradeSymbol) { int i, TradesThisSymbol = 0; for (i = 0; i < OrdersTotal(); i++) if ( OrderSelect (i, SELECT_BY_POS) ) if ( OrderSymbol() == TradeSymbol && OrderMagicNumber() == MagicNumber ) TradesThisSymbol++; return (TradesThisSymbol); } //+------------------------------------------------------------------+ void OrderError (bool OK, bool ResetNewBar=true) { if ( ! OK ) { if ( ResetNewBar ) NewBar(-1); ReportError(); } } //+------------------------------------------------------------------+ void ReportError () { int err = GetLastError(); Print("Error(",err,"): ", ErrorDescription(err)); } //+------------------------------------------------------------------+ int ComparePrices (double Price1, double Price2) { double p1 = NormalizeDouble (Price1, SDigits), p2 = NormalizeDouble (Price2, SDigits); if ( p1 > p2 ) return(1); if ( p1 < p2 ) return(-1); return(0); } //+------------------------------------------------------------------+ bool NewBar (int how=1) { static int ProcessNumber = 2; static datetime PairTime[0]; static int PairNewBar[0]; if ( ArraySize(PairTime) != ArraySize(pairs) ) { ArrayResize (PairTime, ArraySize(pairs) ); ArrayResize (PairNewBar, ArraySize(pairs) ); ArrayInitialize (PairNewBar, 100); if ( TradeOnInit ) ArrayInitialize (PairTime, 0); else ArrayInitialize (PairTime, iTime (TradeSymbol, PeriodTrade, 0 )); } if ( how == -1 ) { PairNewBar[Pair] = MathMax ( 0, PairNewBar[Pair]-1 ); return(true); } if ( PairNewBar[Pair] <= ProcessNumber ) { if ( how == 1 ) PairNewBar[Pair]++; return(true); } if ( PairTime[Pair] != iTime (TradeSymbol, PeriodTrade, 0 ) ) { PairTime[Pair] = iTime (TradeSymbol, PeriodTrade, 0 ); PairNewBar[Pair] = 0; } return(false); } //+------------------------------------------------------------------+ void CommentAll (int Direction, string ValueComment) { string Comments = ""; int i, next = (Pair+1) % ArraySize(pairs); CommentsPairs[Pair] = TradeSymbol + ": " + " Dir("+Direction+") " + ValueComment + " TS(" + DoubleToStr (STS/SPoint, 0) + ")"; CommentsPairs[next] = ">" + CommentsPairs[next]; for (i=0; i < ArraySize(CommentsPairs); i++) Comments = Comments + "\n" + CommentsPairs[i]; if ( ! IsTesting() ) Comment (CommentHeader, Comments); }
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:
Larry William percent range indicator
Custom Indicators Used:
Order Management characteristics:
Checks for the total of open orders
Other Features:
It issuies visual alerts to the screen