//+------------------------------------------------------------------+ //| Strategy: Paulo BB.mq5 | //| Paulo Souza | //| https://www.pensador.com/frases_de_buda_inspiracionais/| //+------------------------------------------------------------------+ #property copyright "CopyRights para Katie EA" #property link "" #property version "3.00" #property description "Alvos definidos para 35pts(gain) 60pts(loss), alterar esses dados pode implicar na perca de capital." #property description "................n é precisa entrar para historia para fazer um mundo melhor........................." int LotDigits; //initialized in OnInit int NextOpenTradeAfterBars = 10; //next open trade after time datetime LastTradeTime = 0; input int Começar_apartir_de_hora = 12; //time of the day input int Começar_apartir_de_Minuto = 00; //time of the day input int Terminar_Hora = 16; //time of the day input int TOD_To_Min = 15; //time of the day input double Numero_Contratos = 1; int MaxSlippage = 3; //adjusted in OnInit int MaxSlippage_; bool crossed[2]; //initialized to true, used in function Cross bool Audible_Alerts = true; int MaxOpenTrades = 1; int MaxLongTrades = 1000; int MaxShortTrades = 1000; int MaxPendingOrders = 1000; bool Hedging = false; int OrderRetry = 5; //# of retries if sending order returns error int OrderWait = 5; //# of seconds to wait if sending order returns error int Bands_handle; double Bands_Upper[]; bool inTimeInterval(datetime t, int TOD_From_Hour, int TOD_From_Min, int TOD_To_Hour, int TOD_To_Min) { string TOD = TimeToString(t, TIME_MINUTES); string TOD_From = StringFormat("%02d", TOD_From_Hour)+":"+StringFormat("%02d", TOD_From_Min); string TOD_To = StringFormat("%02d", TOD_To_Hour)+":"+StringFormat("%02d", TOD_To_Min); return((StringCompare(TOD, TOD_From) >= 0 && StringCompare(TOD, TOD_To) <= 0) || (StringCompare(TOD_From, TOD_To) > 0 && ((StringCompare(TOD, TOD_From) >= 0 && StringCompare(TOD, "23:59") <= 0) || (StringCompare(TOD, "00:00") >= 0 && StringCompare(TOD, TOD_To) <= 0)))); } 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+" | katie Scalper M-Indice 2018 @ "+Symbol()+","+Period()+" | "+message); } else if(type == "order") { Print(type+" | katie Scalper M-Indice 2018 @ "+Symbol()+","+Period()+" | "+message); if(Audible_Alerts) Alert(type+" | katie Scalper M-Indice 2018 @ "+Symbol()+","+Period()+" | "+message); } 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) == Numero_Magico && 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) != Numero_Magico || 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 = Numero_Magico; 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 #"+Numero_Magico); return(result.order); } int myOrderModifyRel(ENUM_ORDER_TYPE type, ulong ticket, double SL, double TP) //works for positions and orders, modify SL and TP (relative to open 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 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, convert relative to absolute double openprice = (type <= 1) ? PositionGetDouble(POSITION_PRICE_OPEN) : OrderGetDouble(ORDER_PRICE_OPEN); if(((type <= 1) ? PositionGetInteger(POSITION_TYPE) : OrderGetInteger(ORDER_TYPE)) % 2 == 0) //buy { if(NormalizeDouble(SL, Digits()) != 0) SL = openprice - SL; if(NormalizeDouble(TP, Digits()) != 0) TP = openprice + TP; } else //sell { if(NormalizeDouble(SL, Digits()) != 0) SL = openprice + SL; if(NormalizeDouble(TP, Digits()) != 0) TP = openprice - TP; } 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); } 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); } //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { bool prototipo=true; // true só roda em demo, false conta real long account=0; // Account login long periodo_licenca=60; // Qtd dias licença datetime dt_expiracao=__DATE__+PeriodSeconds(PERIOD_D1)*periodo_licenca; // Data de expiração ENUM_ACCOUNT_TRADE_MODE tradeMode=(ENUM_ACCOUNT_TRADE_MODE)AccountInfoInteger(ACCOUNT_TRADE_MODE); if(prototipo) { if(tradeMode==ACCOUNT_TRADE_MODE_REAL) { Alert(__FUNCTION__,": Licença somente para conta DEMO"); return(INIT_FAILED); } dt_expiracao=__DATE__+PeriodSeconds(PERIOD_D1)*60; // Expira 60 dias após a compilação if(TimeCurrent()>dt_expiracao) { Alert(__FUNCTION__,": licença DEMO expirada"); return(INIT_FAILED); } } if(!prototipo) { if(AccountInfoInteger(ACCOUNT_LOGIN)!=account) { Alert(__FUNCTION__,": Sua conta não esta aurotizada"); return(INIT_FAILED); } if(TimeCurrent()>dt_expiracao) { Alert(__FUNCTION__,": Licença expirada"); return(INIT_FAILED); } } MaxSlippage_ = MaxSlippage; //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; LastTradeTime = 0; int i; //initialize crossed for (i = 0; i < ArraySize(crossed); i++) crossed[i] = true; Bands_handle = iBands(NULL, PERIOD_CURRENT, 14, 0, 1, PRICE_CLOSE); if(Bands_handle < 0) { Print("The creation of iBands has failed: Bands_handle=", 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 SL; double TP; if(CopyBuffer(Bands_handle, UPPER_BAND, 0, 200, Bands_Upper) <= 0) return; ArraySetAsSeries(Bands_Upper, true); //Open Buy Order (Katie Esta Comprando), instant signal is tested first if(Cross(0, getBid() > Bands_Upper[0]) //Price crosses above Bollinger Bands ) { MqlTick last_tick; SymbolInfoTick(Symbol(), last_tick); price = last_tick.ask; SL = 60 * Point(); //Stop Loss = value in points (relative to price) TP = 35 * Point(); //Take Profit = value in points (relative to price) if(TimeCurrent() - LastTradeTime < NextOpenTradeAfterBars * PeriodSeconds()) return; //next open trade after time if(!inTimeInterval(TimeCurrent(), Começar_apartir_de_hora, Começar_apartir_de_Minuto, Terminar_Hora, TOD_To_Min)) return; //open trades only at specific times of the day if(TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) && MQLInfoInteger(MQL_TRADE_ALLOWED)) { ticket = myOrderSend(ORDER_TYPE_BUY, price, Numero_Contratos, "Katie Esta Comprando"); if(ticket == 0) return; } else //not autotrading => only send alert myAlert("order", "Katie Esta Comprando"); LastTradeTime = TimeCurrent(); myOrderModifyRel(ORDER_TYPE_BUY, ticket, 0, TP); myOrderModifyRel(ORDER_TYPE_BUY, ticket, SL, 0); } //Open Sell Order (Katie Esta Vendendo), instant signal is tested first if(Cross(1, getBid() < Bands_Upper[0]) //Price crosses below Bollinger Bands ) { MqlTick last_tick; SymbolInfoTick(Symbol(), last_tick); price = last_tick.bid; SL = 60 * Point(); //Stop Loss = value in points (relative to price) TP = 35 * Point(); //Take Profit = value in points (relative to price) if(TimeCurrent() - LastTradeTime < NextOpenTradeAfterBars * PeriodSeconds()) return; //next open trade after time if(!inTimeInterval(TimeCurrent(), Começar_apartir_de_hora, Começar_apartir_de_Minuto, Terminar_Hora, TOD_To_Min)) return; //open trades only at specific times of the day if(TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) && MQLInfoInteger(MQL_TRADE_ALLOWED)) { ticket = myOrderSend(ORDER_TYPE_SELL, price, Numero_Contratos, "Katie Esta Vendendo"); if(ticket == 0) return; } else //not autotrading => only send alert myAlert("order", "Katie Esta Vendendo"); LastTradeTime = TimeCurrent(); myOrderModifyRel(ORDER_TYPE_SELL, ticket, 0, TP); myOrderModifyRel(ORDER_TYPE_SELL, ticket, SL, 0); } }