mirror of
https://github.com/softwaredevelop/mql5.git
synced 2026-08-14 12:58:05 +00:00
199 lines
7.4 KiB
Plaintext
199 lines
7.4 KiB
Plaintext
//+------------------------------------------------------------------+
|
|
//| Chandelier_Exit_Oscillator_Calculator.mqh |
|
|
//| Copyright 2026, xxxxxxxx|
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2026, xxxxxxxx"
|
|
#property version "1.10" // Simplified to return raw normalized values for custom wrapper coloring
|
|
#property description "Stateful calculator implementing normalized distance between Price and Trailing Stop."
|
|
|
|
#ifndef CHANDELIER_EXIT_OSCILLATOR_CALCULATOR_MQH
|
|
#define CHANDELIER_EXIT_OSCILLATOR_CALCULATOR_MQH
|
|
|
|
#include <MyIncludes\Chandelier_Exit_Calculator.mqh>
|
|
#include <MyIncludes\ATR_Calculator.mqh>
|
|
#include <MyIncludes\HeikinAshi_Tools.mqh>
|
|
|
|
//+==================================================================+
|
|
//| CLASS: CChandelierExitOscillatorCalculator |
|
|
//+==================================================================+
|
|
class CChandelierExitOscillatorCalculator
|
|
{
|
|
private:
|
|
int m_period;
|
|
double m_multiplier;
|
|
bool m_is_ha;
|
|
|
|
CChandelierExitCalculator *m_exit_calc;
|
|
CATRCalculator *m_atr_calc;
|
|
|
|
// Internal Caches
|
|
double m_stop_line[];
|
|
double m_color_dummy[];
|
|
double m_atr_buffer[];
|
|
double m_price_close[];
|
|
|
|
bool PrepareCloseSeries(int rates_total, int start_index, const double &open[], const double &high[], const double &low[], const double &close[]);
|
|
|
|
public:
|
|
CChandelierExitOscillatorCalculator(void);
|
|
~CChandelierExitOscillatorCalculator(void);
|
|
|
|
bool Init(int period, double multiplier, bool is_ha);
|
|
void Calculate(int rates_total, int prev_calculated,
|
|
const double &open[], const double &high[], const double &low[], const double &close[],
|
|
double &osc_buffer[]);
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Constructor |
|
|
//+------------------------------------------------------------------+
|
|
CChandelierExitOscillatorCalculator::CChandelierExitOscillatorCalculator(void)
|
|
: m_period(22),
|
|
m_multiplier(3.0),
|
|
m_is_ha(false),
|
|
m_exit_calc(NULL),
|
|
m_atr_calc(NULL)
|
|
{
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Destructor |
|
|
//+------------------------------------------------------------------+
|
|
CChandelierExitOscillatorCalculator::~CChandelierExitOscillatorCalculator(void)
|
|
{
|
|
if(CheckPointer(m_exit_calc) != POINTER_INVALID)
|
|
delete m_exit_calc;
|
|
if(CheckPointer(m_atr_calc) != POINTER_INVALID)
|
|
delete m_atr_calc;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Init (Polymorphic Engines Caching) |
|
|
//+------------------------------------------------------------------+
|
|
bool CChandelierExitOscillatorCalculator::Init(int period, double multiplier, bool is_ha)
|
|
{
|
|
m_period = (period < 1) ? 1 : period;
|
|
m_multiplier = (multiplier <= 0.0) ? 3.0 : multiplier;
|
|
m_is_ha = is_ha;
|
|
|
|
if(CheckPointer(m_exit_calc) != POINTER_INVALID)
|
|
{
|
|
delete m_exit_calc;
|
|
m_exit_calc = NULL;
|
|
}
|
|
if(CheckPointer(m_atr_calc) != POINTER_INVALID)
|
|
{
|
|
delete m_atr_calc;
|
|
m_atr_calc = NULL;
|
|
}
|
|
|
|
// 1. Instantiate Trailing Stop calculator (Polymorphic Std/HA internally)
|
|
m_exit_calc = new CChandelierExitCalculator();
|
|
if(CheckPointer(m_exit_calc) == POINTER_INVALID || !m_exit_calc.Init(m_period, m_multiplier, m_is_ha))
|
|
return false;
|
|
|
|
// 2. Instantiate Raw ATR calculator (Polymorphic Std/HA internally)
|
|
if(m_is_ha)
|
|
m_atr_calc = new CATRCalculator_HA();
|
|
else
|
|
m_atr_calc = new CATRCalculator();
|
|
|
|
if(CheckPointer(m_atr_calc) == POINTER_INVALID || !m_atr_calc.Init(m_period, ATR_POINTS))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Calculate (Normalized Volatility Distance) |
|
|
//+------------------------------------------------------------------+
|
|
void CChandelierExitOscillatorCalculator::Calculate(int rates_total, int prev_calculated,
|
|
const double &open[], const double &high[], const double &low[], const double &close[],
|
|
double &osc_buffer[])
|
|
{
|
|
if(rates_total < m_period + 5)
|
|
return;
|
|
|
|
//--- Resize state buffers and enforce chronological safety
|
|
if(ArraySize(m_stop_line) != rates_total)
|
|
{
|
|
ArrayResize(m_stop_line, rates_total);
|
|
ArrayResize(m_color_dummy, rates_total);
|
|
ArrayResize(m_atr_buffer, rates_total);
|
|
ArrayResize(m_price_close, rates_total);
|
|
|
|
ArraySetAsSeries(m_stop_line, false);
|
|
ArraySetAsSeries(m_color_dummy, false);
|
|
ArraySetAsSeries(m_atr_buffer, false);
|
|
ArraySetAsSeries(m_price_close, false);
|
|
}
|
|
|
|
int start_index = (prev_calculated > 0) ? prev_calculated - 1 : 0;
|
|
|
|
if(!PrepareCloseSeries(rates_total, start_index, open, high, low, close))
|
|
return;
|
|
|
|
//--- Run underlying Stop Line and raw ATR values
|
|
m_exit_calc.Calculate(rates_total, prev_calculated, open, high, low, close, m_stop_line, m_color_dummy);
|
|
m_atr_calc.Calculate(rates_total, prev_calculated, open, high, low, close, m_atr_buffer);
|
|
|
|
int loop_start = MathMax(m_period, start_index);
|
|
if(loop_start == m_period)
|
|
{
|
|
for(int i = 0; i < m_period; i++)
|
|
osc_buffer[i] = 0.0;
|
|
}
|
|
|
|
//--- Compute Normalized Distance: (Price - Stop) / ATR
|
|
for(int i = loop_start; i < rates_total; i++)
|
|
{
|
|
double atr = m_atr_buffer[i];
|
|
if(atr > 1.0e-9)
|
|
{
|
|
osc_buffer[i] = (m_price_close[i] - m_stop_line[i]) / atr;
|
|
}
|
|
else
|
|
{
|
|
osc_buffer[i] = 0.0;
|
|
}
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Prepare Close price (Standard or HA - Clean Execution) |
|
|
//+------------------------------------------------------------------+
|
|
bool CChandelierExitOscillatorCalculator::PrepareCloseSeries(int rates_total, int start_index, const double &open[], const double &high[], const double &low[], const double &close[])
|
|
{
|
|
if(m_is_ha)
|
|
{
|
|
static CHeikinAshi_Calculator ha_calc;
|
|
static double ha_open[], ha_high[], ha_low[], ha_close[];
|
|
if(ArraySize(ha_open) != rates_total)
|
|
{
|
|
ArrayResize(ha_open, rates_total);
|
|
ArrayResize(ha_high, rates_total);
|
|
ArrayResize(ha_low, rates_total);
|
|
ArrayResize(ha_close, rates_total);
|
|
|
|
ArraySetAsSeries(ha_open, false);
|
|
ArraySetAsSeries(ha_high, false);
|
|
ArraySetAsSeries(ha_low, false);
|
|
ArraySetAsSeries(ha_close, false);
|
|
}
|
|
|
|
ha_calc.Calculate(rates_total, start_index, open, high, low, close, ha_open, ha_high, ha_low, ha_close);
|
|
|
|
for(int i = start_index; i < rates_total; i++)
|
|
m_price_close[i] = ha_close[i];
|
|
}
|
|
else
|
|
{
|
|
for(int i = start_index; i < rates_total; i++)
|
|
m_price_close[i] = close[i];
|
|
}
|
|
return true;
|
|
}
|
|
|
|
#endif // CHANDELIER_EXIT_OSCILLATOR_CALCULATOR_MQH
|
|
//+------------------------------------------------------------------+
|