//+------------------------------------------------------------------+ //| Strategy: Jas_MT5_OceanBaseline.mq5 | //| Created with EABuilder.com | //| http://eabuilder.com | //+------------------------------------------------------------------+ #property copyright "Created with EABuilder.com" #property link "http://eabuilder.com" #property version "1.00" #property description "" input int Shift = 1; input int Stoploss_ATRPeriod = 10; input double Stoploss_ATRMultiplier = 1.5; input int TakeProfit_ATRPeriod = 10; input double TakeProfit_ATRMultiplier = 1; input int NMAPeriod = 40; input int TEMAPeriod = 1; input int TwoPoleSmoothPeriod = 8; int LotDigits; //initialized in OnInit int MagicNumber = 412658; input double MM_Percent = 1; int MaxSlippage = 3; //adjusted in OnInit int MaxSlippage_; bool crossed[4]; //initialized to true, used in function Cross int MaxOpenTrades = 1; int MaxLongTrades = 1000; int MaxShortTrades = 1000; int MaxPendingOrders = 1000; bool Hedging = true; int OrderRetry = 5; //# of retries if sending order returns error int OrderWait = 5; //# of seconds to wait if sending order returns error double myPoint; //initialized in OnInit double Close[]; int ocn__nma_smooth_handle; double ocn__nma_smooth[]; int ATR_handle; double ATR[]; int ATR_handle2; double ATR2[]; double MM_Size(double SL) //Risk % per trade, SL = relative Stop Loss to calculate risk { double MaxLot = SymbolInfoDouble(Symbol(), SYMBOL_VOLUME_MAX); double MinLot = SymbolInfoDouble(Symbol(), SYMBOL_VOLUME_MIN); double tickvalue = SymbolInfoDouble(Symbol(), SYMBOL_TRADE_TICK_VALUE); double ticksize = SymbolInfoDouble(Symbol(), SYMBOL_TRADE_TICK_SIZE); double lots = MM_Percent * 1.0 / 100 * AccountInfoDouble(ACCOUNT_BALANCE) / (SL / ticksize * tickvalue); if(lots > MaxLot) lots = MaxLot; if(lots < MinLot) lots = MinLot; return(lots); } bool Cross(int i, bool condition) //returns true if "condition" is true and was false in the previous call { bool ret = condition && !crossed[i]; crossed[i] = condition; return(ret); } void myAlert(string type, string message) { if(type == "print") Print(message); else if(type == "error") { Print(type+" | Jas_MT5_OceanBaseline @ "+Symbol()+","+IntegerToString(Period())+" | "+message); } else if(type == "order") { } else if(type == "modify") { } } int TradesCount(ENUM_ORDER_TYPE type) //returns # of open trades for order type, current symbol and magic number { if(type <= 1) { if (PositionSelect(Symbol()) && PositionGetInteger(POSITION_MAGIC) == MagicNumber && PositionGetInteger(POSITION_TYPE) == type) return(1); else return(0); } else { int result = 0; int total = OrdersTotal(); for(int i = 0; i < total; i++) { if(OrderGetTicket(i) <= 0) continue; if(OrderGetInteger(ORDER_MAGIC) != MagicNumber || OrderGetString(ORDER_SYMBOL) != Symbol() || OrderGetInteger(ORDER_TYPE) != type) continue; result++; } return(result); } } ulong myOrderSend(ENUM_ORDER_TYPE type, double price, double volume, string ordername) //send order, return ticket ("price" is irrelevant for market orders) { if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) || !MQLInfoInteger(MQL_TRADE_ALLOWED)) return(0); int retries = 0; int long_trades = TradesCount(ORDER_TYPE_BUY); int short_trades = TradesCount(ORDER_TYPE_SELL); int long_pending = TradesCount(ORDER_TYPE_BUY_LIMIT) + TradesCount(ORDER_TYPE_BUY_STOP) + TradesCount(ORDER_TYPE_BUY_STOP_LIMIT); int short_pending = TradesCount(ORDER_TYPE_SELL_LIMIT) + TradesCount(ORDER_TYPE_SELL_STOP) + TradesCount(ORDER_TYPE_SELL_STOP_LIMIT); string ordername_ = ordername; if(ordername != "") ordername_ = "("+ordername+")"; //test Hedging if(!Hedging && ((type % 2 == 0 && short_trades + short_pending > 0) || (type % 2 == 1 && long_trades + long_pending > 0))) { myAlert("print", "Order"+ordername_+" not sent, hedging not allowed"); return(0); } //test maximum trades if((type % 2 == 0 && long_trades >= MaxLongTrades) || (type % 2 == 1 && short_trades >= MaxShortTrades) || (long_trades + short_trades >= MaxOpenTrades) || (type > 1 && long_pending + short_pending >= MaxPendingOrders)) { myAlert("print", "Order"+ordername_+" not sent, maximum reached"); return(0); } //prepare to send order MqlTradeRequest request; ZeroMemory(request); request.action = (type <= 1) ? TRADE_ACTION_DEAL : TRADE_ACTION_PENDING; //set allowed filling type int filling = (int)SymbolInfoInteger(Symbol(),SYMBOL_FILLING_MODE); if(request.action == TRADE_ACTION_DEAL && (filling & 1) != 1) request.type_filling = ORDER_FILLING_IOC; request.magic = MagicNumber; request.symbol = Symbol(); request.volume = NormalizeDouble(volume, LotDigits); request.sl = 0; request.tp = 0; request.deviation = MaxSlippage_; request.type = type; request.comment = ordername; int expiration=(int)SymbolInfoInteger(Symbol(), SYMBOL_EXPIRATION_MODE); if((expiration & SYMBOL_EXPIRATION_GTC) != SYMBOL_EXPIRATION_GTC) { request.type_time = ORDER_TIME_DAY; request.type_filling = ORDER_FILLING_RETURN; } MqlTradeResult result; ZeroMemory(result); while(!OrderSuccess(result.retcode) && retries < OrderRetry+1) { //refresh price before sending order MqlTick last_tick; SymbolInfoTick(Symbol(), last_tick); if(type == ORDER_TYPE_BUY) price = last_tick.ask; else if(type == ORDER_TYPE_SELL) price = last_tick.bid; else if(price < 0) //invalid price for pending order { myAlert("order", "Order"+ordername_+" not sent, invalid price for pending order"); return(0); } request.price = NormalizeDouble(price, Digits()); OrderSend(request, result); if(!OrderSuccess(result.retcode)) { myAlert("print", "OrderSend"+ordername_+" error: "+result.comment); Sleep(OrderWait*1000); } retries++; } if(!OrderSuccess(result.retcode)) { myAlert("error", "OrderSend"+ordername_+" failed "+(OrderRetry+1)+" times; error: "+result.comment); return(0); } string typestr[8] = {"Buy", "Sell", "Buy Limit", "Sell Limit", "Buy Stop", "Sell Stop", "Buy Stop Limit", "Sell Stop Limit"}; myAlert("order", "Order sent"+ordername_+": "+typestr[type]+" "+Symbol()+" Magic #"+MagicNumber); return(result.order); } int myOrderModify(ENUM_ORDER_TYPE type, ulong ticket, double SL, double TP) //modify SL and TP (absolute price), zero targets do not modify, ticket is irrelevant for open positions { if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) || !MQLInfoInteger(MQL_TRADE_ALLOWED)) return(-1); int retries = 0; int err; SL = NormalizeDouble(SL, Digits()); TP = NormalizeDouble(TP, Digits()); if(SL < 0) SL = 0; if(TP < 0) TP = 0; //prepare to select order Sleep(10); if((type <= 1 && !PositionSelect(Symbol())) || (type > 1 && !OrderSelect(ticket))) { err = GetLastError(); myAlert("error", "PositionSelect / OrderSelect failed; error #"+err); return(-1); } //ignore open positions other than "type" if (type <= 1 && PositionGetInteger(POSITION_TYPE) != type) return(0); //prepare to modify order double currentSL = (type <= 1) ? PositionGetDouble(POSITION_SL) : OrderGetDouble(ORDER_SL); double currentTP = (type <= 1) ? PositionGetDouble(POSITION_TP) : OrderGetDouble(ORDER_TP); if(NormalizeDouble(SL, Digits()) == 0) SL = currentSL; //not to modify if(NormalizeDouble(TP, Digits()) == 0) TP = currentTP; //not to modify if(NormalizeDouble(SL - currentSL, Digits()) == 0 && NormalizeDouble(TP - currentTP, Digits()) == 0) return(0); //nothing to do MqlTradeRequest request; ZeroMemory(request); request.action = (type <= 1) ? TRADE_ACTION_SLTP : TRADE_ACTION_MODIFY; if (type > 1) request.order = ticket; else request.position = PositionGetInteger(POSITION_TICKET); request.symbol = Symbol(); request.price = (type <= 1) ? PositionGetDouble(POSITION_PRICE_OPEN) : OrderGetDouble(ORDER_PRICE_OPEN); request.sl = NormalizeDouble(SL, Digits()); request.tp = NormalizeDouble(TP, Digits()); request.deviation = MaxSlippage_; MqlTradeResult result; ZeroMemory(result); while(!OrderSuccess(result.retcode) && retries < OrderRetry+1) { OrderSend(request, result); if(!OrderSuccess(result.retcode)) { err = GetLastError(); myAlert("print", "OrderModify error #"+err); Sleep(OrderWait*1000); } retries++; } if(!OrderSuccess(result.retcode)) { myAlert("error", "OrderModify failed "+(OrderRetry+1)+" times; error #"+err); return(-1); } string alertstr = "Order modify: ticket="+ticket; if(NormalizeDouble(SL, Digits()) != 0) alertstr = alertstr+" SL="+SL; if(NormalizeDouble(TP, Digits()) != 0) alertstr = alertstr+" TP="+TP; myAlert("modify", alertstr); return(0); } void myOrderClose(ENUM_ORDER_TYPE type, int volumepercent, string ordername) //close open orders for current symbol, magic number and "type" (ORDER_TYPE_BUY or ORDER_TYPE_SELL) { if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) || !MQLInfoInteger(MQL_TRADE_ALLOWED)) return; if (type > 1) { myAlert("error", "Invalid type in myOrderClose"); return; } bool success = false; string ordername_ = ordername; if(ordername != "") ordername_ = "("+ordername+")"; if (!PositionSelect(Symbol())) return; if(PositionGetInteger(POSITION_MAGIC) != MagicNumber || PositionGetInteger(POSITION_TYPE) != type) return; MqlTick last_tick; SymbolInfoTick(Symbol(), last_tick); double price = (type == ORDER_TYPE_SELL) ? last_tick.ask : last_tick.bid; MqlTradeRequest request; ZeroMemory(request); request.action = TRADE_ACTION_DEAL; request.position = PositionGetInteger(POSITION_TICKET); //set allowed filling type int filling = (int)SymbolInfoInteger(Symbol(),SYMBOL_FILLING_MODE); if(request.action == TRADE_ACTION_DEAL && (filling & 1) != 1) request.type_filling = ORDER_FILLING_IOC; request.magic = MagicNumber; request.symbol = Symbol(); request.volume = NormalizeDouble(PositionGetDouble(POSITION_VOLUME)*volumepercent * 1.0 / 100, LotDigits); if (NormalizeDouble(request.volume, LotDigits) == 0) return; request.price = NormalizeDouble(price, Digits()); request.sl = 0; request.tp = 0; request.deviation = MaxSlippage_; request.type = 1-type; //opposite type request.comment = ordername; MqlTradeResult result; ZeroMemory(result); OrderSend(request, result); success = OrderSuccess(result.retcode); if(!success) { myAlert("error", "OrderClose"+ordername_+" failed; error: "+result.comment); } string typestr[8] = {"Buy", "Sell", "Buy Limit", "Sell Limit", "Buy Stop", "Sell Stop", "Buy Stop Limit", "Sell Stop Limit"}; if(success) myAlert("order", "Orders closed"+ordername_+": "+typestr[type]+" "+Symbol()+" Magic #"+MagicNumber); } bool NewBar() { datetime Time[]; ArraySetAsSeries(Time, true); CopyTime(Symbol(), Period(), 0, 1, Time); static datetime LastTime = 0; bool ret = Time[0] > LastTime && LastTime > 0; LastTime = Time[0]; return(ret); } bool OrderSuccess(uint retcode) { return(retcode == TRADE_RETCODE_PLACED || retcode == TRADE_RETCODE_DONE || retcode == TRADE_RETCODE_DONE_PARTIAL || retcode == TRADE_RETCODE_NO_CHANGES); } double getBid() { MqlTick last_tick; SymbolInfoTick(Symbol(), last_tick); return(last_tick.bid); } double getAsk() { MqlTick last_tick; SymbolInfoTick(Symbol(), last_tick); return(last_tick.ask); } //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { MaxSlippage_ = MaxSlippage; //initialize myPoint myPoint = Point(); if(Digits() == 5 || Digits() == 3) { myPoint *= 10; MaxSlippage_ *= 10; } //initialize LotDigits double LotStep = SymbolInfoDouble(Symbol(), SYMBOL_VOLUME_STEP); if(LotStep >= 1) LotDigits = 0; else if(LotStep >= 0.1) LotDigits = 1; else if(LotStep >= 0.01) LotDigits = 2; else LotDigits = 3; int i; //initialize crossed for (i = 0; i < ArraySize(crossed); i++) crossed[i] = true; ocn__nma_smooth_handle = iCustom(NULL, PERIOD_CURRENT, "ocn_-_nma_smooth", "", NMAPeriod, TEMAPeriod, TwoPoleSmoothPeriod); if(ocn__nma_smooth_handle < 0) { Print("The creation of ocn__nma_smooth has failed: ocn__nma_smooth_handle=", INVALID_HANDLE); Print("Runtime error = ", GetLastError()); return(INIT_FAILED); } ATR_handle = iATR(NULL, PERIOD_CURRENT, Stoploss_ATRPeriod); if(ATR_handle < 0) { Print("The creation of iATR has failed: ATR_handle=", INVALID_HANDLE); Print("Runtime error = ", GetLastError()); return(INIT_FAILED); } ATR_handle2 = iATR(NULL, PERIOD_CURRENT, TakeProfit_ATRPeriod); if(ATR_handle2 < 0) { Print("The creation of iATR has failed: ATR_handle2=", INVALID_HANDLE); Print("Runtime error = ", GetLastError()); return(INIT_FAILED); } return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { ulong ticket = 0; double price; double TradeSize; double SL; double TP; bool isNewBar = NewBar(); if(CopyClose(Symbol(), PERIOD_CURRENT, 0, 200, Close) <= 0) return; ArraySetAsSeries(Close, true); if(CopyBuffer(ocn__nma_smooth_handle, 0, 0, 200, ocn__nma_smooth) <= 0) return; ArraySetAsSeries(ocn__nma_smooth, true); if(CopyBuffer(ATR_handle, 0, 0, 200, ATR) <= 0) return; ArraySetAsSeries(ATR, true); if(CopyBuffer(ATR_handle2, 0, 0, 200, ATR2) <= 0) return; ArraySetAsSeries(ATR2, true); //Close Long Positions, instant signal is tested first if(isNewBar //Send order when new bar opens && Cross(1, Close[1] < ocn__nma_smooth[Shift]) //Candlestick Close crosses below ocn_-_nma_smooth ) { if(TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) && MQLInfoInteger(MQL_TRADE_ALLOWED)) myOrderClose(ORDER_TYPE_BUY, 100, ""); else //not autotrading => only send alert myAlert("order", ""); } //Close Short Positions, instant signal is tested first if(isNewBar //Send order when new bar opens && Cross(0, Close[1] > ocn__nma_smooth[Shift]) //Candlestick Close crosses above ocn_-_nma_smooth ) { if(TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) && MQLInfoInteger(MQL_TRADE_ALLOWED)) myOrderClose(ORDER_TYPE_SELL, 100, ""); else //not autotrading => only send alert myAlert("order", ""); } //Open Buy Order, instant signal is tested first if(isNewBar //Send order when new bar opens && Cross(2, Close[1] > ocn__nma_smooth[Shift]) //Candlestick Close crosses above ocn_-_nma_smooth ) { MqlTick last_tick; SymbolInfoTick(Symbol(), last_tick); price = last_tick.ask; SL = getBid() - ATR[0] * Stoploss_ATRMultiplier; //Stop Loss = Price - Average True Range * fixed value TradeSize = MM_Size(price - SL); TP = getAsk() + ATR2[0] * TakeProfit_ATRMultiplier; //Take Profit = Price + Average True Range * fixed value if(TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) && MQLInfoInteger(MQL_TRADE_ALLOWED)) { ticket = myOrderSend(ORDER_TYPE_BUY, price, TradeSize, ""); if(ticket == 0) return; } else //not autotrading => only send alert myAlert("order", ""); myOrderModify(ORDER_TYPE_BUY, ticket, SL, 0); myOrderModify(ORDER_TYPE_BUY, ticket, 0, TP); } //Open Sell Order, instant signal is tested first if(isNewBar //Send order when new bar opens && Cross(3, Close[1] < ocn__nma_smooth[Shift]) //Candlestick Close crosses below ocn_-_nma_smooth ) { MqlTick last_tick; SymbolInfoTick(Symbol(), last_tick); price = last_tick.bid; SL = getBid() + ATR[0] * Stoploss_ATRMultiplier; //Stop Loss = Price + Average True Range * fixed value TradeSize = MM_Size(SL - price); TP = getAsk() - ATR2[0] * TakeProfit_ATRMultiplier; //Take Profit = Price - Average True Range * fixed value if(TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) && MQLInfoInteger(MQL_TRADE_ALLOWED)) { ticket = myOrderSend(ORDER_TYPE_SELL, price, TradeSize, ""); if(ticket == 0) return; } else //not autotrading => only send alert myAlert("order", ""); myOrderModify(ORDER_TYPE_SELL, ticket, SL, 0); myOrderModify(ORDER_TYPE_SELL, ticket, 0, TP); } } //+------------------------------------------------------------------+