From e1ab30c067cc2d46e292efbc51c56f3a62845676 Mon Sep 17 00:00:00 2001 From: Toh4iem9 Date: Thu, 16 Jul 2026 13:56:10 +0200 Subject: [PATCH] refactor: Upgraded with subtle pastel watermark MQL5 colors for multi-template support --- .../MyIndicators/Quant/Absorption_Pro.mq5 | 127 +++++++++++------- 1 file changed, 82 insertions(+), 45 deletions(-) diff --git a/Indicators/MyIndicators/Quant/Absorption_Pro.mq5 b/Indicators/MyIndicators/Quant/Absorption_Pro.mq5 index 4734e63..3f65f1c 100644 --- a/Indicators/MyIndicators/Quant/Absorption_Pro.mq5 +++ b/Indicators/MyIndicators/Quant/Absorption_Pro.mq5 @@ -1,36 +1,37 @@ -//+------------------------------------------------------------------+ +//+------------------------------------------------------------------+ //| Absorption_Pro.mq5 | //| Copyright 2026, xxxxxxxx| //+------------------------------------------------------------------+ #property copyright "Copyright 2026, xxxxxxxx" -#property version "1.10" +#property version "1.22" // Upgraded with subtle pastel watermark MQL5 colors for multi-template support #property description "Institutional Absorption Detector." -#property description "Draws Supply/Demand zones & Outputs State Buffer." +#property description "Draws Supply/Demand zones & Outputs State Buffer with soft pastel styling." #property indicator_chart_window #property indicator_buffers 5 #property indicator_plots 2 -// Plot 1: Bull Arrow +//--- Plot 1: Bull Arrow (Dodger Blue) #property indicator_label1 "Bull Abs" #property indicator_type1 DRAW_ARROW -#property indicator_color1 clrLime +#property indicator_color1 clrDodgerBlue #property indicator_width1 2 -// Plot 2: Bear Arrow +//--- Plot 2: Bear Arrow (Crimson Red) #property indicator_label2 "Bear Abs" #property indicator_type2 DRAW_ARROW -#property indicator_color2 clrRed +#property indicator_color2 clrCrimson #property indicator_width2 2 #include #include -//--- Parameters -input int InpATRPeriod = 14; -input int InpRVOLPeriod = 20; -input int InpHistoryBars = 500; // Limit object creation history -input bool InpShowObjects = true; // Toggle visuals +//--- Input Parameters +input group "--- Indicator Settings ---" +input int InpATRPeriod = 14; // ATR Period +input int InpRVOLPeriod = 20; // RVOL Period (Relative Volume) +input int InpHistoryBars = 500; // Limit object creation history (Bars) +input bool InpShowObjects = true; // Toggle zone and rectangle visuals //--- Buffers double BufBull[]; @@ -43,54 +44,89 @@ CATRCalculator *g_atr; CRelativeVolumeCalculator *g_rvol; //+------------------------------------------------------------------+ -//| | +//| Custom Indicator Initialization | //+------------------------------------------------------------------+ int OnInit() { - SetIndexBuffer(0, BufBull, INDICATOR_DATA); - SetIndexBuffer(1, BufBear, INDICATOR_DATA); - SetIndexBuffer(2, BufATR, INDICATOR_CALCULATIONS); - SetIndexBuffer(3, BufRVOL, INDICATOR_CALCULATIONS); +//--- Bind Buffers to index mapping + SetIndexBuffer(0, BufBull, INDICATOR_DATA); + SetIndexBuffer(1, BufBear, INDICATOR_DATA); + SetIndexBuffer(2, BufATR, INDICATOR_CALCULATIONS); + SetIndexBuffer(3, BufRVOL, INDICATOR_CALCULATIONS); SetIndexBuffer(4, BufState, INDICATOR_CALCULATIONS); +//--- Enforce strict chronological alignment (false = old to new) on dynamic buffers + ArraySetAsSeries(BufBull, false); + ArraySetAsSeries(BufBear, false); + ArraySetAsSeries(BufATR, false); + ArraySetAsSeries(BufRVOL, false); + ArraySetAsSeries(BufState, false); + +//--- Arrow Styles (Wingdings wing arrows) PlotIndexSetInteger(0, PLOT_ARROW, 233); PlotIndexSetInteger(1, PLOT_ARROW, 234); +//--- Instantiate Calculators g_atr = new CATRCalculator(); - g_atr.Init(InpATRPeriod, ATR_POINTS); + if(CheckPointer(g_atr) != POINTER_INVALID) + g_atr.Init(InpATRPeriod, ATR_POINTS); + g_rvol = new CRelativeVolumeCalculator(); - g_rvol.Init(InpRVOLPeriod); + if(CheckPointer(g_rvol) != POINTER_INVALID) + g_rvol.Init(InpRVOLPeriod); IndicatorSetString(INDICATOR_SHORTNAME, "Absorption Pro"); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ -//| | +//| Custom Indicator Deinitialization | //+------------------------------------------------------------------+ void OnDeinit(const int r) { ObjectsDeleteAll(0, "AbsZone_"); - if(CheckPointer(g_atr)==POINTER_DYNAMIC) + if(CheckPointer(g_atr) != POINTER_INVALID) delete g_atr; - if(CheckPointer(g_rvol)==POINTER_DYNAMIC) + if(CheckPointer(g_rvol) != POINTER_INVALID) delete g_rvol; } //+------------------------------------------------------------------+ -//| | +//| Custom Indicator Calculation Loop | //+------------------------------------------------------------------+ -int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) +int OnCalculate(const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[]) { if(rates_total < InpATRPeriod + InpRVOLPeriod) return 0; + if(CheckPointer(g_atr) == POINTER_INVALID || CheckPointer(g_rvol) == POINTER_INVALID) + return 0; + +//--- Force strict chronological alignment on all input price and volume arrays + ArraySetAsSeries(time, false); + ArraySetAsSeries(open, false); + ArraySetAsSeries(high, false); + ArraySetAsSeries(low, false); + ArraySetAsSeries(close, false); + ArraySetAsSeries(tick_volume, false); + ArraySetAsSeries(volume, false); + +//--- Calculate Volatility and Relative Volume indicators g_atr.Calculate(rates_total, prev_calculated, open, high, low, close, BufATR); g_rvol.Calculate(rates_total, prev_calculated, tick_volume, BufRVOL); int start = (prev_calculated > 0) ? prev_calculated - 1 : InpATRPeriod + InpRVOLPeriod; -// Limit Drawing loop to history bars to avoid lag on recompiles with huge history +//--- Limit loop to history bars limit to prevent terminal lag int draw_limit = rates_total - InpHistoryBars; if(draw_limit < 0) draw_limit = 0; @@ -99,29 +135,30 @@ int OnCalculate(const int rates_total, const int prev_calculated, const datetime for(int i = start; i < rates_total; i++) { - BufBull[i] = EMPTY_VALUE; - BufBear[i] = EMPTY_VALUE; - BufState[i] = 0; + BufBull[i] = EMPTY_VALUE; + BufBear[i] = EMPTY_VALUE; + BufState[i] = 0.0; double atr = BufATR[i]; - if(atr == 0) + if(atr <= 0.0) continue; double body = MathAbs(close[i] - open[i]); double total_range = high[i] - low[i]; double rvol = BufRVOL[i]; - bool is_bull = false; - bool is_bear = false; + bool is_bull = false; + bool is_bear = false; bool is_climax = false; + //--- Quantitative VSA rules bool high_effort = (rvol > 2.0); bool low_result = (body < (0.35 * atr)); if(high_effort && low_result) { double close_pos = 0.5; - if(total_range > 0) + if(total_range > 0.0) close_pos = (close[i] - low[i]) / total_range; if(close_pos > 0.66) @@ -147,36 +184,35 @@ int OnCalculate(const int rates_total, const int prev_calculated, const datetime is_climax = true; } - // Visuals & Objects + //--- Render Visuals & Graphical Objects if(is_bull || is_bear || is_climax) { if(InpShowObjects) { - // Arrows + // Arrows Setup if(is_bull) - BufBull[i] = low[i] - atr*0.3; + BufBull[i] = low[i] - atr * 0.3; if(is_bear) - BufBear[i] = high[i] + atr*0.3; + BufBear[i] = high[i] + atr * 0.3; - // ZONES (Rectangles) + // ZONES (Rectangles) using soft, transparent-like native MQL5 pastel colors string name = "AbsZone_" + TimeToString(time[i]); - color zone_col = is_bull ? C'0,64,0' : (is_bear ? C'64,0,0' : C'184,134,11'); // Dark Green/Red/Gold + color zone_col = is_bull ? clrLightSteelBlue : (is_bear ? clrMistyRose : clrWheat); - // Create if not exists + // Create rectangle if not already exists on active chart if(ObjectFind(0, name) < 0) { ObjectCreate(0, name, OBJ_RECTANGLE, 0, time[i], high[i], time[i], low[i]); ObjectSetInteger(0, name, OBJPROP_COLOR, zone_col); ObjectSetInteger(0, name, OBJPROP_FILL, true); ObjectSetInteger(0, name, OBJPROP_BACK, true); - ObjectSetInteger(0, name, OBJPROP_WIDTH, 1); // Borderless look if fill + ObjectSetInteger(0, name, OBJPROP_WIDTH, 1); // Borderless style } - // Extend Logic: Find breaker candle - datetime end_time = time[rates_total-1] + PeriodSeconds()*5; // Default: Live + // Forward scan looking for the break candle + datetime end_time = time[rates_total - 1] + PeriodSeconds() * 5; // Default: Live bar bool broken = false; - // Scan forward from signal bar for(int k = i + 1; k < rates_total; k++) { if(is_bull && close[k] < low[i]) @@ -202,9 +238,10 @@ int OnCalculate(const int rates_total, const int prev_calculated, const datetime } } - // Update Time2 + // Update zone ending time anchor ObjectSetInteger(0, name, OBJPROP_TIME, 1, end_time); - // Optional: Change style if broken + + // Adjust border style if zone was broken by price if(broken) ObjectSetInteger(0, name, OBJPROP_STYLE, STYLE_DOT); }