//+------------------------------------------------------------------+ //| Main.mqh | //| Copyright 2025, Niquel Mendoza. | //| https://www.mql5.com/es/users/nique_372/news | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, Niquel Mendoza." #property link "https://www.mql5.com/es/users/nique_372/news" #property strict //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ #include "Defines.mqh" //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class CEstrategia : public CStrategyBase { private: double asia_mitad; double diff_mitad; double entry_price; double rr_tp_sl; int hora_inicio_ny, min_inicio_ny; ENUM_TYPE_TP_SL type_tp_sl; bool is_trade; datetime fin_ny; ENUM_POSITION_TYPE last_open; bool is_open; //--- void OpenOrder(ENUM_POSITION_TYPE type); public: CEstrategia(ulong magic_number_, string symbol_, ENUM_TIMEFRAMES timeframe_ = PERIOD_CURRENT, long chart_id_ = 0, int subiwn_ = 0, ulong max_deviation_ = NO_MAX_DEVIATION_DEFINED); void SetNy(int hora_init_ny, int min_init_ny); void SetGen(double rr_, ENUM_TYPE_TP_SL type_tp_sl_) { this.rr_tp_sl = rr_; this.type_tp_sl = type_tp_sl_; } void OnNewBar(const datetime &curr_time) override final; void OnTick(const datetime &curr_time) override final {} }; //+------------------------------------------------------------------+ CEstrategia::CEstrategia(ulong magic_number_, string symbol_, ENUM_TIMEFRAMES timeframe_ = PERIOD_CURRENT, long chart_id_ = 0, int subiwn_ = 0, ulong max_deviation_ = NO_MAX_DEVIATION_DEFINED) : CStrategyBase(magic_number_, symbol_, timeframe_, chart_id_, subiwn_, max_deviation_) { is_open = false; } //+------------------------------------------------------------------+ void CEstrategia::SetNy(int hora_init_ny, int min_init_ny) { this.hora_inicio_ny = hora_init_ny; this.min_inicio_ny = min_init_ny; } //+------------------------------------------------------------------+ void CEstrategia::OpenOrder(ENUM_POSITION_TYPE type) { ResetLastError(); SymbolInfoTick(this.m_symbol, m_tick); if(type == POSITION_TYPE_SELL) { double tp = 0, sl = 0; this.last_open = POSITION_TYPE_SELL; if(type_tp_sl == TP_SL_BY_STRATEGY_RR) { //--- primer paso tp tp = sesion_asia.GetMinSession() - diff_mitad; double diff_tp = entry_price - tp; //--- segundo paso sl sl = entry_price + (diff_tp / 2.0); //Relacion riesgo 1 : 2 para empezar con el sl double sl_diff = MathAbs(sl - entry_price); //--- recalculamos el tp para que quede 1:3 tp = entry_price - (sl_diff * rr_tp_sl); } else { tp = GetTP(entry_price, POSITION_TYPE_SELL, m_tick.time); sl = GetSL(entry_price, POSITION_TYPE_SELL, m_tick.time); } risk.SetStopLoss(sl - entry_price); double l = m_LOT_SIZE > 0.00 ? m_LOT_SIZE : risk.GetLote(ORDER_TYPE_SELL_LIMIT, entry_price, m_max_deviation, 0); datetime expiration = HoraYMinutoADatetime(hora_inicio_ny, min_inicio_ny, m_tick.time); //Pones la expiracion en el inicio de ni fin_ny = expiration; if(!m_trade.SellLimit(l, entry_price, this.m_symbol, sl, tp, ORDER_TIME_SPECIFIED, expiration, "Ea sell limit") ) LogError(StringFormat("Error al abrir sell limit, ultimo error = %d", GetLastError()), FUNCION_ACTUAL); } else if(type == POSITION_TYPE_BUY) { this.last_open = POSITION_TYPE_BUY; double tp = 0, sl = 0; if(type_tp_sl == TP_SL_BY_STRATEGY_RR) { //--- primer paso tp tp = sesion_asia.GetMaxSession() + diff_mitad; double diff_tp = MathAbs(tp - entry_price); //--- segundo paso sl sl = entry_price - (diff_tp / 2.0); //Relacion riesgo 1 : 2 para empezar con el sl double sl_diff = MathAbs(entry_price - sl); //--- recalculamos el tp para que quede 1:3 tp = entry_price + (sl_diff * rr_tp_sl); } else { tp = GetTP(entry_price, POSITION_TYPE_BUY, m_tick.time); sl = GetSL(entry_price, POSITION_TYPE_BUY, m_tick.time); } risk.SetStopLoss(entry_price - sl); double l = m_LOT_SIZE > 0.00 ? m_LOT_SIZE : risk.GetLote(ORDER_TYPE_BUY_LIMIT, entry_price, m_max_deviation, 0); datetime expiration = HoraYMinutoADatetime(hora_inicio_ny, min_inicio_ny, m_tick.time); //Pones la expiracion en el inicio de ni fin_ny = expiration; if(!m_trade.BuyLimit(l, entry_price, this.m_symbol, sl, tp, ORDER_TIME_SPECIFIED, expiration, "Ea buy limit")) LogError(StringFormat("Error al abrir buy limit, ultimo error = %d", GetLastError()), FUNCION_ACTUAL); } is_open = true; } //+------------------------------------------------------------------+ void CEstrategia::OnNewBar(const datetime &curr_time) { if(trading_session.IsInitSession()) //Paso 1 abrir operaciones { LogInfo("Inicio la sesion, poniendo las ordenes..", FUNCION_ACTUAL); LogInfo(StringFormat("Maximo %.*f | Minimo %.*f", m_digits, sesion_asia.GetMaxSession(), m_digits, sesion_asia.GetMinSession()), FUNCION_ACTUAL); this.asia_mitad = sesion_asia.GetMinSession() + (sesion_asia.GetRangeSession() / 2.0); double close_prev = iClose(this.m_symbol, this.m_timeframe, 1); LogInfo(StringFormat("La mitad de asia %.*f | El cierre anterior %.*f", m_digits, this.asia_mitad, m_digits, close_prev), FUNCION_ACTUAL); this.diff_mitad = (sesion_asia.GetRangeSession() / 2.0); if(close_prev > asia_mitad) { this.entry_price = sesion_asia.GetMaxSession(); OpenOrder(POSITION_TYPE_SELL); } else if(close_prev < asia_mitad) { this.entry_price = sesion_asia.GetMinSession(); OpenOrder(POSITION_TYPE_BUY); } } else if(trading_session.IsEndSession()) //Paso 2 modificar la orden si ha cambiado de posicion { LogInfo("Fin de la sesion, revisando si se cambio de direccion", FUNCION_ACTUAL); double close_prev = iClose(this.m_symbol, this.m_timeframe, 1); if(close_prev > asia_mitad && last_open == POSITION_TYPE_BUY) //Si la posicion inicial era buy limit y se detecta venta cambiamos { this.entry_price = sesion_asia.GetMaxSession(); LogInfo("La direccion del mercado a cambiado de compra - venta ", FUNCION_ACTUAL); CloseAllOrders(ALL_FLAGS_LIMITS, m_trade, m_magic_number); OpenOrder(POSITION_TYPE_SELL); } else if(close_prev < asia_mitad && last_open == POSITION_TYPE_SELL) { this.entry_price = sesion_asia.GetMinSession(); LogInfo("La direccion del mercado a cambiado de venta - compra", FUNCION_ACTUAL); CloseAllOrders(ALL_FLAGS_LIMITS, m_trade, m_magic_number); OpenOrder(POSITION_TYPE_BUY); } } if(!is_open) //Si no hay posiciones abiertas no ejecutamos el codigo que esta delante de esta condicion return; if(curr_time >= fin_ny) //Verificamos si la sesion de ny finaliza para cerrar todas las ordenes abiertas { risk.CloseAllPositions(); is_open = false; } } //+------------------------------------------------------------------+