//+------------------------------------------------------------------+ //| Rhythm.mq4 | //| Copyright © 2007, MQLService | //| http://www.mqlservice.com | //| $Id: //mqlservice/mt4files/experts/Rhythm.mq4#6 $ //+------------------------------------------------------------------+ /* Alan Strawbridge [strawstock2@yahoo.com] Many thanks to Tkimble on the ForexFactory for the simple strategy that this EA is designed to manage. Name: Rhythm Pair: Any Pair You like. This is a simple Stop @ Reverse system. It should be able to be used with Daily and weekly trading Once trade is initiated the stop loss and reversals are equal. Example: the stop is placed at 40 PIPs and the reversal is likewise placed at 40 PIPs. When the stop is activated, the reversal is simultaneously activated. There is no limit on how many reversals there can be in a day unless Max Trades variable is used EA- Variables: Overrule Direction: = True/False EA makes next day trade decision on the basis of the previous Days trend (i.e.; previous day up, Place "Buy" market order, previous day down, enter "Sell" market order) Example: Yesterdays open/close positive = LongEntry) (Yesterdays open/close negative = ShortEntry) 00:00 >< 23:55 Set it to False if you want to choose your own initial entry direction Direction Long: =True/False this is the manual way to either go Long or Short for your opening trade. If using this variable Overrule Direction should be set to True EntryTime Hour: = Entry will execute on the Open of the hour chosen. 00:00 thru 23:00 ExitTime Hour: = 00:00 thru 23:00 Exit will execute on the Open of the preceding bar from exit hour chosen Example: exit set for 17:00 exit will execute on the open of the 18:00 bar. Max Trades: = 0=False or 1,2,3,4 etc Set this variable if you want to limit on how many whipsaws you want in a day or week. EA will not take anymore trades for current day or week once variable is reached TrailStop Once: = True/False (If set to True, Stop and Reverse order will move positive one time at the value of the Stop loss variable) Example: I am long at 1.2000 and I have my stop set at 1.1960 (-40) If price was to advance to 1.2040 then my Stop & Reverse orders would move positive to 1.2000 This would be the only positive move they would make. Trailing Stop: = True/False (If set to True, Stop and Reverse order will move every time price moves positive at the value of the Stop loss variable) Stoploss: = Default 40 "Very important". It is the Value that all Stops will use. (i.e.; TrailStop Once, Trailing Stop) It is the value that all Stop and Reverse orders are placed. ProfitTarget: = 0=False, Default 120 If Profit Target or Time exit is not used than trade will remain open until manually closed or when Profit Target or Time exit is initiated and executed in the future. Lots: = Default 0.1 Mini */ #property copyright "Copyright © 2007, MQLService" #property link "http://www.mqlservice.com" #include <stdlib.mqh> #include <stderror.mqh> //---- input parameters extern bool OverruleDirection = false; extern bool DirectionLong = false; extern int EntryTimeHour = 0; extern int ExitTimeHour = 23; // Set it equal of lower of extern int MaxTrades = 0; // Set <= 0 to disable extern bool TrailOnceStop = false; extern bool TrailingStop = false; extern double Lots = 0.1; extern int StopLoss = 40; extern int TakeProfit = 120; extern int Magic = 361; int init() { Comment("Waiting for tick"); return(0); } int deinit() { Comment(""); return(0); } int start() { if(Bars<100) { Comment("Waiting for bars..."); return(0); } return(Rhythm(Symbol(),Period(), Magic, Lots, StopLoss, TakeProfit, MaxTrades)); } bool Visual = true; #define MAX_CNT 120 // 1 minute int Rhythm(string sym, int per, int magic, double vol, int sl, int tp, int mt) { // Internals int _Digits = MarketInfo(sym, MODE_DIGITS); if(_Digits == 0) _Digits = 4; double _Point = MarketInfo(sym, MODE_POINT); if(NormalizeDouble(_Point, _Digits) == 0.0) _Point = Point; double _Bid = MarketInfo(sym, MODE_BID); double _Ask = MarketInfo(sym, MODE_ASK); static int dir = -1; static int reverse = 0; // Find trend (override possible and skip Sundays for Monday trend) if(dir < 0){ if(OverruleDirection) if(DirectionLong) dir = OP_BUY; else dir = OP_SELL; else { if(DayOfWeek() == 1) int bs = iBarShift(sym, PERIOD_D1, TimeCurrent()-72*3600); else bs = 1; if(iOpen(sym, PERIOD_D1, bs) < iClose(sym, PERIOD_D1, bs)) dir = OP_BUY; else dir = OP_SELL; } if(dir == OP_BUY) reverse = MathRound(_Ask/_Point); else reverse = MathRound(_Bid/_Point); } // Calculate how many trades today and if one ended with TP bool ct = _Rhythm_CanTrade(sym, magic, mt) && IsTradeAllowed(); bool tt = _Rhythm_tt(per, EntryTimeHour, ExitTimeHour); ct = ct && tt; if(tt) { if(Visual) Comment("Trading times"); // Check for active position int cnt = 0; while(!_Rhythm_ActivePosition(sym, magic) && ct) { int tic = -1; if(dir == OP_BUY){ if(ct) { _Ask = MarketInfo(sym, MODE_ASK); if(MathRound(_Ask/_Point) >= reverse) tic = OrderSend(sym, dir, vol, _Ask, 1, _sl(dir, sym, sl), _tp(dir, sym, tp), "Rhythm", magic, 0, Blue); else break; _ce(); } }else{ if(ct) { _Bid = MarketInfo(sym, MODE_BID); if(MathRound(_Bid/_Point) <= reverse) tic = OrderSend(sym, dir, vol, _Bid, 1, _sl(dir, sym, sl), _tp(dir, sym, tp), "Rhythm", magic, 0, Red); else break; _ce(); } } Sleep(500); cnt++; if(cnt >= MAX_CNT) break; // Recalculate conditions ct = _Rhythm_CanTrade(sym, magic, mt) && IsTradeAllowed(); ct = ct && _Rhythm_tt(per, EntryTimeHour, ExitTimeHour); } // Find reverse: if(_Rhythm_ActivePosition(sym, magic)) { reverse = MathRound(OrderStopLoss()/_Point); if(OrderType() == OP_BUY) dir = OP_SELL; else dir = OP_BUY; } if(Visual) Comment("Trading times. Reverse at ", DoubleToStr(reverse*_Point, _Digits)); } if(!tt) { if(Visual) Comment("Outside of trading times"); reverse = 0; dir = -1; //close all open trades for(int i=OrdersTotal()-1; i >= 0; i--) if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)){ if(OrderSymbol() == sym) if(OrderMagicNumber() == magic) if(!OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 1)) _ce(); } } if(_Rhythm_ActivePosition(sym, magic)) { // manage sl/reverse if(TrailingStop){ if(OrderType() == OP_BUY){ double nsl = OrderClosePrice()-sl*_Point; if(MathRound((_Bid-OrderStopLoss())/_Point)-sl > 0) if(OrderModify(OrderTicket(), OrderOpenPrice(), nsl, OrderTakeProfit(), OrderExpiration(), Blue)) reverse = MathRound(nsl/_Point); else _ce(); }else{ nsl = OrderClosePrice()+sl*_Point; if(MathRound((OrderStopLoss()-_Ask)/_Point)-sl > 0) if(OrderModify(OrderTicket(), OrderOpenPrice(), nsl, OrderTakeProfit(), OrderExpiration(), Red)) reverse = MathRound(nsl/_Point); else _ce(); } }else if(TrailOnceStop){ nsl = OrderOpenPrice(); if(OrderType() == OP_BUY){ if(MathRound((_Bid-nsl)/_Point)-sl > 0) if(MathRound((nsl-OrderStopLoss())/_Point) != 0) if(OrderModify(OrderTicket(), OrderOpenPrice(), nsl, OrderTakeProfit(), OrderExpiration(), Blue)) reverse = MathRound(nsl/_Point); else _ce(); }else{ if(MathRound((nsl-_Ask)/_Point) - sl > 0) if(MathRound((nsl-OrderStopLoss())/_Point) != 0) if(OrderModify(OrderTicket(), OrderOpenPrice(), nsl, OrderTakeProfit(), OrderExpiration(), Blue)) reverse = MathRound(nsl/_Point); else _ce(); } } } return(0); } bool _Rhythm_CanTrade(string symbol, int magic, int max) { int today_trades = 0; datetime today = iTime(symbol, PERIOD_D1, 0); for(int i=OrdersHistoryTotal()-1; i >= 0; i--) if(OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)){ if(OrderSymbol() == symbol) if(OrderMagicNumber() == magic) if(OrderOpenTime() >= today){ today_trades++; if(MaxTrades > 0) if(today_trades >= MaxTrades) return(false); if(TakeProfit > 0) if(StringFind(OrderComment(), "[tp]") >= 0) return(false); } }else Print("OrderSelect() error - ", ErrorDescription(GetLastError())); return(true); } bool _Rhythm_ActivePosition(string symbol, int magic) { for(int i=OrdersTotal()-1; i >= 0; i--) if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)){ if(OrderType() <= OP_SELL) if(OrderSymbol() == symbol) if(OrderMagicNumber() == magic) return(true); }else Print("OrderSelect() error - ", ErrorDescription(GetLastError())); return(false); } bool _Rhythm_tt(int period, int openh, int closeh) { // Trade times datetime st = MathFloor(TimeCurrent()/86400)*86400 + openh*3600; datetime en = MathFloor(TimeCurrent()/86400)*86400 + closeh*3600+period*60; datetime now = TimeCurrent(); while(st > now) st -= 86400; while(en > now) en -= 86400; if(st<en) return(false); return(true); } bool _ce() { int err=GetLastError(); if(err != ERR_NO_ERROR){ Print("Error #", err, " ", ErrorDescription(err)); return(true); } return(false); } double _sl(int type, string symbol, int stoploss) { if(type == OP_BUY) if(stoploss > 0) return(MarketInfo(symbol, MODE_BID)-stoploss*MarketInfo(symbol, MODE_POINT)); else return(0.0); else if(type == OP_SELL) if(stoploss > 0) return(MarketInfo(symbol, MODE_ASK)+stoploss*MarketInfo(symbol, MODE_POINT)); else return(0.0); } double _tp(int type, string symbol, int takeprofit) { if(type == OP_BUY) if(takeprofit > 0) return(MarketInfo(symbol, MODE_BID)+takeprofit*MarketInfo(symbol, MODE_POINT)); else return(0.0); else if(type == OP_SELL) if(takeprofit > 0) return(MarketInfo(symbol, MODE_ASK)-takeprofit*MarketInfo(symbol, MODE_POINT)); else return(0.0); } //+---- Programmed by Michal Rutka ----------------------------------+
Sample
Analysis
Market Information Used:
Series array that contains open prices of each bar
Series array that contains close prices for each bar
Indicator Curves created:
Indicators Used:
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
Checks for the total of closed orders
Other Features: