ICTLibraryEasy/Examples/ETN/Main.mqh
Nique_372 965b366299
2026-01-02 10:20:52 -05:00

188 lines
7.6 KiB
MQL5

//+------------------------------------------------------------------+
//| 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;
}
}
//+------------------------------------------------------------------+