ICTLibraryExamples/TradingLab/CrtTradingLab/Main.mqh
274 lines
10 KiB
MQL5
Nique_372
2025-11-26 07:19:36 -05:00
//+------------------------------------------------------------------+
//| 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
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
Nique_372
2026-11-06 17:08:44 -05:00
#include "Defines.mqh"
Nique_372
2025-11-26 07:19:36 -05:00
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
Nique_372
2026-10-23 21:51:38 -05:00
class CEstrategia : public TSN::CStrategyBase
Nique_372
2025-11-26 07:19:36 -05:00
{
private:
Nique_372
2026-11-06 17:08:44 -05:00
ENUM_CRT_STATE m_state;
bool m_draw_line; // dibuja la linea de roptura del modelo crt
Nique_372
2025-11-26 07:19:36 -05:00
ENUM_TIMEFRAMES m_timeframe_htf_crt;
Nique_372
2026-01-06 06:46:34 -05:00
int8_t m_index_controler_fast_htf_crt;
Nique_372
2025-11-26 07:19:36 -05:00
CrtModel m_current_crt_model;
int m_secods_in_period_htf;
//---
void CheckCrt();
//---
void Clean();
//---
void OpenOrder(ENUM_POSITION_TYPE type);
public:
Nique_372
2026-11-06 17:08:44 -05:00
CEstrategia(ulong magic_number_, string symbol_, bool draw_line, ENUM_TIMEFRAMES timeframe_ = PERIOD_CURRENT,
Nique_372
2025-11-26 07:19:36 -05:00
long chart_id_ = 0, int subwindow_ = 0, ulong max_deviation_ = NO_MAX_DEVIATION_DEFINED);
~CEstrategia(void);
//---
void Set(ENUM_TIMEFRAMES timeframe_crt_htf);
//---
Nique_372
2026-11-06 17:08:44 -05:00
void OnNewBar(const datetime curr_time) override final;
void OnTick(const datetime curr_time) override final { }
Nique_372
2025-11-26 07:19:36 -05:00
//---
Nique_372
2026-11-06 17:08:44 -05:00
void OnNewWeek(const datetime curr_time) override final;
Nique_372
2025-11-26 07:19:36 -05:00
//---
Nique_372
2026-11-06 17:08:44 -05:00
void OnInterupcion() override final;
Nique_372
2025-11-26 07:19:36 -05:00
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
Nique_372
2026-11-06 17:08:44 -05:00
CEstrategia::CEstrategia(ulong magic_number_, string symbol_, bool draw_line, ENUM_TIMEFRAMES timeframe_ = PERIOD_CURRENT,
Nique_372
2025-11-26 07:19:36 -05:00
long chart_id_ = 0, int subwindow_ = 0, ulong max_deviation_ = NO_MAX_DEVIATION_DEFINED)
: CStrategyBase(magic_number_, symbol_, timeframe_, chart_id_, subwindow_, max_deviation_, "TradingLabCrt"),
Nique_372
2026-11-06 17:08:44 -05:00
m_timeframe_htf_crt(WRONG_VALUE), m_index_controler_fast_htf_crt(INVALID_INDEX), m_draw_line(draw_line)
Nique_372
2025-11-26 07:19:36 -05:00
{
Nique_372
2026-11-06 17:08:44 -05:00
//---
Nique_372
2026-02-01 12:28:19 -05:00
CBasicEvents::RegisterEvent(&this, BASICEVENT_REG_FLAG_ON_NEW_WEEK);
Nique_372
2025-11-26 07:19:36 -05:00
Clean();
Nique_372
2026-11-06 17:08:44 -05:00
//---
m_current_crt_model.name = string(s_rand.nextUInt32()) + "_line_rop_"; // id propio
if(m_draw_line)
TSN::CNativeoGObjs::TrendCreate(m_chart_id, m_current_crt_model.name, m_subwindow, 0, 0, 0, 0, clrRed, STYLE_SOLID, 1, true, false, "LineaRop");
Nique_372
2025-11-26 07:19:36 -05:00
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
CEstrategia::~CEstrategia(void)
{
Nique_372
2026-02-01 12:28:19 -05:00
if(CBasicEvents::IsActive()) // CONSULTAMOS si aun esta activo
{
// Si esta activo entonces nos desuscribirremos
CBasicEvents::UnregisterEvent(&this, BASICEVENT_REG_FLAG_ON_NEW_WEEK);
}
Nique_372
2026-11-06 17:08:44 -05:00
//--- Linea de roptura (solo si se dibujo)
if(m_draw_line)
::ObjectDelete(m_chart_id, m_current_crt_model.name);
Nique_372
2025-11-26 07:19:36 -05:00
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CEstrategia::Set(ENUM_TIMEFRAMES timeframe_crt_htf)
{
Nique_372
2026-01-06 06:46:34 -05:00
g_new_bar_manager.GetPosExecute(timeframe_crt_htf, m_index_controler_fast_htf_crt);
Nique_372
2025-11-26 07:19:36 -05:00
m_timeframe_htf_crt = timeframe_crt_htf;
Nique_372
2026-11-06 17:08:44 -05:00
m_secods_in_period_htf = TSN::CTimeframe::PeriodSecondsFast(timeframe_crt_htf);
Nique_372
2025-11-26 07:19:36 -05:00
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CEstrategia::OnInterupcion()
{
g_fvg.SetParo();
g_ob.SetParo();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
Nique_372
2026-02-14 17:50:28 -05:00
void CEstrategia::OnNewWeek(const datetime curr_time)
Nique_372
2025-11-26 07:19:36 -05:00
{
g_fvg.DeleteAll();
g_ob.DeleteAll();
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CEstrategia::Clean(void)
{
Nique_372
2026-11-06 17:08:44 -05:00
m_state = CRT_STATE_ESPERAR_MODELO;
Nique_372
2025-11-26 07:19:36 -05:00
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void CEstrategia::CheckCrt(void)
{
//---
m_current_crt_model.direction = WRONG_VALUE;
m_current_crt_model.price_to_superate = 0.00;
//---
const double prev_prev_high = iHigh(m_symbol, m_timeframe_htf_crt, 2);
const double prev_prev_low = iLow(m_symbol, m_timeframe_htf_crt, 2);
//---
const double prev_high = iHigh(m_symbol, m_timeframe_htf_crt, 1);
const double prev_low = iLow(m_symbol, m_timeframe_htf_crt, 1);
const double prev_close = iClose(m_symbol, m_timeframe_htf_crt, 1);
const double prev_open = iOpen(m_symbol, m_timeframe_htf_crt, 1);
//---
if(prev_close > prev_open) // Buscar manipuacion de bajo modelo compra
{
if(prev_prev_low > prev_low && prev_open > prev_prev_low && prev_prev_high > prev_high)
{
m_current_crt_model.direction = CRT_DIR_ARRIBA;
m_current_crt_model.price_to_superate = prev_high; // Roptura de este precio
Nique_372
2026-11-06 17:08:44 -05:00
if(m_draw_line)
{
const datetime prev_time = iTime(m_symbol, m_timeframe_htf_crt, 1);
Nique_372
2025-11-26 07:19:36 -05:00
Nique_372
2026-11-06 17:08:44 -05:00
ObjectMove(m_chart_id, m_current_crt_model.name, 0, prev_time, prev_high);
ObjectMove(m_chart_id, m_current_crt_model.name, 1, prev_time + (m_secods_in_period_htf * 2), prev_high);
}
Nique_372
2025-11-26 07:19:36 -05:00
}
}
else
if(prev_close < prev_open) // Buscar manipuacion de alto modelo venta
{
if(prev_high > prev_prev_high && prev_prev_high > prev_open && prev_low > prev_prev_low)
{
m_current_crt_model.direction = CRT_DIR_ABAJO;
m_current_crt_model.price_to_superate = prev_low; // Roptura de este precio
Nique_372
2026-11-06 17:08:44 -05:00
if(m_draw_line)
{
const datetime prev_time = iTime(m_symbol, m_timeframe_htf_crt, 1);
Nique_372
2025-11-26 07:19:36 -05:00
Nique_372
2026-11-06 17:08:44 -05:00
ObjectMove(m_chart_id, m_current_crt_model.name, 0, prev_time, prev_low);
ObjectMove(m_chart_id, m_current_crt_model.name, 1, prev_time + (m_secods_in_period_htf * 2), prev_low);
}
Nique_372
2025-11-26 07:19:36 -05:00
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
Nique_372
2026-02-14 17:50:28 -05:00
void CEstrategia::OnNewBar(const datetime curr_time)
Nique_372
2025-11-26 07:19:36 -05:00
{
//---
if(risk.GetPositionsTotal() > 0)
return;
//---
Nique_372
2026-01-06 06:46:34 -05:00
if(CNewBarManager_IsNewBar(g_new_bar_manager, m_index_controler_fast_htf_crt))
Nique_372
2025-11-26 07:19:36 -05:00
{
Clean();
//---
CheckCrt();
//---
if(m_current_crt_model.direction != WRONG_VALUE)
Nique_372
2026-11-06 17:08:44 -05:00
m_state = CRT_STATE_BUSCAR_ROPTURA;
Nique_372
2025-11-26 07:19:36 -05:00
LogInfo(StringFormat("Direccion buscada: %s", EnumToString(m_current_crt_model.direction)), FUNCION_ACTUAL);
}
Nique_372
2026-11-06 17:08:44 -05:00
//--- Un paso por llamada. El modelo (arriba) y la roptura se evaluan en la misma llamada, el pda en las siguientes
switch(m_state)
Nique_372
2025-11-26 07:19:36 -05:00
{
Nique_372
2026-11-06 17:08:44 -05:00
//--- Hay modelo: esperamos la roptura del high/low previo del htf
case CRT_STATE_BUSCAR_ROPTURA:
Nique_372
2025-11-26 07:19:36 -05:00
{
const double prev_close = iClose(m_symbol, m_timeframe, 1);
if(m_current_crt_model.direction == CRT_DIR_ARRIBA && prev_close > m_current_crt_model.price_to_superate) // COmpra, roptura del high previo para 1er paso
{
LogInfo("Roptura del high concretada", FUNCION_ACTUAL);
Nique_372
2026-11-06 17:08:44 -05:00
m_state = CRT_STATE_BUSCAR_PDA_ALCISTA;
Nique_372
2025-11-26 07:19:36 -05:00
}
else
if(m_current_crt_model.direction == CRT_DIR_ABAJO && m_current_crt_model.price_to_superate > prev_close) // Venta, roptura del low
{
LogInfo("Roptura del low concretada", FUNCION_ACTUAL);
Nique_372
2026-11-06 17:08:44 -05:00
m_state = CRT_STATE_BUSCAR_PDA_BAJISTA;
Nique_372
2025-11-26 07:19:36 -05:00
}
Nique_372
2026-11-06 17:08:44 -05:00
break;
Nique_372
2025-11-26 07:19:36 -05:00
}
Nique_372
2026-11-06 17:08:44 -05:00
//--- Roptura concretada: buscamos que un pda sea tocado dentro de una sesion
case CRT_STATE_BUSCAR_PDA_ALCISTA:
{
if(g_sesiones.GetSesionActualIdx() != INVALID_SESION && g_pdas.PdaBullIsTouched())
OpenOrder(POSITION_TYPE_BUY);
break;
}
case CRT_STATE_BUSCAR_PDA_BAJISTA:
{
if(g_sesiones.GetSesionActualIdx() != INVALID_SESION && g_pdas.PdaBearIsTouched())
OpenOrder(POSITION_TYPE_SELL);
break;
}
default:
break;
Nique_372
2025-11-26 07:19:36 -05:00
}
}
//+------------------------------------------------------------------+
//| Open Order Default |
//+------------------------------------------------------------------+
void CEstrategia::OpenOrder(ENUM_POSITION_TYPE type)
{
SymbolInfoTick(m_symbol, m_tick);
if(type == POSITION_TYPE_BUY)
{
double entry = m_tick.ask;
double sl = GetSL(entry, type, m_tick.time);
double tp = GetTP(entry, type, m_tick.time);
Nique_372
2026-11-01 22:12:14 -05:00
risk.SetStopLoss(m_symbol, entry - sl);
Nique_372
2025-11-26 07:19:36 -05:00
double l = m_LOT_SIZE > 0.00 ? m_LOT_SIZE : risk.GetLote(ORDER_TYPE_BUY, entry, m_max_deviation, 0);
m_trade.Buy(l, m_symbol, entry, sl, tp, "Ea buy");
}
else
if(type == POSITION_TYPE_SELL)
{
double entry = m_tick.bid;
double sl = GetSL(entry, type, m_tick.time);
double tp = GetTP(entry, type, m_tick.time);
Nique_372
2026-11-01 22:12:14 -05:00
risk.SetStopLoss(m_symbol, sl - entry);
Nique_372
2025-11-26 07:19:36 -05:00
double l = m_LOT_SIZE > 0.00 ? m_LOT_SIZE : risk.GetLote(ORDER_TYPE_SELL, entry, m_max_deviation, 0);
m_trade.Sell(l, m_symbol, entry, sl, tp, "Ea sell");
}
Clean();
}
//+------------------------------------------------------------------+