diff --git a/Include/MyIncludes/Cyber_Cycle_Calculator.mqh b/Include/MyIncludes/Cyber_Cycle_Calculator.mqh index d81993f..ae37d43 100644 --- a/Include/MyIncludes/Cyber_Cycle_Calculator.mqh +++ b/Include/MyIncludes/Cyber_Cycle_Calculator.mqh @@ -1,10 +1,12 @@ //+------------------------------------------------------------------+ //| Cyber_Cycle_Calculator.mqh| -//| Calculation engine for the John Ehlers' Cyber Cycle. | -//| VERSION 3.00: Added flexible Signal Line support. | -//| Copyright 2026, xxxxxxxx | +//| Copyright 2026, xxxxxxxx| //+------------------------------------------------------------------+ #property copyright "Copyright 2026, xxxxxxxx" +#property version "3.05" // Coerced internal array direction safety on resize actions + +#ifndef CYBER_CYCLE_CALCULATOR_MQH +#define CYBER_CYCLE_CALCULATOR_MQH #include #include @@ -37,7 +39,6 @@ protected: double m_smooth[]; // Pre-smoothing buffer double m_cycle[]; // Internal cycle buffer - //--- Updated: Accepts start_index virtual bool PreparePriceSeries(int rates_total, int start_index, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[]); public: @@ -83,7 +84,7 @@ bool CCyberCycleCalculator::Init(double alpha, ENUM_CYBER_SIGNAL_TYPE sig_type, if(m_signal_type == SIGNAL_MA) { - if(!m_signal_engine.Init(m_signal_period, m_signal_method)) + if(CheckPointer(m_signal_engine) == POINTER_INVALID || !m_signal_engine.Init(m_signal_period, m_signal_method)) return false; } return true; @@ -101,7 +102,10 @@ void CCyberCycleCalculator::Calculate(int rates_total, int prev_calculated, ENUM int start_index = (prev_calculated == 0) ? 0 : prev_calculated - 1; if(ArraySize(m_price) != rates_total) + { ArrayResize(m_price, rates_total); + ArraySetAsSeries(m_price, false); + } if(!PreparePriceSeries(rates_total, start_index, price_type, open, high, low, close)) return; @@ -120,25 +124,27 @@ void CCyberCycleCalculator::CalculateOnArray(int rates_total, int prev_calculate int start_index = (prev_calculated == 0) ? 0 : prev_calculated - 1; -// Resize internal buffers +// Resize internal buffers and ensure strict chronological indexing if(ArraySize(m_smooth) != rates_total) { ArrayResize(m_smooth, rates_total); ArrayResize(m_cycle, rates_total); + ArraySetAsSeries(m_smooth, false); + ArraySetAsSeries(m_cycle, false); } // Main Loop int loop_start = MathMax(6, start_index); -// Initialization +// Explicitly zero-initialize historical indices 0 to 5 to avoid trash values in the terminal data window if(loop_start == 6) { for(int k=0; k<6; k++) { m_smooth[k] = src_buffer[k]; - m_cycle[k] = 0; - cycle_out[k] = 0; - // Signal init handled later or by engine + m_cycle[k] = 0.0; + cycle_out[k] = 0.0; + signal_out[k] = 0.0; } } @@ -158,7 +164,7 @@ void CCyberCycleCalculator::CalculateOnArray(int rates_total, int prev_calculate cycle_out[i] = m_cycle[i]; } -// Step 3: Signal Line +// Step 3: Signal Line calculation based on structural selections if(m_signal_type == SIGNAL_DELAY_1BAR) { for(int i = loop_start; i < rates_total; i++) @@ -166,9 +172,11 @@ void CCyberCycleCalculator::CalculateOnArray(int rates_total, int prev_calculate } else // SIGNAL_MA { - // Use MA Engine on the Cycle Line - // Offset: Cyber Cycle needs ~6 bars to start, so offset 6 is safe - m_signal_engine.CalculateOnArray(rates_total, prev_calculated, m_cycle, signal_out, 6); + // Use MA Engine on the Cycle Line starting from safe offset boundary 6 + if(CheckPointer(m_signal_engine) != POINTER_INVALID) + { + m_signal_engine.CalculateOnArray(rates_total, prev_calculated, m_cycle, signal_out, 6); + } } } @@ -200,7 +208,7 @@ bool CCyberCycleCalculator::PreparePriceSeries(int rates_total, int start_index, m_price[i] = (high[i] + low[i] + close[i]) / 3.0; break; case PRICE_WEIGHTED: - m_price[i] = (high[i] + low[i] + 2 * close[i]) / 4.0; + m_price[i] = (high[i] + low[i] + 2.0 * close[i]) / 4.0; break; default: m_price[i] = (high[i] + low[i]) / 2.0; @@ -234,6 +242,11 @@ bool CCyberCycleCalculator_HA::PreparePriceSeries(int rates_total, int start_ind ArrayResize(m_ha_high, rates_total); ArrayResize(m_ha_low, rates_total); ArrayResize(m_ha_close, rates_total); + + ArraySetAsSeries(m_ha_open, false); + ArraySetAsSeries(m_ha_high, false); + ArraySetAsSeries(m_ha_low, false); + ArraySetAsSeries(m_ha_close, false); } m_ha_calculator.Calculate(rates_total, start_index, open, high, low, close, @@ -262,7 +275,7 @@ bool CCyberCycleCalculator_HA::PreparePriceSeries(int rates_total, int start_ind m_price[i] = (m_ha_high[i] + m_ha_low[i] + m_ha_close[i]) / 3.0; break; case PRICE_WEIGHTED: - m_price[i] = (m_ha_high[i] + m_ha_low[i] + 2 * m_ha_close[i]) / 4.0; + m_price[i] = (m_ha_high[i] + m_ha_low[i] + 2.0 * m_ha_close[i]) / 4.0; break; default: m_price[i] = (m_ha_high[i] + m_ha_low[i]) / 2.0; @@ -271,4 +284,6 @@ bool CCyberCycleCalculator_HA::PreparePriceSeries(int rates_total, int start_ind } return true; } + +#endif // CYBER_CYCLE_CALCULATOR_MQH //+------------------------------------------------------------------+