//+------------------------------------------------------------------+ //| 3barHiLoEA.mq4 | //| Copyright © 2007, MQL Service | //| http://www.mqlservice.com | //+------------------------------------------------------------------+ //| $Id: //mqlservice/mt4files/experts/3barHiLoEA.mq4#1 $ //+------------------------------------------------------------------+ #property copyright "Copyright © 2007, MQL Service" #property link "http://www.mqlservice.com" #include <stdlib.mqh> extern double Lots = 0.1; extern int StartTimeGMT = 400; // Start trading at 4:00 GMT extern int StopTimeGMT = 900; // Stop trading at 9:00 GMT extern int Hi_Timeframe = PERIOD_H4; // Higher timeframe to test extern int Lo_Timeframe = PERIOD_H1; // Lower timeframe to test extern int NoBars = 3; // Number of bars extern int Pips_offset = 1; // Offset for entry above 3 Bars extern int DaysExit = 1; // Exit the same day close (2-next day close, etc). extern int StopLoss = 30; // 0 deactivates Stop Loss extern int TrailingStop = 0; // 0 deactivates Trailing Stop extern int TakeProfit = 0; // 0 deactivates Take Profit extern int GainForBE = 0; // How many pips will trigger Break Even extern int PipsBE = 0; // Level at which Break Even will be put extern int Slippage = 3; #define MAGIC 200707012 int init() { Comment("Waiting for the first tick..."); return(0); } int deinit() { Comment(WindowExpertName()," finished."); return(0); } int start() { if(Bars<100) { Comment("Waiting for bars..."); return(0); } int _gmt_offset = MathRound(TimeZoneServer()); datetime _StartTime = StartTimeGMT + _gmt_offset; datetime _StopTime = StopTimeGMT + _gmt_offset; return(_3barHiLo(Symbol(), Period(), MAGIC, Lots, StopLoss, TrailingStop, TakeProfit, GainForBE, PipsBE, Slippage, _StartTime, _StopTime, Hi_Timeframe, Lo_Timeframe, NoBars, Pips_offset, DaysExit)); } int _3barHiLo(string symbol, int period, int magic, double lots, int stoploss, int trailingstop, int takeprofit, int gainforbe, int pipsbe, int slippage, int starttime, int stoptime, int hi_timeframe=PERIOD_H4, int lo_timeframe=PERIOD_H1, int nobars=3, int pips_offset=1, int daysexit=0) { // Internals int _Digits = MarketInfo(symbol, MODE_DIGITS), i; if(_Digits == 0) _Digits = 4; double _Point = MarketInfo(symbol, MODE_POINT); if(NormalizeDouble(_Point, _Digits) == 0.0) _Point = Point; double _Bid = MarketInfo(symbol, MODE_BID); double _Ask = MarketInfo(symbol, MODE_ASK); int _iBid = MathRound(_Bid/_Point); string _cm = "Time GMT: " + TimeToStr(TimeGMT()); bool _can_open = true; // TRADING TIMES If not in trading times close all positions and exit datetime _now = TimeCurrent(); datetime _st = MathFloor(_now/86400)*86400 + MathRound(starttime/100)*3600+MathMod(starttime, 100)*60; datetime _en = MathFloor(_now/86400)*86400 + MathRound(stoptime/100)*3600+MathMod(stoptime, 100)*60; while(_st <= _now) _st += 86400; while(_en <= _now) _en += 86400; if(_st<_en) _can_open = false; // END OF TRADING TIMES // Signals static bool _long = false; static bool _short = false; if(_iBid > MathRound(iHigh(symbol, hi_timeframe, iHighest(symbol, hi_timeframe, MODE_HIGH, nobars, 1))/_Point)) if(_iBid >= MathRound(iHigh(symbol, lo_timeframe, iHighest(symbol, lo_timeframe, MODE_HIGH, nobars,1))/_Point)+pips_offset) _long = _can_open; if(_iBid < MathRound(iLow(symbol, hi_timeframe, iLowest(symbol, hi_timeframe, MODE_LOW, nobars, 1))/_Point)) if(_iBid >= MathRound(iLow(symbol, lo_timeframe, iLowest(symbol, lo_timeframe, MODE_LOW, nobars,1))/_Point)+pips_offset) _short = _can_open; if(!_ip(OP_BUY, symbol, magic)) if(_long) Print("Bid: ", _iBid,"; H4: ",MathRound(iHigh(symbol, hi_timeframe, iHighest(symbol, hi_timeframe, MODE_HIGH, nobars, 1))/_Point),"; H1: ", MathRound(iHigh(symbol, lo_timeframe, iHighest(symbol, lo_timeframe, MODE_HIGH, nobars,1))/_Point)); if(!_ip(OP_SELL, symbol, magic)) if(_short) Print("Bid: ",_iBid,"; H4: ",MathRound(iLow(symbol, hi_timeframe, iLowest(symbol, hi_timeframe, MODE_LOW, nobars, 1))/_Point),"; H1: ", MathRound(iLow(symbol, lo_timeframe, iLowest(symbol, lo_timeframe, MODE_LOW, nobars,1))/_Point)); // Signals // S&R bool _send_ok = true; if(_long){ if(_ip(OP_SELL, symbol, magic)) _OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), slippage, Red); if(!_ip(OP_BUY, symbol, magic)) _send_ok = _OrderSend(symbol, OP_BUY, _nv(symbol, lots), _Ask, slippage, _sl(OP_BUY, symbol, _Bid, stoploss), _tp(OP_BUY, symbol, _Bid, takeprofit), WindowExpertName(), magic, 0, Blue) > 0; } if(_short){ if(_ip(OP_BUY, symbol, magic)) _OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), slippage, Blue); if(!_ip(OP_SELL, symbol, magic)) _send_ok = _OrderSend(symbol, OP_SELL, _nv(symbol, lots), _Bid, slippage, _sl(OP_SELL, symbol, _Ask, stoploss), _tp(OP_SELL, symbol, _Ask, takeprofit), WindowExpertName(), magic, 0, Red) > 0; } // S&R if(_ip(OP_BUY, symbol, magic)) { int diff = MathFloor((TimeCurrent()-OrderOpenTime())/86400.0); if(TimeDayOfYear(OrderOpenTime())!=DayOfYear()) diff++; if(diff>=daysexit) _fa(symbol, magic); } if(_ip(OP_SELL, symbol, magic)) { diff = MathFloor((TimeCurrent()-OrderOpenTime())/86400.0); if(TimeDayOfYear(OrderOpenTime())!=DayOfYear()) diff++; if(diff>=daysexit) _fa(symbol, magic); } // TrailingStop if(trailingstop > 0) for(i=0; i < OrdersTotal(); i++) if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)){ if(OrderSymbol() == symbol) if(OrderMagicNumber() == magic) if(OrderType() == OP_BUY){ if(MathRound((OrderClosePrice()-OrderStopLoss())/_Point) > trailingstop) if(!OrderModify(OrderTicket(), OrderOpenPrice(), OrderClosePrice()-trailingstop*_Point, OrderTakeProfit(), OrderExpiration(), Blue)) Print("OrderModify(OP_BUY) error - ", ErrorDescription(GetLastError())); }else if(OrderType() == OP_SELL){ if((MathRound((OrderStopLoss()-OrderClosePrice())/_Point) > trailingstop)||(OrderStopLoss()<_Bid)) if(!OrderModify(OrderTicket(), OrderOpenPrice(), OrderClosePrice()+trailingstop*_Point, OrderTakeProfit(), OrderExpiration(), Red)) Print("OrderModify(OP_SELL) error - ", ErrorDescription(GetLastError())); } }else Print("OrderSelect() error - ", ErrorDescription(GetLastError())); // TrailingStop // BreakEven if(gainforbe > 0) for(i=0; i < OrdersTotal(); i++) if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)){ if(OrderSymbol() == symbol) if(OrderMagicNumber() == magic) if(OrderType() == OP_BUY){ if(MathRound((OrderClosePrice()-OrderOpenPrice())/_Point) >= gainforbe) if(MathRound((OrderStopLoss()-OrderOpenPrice())/_Point) < pipsbe) if(!OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice()+pipsbe*_Point, OrderTakeProfit(), OrderExpiration(), Blue)) Print("OrderModify(OP_BUY) error - ", ErrorDescription(GetLastError())); }else if(OrderType() == OP_SELL){ if(MathRound((OrderOpenPrice()-OrderClosePrice())/_Point) >= gainforbe) if(MathRound((OrderOpenPrice()-OrderStopLoss())/_Point) < pipsbe) if(!OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice()-pipsbe*_Point, OrderTakeProfit(), OrderExpiration(), Red)) Print("OrderModify(OP_SELL) error - ", ErrorDescription(GetLastError())); } }else Print("OrderSelect() error - ", ErrorDescription(GetLastError())); // BreakEven if(_send_ok){ _long = false; _short = false; } Comment(_cm); return(0); } bool _ip(int type, string symbol, int magic) { for(int i=OrdersTotal()-1; i >= 0; i--) if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)){ if(OrderType() == type) if(OrderSymbol() == symbol) if(OrderMagicNumber() == magic) return(true); }else Print("OrderSelect() error - ", ErrorDescription(GetLastError())); return(false); } void _fa(string symbol, int magic, bool manualmode=false) // Flat all { for(int i=OrdersTotal()-1; i >= 0; i--) if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)){ if(OrderSymbol() == symbol) if(OrderMagicNumber() == magic||manualmode) if(OrderType() <= OP_SELL) _OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), Slippage, Gray); else _OrderDelete(OrderTicket()); }else Print("OrderSelect() error - ", ErrorDescription(GetLastError())); } double _sl(int type, string symbol, double price, int stoploss, int offset=0) { if(type == OP_BUY||type == OP_BUYSTOP||type == OP_BUYLIMIT) if(stoploss > 0) return(price-(stoploss+offset)*MarketInfo(symbol, MODE_POINT)); else return(0.0); else if(type == OP_SELL||type == OP_SELLSTOP||type == OP_SELLLIMIT) if(stoploss > 0) return(price+(stoploss+offset)*MarketInfo(symbol, MODE_POINT)); else return(0.0); return(0.0); } double _tp(int type, string symbol, double price, int takeprofit, int offset=0) { if(type == OP_BUY) if(takeprofit > 0||type == OP_BUYSTOP||type == OP_BUYLIMIT) return(price+(takeprofit+offset)*MarketInfo(symbol, MODE_POINT)); else return(0.0); else if(type == OP_SELL||type == OP_SELLSTOP||type == OP_SELLLIMIT) if(takeprofit > 0) return(price-(takeprofit+offset)*MarketInfo(symbol, MODE_POINT)); else return(0.0); return(0.0); } double _nv(string symbol, double lots, bool return_zero=false){ // Adjust trade volume to broker. Take into account minimum & maximum position size. double step = MarketInfo(symbol, MODE_LOTSTEP); double min = MarketInfo(symbol, MODE_MINLOT); double max = MarketInfo(symbol, MODE_MAXLOT); if(step > 0) if(max > 0) if(return_zero) return(MathMin(MathRound(lots/step)*step, max)); else if(min > 0) // When you don't want return 0 lots (default) return(MathMax(MathMin(MathRound(lots/step)*step, max), min)); return(lots); } #include <stderror.mqh> int _OrderSend(string symbol, int cmd, double lots, double price, int slippage, double stoploss, double takeprofit, string comment, int magic, datetime expiration, color cl) { int ticket = OrderSend(symbol, cmd, lots, price, slippage, stoploss, takeprofit, comment, magic, expiration, cl); if(ticket < 0){ int err = GetLastError(); Print("ERROR OrderSend #",err,": ", ErrorDescription(err),_strcmd(cmd, symbol, price)); } return(ticket); } string _strcmd(int cmd, string symbol, double price) { int _mode; int _d = MarketInfo(symbol, Digits); string _str = ""; switch(cmd) { case OP_BUY: _mode = MODE_ASK; _str = "; BUY @"+DoubleToStr(price, _d); break; case OP_SELL: _mode = MODE_BID; _str = "; BUY @"+DoubleToStr(price, _d); break; default: break; } _str = _str +"; market @" + DoubleToStr(MarketInfo(symbol, _mode), _d); return(_str); } bool _OrderClose(int ticket, double lots, double price, int slippage, color cl=CLR_NONE) { bool result = OrderClose(ticket, lots, price, slippage, cl); if(!result){ int err = GetLastError(); Print("ERROR OrderClose #",err,": ", ErrorDescription(err)); } return(result); } bool _OrderDelete(int ticket) { bool result = OrderDelete(ticket); if(!result){ int err = GetLastError(); Print("ERROR OrderDelete #",err,": ", ErrorDescription(err)); } return(result); } #import "kernel32.dll" int GetTimeZoneInformation(int& TZInfoArray[]); #import #define TIME_ZONE_ID_UNKNOWN 0 #define TIME_ZONE_ID_STANDARD 1 #define TIME_ZONE_ID_DAYLIGHT 2 // Local timezone in hours, adjusting for daylight saving double TimeZoneLocal() { int TZInfoArray[43]; switch(GetTimeZoneInformation(TZInfoArray)) { case TIME_ZONE_ID_UNKNOWN: Print("Error obtaining PC timezone from GetTimeZoneInformation in kernel32.dll. Returning 0"); return(0); case TIME_ZONE_ID_STANDARD: return(TZInfoArray[0]/(-60.0)); case TIME_ZONE_ID_DAYLIGHT: return((TZInfoArray[0]+TZInfoArray[42])/(-60.0)); default: Print("Unkown return value from GetTimeZoneInformation in kernel32.dll. Returning 0"); return(0); } } // Server timezone in hours double TimeZoneServer() { int ServerToLocalDiffMinutes = (TimeCurrent()-TimeLocal())/60; // round to nearest 30 minutes to allow for inaccurate PC clock int nHalfHourDiff = MathRound(ServerToLocalDiffMinutes/30.0); ServerToLocalDiffMinutes = nHalfHourDiff*30; return(TimeZoneLocal() + ServerToLocalDiffMinutes/60.0); } // Uses local PC time, local PC timezone, and server time to calculate GMT time at arrival of last tick datetime TimeGMT() { // two ways of calculating // 1. From PC time, which may not be accurate // 2. From server time. Most accurate except when server is down on weekend datetime dtGmtFromLocal = TimeLocal() - TimeZoneLocal()*3600; datetime dtGmtFromServer = TimeCurrent() - TimeZoneServer()*3600; // return local-derived value if server value is out by more than 5 minutes, eg during weekend if (dtGmtFromLocal > dtGmtFromServer + 300) { return(dtGmtFromLocal); } else { return(dtGmtFromServer); } } //+---- Programmed by Michal Rutka @ MQLService.com -----------------+
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
Indicator Curves created:
Indicators Used:
Custom Indicators Used:
kernel32
Order Management characteristics:
It Closes Orders by itself
Checks for the total of open orders
It can change open orders parameters, due to possible stepping strategy
It automatically opens orders when conditions are reached
Other Features: