From 047a87e0729c333aea2f317bcd97ddb8765a327c Mon Sep 17 00:00:00 2001 From: Toh4iem9 Date: Thu, 16 Oct 2025 09:05:47 +0200 Subject: [PATCH] refactor: --- .../Session_Analysis_Calculator.mqh | 185 ++++++++---------- 1 file changed, 87 insertions(+), 98 deletions(-) diff --git a/Include/MyIncludes/Session_Analysis_Calculator.mqh b/Include/MyIncludes/Session_Analysis_Calculator.mqh index 4c1cdf3..4fb41d4 100644 --- a/Include/MyIncludes/Session_Analysis_Calculator.mqh +++ b/Include/MyIncludes/Session_Analysis_Calculator.mqh @@ -30,6 +30,7 @@ protected: bool IsTimeInSession(const MqlDateTime &dt); virtual bool PrepareSourceData(int rates_total, const double &open[], const double &high[], const double &low[], const double &close[], ENUM_APPLIED_PRICE price_type); + void DrawSession(int start_bar, int end_bar, long session_id, const datetime &time[], const long &tick_volume[], const long &volume[]); public: void Init(bool enabled, string start_time, string end_time, color box_color, bool fill_box, bool show_vwap, bool show_mean, bool show_linreg, ENUM_APPLIED_VOLUME vol_type, string prefix); @@ -69,11 +70,11 @@ bool CSessionAnalyzer::IsTimeInSession(const MqlDateTime &dt) int start_time_in_minutes = m_start_hour * 60 + m_start_min; int end_time_in_minutes = m_end_hour * 60 + m_end_min; - if(end_time_in_minutes < start_time_in_minutes) + if(end_time_in_minutes < start_time_in_minutes) // Overnight session { return (current_time_in_minutes >= start_time_in_minutes || current_time_in_minutes < end_time_in_minutes); } - else + else // Same-day session { return (current_time_in_minutes >= start_time_in_minutes && current_time_in_minutes < end_time_in_minutes); } @@ -82,8 +83,6 @@ bool CSessionAnalyzer::IsTimeInSession(const MqlDateTime &dt) //+------------------------------------------------------------------+ void CSessionAnalyzer::Cleanup(void) { - if(!m_enabled) - return; ObjectsDeleteAll(0, m_prefix); } @@ -95,53 +94,73 @@ void CSessionAnalyzer::Update(const int rates_total, const datetime &time[], con if(!PrepareSourceData(rates_total, open, high, low, close, price_type)) return; - Cleanup(); - bool in_session = false; int session_start_bar = -1; - double session_high = 0, session_low = 0; - long session_id = 0; - - double cumulative_tpv = 0, cumulative_vol = 0, prev_vwap = 0; - double cumulative_price = 0; - int bar_count = 0; - double sum_x = 0, sum_y = 0, sum_xy = 0, sum_x2 = 0; for(int i = 1; i < rates_total; i++) { MqlDateTime dt; TimeToStruct(time[i], dt); - bool is_in_current_session = IsTimeInSession(dt); if(is_in_current_session && !in_session) { in_session = true; session_start_bar = i; - session_high = m_src_high[i]; - session_low = m_src_low[i]; - session_id = (long)time[i] - (dt.hour*3600 + dt.min*60 + dt.sec); - cumulative_tpv = 0; - cumulative_vol = 0; - prev_vwap = 0; - cumulative_price = 0; - bar_count = 0; - sum_x = 0; - sum_y = 0; - sum_xy = 0; - sum_x2 = 0; } else if(!is_in_current_session && in_session) { in_session = false; + MqlDateTime start_dt; + TimeToStruct(time[session_start_bar], start_dt); + long session_id = (long)time[session_start_bar] - (start_dt.hour * 3600 + start_dt.min * 60 + start_dt.sec); + DrawSession(session_start_bar, i - 1, session_id, time, tick_volume, volume); + session_start_bar = -1; } + } - if(in_session) + if(in_session && session_start_bar != -1) + { + MqlDateTime start_dt; + TimeToStruct(time[session_start_bar], start_dt); + long session_id = (long)time[session_start_bar] - (start_dt.hour * 3600 + start_dt.min * 60 + start_dt.sec); + DrawSession(session_start_bar, rates_total - 1, session_id, time, tick_volume, volume); + } + } + +//+------------------------------------------------------------------+ +void CSessionAnalyzer::DrawSession(int start_bar, int end_bar, long session_id, const datetime &time[], const long &tick_volume[], const long &volume[]) + { + if(start_bar < 0 || end_bar < start_bar) + return; + + double session_high = m_src_high[ArrayMaximum(m_src_high, start_bar, end_bar - start_bar + 1)]; + double session_low = m_src_low[ArrayMinimum(m_src_low, start_bar, end_bar - start_bar + 1)]; + + string box_name = m_prefix + "Box_" + (string)session_id; + if(ObjectFind(0, box_name) < 0) + { + ObjectCreate(0, box_name, OBJ_RECTANGLE, 0, time[start_bar], session_high, time[end_bar], session_low); + ObjectSetInteger(0, box_name, OBJPROP_COLOR, m_color); + ObjectSetInteger(0, box_name, OBJPROP_STYLE, STYLE_SOLID); + ObjectSetInteger(0, box_name, OBJPROP_BACK, true); + ObjectSetInteger(0, box_name, OBJPROP_FILL, m_fill_box); + } + else + { + ObjectMove(0, box_name, 0, time[start_bar], session_high); + ObjectMove(0, box_name, 1, time[end_bar], session_low); + } + + if(m_show_vwap || m_show_mean || m_show_linreg) + { + double cumulative_tpv = 0, cumulative_vol = 0, prev_vwap = 0; + double cumulative_price = 0; + double sum_x = 0, sum_y = 0, sum_xy = 0, sum_x2 = 0; + + for(int i = start_bar; i <= end_bar; i++) { - session_high = MathMax(session_high, m_src_high[i]); - session_low = MathMin(session_low, m_src_low[i]); - if(m_show_vwap) { double typical_price = (m_src_high[i] + m_src_low[i] + m_src_close[i]) / 3.0; @@ -153,87 +172,69 @@ void CSessionAnalyzer::Update(const int rates_total, const datetime &time[], con double current_vwap = (cumulative_vol > 0) ? cumulative_tpv / cumulative_vol : 0; if(prev_vwap > 0) { - //--- *** KEY CHANGE: Name the VWAP segment by its STARTING time for consistency *** - string vwap_line_name = m_prefix + "VWAP_" + (string)time[i-1]; - ObjectCreate(0, vwap_line_name, OBJ_TREND, 0, time[i-1], prev_vwap, time[i], current_vwap); - ObjectSetInteger(0, vwap_line_name, OBJPROP_COLOR, m_color); - ObjectSetInteger(0, vwap_line_name, OBJPROP_WIDTH, 1); + string vwap_line_name = m_prefix + "VWAP_" + (string)time[i - 1]; + if(ObjectFind(0, vwap_line_name) < 0) + { + ObjectCreate(0, vwap_line_name, OBJ_TREND, 0, time[i - 1], prev_vwap, time[i], current_vwap); + ObjectSetInteger(0, vwap_line_name, OBJPROP_COLOR, m_color); + ObjectSetInteger(0, vwap_line_name, OBJPROP_WIDTH, 1); + } } prev_vwap = current_vwap; } - if(m_show_mean || m_show_linreg) { cumulative_price += m_src_price[i]; - double x = bar_count; + double x = i - start_bar; double y = m_src_price[i]; sum_x += x; sum_y += y; sum_xy += x * y; sum_x2 += x * x; - bar_count++; } + } - string box_name = m_prefix + "Box_" + (string)session_id; - if(ObjectFind(0, box_name) < 0) - { - ObjectCreate(0, box_name, OBJ_RECTANGLE, 0, time[session_start_bar], session_high, time[i], session_low); - ObjectSetInteger(0, box_name, OBJPROP_COLOR, m_color); - ObjectSetInteger(0, box_name, OBJPROP_STYLE, STYLE_SOLID); - ObjectSetInteger(0, box_name, OBJPROP_BACK, true); - ObjectSetInteger(0, box_name, OBJPROP_FILL, m_fill_box); - } + int bar_count = end_bar - start_bar + 1; + if(m_show_mean && bar_count > 0) + { + double mean_price = cumulative_price / bar_count; + string mean_line_name = m_prefix + "Mean_" + (string)session_id; + if(ObjectFind(0, mean_line_name) < 0) + ObjectCreate(0, mean_line_name, OBJ_TREND, 0, time[start_bar], mean_price, time[end_bar], mean_price); else { - ObjectSetDouble(0, box_name, OBJPROP_PRICE, 0, session_high); - ObjectSetDouble(0, box_name, OBJPROP_PRICE, 1, session_low); - ObjectSetInteger(0, box_name, OBJPROP_TIME, 1, time[i]); + ObjectMove(0, mean_line_name, 0, time[start_bar], mean_price); + ObjectMove(0, mean_line_name, 1, time[end_bar], mean_price); } - - if(m_show_mean && bar_count > 0) + ObjectSetInteger(0, mean_line_name, OBJPROP_COLOR, m_color); + ObjectSetInteger(0, mean_line_name, OBJPROP_STYLE, STYLE_SOLID); + } + if(m_show_linreg && bar_count > 1) + { + double denominator = (bar_count * sum_x2 - sum_x * sum_x); + if(denominator != 0) { - double mean_price = cumulative_price / bar_count; - string mean_line_name = m_prefix + "Mean_" + (string)session_id; - if(ObjectFind(0, mean_line_name) < 0) - ObjectCreate(0, mean_line_name, OBJ_TREND, 0, time[session_start_bar], mean_price, time[i], mean_price); + double b = (bar_count * sum_xy - sum_x * sum_y) / denominator; + double a = (sum_y - b * sum_x) / bar_count; + double start_price = a; + double end_price = a + b * (bar_count - 1); + string lr_line_name = m_prefix + "LinReg_" + (string)session_id; + if(ObjectFind(0, lr_line_name) < 0) + ObjectCreate(0, lr_line_name, OBJ_TREND, 0, time[start_bar], start_price, time[end_bar], end_price); else { - ObjectSetDouble(0, mean_line_name, OBJPROP_PRICE, 0, mean_price); - ObjectSetDouble(0, mean_line_name, OBJPROP_PRICE, 1, mean_price); - ObjectSetInteger(0, mean_line_name, OBJPROP_TIME, 1, time[i]); - } - ObjectSetInteger(0, mean_line_name, OBJPROP_COLOR, m_color); - ObjectSetInteger(0, mean_line_name, OBJPROP_STYLE, STYLE_SOLID); - } - - if(m_show_linreg && bar_count > 1) - { - double denominator = (bar_count * sum_x2 - sum_x * sum_x); - if(denominator != 0) - { - double b = (bar_count * sum_xy - sum_x * sum_y) / denominator; - double a = (sum_y - b * sum_x) / bar_count; - double start_price = a; - double end_price = a + b * (bar_count - 1); - string lr_line_name = m_prefix + "LinReg_" + (string)session_id; - if(ObjectFind(0, lr_line_name) < 0) - ObjectCreate(0, lr_line_name, OBJ_TREND, 0, time[session_start_bar], start_price, time[i], end_price); - else - { - ObjectMove(0, lr_line_name, 0, time[session_start_bar], start_price); - ObjectMove(0, lr_line_name, 1, time[i], end_price); - } - ObjectSetInteger(0, lr_line_name, OBJPROP_COLOR, m_color); - ObjectSetInteger(0, lr_line_name, OBJPROP_STYLE, STYLE_SOLID); - ObjectSetInteger(0, lr_line_name, OBJPROP_WIDTH, 1); + ObjectMove(0, lr_line_name, 0, time[start_bar], start_price); + ObjectMove(0, lr_line_name, 1, time[end_bar], end_price); } + ObjectSetInteger(0, lr_line_name, OBJPROP_COLOR, m_color); + ObjectSetInteger(0, lr_line_name, OBJPROP_STYLE, STYLE_SOLID); + ObjectSetInteger(0, lr_line_name, OBJPROP_WIDTH, 1); } } } } -//+------------------------------------------------------------------+ -//| CSessionAnalyzer: Prepares the standard source data. | +//--- PrepareSourceData and the HA class remain unchanged --- //+------------------------------------------------------------------+ bool CSessionAnalyzer::PrepareSourceData(int rates_total, const double &open[], const double &high[], const double &low[], const double &close[], ENUM_APPLIED_PRICE price_type) { @@ -243,7 +244,6 @@ bool CSessionAnalyzer::PrepareSourceData(int rates_total, const double &open[], ArrayCopy(m_src_low, low, 0, 0, rates_total); ArrayResize(m_src_close, rates_total); ArrayCopy(m_src_close, close, 0, 0, rates_total); - ArrayResize(m_src_price, rates_total); switch(price_type) { @@ -274,11 +274,6 @@ bool CSessionAnalyzer::PrepareSourceData(int rates_total, const double &open[], } return true; } - -//+==================================================================+ -//| | -//| CLASS 2: CSessionAnalyzer_HA (Heikin Ashi) | -//| | //+==================================================================+ class CSessionAnalyzer_HA : public CSessionAnalyzer { @@ -287,9 +282,6 @@ private: protected: virtual bool PrepareSourceData(int rates_total, const double &open[], const double &high[], const double &low[], const double &close[], ENUM_APPLIED_PRICE price_type) override; }; - -//+------------------------------------------------------------------+ -//| CSessionAnalyzer_HA: Prepares the HA source data. | //+------------------------------------------------------------------+ bool CSessionAnalyzer_HA::PrepareSourceData(int rates_total, const double &open[], const double &high[], const double &low[], const double &close[], ENUM_APPLIED_PRICE price_type) { @@ -298,13 +290,10 @@ bool CSessionAnalyzer_HA::PrepareSourceData(int rates_total, const double &open[ ArrayResize(ha_high, rates_total); ArrayResize(ha_low, rates_total); ArrayResize(ha_close, rates_total); - m_ha_calculator.Calculate(rates_total, open, high, low, close, ha_open, ha_high, ha_low, ha_close); - ArrayCopy(m_src_high, ha_high, 0, 0, rates_total); ArrayCopy(m_src_low, ha_low, 0, 0, rates_total); ArrayCopy(m_src_close, ha_close, 0, 0, rates_total); - ArrayResize(m_src_price, rates_total); switch(price_type) {