From f0f180ed3eb441f452ff3132b98bc33b123b3d32 Mon Sep 17 00:00:00 2001 From: Toh4iem9 Date: Thu, 18 Dec 2025 00:23:16 +0100 Subject: [PATCH] refactor: Updated for Colors and Background --- .../MyIndicators/Chart_HeikinAshi_Objects.mq5 | 125 ++++++++++++------ 1 file changed, 82 insertions(+), 43 deletions(-) diff --git a/Indicators/MyIndicators/Chart_HeikinAshi_Objects.mq5 b/Indicators/MyIndicators/Chart_HeikinAshi_Objects.mq5 index 054d378..d274d45 100644 --- a/Indicators/MyIndicators/Chart_HeikinAshi_Objects.mq5 +++ b/Indicators/MyIndicators/Chart_HeikinAshi_Objects.mq5 @@ -1,64 +1,94 @@ //+------------------------------------------------------------------+ //| Chart_HeikinAshi_Objects.mq5 | -//| Copyright 2025, xxxxxxxx | +//| Copyright 2025, xxxxxxxx | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, xxxxxxxx" -#property version "1.10" // Added Width inputs +#property version "1.20" // Updated for Colors and Background #property description "Draws Heikin Ashi candles using Objects for perfect sharpness." +//--- Include the Tools (Assuming user's path) #include #property indicator_chart_window #property indicator_buffers 4 -#property indicator_plots 0 +#property indicator_plots 0 // No drawing buffers, only objects -input int InpMaxHistory = 500; // Limit bars to draw -input int InpBodyWidth = 3; // Width of the candle body -input int InpWickWidth = 1; // Width of the candle wick +//--- Inputs +input group "Visual Settings" +input int InpMaxHistory = 500; // Limit bars to draw +input int InpBodyWidth = 3; // Width of the candle body +input int InpWickWidth = 1; // Width of the candle wick +input color InpColorBull = clrCornflowerBlue; // Bullish Color +input color InpColorBear = clrChocolate; // Bearish Color +input bool InpBack = true; // Draw in Background +//--- Buffers (for calculation only) double BufHA_Open[], BufHA_High[], BufHA_Low[], BufHA_Close[]; + +//--- Global Objects CHeikinAshi_Calculator *g_ha_calculator; string g_prefix; +//+------------------------------------------------------------------+ +//| OnInit | //+------------------------------------------------------------------+ int OnInit() { +//--- Setup Buffers SetIndexBuffer(0, BufHA_Open, INDICATOR_CALCULATIONS); SetIndexBuffer(1, BufHA_High, INDICATOR_CALCULATIONS); SetIndexBuffer(2, BufHA_Low, INDICATOR_CALCULATIONS); SetIndexBuffer(3, BufHA_Close, INDICATOR_CALCULATIONS); +//--- Initialize Calculator g_ha_calculator = new CHeikinAshi_Calculator(); + +//--- Create Unique Prefix for Objects g_prefix = "HA_Obj_" + IntegerToString(ChartID()) + "_"; + +//--- Cleanup stale objects from previous runs ObjectsDeleteAll(0, g_prefix); return(INIT_SUCCEEDED); } +//+------------------------------------------------------------------+ +//| OnDeinit | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { if(CheckPointer(g_ha_calculator) != POINTER_INVALID) delete g_ha_calculator; + +//--- Clean up objects created by this indicator ObjectsDeleteAll(0, g_prefix); + ChartRedraw(); } //+------------------------------------------------------------------+ -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[]) +//| OnCalculate | +//+------------------------------------------------------------------+ +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 < 2) return(0); - int start_index; - if(prev_calculated == 0) - start_index = 0; - else - start_index = prev_calculated - 1; +//--- 1. Calculate Heikin Ashi Values (Incremental) + int start_index = (prev_calculated > 0) ? prev_calculated - 1 : 0; g_ha_calculator.Calculate(rates_total, start_index, open, high, low, close, BufHA_Open, BufHA_High, BufHA_Low, BufHA_Close); -// Draw Objects +//--- 2. Draw/Update Objects int draw_start = MathMax(start_index, rates_total - InpMaxHistory); for(int i = draw_start; i < rates_total; i++) @@ -66,41 +96,50 @@ int OnCalculate(const int rates_total, const int prev_calculated, const datetime string name_body = g_prefix + "B_" + IntegerToString(i); string name_wick = g_prefix + "W_" + IntegerToString(i); - double o = BufHA_Open[i]; - double c = BufHA_Close[i]; - double h = BufHA_High[i]; - double l = BufHA_Low[i]; + double ha_open = BufHA_Open[i]; + double ha_close = BufHA_Close[i]; + double ha_high = BufHA_High[i]; + double ha_low = BufHA_Low[i]; + datetime t = time[i]; - color col = (c > o) ? clrCornflowerBlue : clrChocolate; + // Determine Color + bool is_bull = (ha_close >= ha_open); + color candle_color = is_bull ? InpColorBull : InpColorBear; - // Body - if(ObjectFind(0, name_body) < 0) - { - ObjectCreate(0, name_body, OBJ_RECTANGLE, 0, time[i], o, time[i], c); - } + //--- Draw Wick (Low to High) + UpdateObject(name_wick, t, ha_high, ha_low, InpWickWidth, candle_color); - if(ObjectFind(0, name_body) < 0) - { - ObjectCreate(0, name_body, OBJ_TREND, 0, time[i], o, time[i], c); - ObjectSetInteger(0, name_body, OBJPROP_RAY, false); - } - ObjectSetInteger(0, name_body, OBJPROP_COLOR, col); - ObjectSetInteger(0, name_body, OBJPROP_WIDTH, InpBodyWidth); // Body Width - ObjectMove(0, name_body, 0, time[i], o); - ObjectMove(0, name_body, 1, time[i], c); - - // Wick - if(ObjectFind(0, name_wick) < 0) - { - ObjectCreate(0, name_wick, OBJ_TREND, 0, time[i], h, time[i], l); - ObjectSetInteger(0, name_wick, OBJPROP_RAY, false); - } - ObjectSetInteger(0, name_wick, OBJPROP_COLOR, col); - ObjectSetInteger(0, name_wick, OBJPROP_WIDTH, InpWickWidth); // Wick Width - ObjectMove(0, name_wick, 0, time[i], h); - ObjectMove(0, name_wick, 1, time[i], l); + //--- Draw Body (Open to Close) + UpdateObject(name_body, t, ha_open, ha_close, InpBodyWidth, candle_color); } return(rates_total); } + +//+------------------------------------------------------------------+ +//| Helper: Create or Update Trend Object | +//+------------------------------------------------------------------+ +void UpdateObject(string name, datetime time, double price1, double price2, int width, color col) + { +// If object doesn't exist, create it + if(ObjectFind(0, name) < 0) + { + ObjectCreate(0, name, OBJ_TREND, 0, time, price1, time, price2); + // Essential properties for "Candle-like" appearance + ObjectSetInteger(0, name, OBJPROP_RAY, false); + ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false); // Prevent accidental selection + ObjectSetInteger(0, name, OBJPROP_HIDDEN, true); // Hide from Object List (optional) + } + else + { + ObjectMove(0, name, 0, time, price1); + ObjectMove(0, name, 1, time, price2); + } + +// Update visual properties + ObjectSetInteger(0, name, OBJPROP_COLOR, col); + ObjectSetInteger(0, name, OBJPROP_WIDTH, width); + ObjectSetInteger(0, name, OBJPROP_BACK, InpBack); // Set Background property + } +//+------------------------------------------------------------------+ //+------------------------------------------------------------------+