From e078550a14539f5a827d2c15cb2c15b780199fdf Mon Sep 17 00:00:00 2001 From: Toh4iem9 Date: Thu, 3 Sep 2026 14:06:44 +0200 Subject: [PATCH] refactor: 100% Backward Compatible Universal Moving Average Engine --- Include/MyIncludes/MovingAverage_Engine.mqh | 359 +++++++++++++------- 1 file changed, 237 insertions(+), 122 deletions(-) diff --git a/Include/MyIncludes/MovingAverage_Engine.mqh b/Include/MyIncludes/MovingAverage_Engine.mqh index bc360e6c..99a153b4 100644 --- a/Include/MyIncludes/MovingAverage_Engine.mqh +++ b/Include/MyIncludes/MovingAverage_Engine.mqh @@ -1,10 +1,10 @@ //+------------------------------------------------------------------+ //| MovingAverage_Engine.mqh | -//| VERSION 2.45: Added VWMA support with empty-value fallback. | -//| Copyright 2026, xxxxxxxx | +//| VERSION 2.50: Enhanced Chronological Safeguards & VWMA | +//| Copyright 2026, xxxxxxxx| //+------------------------------------------------------------------+ #property copyright "Copyright 2026, xxxxxxxx" -#property version "2.45" +#property version "2.50" // 100% Backward Compatible Universal Moving Average Engine #ifndef MOVING_AVERAGE_ENGINE_MQH #define MOVING_AVERAGE_ENGINE_MQH @@ -12,6 +12,8 @@ #include //--- Enum to select the MA type for calculation +#ifndef ENUM_MA_TYPE_DEFINED +#define ENUM_MA_TYPE_DEFINED enum ENUM_MA_TYPE { SMA, @@ -23,6 +25,7 @@ enum ENUM_MA_TYPE TEMA, VWMA }; +#endif //+==================================================================+ //| CLASS: CMovingAverageCalculator | @@ -33,48 +36,71 @@ protected: int m_period; ENUM_MA_TYPE m_ma_type; - //--- Persistent Buffers + //--- Persistent State Buffers double m_price[]; - double m_volume[]; // Kept for VWMA support + double m_volume[]; double m_temp_buffer1[]; double m_temp_buffer2[]; double m_temp_buffer3[]; - 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[]); - void CalculateEMA(int rates_total, int start_index, int period, const double &source[], double &dest[]); - - //--- Internal Core Calculation that works on m_price and m_volume - //--- data_offset: The index where valid data starts in m_price - void RunCalculation(int rates_total, int start_index, double &output_buffer[], int data_offset = 0); + virtual bool PreparePriceSeries(const int rates_total, const int start_index, const ENUM_APPLIED_PRICE price_type, + const double &open[], const double &high[], const double &low[], const double &close[]); + void CalculateEMA(const int rates_total, const int start_index, const int period, const double &source[], double &dest[]); + void RunCalculation(const int rates_total, const int start_index, double &output_buffer[], const int data_offset = 0); public: - CMovingAverageCalculator(void) {}; + CMovingAverageCalculator(void); virtual ~CMovingAverageCalculator(void) {}; - bool Init(int period, ENUM_MA_TYPE ma_type); + bool Init(const int period, const ENUM_MA_TYPE ma_type); - //--- Standard Calculation (OHLC input - No Volume, legacy/fallback compatible) - void Calculate(int rates_total, int prev_calculated, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[], double &ma_buffer[]); + //--- Standard Calculation (OHLC input - No Volume, legacy compatible) + void Calculate(const int rates_total, const int prev_calculated, const ENUM_APPLIED_PRICE price_type, + const double &open[], const double &high[], const double &low[], const double &close[], + double &ma_buffer[]); //--- Overloaded Calculation with Volume (Specifically for VWMA support) - void Calculate(int rates_total, int prev_calculated, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[], const long &volume[], double &ma_buffer[]); + void Calculate(const int rates_total, const int prev_calculated, const ENUM_APPLIED_PRICE price_type, + const double &open[], const double &high[], const double &low[], const double &close[], + const long &volume[], + double &ma_buffer[]); + + //--- Overloaded Calculation with Double Volume Array (For MTF VWMA) + void Calculate(const int rates_total, const int prev_calculated, const ENUM_APPLIED_PRICE price_type, + const double &open[], const double &high[], const double &low[], const double &close[], + const double &volume[], + double &ma_buffer[]); //--- Calculation on Custom Array (No Volume) - //--- src_start_index: The index where valid data starts in src_buffer (default 0) - void CalculateOnArray(int rates_total, int prev_calculated, const double &src_buffer[], double &output_buffer[], int src_start_index = 0); + void CalculateOnArray(const int rates_total, const int prev_calculated, const double &src_buffer[], + double &output_buffer[], const int src_start_index = 0); - //--- Overloaded Calculation on Custom Array with Volume - void CalculateOnArray(int rates_total, int prev_calculated, const double &src_buffer[], const double &volume_buffer[], double &output_buffer[], int src_start_index = 0); + //--- Overloaded Calculation on Custom Array with Volume (For VWMA Signals) + void CalculateOnArray(const int rates_total, const int prev_calculated, const double &src_buffer[], + const double &volume_buffer[], double &output_buffer[], const int src_start_index = 0); int GetPeriod(void) const { return m_period; } + ENUM_MA_TYPE GetMAType(void) const { return m_ma_type; } }; +//+------------------------------------------------------------------+ +//| Constructor | +//+------------------------------------------------------------------+ +CMovingAverageCalculator::CMovingAverageCalculator(void) : m_period(20), m_ma_type(SMA) + { + ArraySetAsSeries(m_price, false); + ArraySetAsSeries(m_volume, false); + ArraySetAsSeries(m_temp_buffer1, false); + ArraySetAsSeries(m_temp_buffer2, false); + ArraySetAsSeries(m_temp_buffer3, false); + } + //+------------------------------------------------------------------+ //| Init | //+------------------------------------------------------------------+ -bool CMovingAverageCalculator::Init(int period, ENUM_MA_TYPE ma_type) +bool CMovingAverageCalculator::Init(const int period, const ENUM_MA_TYPE ma_type) { - m_period = (period < 1) ? 1 : period; + m_period = (period < 1) ? 1 : period; m_ma_type = ma_type; return true; } @@ -82,94 +108,176 @@ bool CMovingAverageCalculator::Init(int period, ENUM_MA_TYPE ma_type) //+------------------------------------------------------------------+ //| Calculate (Standard OHLC - No Volume) | //+------------------------------------------------------------------+ -void CMovingAverageCalculator::Calculate(int rates_total, int prev_calculated, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[], double &ma_buffer[]) +void CMovingAverageCalculator::Calculate(const int rates_total, const int prev_calculated, const ENUM_APPLIED_PRICE price_type, + const double &open[], const double &high[], const double &low[], const double &close[], + double &ma_buffer[]) { if(rates_total < m_period) return; - int start_index = (prev_calculated == 0) ? 0 : prev_calculated - 1; + int start_index = (prev_calculated == 0) ? 0 : (prev_calculated - 1); if(ArraySize(m_price) != rates_total) { ArrayResize(m_price, rates_total); - // Resize temp buffers if needed + ArraySetAsSeries(m_price, false); + if(m_ma_type == TMA || m_ma_type == DEMA || m_ma_type == TEMA) + { ArrayResize(m_temp_buffer1, rates_total); + ArraySetAsSeries(m_temp_buffer1, false); + } if(m_ma_type == DEMA || m_ma_type == TEMA) + { ArrayResize(m_temp_buffer2, rates_total); + ArraySetAsSeries(m_temp_buffer2, false); + } if(m_ma_type == TEMA) + { ArrayResize(m_temp_buffer3, rates_total); + ArraySetAsSeries(m_temp_buffer3, false); + } } if(!PreparePriceSeries(rates_total, start_index, price_type, open, high, low, close)) return; -// Standard OHLC data is valid from index 0 RunCalculation(rates_total, start_index, ma_buffer, 0); } //+------------------------------------------------------------------+ -//| Calculate (Overloaded OHLC - With Volume) | +//| Calculate (Overloaded OHLC - With Long Volume) | //+------------------------------------------------------------------+ -void CMovingAverageCalculator::Calculate(int rates_total, int prev_calculated, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[], const long &volume[], double &ma_buffer[]) +void CMovingAverageCalculator::Calculate(const int rates_total, const int prev_calculated, const ENUM_APPLIED_PRICE price_type, + const double &open[], const double &high[], const double &low[], const double &close[], + const long &volume[], + double &ma_buffer[]) { if(rates_total < m_period) return; - int start_index = (prev_calculated == 0) ? 0 : prev_calculated - 1; + 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(m_ma_type == TMA || m_ma_type == DEMA || m_ma_type == TEMA) + { ArrayResize(m_temp_buffer1, rates_total); + ArraySetAsSeries(m_temp_buffer1, false); + } if(m_ma_type == DEMA || m_ma_type == TEMA) + { ArrayResize(m_temp_buffer2, rates_total); + ArraySetAsSeries(m_temp_buffer2, false); + } if(m_ma_type == TEMA) + { ArrayResize(m_temp_buffer3, rates_total); + ArraySetAsSeries(m_temp_buffer3, false); + } } -// Dynamic allocation check for volume buffer (Crucial for parameter switches) if(ArraySize(m_volume) != rates_total) { ArrayResize(m_volume, rates_total); + ArraySetAsSeries(m_volume, false); } if(!PreparePriceSeries(rates_total, start_index, price_type, open, high, low, close)) return; -// Copy volumes locally with casting for(int i = start_index; i < rates_total; i++) + m_volume[i] = (volume[i] < 1) ? 1.0 : (double)volume[i]; + + RunCalculation(rates_total, start_index, ma_buffer, 0); + } + +//+------------------------------------------------------------------+ +//| Calculate (Overloaded OHLC - With Double Volume) | +//+------------------------------------------------------------------+ +void CMovingAverageCalculator::Calculate(const int rates_total, const int prev_calculated, const ENUM_APPLIED_PRICE price_type, + const double &open[], const double &high[], const double &low[], const double &close[], + const double &volume[], + double &ma_buffer[]) + { + if(rates_total < m_period) + return; + + int start_index = (prev_calculated == 0) ? 0 : (prev_calculated - 1); + + if(ArraySize(m_price) != rates_total) { - m_volume[i] = (double)volume[i]; + ArrayResize(m_price, rates_total); + ArraySetAsSeries(m_price, false); + + if(m_ma_type == TMA || m_ma_type == DEMA || m_ma_type == TEMA) + { + ArrayResize(m_temp_buffer1, rates_total); + ArraySetAsSeries(m_temp_buffer1, false); + } + if(m_ma_type == DEMA || m_ma_type == TEMA) + { + ArrayResize(m_temp_buffer2, rates_total); + ArraySetAsSeries(m_temp_buffer2, false); + } + if(m_ma_type == TEMA) + { + ArrayResize(m_temp_buffer3, rates_total); + ArraySetAsSeries(m_temp_buffer3, false); + } } + if(ArraySize(m_volume) != rates_total) + { + ArrayResize(m_volume, rates_total); + ArraySetAsSeries(m_volume, false); + } + + if(!PreparePriceSeries(rates_total, start_index, price_type, open, high, low, close)) + return; + + for(int i = start_index; i < rates_total; i++) + m_volume[i] = (volume[i] < 1.0) ? 1.0 : volume[i]; + RunCalculation(rates_total, start_index, ma_buffer, 0); } //+------------------------------------------------------------------+ //| CalculateOnArray (Custom Input - No Volume) | //+------------------------------------------------------------------+ -void CMovingAverageCalculator::CalculateOnArray(int rates_total, int prev_calculated, const double &src_buffer[], double &output_buffer[], int src_start_index) +void CMovingAverageCalculator::CalculateOnArray(const int rates_total, const int prev_calculated, const double &src_buffer[], + double &output_buffer[], const int src_start_index) { if(rates_total < src_start_index + m_period) return; - int start_index = (prev_calculated == 0) ? 0 : prev_calculated - 1; + int start_index = (prev_calculated == 0) ? 0 : (prev_calculated - 1); -// Resize internal buffers if(ArraySize(m_price) != rates_total) { ArrayResize(m_price, rates_total); + ArraySetAsSeries(m_price, false); + if(m_ma_type == TMA || m_ma_type == DEMA || m_ma_type == TEMA) + { ArrayResize(m_temp_buffer1, rates_total); + ArraySetAsSeries(m_temp_buffer1, false); + } if(m_ma_type == DEMA || m_ma_type == TEMA) + { ArrayResize(m_temp_buffer2, rates_total); + ArraySetAsSeries(m_temp_buffer2, false); + } if(m_ma_type == TEMA) + { ArrayResize(m_temp_buffer3, rates_total); + ArraySetAsSeries(m_temp_buffer3, false); + } } -// Copy source array to internal m_price buffer int copy_start = MathMax(start_index, src_start_index); for(int i = copy_start; i < rates_total; i++) @@ -181,51 +289,59 @@ void CMovingAverageCalculator::CalculateOnArray(int rates_total, int prev_calcul //+------------------------------------------------------------------+ //| CalculateOnArray (Overloaded Custom Input - With Volume) | //+------------------------------------------------------------------+ -void CMovingAverageCalculator::CalculateOnArray(int rates_total, int prev_calculated, const double &src_buffer[], const double &volume_buffer[], double &output_buffer[], int src_start_index) +void CMovingAverageCalculator::CalculateOnArray(const int rates_total, const int prev_calculated, const double &src_buffer[], + const double &volume_buffer[], double &output_buffer[], const int src_start_index) { if(rates_total < src_start_index + m_period) return; - int start_index = (prev_calculated == 0) ? 0 : prev_calculated - 1; + int start_index = (prev_calculated == 0) ? 0 : (prev_calculated - 1); -// Resize internal buffers if(ArraySize(m_price) != rates_total) { ArrayResize(m_price, rates_total); + ArraySetAsSeries(m_price, false); + if(m_ma_type == TMA || m_ma_type == DEMA || m_ma_type == TEMA) + { ArrayResize(m_temp_buffer1, rates_total); + ArraySetAsSeries(m_temp_buffer1, false); + } if(m_ma_type == DEMA || m_ma_type == TEMA) + { ArrayResize(m_temp_buffer2, rates_total); + ArraySetAsSeries(m_temp_buffer2, false); + } if(m_ma_type == TEMA) + { ArrayResize(m_temp_buffer3, rates_total); + ArraySetAsSeries(m_temp_buffer3, false); + } } if(ArraySize(m_volume) != rates_total) { ArrayResize(m_volume, rates_total); + ArraySetAsSeries(m_volume, false); } -// Copy source array and volume to internal buffers int copy_start = MathMax(start_index, src_start_index); for(int i = copy_start; i < rates_total; i++) { - m_price[i] = src_buffer[i]; - m_volume[i] = volume_buffer[i]; + m_price[i] = src_buffer[i]; + m_volume[i] = (volume_buffer[i] < 1.0) ? 1.0 : volume_buffer[i]; } RunCalculation(rates_total, start_index, output_buffer, src_start_index); } //+------------------------------------------------------------------+ -//| RunCalculation (Core Logic) | +//| RunCalculation (Core Mathematical Execution Engine) | //+------------------------------------------------------------------+ -void CMovingAverageCalculator::RunCalculation(int rates_total, int start_index, double &output_buffer[], int data_offset) +void CMovingAverageCalculator::RunCalculation(const int rates_total, const int start_index, double &output_buffer[], const int data_offset) { -// The first valid MA value can be calculated at (offset + period - 1) - int start_pos = data_offset + m_period - 1; - -// Ensure loop starts at valid position + int start_pos = data_offset + m_period - 1; int loop_start = MathMax(start_pos, start_index); switch(m_ma_type) @@ -239,69 +355,71 @@ void CMovingAverageCalculator::RunCalculation(int rates_total, int start_index, { if(i == start_pos) { - double sum=0; - for(int j=0; j0) - output_buffer[i]=sum/w_sum; + output_buffer[i] = (w_sum > 0.0) ? (sum / w_sum) : m_price[i]; } break; case TMA: { int period1 = (int)ceil((m_period + 1.0) / 2.0); - // TMA logic is complex with offsets. - // First MA starts at: data_offset + period1 - 1 int start_pos1 = data_offset + period1 - 1; int loop_start_tma = MathMax(start_pos1, start_index); for(int i = loop_start_tma; i < rates_total; i++) { - double sum = 0; + double sum = 0.0; for(int j = 0; j < period1; j++) - sum += m_price[i-j]; - m_temp_buffer1[i] = sum / period1; + sum += m_price[i - j]; + m_temp_buffer1[i] = sum / (double)period1; } - // Second MA starts at: start_pos1 + period2 - 1 int period2 = m_period - period1 + 1; int start_pos2 = start_pos1 + period2 - 1; int loop_start_final = MathMax(start_pos2, start_index); for(int i = loop_start_final; i < rates_total; i++) { - double sum = 0; + double sum = 0.0; for(int j = 0; j < period2; j++) - sum += m_temp_buffer1[i-j]; - output_buffer[i] = sum / period2; + sum += m_temp_buffer1[i - j]; + output_buffer[i] = sum / (double)period2; } + break; } - break; case DEMA: CalculateEMA(rates_total, loop_start, m_period, m_price, m_temp_buffer1); CalculateEMA(rates_total, loop_start, m_period, m_temp_buffer1, m_temp_buffer2); for(int i = loop_start; i < rates_total; i++) - output_buffer[i] = 2 * m_temp_buffer1[i] - m_temp_buffer2[i]; + { + if(m_temp_buffer1[i] != EMPTY_VALUE && m_temp_buffer2[i] != EMPTY_VALUE) + output_buffer[i] = 2.0 * m_temp_buffer1[i] - m_temp_buffer2[i]; + else + output_buffer[i] = EMPTY_VALUE; + } break; case TEMA: @@ -310,47 +428,46 @@ void CMovingAverageCalculator::RunCalculation(int rates_total, int start_index, CalculateEMA(rates_total, loop_start, m_period, m_temp_buffer2, m_temp_buffer3); for(int i = loop_start; i < rates_total; i++) - output_buffer[i] = 3 * m_temp_buffer1[i] - 3 * m_temp_buffer2[i] + m_temp_buffer3[i]; + { + if(m_temp_buffer1[i] != EMPTY_VALUE && m_temp_buffer2[i] != EMPTY_VALUE && m_temp_buffer3[i] != EMPTY_VALUE) + output_buffer[i] = 3.0 * m_temp_buffer1[i] - 3.0 * m_temp_buffer2[i] + m_temp_buffer3[i]; + else + output_buffer[i] = EMPTY_VALUE; + } break; case VWMA: { - // Robust empty-value fallback pattern if(ArraySize(m_volume) != rates_total) { - if(start_index == 0) - Print("Warning: VWMA selected but no volume data provided. Line will not be drawn."); - for(int i = loop_start; i < rates_total; i++) - { output_buffer[i] = EMPTY_VALUE; - } } else { for(int i = loop_start; i < rates_total; i++) { - double sum_pv = 0; - double sum_v = 0; + double sum_pv = 0.0; + double sum_v = 0.0; for(int j = 0; j < m_period; j++) { - double v = m_volume[i-j]; - sum_pv += m_price[i-j] * v; + double v = m_volume[i - j]; + sum_pv += m_price[i - j] * v; sum_v += v; } - output_buffer[i] = (sum_v > 0) ? (sum_pv / sum_v) : m_price[i]; + output_buffer[i] = (sum_v > 0.0) ? (sum_pv / sum_v) : m_price[i]; } } + break; } - break; default: // SMA for(int i = loop_start; i < rates_total; i++) { - double sum=0; - for(int j=0; j 0 && dest[i-1] != 0.0 && dest[i-1] != EMPTY_VALUE); + bool has_prev = (!force_init && i > 0 && dest[i - 1] != 0.0 && dest[i - 1] != EMPTY_VALUE); if(has_prev) { if(source[i] != EMPTY_VALUE) - dest[i] = source[i]*pr + dest[i-1]*(1.0-pr); + dest[i] = source[i] * pr + dest[i - 1] * (1.0 - pr); else - dest[i] = dest[i-1]; + dest[i] = dest[i - 1]; } else { - // Initialization (SMA) - // Safety check: can we look back 'period' bars? if(i < period - 1) { - dest[i] = EMPTY_VALUE; // Not enough data yet + dest[i] = EMPTY_VALUE; continue; } - double sum=0; - int count=0; - for(int j=0; j 0) - dest[i] = sum/count; - else - dest[i] = source[i]; // Fallback + dest[i] = (count > 0) ? (sum / (double)count) : source[i]; } } } @@ -413,7 +521,8 @@ void CMovingAverageCalculator::CalculateEMA(int rates_total, int start_index, in //+------------------------------------------------------------------+ //| Prepare Price (Standard - Optimized) | //+------------------------------------------------------------------+ -bool CMovingAverageCalculator::PreparePriceSeries(int rates_total, int start_index, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[]) +bool CMovingAverageCalculator::PreparePriceSeries(const int rates_total, const int start_index, const ENUM_APPLIED_PRICE price_type, + const double &open[], const double &high[], const double &low[], const double &close[]) { for(int i = start_index; i < rates_total; i++) { @@ -432,13 +541,13 @@ bool CMovingAverageCalculator::PreparePriceSeries(int rates_total, int start_ind m_price[i] = low[i]; break; case PRICE_MEDIAN: - m_price[i] = (high[i]+low[i])/2.0; + m_price[i] = (high[i] + low[i]) / 2.0; break; case PRICE_TYPICAL: - m_price[i] = (high[i]+low[i]+close[i])/3.0; + 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] = close[i]; @@ -455,23 +564,29 @@ class CMovingAverageCalculator_HA : public CMovingAverageCalculator { private: CHeikinAshi_Calculator m_ha_calculator; - double m_ha_open[], m_ha_high[], m_ha_low[], m_ha_close[]; + double m_ha_open[], m_ha_high[], m_ha_low[], m_ha_close[]; protected: - 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[]) override; + virtual bool PreparePriceSeries(const int rates_total, const int start_index, const ENUM_APPLIED_PRICE price_type, + const double &open[], const double &high[], const double &low[], const double &close[]) override; }; //+------------------------------------------------------------------+ //| Prepare Price (Heikin Ashi - Optimized) | //+------------------------------------------------------------------+ -bool CMovingAverageCalculator_HA::PreparePriceSeries(int rates_total, int start_index, ENUM_APPLIED_PRICE price_type, const double &open[], const double &high[], const double &low[], const double &close[]) +bool CMovingAverageCalculator_HA::PreparePriceSeries(const int rates_total, const int start_index, const ENUM_APPLIED_PRICE price_type, + const double &open[], const double &high[], const double &low[], const double &close[]) { if(ArraySize(m_ha_open) != rates_total) { - ArrayResize(m_ha_open, rates_total); - ArrayResize(m_ha_high, rates_total); - ArrayResize(m_ha_low, rates_total); + ArrayResize(m_ha_open, rates_total); + ArraySetAsSeries(m_ha_open, false); + ArrayResize(m_ha_high, rates_total); + ArraySetAsSeries(m_ha_high, false); + ArrayResize(m_ha_low, rates_total); + ArraySetAsSeries(m_ha_low, false); ArrayResize(m_ha_close, rates_total); + ArraySetAsSeries(m_ha_close, false); } m_ha_calculator.Calculate(rates_total, start_index, open, high, low, close, @@ -494,13 +609,13 @@ bool CMovingAverageCalculator_HA::PreparePriceSeries(int rates_total, int start_ m_price[i] = m_ha_low[i]; break; case PRICE_MEDIAN: - m_price[i] = (m_ha_high[i]+m_ha_low[i])/2.0; + m_price[i] = (m_ha_high[i] + m_ha_low[i]) / 2.0; break; case PRICE_TYPICAL: - m_price[i] = (m_ha_high[i]+m_ha_low[i]+m_ha_close[i])/3.0; + 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_close[i];