From b593acac19fb787acd760648753a457dd74de22d Mon Sep 17 00:00:00 2001 From: Toh4iem9 Date: Thu, 2 Oct 2025 14:51:53 +0200 Subject: [PATCH] chore: delete old indicators --- Indicators/MyIndicators/StochRSI_Fast.md | 63 ---- Indicators/MyIndicators/StochRSI_Fast.mq5 | 181 ------------ .../MyIndicators/StochRSI_Fast_HeikinAshi.mq5 | 189 ------------ Indicators/MyIndicators/StochRSI_Pro.md | 65 ---- Indicators/MyIndicators/StochRSI_Pro.mq5 | 274 ----------------- .../MyIndicators/StochRSI_Pro_HeikinAshi.mq5 | 279 ------------------ Indicators/MyIndicators/StochRSI_Slow.md | 69 ----- Indicators/MyIndicators/StochRSI_Slow.mq5 | 197 ------------- .../MyIndicators/StochRSI_Slow_HeikinAshi.mq5 | 201 ------------- Indicators/MyIndicators/StochasticFast.md | 57 ---- Indicators/MyIndicators/StochasticFast.mq5 | 154 ---------- .../StochasticFast_HeikinAshi.mq5 | 194 ------------ Indicators/MyIndicators/StochasticSlow.md | 61 ---- Indicators/MyIndicators/StochasticSlow.mq5 | 171 ----------- .../StochasticSlow_HeikinAshi.mq5 | 198 ------------- Indicators/MyIndicators/Stochastic_Pro.md | 72 ----- Indicators/MyIndicators/Stochastic_Pro.mq5 | 239 --------------- .../Stochastic_Pro_HeikinAshi.mq5 | 270 ----------------- Indicators/MyIndicators/Supertrend.md | 85 ------ Indicators/MyIndicators/Supertrend.mq5 | 169 ----------- .../MyIndicators/Supertrend_HeikinAshi.mq5 | 201 ------------- .../Supertrend_HeikinAshi_Pure.mq5 | 200 ------------- Indicators/MyIndicators/Symmetric_WMA.md | 66 ----- Indicators/MyIndicators/Symmetric_WMA.mq5 | 188 ------------ Indicators/MyIndicators/TDI.md | 79 ----- Indicators/MyIndicators/TDI.mq5 | 127 -------- Indicators/MyIndicators/TDI_HeikinAshi.mq5 | 119 -------- Indicators/MyIndicators/TSI.md | 82 ----- Indicators/MyIndicators/TSI.mq5 | 241 --------------- Indicators/MyIndicators/TSI_HeikinAshi.mq5 | 267 ----------------- Indicators/MyIndicators/TSI_Oscillator.mq5 | 233 --------------- .../TSI_Oscillator_HeikinAshi.mq5 | 267 ----------------- .../MyIndicators/Ultimate_Oscillator.md | 75 ----- .../MyIndicators/Ultimate_Oscillator.mq5 | 129 -------- .../Ultimate_Oscillator_HeikinAshi.mq5 | 161 ---------- Indicators/MyIndicators/VIDYA.md | 65 ---- Indicators/MyIndicators/VIDYA.mq5 | 158 ---------- Indicators/MyIndicators/VIDYA_HeikinAshi.mq5 | 187 ------------ .../MyIndicators/VIDYA_TrendActivity.md | 66 ----- .../MyIndicators/VIDYA_TrendActivity.mq5 | 222 -------------- .../VIDYA_TrendActivity_HeikinAshi.mq5 | 251 ---------------- Indicators/MyIndicators/WPR.md | 56 ---- Indicators/MyIndicators/WPR.mq5 | 121 -------- Indicators/MyIndicators/WPRMA_HeikinAshi.mq5 | 227 -------------- Indicators/MyIndicators/WPR_HeikinAshi.mq5 | 181 ------------ 45 files changed, 7157 deletions(-) delete mode 100644 Indicators/MyIndicators/StochRSI_Fast.md delete mode 100644 Indicators/MyIndicators/StochRSI_Fast.mq5 delete mode 100644 Indicators/MyIndicators/StochRSI_Fast_HeikinAshi.mq5 delete mode 100644 Indicators/MyIndicators/StochRSI_Pro.md delete mode 100644 Indicators/MyIndicators/StochRSI_Pro.mq5 delete mode 100644 Indicators/MyIndicators/StochRSI_Pro_HeikinAshi.mq5 delete mode 100644 Indicators/MyIndicators/StochRSI_Slow.md delete mode 100644 Indicators/MyIndicators/StochRSI_Slow.mq5 delete mode 100644 Indicators/MyIndicators/StochRSI_Slow_HeikinAshi.mq5 delete mode 100644 Indicators/MyIndicators/StochasticFast.md delete mode 100644 Indicators/MyIndicators/StochasticFast.mq5 delete mode 100644 Indicators/MyIndicators/StochasticFast_HeikinAshi.mq5 delete mode 100644 Indicators/MyIndicators/StochasticSlow.md delete mode 100644 Indicators/MyIndicators/StochasticSlow.mq5 delete mode 100644 Indicators/MyIndicators/StochasticSlow_HeikinAshi.mq5 delete mode 100644 Indicators/MyIndicators/Stochastic_Pro.md delete mode 100644 Indicators/MyIndicators/Stochastic_Pro.mq5 delete mode 100644 Indicators/MyIndicators/Stochastic_Pro_HeikinAshi.mq5 delete mode 100644 Indicators/MyIndicators/Supertrend.md delete mode 100644 Indicators/MyIndicators/Supertrend.mq5 delete mode 100644 Indicators/MyIndicators/Supertrend_HeikinAshi.mq5 delete mode 100644 Indicators/MyIndicators/Supertrend_HeikinAshi_Pure.mq5 delete mode 100644 Indicators/MyIndicators/Symmetric_WMA.md delete mode 100644 Indicators/MyIndicators/Symmetric_WMA.mq5 delete mode 100644 Indicators/MyIndicators/TDI.md delete mode 100644 Indicators/MyIndicators/TDI.mq5 delete mode 100644 Indicators/MyIndicators/TDI_HeikinAshi.mq5 delete mode 100644 Indicators/MyIndicators/TSI.md delete mode 100644 Indicators/MyIndicators/TSI.mq5 delete mode 100644 Indicators/MyIndicators/TSI_HeikinAshi.mq5 delete mode 100644 Indicators/MyIndicators/TSI_Oscillator.mq5 delete mode 100644 Indicators/MyIndicators/TSI_Oscillator_HeikinAshi.mq5 delete mode 100644 Indicators/MyIndicators/Ultimate_Oscillator.md delete mode 100644 Indicators/MyIndicators/Ultimate_Oscillator.mq5 delete mode 100644 Indicators/MyIndicators/Ultimate_Oscillator_HeikinAshi.mq5 delete mode 100644 Indicators/MyIndicators/VIDYA.md delete mode 100644 Indicators/MyIndicators/VIDYA.mq5 delete mode 100644 Indicators/MyIndicators/VIDYA_HeikinAshi.mq5 delete mode 100644 Indicators/MyIndicators/VIDYA_TrendActivity.md delete mode 100644 Indicators/MyIndicators/VIDYA_TrendActivity.mq5 delete mode 100644 Indicators/MyIndicators/VIDYA_TrendActivity_HeikinAshi.mq5 delete mode 100644 Indicators/MyIndicators/WPR.md delete mode 100644 Indicators/MyIndicators/WPR.mq5 delete mode 100644 Indicators/MyIndicators/WPRMA_HeikinAshi.mq5 delete mode 100644 Indicators/MyIndicators/WPR_HeikinAshi.mq5 diff --git a/Indicators/MyIndicators/StochRSI_Fast.md b/Indicators/MyIndicators/StochRSI_Fast.md deleted file mode 100644 index 33b77ff..0000000 --- a/Indicators/MyIndicators/StochRSI_Fast.md +++ /dev/null @@ -1,63 +0,0 @@ -# Fast Stochastic RSI (StochRSI) Indicator - -## 1. Summary (Introduction) - -The Stochastic RSI, or StochRSI, is a technical analysis indicator developed by Tushar Chande and Stanley Kroll. It is an "indicator of an indicator," applying the Stochastic Oscillator formula to a set of Relative Strength Index (RSI) values instead of standard price data. The primary goal of the StochRSI is to identify overbought and oversold conditions with greater sensitivity and speed than the RSI alone. - -The "Fast" version of the StochRSI represents the raw, unsmoothed calculation of the Stochastic on the RSI. It is more responsive to momentum changes than its "Slow" counterpart but can also be more prone to generating false signals. - -## 2. Mathematical Foundations and Calculation Logic - -The Fast StochRSI calculation is a direct application of the Stochastic formula to an RSI data series. - -### Required Components - -- **RSI (Relative Strength Index):** The underlying data series for the calculation. -- **Stochastic %K Period:** The lookback period used to find the highest and lowest RSI values. -- **%D Period:** The period for the smoothing of the %K line to create the signal line. - -### Calculation Steps (Algorithm) - -1. **Calculate the RSI:** First, calculate the standard RSI for a given period (e.g., 14) on the source price (e.g., Close). Let's denote this as $\text{RSI}_i$. - -2. **Calculate the Fast %K:** Apply the Stochastic formula to the RSI data series. This finds where the current RSI value lies in relation to its highest and lowest values over the Stochastic period. This line is the main line of the Fast StochRSI. - $\text{Fast \%K}_i = \frac{\text{RSI}_i - \text{Lowest Low RSI}_{\text{Stoch Period}}}{\text{Highest High RSI}_{\text{Stoch Period}} - \text{Lowest Low RSI}_{\text{Stoch Period}}} \times 100$ - Where: - - - $\text{Lowest Low RSI}$ is the minimum RSI value over the Stochastic lookback period. - - $\text{Highest High RSI}$ is the maximum RSI value over the Stochastic lookback period. - -3. **Calculate the %D (Signal Line):** The signal line is a moving average (typically a Simple Moving Average) of the Fast %K line. - $\text{\%D}_i = \text{SMA}(\text{Fast \%K}, \text{\%D Period})_i$ - -## 3. MQL5 Implementation Details - -Our MQL5 implementation is designed for stability, clarity, and consistency with our existing indicator toolkit. - -- **Stability via Full Recalculation:** We employ a "brute-force" full recalculation within the `OnCalculate` function. This ensures that the multi-stage calculation (Price -> RSI -> %K -> %D) remains stable and accurate, especially during timeframe changes or history loading. - -- **Leveraging Standard Indicators:** For the initial RSI calculation, we use a handle to MQL5's built-in `iRSI` indicator. This is a robust and efficient method for obtaining the underlying RSI data series. The handle's resources are properly managed and released in the `OnDeinit` function. - -- **Clear, Staged Calculation:** The `OnCalculate` function is structured into clear, sequential steps, each handled by a dedicated `for` loop. This improves code readability and makes the logic easy to follow: - - 1. **Step 1:** RSI data is retrieved into the `BufferRSI` calculation buffer. - 2. **Step 2:** The Fast %K line is calculated from `BufferRSI` and stored in the `BufferK` plot buffer. - 3. **Step 3:** The %D signal line is calculated by applying a simple moving average to `BufferK` and storing the result in the `BufferD` plot buffer. - -- **Heikin Ashi Variant (`StochRSI_Fast_HeikinAshi.mq5`):** - - Our toolkit also includes a "pure" Heikin Ashi version of this indicator. Instead of using the standard `iRSI`, it utilizes our custom `CHeikinAshi_RSI_Calculator` from the `HeikinAshi_Tools.mqh` library. - - This ensures that the entire calculation, from the very first RSI value to the final %D line, is based on the smoothed Heikin Ashi price data, providing a consistent, filtered view of momentum. - -## 4. Parameters - -- **RSI Length (`InpLengthRSI`):** The lookback period for the underlying RSI calculation. Default is `14`. -- **Stochastic Length (`InpLengthStoch`):** The lookback period for finding the highest and lowest RSI values (%K calculation). Default is `14`. -- **%D Smoothing (`InpSmoothD`):** The smoothing period for the signal line (%D). Default is `3`. -- **Applied Price (`InpAppliedPrice`):** The source price used for the initial RSI calculation (e.g., `PRICE_CLOSE`). - -## 5. Usage and Interpretation - -- **Overbought/Oversold Levels:** The primary use of StochRSI is to identify overbought (typically above 80) and oversold (typically below 20) conditions. The Fast version will reach these levels more quickly and frequently than the Slow version or the standard RSI. -- **Crossovers:** The crossover of the %K line and the %D signal line can be used to generate trade signals. A crossover of %K above %D can be a bullish signal, especially when occurring in oversold territory. A crossover of %K below %D can be a bearish signal, especially in overbought territory. -- **Divergence:** Look for divergences between the StochRSI and the price action. For example, if the price is making a new high but the StochRSI is failing to do so (bearish divergence), it could signal a potential trend reversal. -- **Caution:** The Fast StochRSI is extremely sensitive and can produce a significant number of false signals ("whipsaws"), especially in choppy or strongly trending markets. It is often used as a component in a larger trading system or confirmed with other, less sensitive indicators. diff --git a/Indicators/MyIndicators/StochRSI_Fast.mq5 b/Indicators/MyIndicators/StochRSI_Fast.mq5 deleted file mode 100644 index f82352e..0000000 --- a/Indicators/MyIndicators/StochRSI_Fast.mq5 +++ /dev/null @@ -1,181 +0,0 @@ -//+------------------------------------------------------------------+ -//| StochRSI_Fast.mq5 | -//| Copyright 2025, xxxxxxxx | -//| | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2025, xxxxxxxx" -#property link "" -#property version "2.00" // Refactored for stability and clarity -#property description "Fast Stochastic RSI Oscillator" - -//--- Indicator Window and Level Properties --- -#property indicator_separate_window -#property indicator_buffers 3 // %K, %D, and RSI calculation buffer -#property indicator_plots 2 -#property indicator_level1 20.0 -#property indicator_level2 80.0 -#property indicator_minimum -10.0 -#property indicator_maximum 110.0 - -//--- Plot 1: %K line -#property indicator_label1 "%K" -#property indicator_type1 DRAW_LINE -#property indicator_color1 clrBlue -#property indicator_style1 STYLE_SOLID -#property indicator_width1 1 - -//--- Plot 2: %D line -#property indicator_label2 "%D" -#property indicator_type2 DRAW_LINE -#property indicator_color2 clrOrange -#property indicator_style2 STYLE_SOLID -#property indicator_width2 1 - -//--- Input Parameters --- -input int InpLengthRSI = 14; // RSI Length -input int InpLengthStoch = 14; // Stochastic Length (%K Period) -input int InpSmoothD = 3; // %D Smoothing (Signal Line) -input ENUM_APPLIED_PRICE InpAppliedPrice = PRICE_CLOSE; // RSI Source Price - -//--- Indicator Buffers --- -double BufferK[]; -double BufferD[]; -double BufferRSI[]; - -//--- Global Variables --- -int g_ExtLengthRSI, g_ExtLengthStoch, g_ExtSmoothD; -int g_handle_rsi; - -//--- Forward declarations for helper functions --- -double Highest(const double &array[], int period, int current_pos); -double Lowest(const double &array[], int period, int current_pos); - -//+------------------------------------------------------------------+ -//| Custom indicator initialization function. | -//+------------------------------------------------------------------+ -int OnInit() - { - g_ExtLengthRSI = (InpLengthRSI < 1) ? 1 : InpLengthRSI; - g_ExtLengthStoch = (InpLengthStoch < 1) ? 1 : InpLengthStoch; - g_ExtSmoothD = (InpSmoothD < 1) ? 1 : InpSmoothD; - - SetIndexBuffer(0, BufferK, INDICATOR_DATA); - SetIndexBuffer(1, BufferD, INDICATOR_DATA); - SetIndexBuffer(2, BufferRSI, INDICATOR_CALCULATIONS); - - ArraySetAsSeries(BufferK, false); - ArraySetAsSeries(BufferD, false); - ArraySetAsSeries(BufferRSI, false); - - g_handle_rsi = iRSI(_Symbol, _Period, g_ExtLengthRSI, InpAppliedPrice); - if(g_handle_rsi == INVALID_HANDLE) - { - Print("Error creating iRSI handle."); - return(INIT_FAILED); - } - - IndicatorSetInteger(INDICATOR_DIGITS, 2); - PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, g_ExtLengthRSI + g_ExtLengthStoch - 2); - PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, g_ExtLengthRSI + g_ExtLengthStoch + g_ExtSmoothD - 3); - IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("Fast StochRSI(%d,%d,%d)", g_ExtLengthRSI, g_ExtLengthStoch, g_ExtSmoothD)); - - return(INIT_SUCCEEDED); - } - -//+------------------------------------------------------------------+ -//| Custom indicator deinitialization function. | -//+------------------------------------------------------------------+ -void OnDeinit(const int reason) - { -//--- Release the indicator handle - IndicatorRelease(g_handle_rsi); - } - -//+------------------------------------------------------------------+ -//| Fast Stochastic RSI calculation function. | -//+------------------------------------------------------------------+ -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 start_pos = g_ExtLengthRSI + g_ExtLengthStoch + g_ExtSmoothD - 2; - if(rates_total <= start_pos) - return(0); - -//--- STEP 1: Get RSI values from the standard indicator - if(CopyBuffer(g_handle_rsi, 0, 0, rates_total, BufferRSI) < rates_total) - { - Print("Error copying iRSI buffer data."); - } - -//--- STEP 2: Calculate Fast %K on the RSI buffer - int k_start_pos = g_ExtLengthRSI + g_ExtLengthStoch - 2; - for(int i = k_start_pos; i < rates_total; i++) - { - double highest_rsi = Highest(BufferRSI, g_ExtLengthStoch, i); - double lowest_rsi = Lowest(BufferRSI, g_ExtLengthStoch, i); - - double range = highest_rsi - lowest_rsi; - if(range > 0.00001) - BufferK[i] = (BufferRSI[i] - lowest_rsi) / range * 100.0; - else - BufferK[i] = (i > 0) ? BufferK[i-1] : 50.0; - } - -//--- STEP 3: Calculate %D (Signal Line) as an SMA of %K - int d_start_pos = g_ExtLengthRSI + g_ExtLengthStoch + g_ExtSmoothD - 3; - for(int i = d_start_pos; i < rates_total; i++) - { - double sum = 0; - for(int j = 0; j < g_ExtSmoothD; j++) - { - sum += BufferK[i-j]; - } - BufferD[i] = sum / g_ExtSmoothD; - } - - return(rates_total); - } - -//+------------------------------------------------------------------+ -//| Finds the highest value in a given period of an array. | -//+------------------------------------------------------------------+ -double Highest(const double &array[], int period, int current_pos) - { - double res = array[current_pos]; - for(int i = 1; i < period; i++) - { - int index = current_pos - i; - if(index < 0) - break; - if(res < array[index]) - res = array[index]; - } - return(res); - } - -//+------------------------------------------------------------------+ -//| Finds the lowest value in a given period of an array. | -//+------------------------------------------------------------------+ -double Lowest(const double &array[], int period, int current_pos) - { - double res = array[current_pos]; - for(int i = 1; i < period; i++) - { - int index = current_pos - i; - if(index < 0) - break; - if(res > array[index]) - res = array[index]; - } - return(res); - } -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ diff --git a/Indicators/MyIndicators/StochRSI_Fast_HeikinAshi.mq5 b/Indicators/MyIndicators/StochRSI_Fast_HeikinAshi.mq5 deleted file mode 100644 index d52bac9..0000000 --- a/Indicators/MyIndicators/StochRSI_Fast_HeikinAshi.mq5 +++ /dev/null @@ -1,189 +0,0 @@ -//+------------------------------------------------------------------+ -//| StochRSI_Fast_HeikinAshi.mq5 | -//| Copyright 2025, xxxxxxxx | -//| | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2025, xxxxxxxx" -#property link "" -#property version "2.00" // Refactored to be self-contained, no iCustom -#property description "Fast Stochastic on a Heikin Ashi based RSI" - -//--- Custom Toolkit Include --- -#include - -//--- Indicator Window and Level Properties --- -#property indicator_separate_window -#property indicator_buffers 3 // %K, %D, and HA_RSI for calculation -#property indicator_plots 2 -#property indicator_level1 20.0 -#property indicator_level2 80.0 -#property indicator_minimum -10.0 -#property indicator_maximum 110.0 - -//--- Plot 1: %K line -#property indicator_label1 "HA_%K" -#property indicator_type1 DRAW_LINE -#property indicator_color1 clrBlue -#property indicator_style1 STYLE_SOLID -#property indicator_width1 1 - -//--- Plot 2: %D line -#property indicator_label2 "HA_%D" -#property indicator_type2 DRAW_LINE -#property indicator_color2 clrOrange -#property indicator_style2 STYLE_SOLID -#property indicator_width2 1 - -//--- Input Parameters --- -input int InpLengthRSI = 14; // RSI Length -input int InpLengthStoch = 14; // Stochastic Length (%K Period) -input int InpSmoothD = 3; // %D Smoothing (Signal Line) - -//--- Indicator Buffers --- -double BufferK[]; -double BufferD[]; -double BufferHA_RSI[]; // Buffer to store the Heikin Ashi RSI values - -//--- Global Objects and Variables --- -int g_ExtLengthRSI, g_ExtLengthStoch, g_ExtSmoothD; -CHeikinAshi_RSI_Calculator *g_ha_rsi_calculator; // Pointer to our new calculator - -//--- Forward declarations for helper functions --- -double Highest(const double &array[], int period, int current_pos); -double Lowest(const double &array[], int period, int current_pos); - -//+------------------------------------------------------------------+ -//| Custom indicator initialization function. | -//+------------------------------------------------------------------+ -int OnInit() - { - g_ExtLengthRSI = (InpLengthRSI < 1) ? 1 : InpLengthRSI; - g_ExtLengthStoch = (InpLengthStoch < 1) ? 1 : InpLengthStoch; - g_ExtSmoothD = (InpSmoothD < 1) ? 1 : InpSmoothD; - - SetIndexBuffer(0, BufferK, INDICATOR_DATA); - SetIndexBuffer(1, BufferD, INDICATOR_DATA); - SetIndexBuffer(2, BufferHA_RSI, INDICATOR_CALCULATIONS); - - ArraySetAsSeries(BufferK, false); - ArraySetAsSeries(BufferD, false); - ArraySetAsSeries(BufferHA_RSI, false); - - IndicatorSetInteger(INDICATOR_DIGITS, 2); - PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, g_ExtLengthRSI + g_ExtLengthStoch - 2); - PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, g_ExtLengthRSI + g_ExtLengthStoch + g_ExtSmoothD - 3); - IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("HA_StochRSI_Fast(%d,%d,%d)", g_ExtLengthRSI, g_ExtLengthStoch, g_ExtSmoothD)); - -//--- Create the calculator instance - g_ha_rsi_calculator = new CHeikinAshi_RSI_Calculator(); - if(CheckPointer(g_ha_rsi_calculator) == POINTER_INVALID) - { - Print("Error creating CHeikinAshi_RSI_Calculator object"); - return(INIT_FAILED); - } - - return(INIT_SUCCEEDED); - } - -//+------------------------------------------------------------------+ -//| Custom indicator deinitialization function. | -//+------------------------------------------------------------------+ -void OnDeinit(const int reason) - { -//--- Free the calculator object - if(CheckPointer(g_ha_rsi_calculator) != POINTER_INVALID) - { - delete g_ha_rsi_calculator; - g_ha_rsi_calculator = NULL; - } - } - -//+------------------------------------------------------------------+ -//| Fast StochRSI on Heikin Ashi calculation function. | -//+------------------------------------------------------------------+ -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 start_pos = g_ExtLengthRSI + g_ExtLengthStoch + g_ExtSmoothD - 2; - if(rates_total <= start_pos) - return(0); - -//--- STEP 1: Calculate Heikin Ashi RSI values using our new toolkit - if(!g_ha_rsi_calculator.Calculate(rates_total, g_ExtLengthRSI, open, high, low, close, BufferHA_RSI)) - { - Print("Heikin Ashi RSI calculation failed."); - return(0); - } - -//--- STEP 2: Calculate Fast %K on the HA_RSI buffer - int k_start_pos = g_ExtLengthRSI + g_ExtLengthStoch - 2; - for(int i = k_start_pos; i < rates_total; i++) - { - double highest_ha_rsi = Highest(BufferHA_RSI, g_ExtLengthStoch, i); - double lowest_ha_rsi = Lowest(BufferHA_RSI, g_ExtLengthStoch, i); - - double range = highest_ha_rsi - lowest_ha_rsi; - if(range > 0.00001) - BufferK[i] = (BufferHA_RSI[i] - lowest_ha_rsi) / range * 100.0; - else - BufferK[i] = (i > 0) ? BufferK[i-1] : 50.0; - } - -//--- STEP 3: Calculate %D (Signal Line) as an SMA of %K - int d_start_pos = g_ExtLengthRSI + g_ExtLengthStoch + g_ExtSmoothD - 3; - for(int i = d_start_pos; i < rates_total; i++) - { - double sum = 0; - for(int j = 0; j < g_ExtSmoothD; j++) - { - sum += BufferK[i-j]; - } - BufferD[i] = sum / g_ExtSmoothD; - } - - return(rates_total); - } - -//+------------------------------------------------------------------+ -//| Finds the highest value in a given period of an array. | -//+------------------------------------------------------------------+ -double Highest(const double &array[], int period, int current_pos) - { - double res = array[current_pos]; - for(int i = 1; i < period; i++) - { - int index = current_pos - i; - if(index < 0) - break; - if(res < array[index]) - res = array[index]; - } - return(res); - } - -//+------------------------------------------------------------------+ -//| Finds the lowest value in a given period of an array. | -//+------------------------------------------------------------------+ -double Lowest(const double &array[], int period, int current_pos) - { - double res = array[current_pos]; - for(int i = 1; i < period; i++) - { - int index = current_pos - i; - if(index < 0) - break; - if(res > array[index]) - res = array[index]; - } - return(res); - } -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ diff --git a/Indicators/MyIndicators/StochRSI_Pro.md b/Indicators/MyIndicators/StochRSI_Pro.md deleted file mode 100644 index ab28ee4..0000000 --- a/Indicators/MyIndicators/StochRSI_Pro.md +++ /dev/null @@ -1,65 +0,0 @@ -# Stochastic RSI Pro - -## 1. Summary (Introduction) - -The Stochastic RSI Pro is an enhanced, "indicator of an indicator" that applies the flexible **Stochastic Pro** formula to a **Relative Strength Index (RSI)** data series instead of standard price data. - -While the standard StochRSI uses a fixed smoothing method, this "Pro" version grants the trader full control over the oscillator's behavior by allowing the independent selection of the moving average type (**SMA, EMA, SMMA, LWMA**) for both the %K and %D lines. This allows for a vast range of customization, from replicating the classic textbook definition to creating entirely new, hybrid oscillators. - -## 2. Mathematical Foundations and Calculation Logic - -The StochRSI Pro follows the structure of the Slow Stochastic but uses an RSI series as its input and allows for generalized moving average calculations. - -### Required Components - -- **RSI Data Series:** The underlying data, calculated with a specific period. -- **%K Period:** The lookback period for the initial Stochastic calculation on the RSI data. -- **Slowing Period & MA Type:** The period and MA type for the first smoothing step (%K line). -- **%D Period & MA Type:** The period and MA type for the second smoothing step (the signal line). - -### Calculation Steps (Algorithm) - -1. **Calculate the RSI:** First, the standard RSI is calculated for a given period. - $\text{RSI}_i = \text{RSI}(\text{Price}, \text{RSI Period})_i$ - -2. **Calculate the Raw %K (Fast StochRSI):** Apply the Stochastic formula to the RSI data series. - $\text{Raw \%K}_i = 100 \times \frac{\text{RSI}_i - \text{Lowest(RSI, \%K Period)}}{\text{Highest(RSI, \%K Period)} - \text{Lowest(RSI, \%K Period)}}$ - -3. **Calculate the %K Line (Slowing):** The Raw %K line is smoothed using the selected `Slowing Period` and `Slowing MA Type`. - $\text{\%K}_i = \text{MA}(\text{Raw \%K}, \text{Slowing Period}, \text{Slowing MA Type})_i$ - -4. **Calculate the %D Line (Signal):** The signal line is a moving average of the %K line, using the selected `%D Period` and `%D MA Type`. - $\text{\%D}_i = \text{MA}(\text{\%K}, \text{\%D Period}, \text{\%D MA Type})_i$ - -## 3. MQL5 Implementation Details - -Our MQL5 implementations are self-contained, robust, and highly flexible indicators built upon our established coding principles. - -- **Stability via Full Recalculation:** We employ a "brute-force" full recalculation within the `OnCalculate` function for maximum stability. - -- **Robust MA Calculations:** All moving average calculations for the Slowing and %D steps are performed **manually**. This guarantees 100% accuracy and consistency within our `non-timeseries` model. Recursive MA types (EMA, SMMA) are carefully initialized with a manual Simple Moving Average (SMA). - -- **Clear, Staged Calculation:** The `OnCalculate` function is structured into clear, sequential steps, each handled by a dedicated `for` loop, making the logic easy to follow. - -- **Efficient RSI Source:** - - The standard version (`StochRSI_Pro.mq5`) uses a handle to MQL5's built-in `iRSI` indicator for efficiency and guaranteed accuracy. - - The Heikin Ashi version (`StochRSI_Pro_HeikinAshi.mq5`) uses our custom `CHeikinAshi_RSI_Calculator` from the `HeikinAshi_Tools.mqh` library to generate a "pure" Heikin Ashi RSI data series. - -## 4. Parameters - -- **`InpRSIPeriod`**: The lookback period for the underlying RSI calculation. -- **`InpKPeriod`**: The lookback period for the Stochastic calculation on the RSI data. -- **`InpSlowingPeriod`**: The period for the first smoothing step (%K line). -- **`InpSlowingMAType`**: The MA type for the first smoothing step. -- **`InpDPeriod`**: The period for the signal line smoothing (%D line). -- **`InpDMAType`**: The MA type for the signal line. -- **`InpAppliedPrice`**: The source price for the underlying RSI calculation. - -## 5. Usage and Interpretation - -The interpretation of the StochRSI Pro is identical to the standard StochRSI, but its sensitivity can be adjusted. - -- **Overbought/Oversold Levels:** The primary use is to identify overbought (typically above 80) and oversold (typically below 20) conditions. It reaches these levels more frequently than the standard RSI. -- **Crossovers:** The crossover of the %K line and the %D signal line can be used to generate trade signals. A bullish crossover in oversold territory is a strong signal, and a bearish crossover in overbought territory is a strong signal. -- **Divergence:** Divergences between the oscillator and the price can signal weakening momentum and potential reversals. -- **Caution:** Due to its nature as an "indicator of an indicator," the StochRSI is very sensitive and can produce many signals in choppy markets. It is best used for confirmation alongside other, broader trend analysis tools. diff --git a/Indicators/MyIndicators/StochRSI_Pro.mq5 b/Indicators/MyIndicators/StochRSI_Pro.mq5 deleted file mode 100644 index 26d6847..0000000 --- a/Indicators/MyIndicators/StochRSI_Pro.mq5 +++ /dev/null @@ -1,274 +0,0 @@ -//+------------------------------------------------------------------+ -//| StochRSI_Pro.mq5| -//| Copyright 2025, xxxxxxxx | -//| | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2025, xxxxxxxx" -#property link "" -#property version "1.00" -#property description "Stochastic RSI with selectable MA types for %K and %D." - -//--- Indicator Window and Level Properties --- -#property indicator_separate_window -#property indicator_buffers 4 // %K, %D, RawK, and RSI buffer -#property indicator_plots 2 -#property indicator_level1 20.0 -#property indicator_level2 80.0 -#property indicator_minimum -10.0 -#property indicator_maximum 110.0 - -//--- Plot 1: %K line -#property indicator_label1 "%K" -#property indicator_type1 DRAW_LINE -#property indicator_color1 clrLightSeaGreen -#property indicator_style1 STYLE_SOLID -#property indicator_width1 1 - -//--- Plot 2: %D line -#property indicator_label2 "%D" -#property indicator_type2 DRAW_LINE -#property indicator_color2 clrRed -#property indicator_style2 STYLE_DOT -#property indicator_width2 1 - -//--- Input Parameters --- -input int InpRSIPeriod = 14; -input int InpKPeriod = 14; -input int InpSlowingPeriod = 3; -input ENUM_MA_METHOD InpSlowingMAType = MODE_SMA; // MA type for Slowing -input int InpDPeriod = 3; -input ENUM_MA_METHOD InpDMAType = MODE_SMMA; // MA type for %D (Signal) -input ENUM_APPLIED_PRICE InpAppliedPrice = PRICE_CLOSE; - -//--- Indicator Buffers --- -double BufferK[]; -double BufferD[]; -double BufferRSI[]; -double BufferRawStochK[]; - -//--- Global Variables --- -int g_ExtRSIPeriod, g_ExtKPeriod, g_ExtSlowingPeriod, g_ExtDPeriod; -int g_handle_rsi; - -//--- Forward declarations for helper functions --- -double Highest(const double &array[], int period, int current_pos); -double Lowest(const double &array[], int period, int current_pos); - -//+------------------------------------------------------------------+ -//| Custom indicator initialization function. | -//+------------------------------------------------------------------+ -int OnInit() - { - g_ExtRSIPeriod = (InpRSIPeriod < 1) ? 1 : InpRSIPeriod; - g_ExtKPeriod = (InpKPeriod < 1) ? 1 : InpKPeriod; - g_ExtSlowingPeriod = (InpSlowingPeriod < 1) ? 1 : InpSlowingPeriod; - g_ExtDPeriod = (InpDPeriod < 1) ? 1 : InpDPeriod; - - SetIndexBuffer(0, BufferK, INDICATOR_DATA); - SetIndexBuffer(1, BufferD, INDICATOR_DATA); - SetIndexBuffer(2, BufferRSI, INDICATOR_CALCULATIONS); - SetIndexBuffer(3, BufferRawStochK, INDICATOR_CALCULATIONS); - - ArraySetAsSeries(BufferK, false); - ArraySetAsSeries(BufferD, false); - ArraySetAsSeries(BufferRSI, false); - ArraySetAsSeries(BufferRawStochK, false); - - g_handle_rsi = iRSI(_Symbol, _Period, g_ExtRSIPeriod, InpAppliedPrice); - if(g_handle_rsi == INVALID_HANDLE) - { - Print("Error creating iRSI handle."); - return(INIT_FAILED); - } - - IndicatorSetInteger(INDICATOR_DIGITS, 2); - PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, g_ExtRSIPeriod + g_ExtKPeriod + g_ExtSlowingPeriod - 3); - PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, g_ExtRSIPeriod + g_ExtKPeriod + g_ExtSlowingPeriod + g_ExtDPeriod - 4); - IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("StochRSI Pro(%d,%d,%d,%d)", g_ExtRSIPeriod, g_ExtKPeriod, g_ExtSlowingPeriod, g_ExtDPeriod)); - - return(INIT_SUCCEEDED); - } - -//+------------------------------------------------------------------+ -//| Custom indicator deinitialization function. | -//+------------------------------------------------------------------+ -void OnDeinit(const int reason) - { - IndicatorRelease(g_handle_rsi); - } - -//+------------------------------------------------------------------+ -//| Pro Stochastic RSI calculation function. | -//+------------------------------------------------------------------+ -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 start_pos = g_ExtRSIPeriod + g_ExtKPeriod + g_ExtSlowingPeriod + g_ExtDPeriod - 3; - if(rates_total <= start_pos) - return(0); - -//--- STEP 1: Get RSI values - if(CopyBuffer(g_handle_rsi, 0, 0, rates_total, BufferRSI) < rates_total) - { - Print("Error copying iRSI buffer data."); - } - -//--- STEP 2: Calculate Raw Stochastic %K on the RSI buffer - int raw_k_start_pos = g_ExtRSIPeriod + g_ExtKPeriod - 2; - for(int i = raw_k_start_pos; i < rates_total; i++) - { - double highest_rsi = Highest(BufferRSI, g_ExtKPeriod, i); - double lowest_rsi = Lowest(BufferRSI, g_ExtKPeriod, i); - double range = highest_rsi - lowest_rsi; - if(range > 0.00001) - BufferRawStochK[i] = (BufferRSI[i] - lowest_rsi) / range * 100.0; - else - BufferRawStochK[i] = (i > 0) ? BufferRawStochK[i-1] : 50.0; - } - -//--- STEP 3: Calculate %K (Main Line) by smoothing Raw %K - int k_slow_start_pos = g_ExtRSIPeriod + g_ExtKPeriod + g_ExtSlowingPeriod - 3; - for(int i = k_slow_start_pos; i < rates_total; i++) - { - switch(InpSlowingMAType) - { - case MODE_EMA: - case MODE_SMMA: - if(i == k_slow_start_pos) - { - double sum=0; - for(int j=0; j0) - BufferK[i]=lwma_sum/weight_sum; - } - break; - default: // MODE_SMA - { - double sum=0; - for(int j=0; j0) - BufferD[i]=lwma_sum/weight_sum; - } - break; - default: // MODE_SMA - { - double sum=0; - for(int j=0; j array[index]) - res = array[index]; - } - return(res); - } -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ diff --git a/Indicators/MyIndicators/StochRSI_Pro_HeikinAshi.mq5 b/Indicators/MyIndicators/StochRSI_Pro_HeikinAshi.mq5 deleted file mode 100644 index 432c6e9..0000000 --- a/Indicators/MyIndicators/StochRSI_Pro_HeikinAshi.mq5 +++ /dev/null @@ -1,279 +0,0 @@ -//+------------------------------------------------------------------+ -//| StochRSI_Pro_HeikinAshi.mq5 | -//| Copyright 2025, xxxxxxxx | -//| | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2025, xxxxxxxx" -#property link "" -#property version "1.00" -#property description "Stochastic RSI Pro on Heikin Ashi data" - -#include - -//--- Indicator Window and Level Properties --- -#property indicator_separate_window -#property indicator_buffers 4 // %K, %D, RawK, and HA_RSI buffer -#property indicator_plots 2 -#property indicator_level1 20.0 -#property indicator_level2 80.0 -#property indicator_minimum -10.0 -#property indicator_maximum 110.0 - -//--- Plot 1: %K line -#property indicator_label1 "HA_%K" -#property indicator_type1 DRAW_LINE -#property indicator_color1 clrLightSeaGreen -#property indicator_style1 STYLE_SOLID -#property indicator_width1 1 - -//--- Plot 2: %D line -#property indicator_label2 "HA_%D" -#property indicator_type2 DRAW_LINE -#property indicator_color2 clrRed -#property indicator_style2 STYLE_DOT -#property indicator_width2 1 - -//--- Input Parameters --- -input int InpRSIPeriod = 14; -input int InpKPeriod = 14; -input int InpSlowingPeriod = 3; -input ENUM_MA_METHOD InpSlowingMAType = MODE_SMA; -input int InpDPeriod = 3; -input ENUM_MA_METHOD InpDMAType = MODE_SMMA; - -//--- Indicator Buffers --- -double BufferK[]; -double BufferD[]; -double BufferHA_RSI[]; -double BufferRawStochK[]; - -//--- Global Objects and Variables --- -int g_ExtRSIPeriod, g_ExtKPeriod, g_ExtSlowingPeriod, g_ExtDPeriod; -CHeikinAshi_RSI_Calculator *g_ha_rsi_calculator; - -//--- Forward declarations for helper functions --- -double Highest(const double &array[], int period, int current_pos); -double Lowest(const double &array[], int period, int current_pos); - -//+------------------------------------------------------------------+ -//| Custom indicator initialization function. | -//+------------------------------------------------------------------+ -int OnInit() - { - g_ExtRSIPeriod = (InpRSIPeriod < 1) ? 1 : InpRSIPeriod; - g_ExtKPeriod = (InpKPeriod < 1) ? 1 : InpKPeriod; - g_ExtSlowingPeriod = (InpSlowingPeriod < 1) ? 1 : InpSlowingPeriod; - g_ExtDPeriod = (InpDPeriod < 1) ? 1 : InpDPeriod; - - SetIndexBuffer(0, BufferK, INDICATOR_DATA); - SetIndexBuffer(1, BufferD, INDICATOR_DATA); - SetIndexBuffer(2, BufferHA_RSI, INDICATOR_CALCULATIONS); - SetIndexBuffer(3, BufferRawStochK, INDICATOR_CALCULATIONS); - - ArraySetAsSeries(BufferK, false); - ArraySetAsSeries(BufferD, false); - ArraySetAsSeries(BufferHA_RSI, false); - ArraySetAsSeries(BufferRawStochK, false); - - IndicatorSetInteger(INDICATOR_DIGITS, 2); - PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, g_ExtRSIPeriod + g_ExtKPeriod + g_ExtSlowingPeriod - 3); - PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, g_ExtRSIPeriod + g_ExtKPeriod + g_ExtSlowingPeriod + g_ExtDPeriod - 4); - IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("HA_StochRSI_Pro(%d,%d,%d,%d)", g_ExtRSIPeriod, g_ExtKPeriod, g_ExtSlowingPeriod, g_ExtDPeriod)); - - g_ha_rsi_calculator = new CHeikinAshi_RSI_Calculator(); - if(CheckPointer(g_ha_rsi_calculator) == POINTER_INVALID) - { - Print("Error creating CHeikinAshi_RSI_Calculator object"); - return(INIT_FAILED); - } - return(INIT_SUCCEEDED); - } - -//+------------------------------------------------------------------+ -//| Custom indicator deinitialization function. | -//+------------------------------------------------------------------+ -void OnDeinit(const int reason) - { - if(CheckPointer(g_ha_rsi_calculator) != POINTER_INVALID) - { - delete g_ha_rsi_calculator; - g_ha_rsi_calculator = NULL; - } - } - -//+------------------------------------------------------------------+ -//| Pro Stochastic RSI on Heikin Ashi calculation function. | -//+------------------------------------------------------------------+ -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 start_pos = g_ExtRSIPeriod + g_ExtKPeriod + g_ExtSlowingPeriod + g_ExtDPeriod - 3; - if(rates_total <= start_pos) - return(0); - -//--- STEP 1: Calculate Heikin Ashi RSI values using our toolkit - if(!g_ha_rsi_calculator.Calculate(rates_total, g_ExtRSIPeriod, open, high, low, close, BufferHA_RSI)) - { - Print("Heikin Ashi RSI calculation failed."); - return(0); - } - -//--- STEP 2: Calculate Raw Stochastic %K on the HA_RSI buffer - int raw_k_start_pos = g_ExtRSIPeriod + g_ExtKPeriod - 2; - for(int i = raw_k_start_pos; i < rates_total; i++) - { - double highest_ha_rsi = Highest(BufferHA_RSI, g_ExtKPeriod, i); - double lowest_ha_rsi = Lowest(BufferHA_RSI, g_ExtKPeriod, i); - double range = highest_ha_rsi - lowest_ha_rsi; - if(range > 0.00001) - BufferRawStochK[i] = (BufferHA_RSI[i] - lowest_ha_rsi) / range * 100.0; - else - BufferRawStochK[i] = (i > 0) ? BufferRawStochK[i-1] : 50.0; - } - -//--- STEP 3: Calculate %K (Main Line) by smoothing Raw %K - int k_slow_start_pos = g_ExtRSIPeriod + g_ExtKPeriod + g_ExtSlowingPeriod - 3; - for(int i = k_slow_start_pos; i < rates_total; i++) - { - switch(InpSlowingMAType) - { - case MODE_EMA: - case MODE_SMMA: - if(i == k_slow_start_pos) - { - double sum=0; - for(int j=0; j0) - BufferK[i]=lwma_sum/weight_sum; - } - break; - default: // MODE_SMA - { - double sum=0; - for(int j=0; j0) - BufferD[i]=lwma_sum/weight_sum; - } - break; - default: // MODE_SMA - { - double sum=0; - for(int j=0; j array[index]) - res = array[index]; - } - return(res); - } -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ diff --git a/Indicators/MyIndicators/StochRSI_Slow.md b/Indicators/MyIndicators/StochRSI_Slow.md deleted file mode 100644 index ff00de3..0000000 --- a/Indicators/MyIndicators/StochRSI_Slow.md +++ /dev/null @@ -1,69 +0,0 @@ -# Slow Stochastic RSI (StochRSI) Indicator - -## 1. Summary (Introduction) - -The Stochastic RSI, or StochRSI, is a technical analysis indicator developed by Tushar Chande and Stanley Kroll. It is essentially an "indicator of an indicator," applying the Stochastic Oscillator formula to a set of Relative Strength Index (RSI) values instead of standard price data. The primary goal of the StochRSI is to identify overbought and oversold conditions with greater sensitivity and speed than the RSI alone. - -The "Slow" version of the StochRSI adds an extra layer of smoothing to its main line, making it less erratic than the "Fast" version and helping to filter out minor, insignificant fluctuations. - -## 2. Mathematical Foundations and Calculation Logic - -The StochRSI calculation is a multi-step process that builds upon the standard RSI and Stochastic formulas. - -### Required Components - -- **RSI (Relative Strength Index):** The underlying data series for the calculation. -- **Stochastic %K Period:** The lookback period used to find the highest and lowest RSI values. -- **Slowing Period:** The period for the first smoothing step, which transforms the "Fast %K" into the "Slow %K". -- **%D Period:** The period for the second smoothing step, which creates the signal line (%D) from the Slow %K. - -### Calculation Steps (Algorithm) - -1. **Calculate the RSI:** First, calculate the standard RSI for a given period (e.g., 14) on the source price (e.g., Close). Let's denote this as $\text{RSI}_i$. - -2. **Calculate the Raw %K (Fast StochRSI):** Apply the Stochastic formula to the RSI data series. This finds where the current RSI value lies in relation to its highest and lowest values over a given period. - $\text{Raw \%K}_i = \frac{\text{RSI}_i - \text{Lowest Low RSI}_{\text{Stoch Period}}}{\text{Highest High RSI}_{\text{Stoch Period}} - \text{Lowest Low RSI}_{\text{Stoch Period}}} \times 100$ - Where: - - - $\text{Lowest Low RSI}$ is the minimum RSI value over the Stochastic lookback period. - - $\text{Highest High RSI}$ is the maximum RSI value over the Stochastic lookback period. - -3. **Calculate the Slow %K (Main Line):** This is the key step that differentiates the "Slow" from the "Fast" StochRSI. The Raw %K line is smoothed, typically with a Simple Moving Average (SMA), to create the final %K line. - $\text{Slow \%K}_i = \text{SMA}(\text{Raw \%K}, \text{Slowing Period})_i$ - -4. **Calculate the %D (Signal Line):** The signal line is a moving average of the Slow %K line, providing an additional layer of smoothing. - $\text{Slow \%D}_i = \text{SMA}(\text{Slow \%K}, \text{\%D Period})_i$ - -## 3. MQL5 Implementation Details - -Our MQL5 implementation is designed for stability, clarity, and consistency with our existing indicator toolkit. - -- **Stability via Full Recalculation:** We employ a "brute-force" full recalculation within the `OnCalculate` function. This ensures that the multi-stage calculation (Price -> RSI -> Raw %K -> Slow %K -> %D) remains stable and accurate, especially during timeframe changes or history loading. - -- **Leveraging Standard Indicators:** For the initial RSI calculation, we use a handle to MQL5's built-in `iRSI` indicator. This is a robust and efficient method for obtaining the underlying RSI data series without re-implementing the logic ourselves. The handle's resources are properly managed and released in the `OnDeinit` function. - -- **Clear, Staged Calculation:** The `OnCalculate` function is structured into clear, sequential steps, each handled by a dedicated `for` loop. This improves code readability and makes the logic easy to follow: - - 1. **Step 1:** RSI data is retrieved into `BufferRSI`. - 2. **Step 2:** Raw %K is calculated from `BufferRSI` and stored in `BufferRawStochK`. - 3. **Step 3:** Slow %K (the main plot line) is calculated by smoothing `BufferRawStochK` and stored in `BufferK`. - 4. **Step 4:** The %D signal line is calculated by smoothing `BufferK` and stored in `BufferD`. - -- **Heikin Ashi Variant (`StochRSI_Slow_HeikinAshi.mq5`):** - - Our toolkit also includes a "pure" Heikin Ashi version of this indicator. Instead of using the standard `iRSI`, it utilizes our custom `CHeikinAshi_RSI_Calculator` from the `HeikinAshi_Tools.mqh` library. - - This ensures that the entire calculation, from the very first RSI value to the final %D line, is based on the smoothed Heikin Ashi price data, providing a consistent, filtered view of momentum. - -## 4. Parameters - -- **RSI Length (`InpLengthRSI`):** The lookback period for the underlying RSI calculation. Default is `14`. -- **Stochastic Length (`InpLengthStoch`):** The lookback period for finding the highest and lowest RSI values (%K calculation). Default is `14`. -- **Slowing (`InpSlowing`):** The smoothing period applied to the Raw %K to create the final Slow %K line. A value of `1` results in a Fast StochRSI. Default is `3`. -- **%D Smoothing (`InpSmoothD`):** The smoothing period for the signal line (%D). Default is `3`. -- **Applied Price (`InpAppliedPrice`):** The source price used for the initial RSI calculation (e.g., `PRICE_CLOSE`). - -## 5. Usage and Interpretation - -- **Overbought/Oversold Levels:** The primary use of StochRSI is to identify overbought (typically above 80) and oversold (typically below 20) conditions. Because it is more sensitive than RSI, it tends to reach these levels more frequently. -- **Crossovers:** The crossover of the %K line and the %D signal line can be used to generate trade signals. A crossover of %K above %D can be a bullish signal, especially when occurring in oversold territory. A crossover of %K below %D can be a bearish signal, especially in overbought territory. -- **Divergence:** Look for divergences between the StochRSI and the price action. For example, if the price is making a new high but the StochRSI is failing to do so (bearish divergence), it could signal a potential trend reversal. -- **Caution:** Due to its sensitivity, StochRSI can produce many false signals, especially in strongly trending markets where it may remain in overbought/oversold territory for extended periods. It is best used for confirmation alongside other trend-following indicators. diff --git a/Indicators/MyIndicators/StochRSI_Slow.mq5 b/Indicators/MyIndicators/StochRSI_Slow.mq5 deleted file mode 100644 index 42a3d6e..0000000 --- a/Indicators/MyIndicators/StochRSI_Slow.mq5 +++ /dev/null @@ -1,197 +0,0 @@ -//+------------------------------------------------------------------+ -//| StochRSI_Slow.mq5 | -//| Copyright 2025, xxxxxxxx | -//| | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2025, xxxxxxxx" -#property link "" -#property version "2.01" // Harmonized input parameter names -#property description "Slow Stochastic RSI Oscillator" - -//--- Indicator Window and Level Properties --- -#property indicator_separate_window -#property indicator_buffers 4 // %K, %D, RawK, and RSI buffer -#property indicator_plots 2 -#property indicator_level1 20.0 -#property indicator_level2 80.0 -#property indicator_minimum -10.0 -#property indicator_maximum 110.0 - -//--- Plot 1: %K line (Slow) -#property indicator_label1 "%K" -#property indicator_type1 DRAW_LINE -#property indicator_color1 clrLightSeaGreen -#property indicator_style1 STYLE_SOLID -#property indicator_width1 1 - -//--- Plot 2: %D line (Signal) -#property indicator_label2 "%D" -#property indicator_type2 DRAW_LINE -#property indicator_color2 clrRed -#property indicator_style2 STYLE_DOT -#property indicator_width2 1 - -//--- Input Parameters --- -input int InpRSIPeriod = 14; // RSI Period -input int InpKPeriod = 14; // Stochastic %K Period -input int InpSlowingPeriod = 3; // Slowing Period -input int InpDPeriod = 3; // %D Period -input ENUM_APPLIED_PRICE InpAppliedPrice = PRICE_CLOSE; - -//--- Indicator Buffers --- -double BufferK[]; -double BufferD[]; -double BufferRSI[]; -double BufferRawStochK[]; - -//--- Global Variables --- -int g_ExtRSIPeriod, g_ExtKPeriod, g_ExtSlowingPeriod, g_ExtDPeriod; -int g_handle_rsi; - -//--- Forward declarations for helper functions --- -double Highest(const double &array[], int period, int current_pos); -double Lowest(const double &array[], int period, int current_pos); - -//+------------------------------------------------------------------+ -//| Custom indicator initialization function. | -//+------------------------------------------------------------------+ -int OnInit() - { - g_ExtRSIPeriod = (InpRSIPeriod < 1) ? 1 : InpRSIPeriod; - g_ExtKPeriod = (InpKPeriod < 1) ? 1 : InpKPeriod; - g_ExtSlowingPeriod = (InpSlowingPeriod < 1) ? 1 : InpSlowingPeriod; - g_ExtDPeriod = (InpDPeriod < 1) ? 1 : InpDPeriod; - - SetIndexBuffer(0, BufferK, INDICATOR_DATA); - SetIndexBuffer(1, BufferD, INDICATOR_DATA); - SetIndexBuffer(2, BufferRSI, INDICATOR_CALCULATIONS); - SetIndexBuffer(3, BufferRawStochK, INDICATOR_CALCULATIONS); - - ArraySetAsSeries(BufferK, false); - ArraySetAsSeries(BufferD, false); - ArraySetAsSeries(BufferRSI, false); - ArraySetAsSeries(BufferRawStochK, false); - - g_handle_rsi = iRSI(_Symbol, _Period, g_ExtRSIPeriod, InpAppliedPrice); - if(g_handle_rsi == INVALID_HANDLE) - { - Print("Error creating iRSI handle."); - return(INIT_FAILED); - } - - IndicatorSetInteger(INDICATOR_DIGITS, 2); - PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, g_ExtRSIPeriod + g_ExtKPeriod + g_ExtSlowingPeriod - 3); - PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, g_ExtRSIPeriod + g_ExtKPeriod + g_ExtSlowingPeriod + g_ExtDPeriod - 4); - IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("Slow StochRSI(%d,%d,%d,%d)", g_ExtRSIPeriod, g_ExtKPeriod, g_ExtSlowingPeriod, g_ExtDPeriod)); - - return(INIT_SUCCEEDED); - } - -//+------------------------------------------------------------------+ -//| Custom indicator deinitialization function. | -//+------------------------------------------------------------------+ -void OnDeinit(const int reason) - { - IndicatorRelease(g_handle_rsi); - } - -//+------------------------------------------------------------------+ -//| Slow Stochastic RSI calculation function. | -//+------------------------------------------------------------------+ -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 start_pos = g_ExtRSIPeriod + g_ExtKPeriod + g_ExtSlowingPeriod + g_ExtDPeriod - 3; - if(rates_total <= start_pos) - return(0); - -//--- STEP 1: Get RSI values from the standard indicator - if(CopyBuffer(g_handle_rsi, 0, 0, rates_total, BufferRSI) < rates_total) - { - Print("Error copying iRSI buffer data."); - } - -//--- STEP 2: Calculate Raw Stochastic %K on the RSI buffer - int raw_k_start_pos = g_ExtRSIPeriod + g_ExtKPeriod - 2; - for(int i = raw_k_start_pos; i < rates_total; i++) - { - double highest_rsi = Highest(BufferRSI, g_ExtKPeriod, i); - double lowest_rsi = Lowest(BufferRSI, g_ExtKPeriod, i); - - double range = highest_rsi - lowest_rsi; - if(range > 0.00001) - BufferRawStochK[i] = (BufferRSI[i] - lowest_rsi) / range * 100.0; - else - BufferRawStochK[i] = (i > 0) ? BufferRawStochK[i-1] : 50.0; - } - -//--- STEP 3: Calculate Slow %K (Main Line) by smoothing Raw %K - int k_slow_start_pos = g_ExtRSIPeriod + g_ExtKPeriod + g_ExtSlowingPeriod - 3; - for(int i = k_slow_start_pos; i < rates_total; i++) - { - double sum = 0; - for(int j = 0; j < g_ExtSlowingPeriod; j++) - { - sum += BufferRawStochK[i-j]; - } - BufferK[i] = sum / g_ExtSlowingPeriod; - } - -//--- STEP 4: Calculate %D (Signal Line) by smoothing Slow %K - int d_start_pos = g_ExtRSIPeriod + g_ExtKPeriod + g_ExtSlowingPeriod + g_ExtDPeriod - 4; - for(int i = d_start_pos; i < rates_total; i++) - { - double sum = 0; - for(int j = 0; j < g_ExtDPeriod; j++) - { - sum += BufferK[i-j]; - } - BufferD[i] = sum / g_ExtDPeriod; - } - - return(rates_total); - } - -//+------------------------------------------------------------------+ -//| Finds the highest value in a given period of an array. | -//+------------------------------------------------------------------+ -double Highest(const double &array[], int period, int current_pos) - { - double res = array[current_pos]; - for(int i = 1; i < period; i++) - { - int index = current_pos - i; - if(index < 0) - break; - if(res < array[index]) - res = array[index]; - } - return(res); - } - -//+------------------------------------------------------------------+ -//| Finds the lowest value in a given period of an array. | -//+------------------------------------------------------------------+ -double Lowest(const double &array[], int period, int current_pos) - { - double res = array[current_pos]; - for(int i = 1; i < period; i++) - { - int index = current_pos - i; - if(index < 0) - break; - if(res > array[index]) - res = array[index]; - } - return(res); - } -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ diff --git a/Indicators/MyIndicators/StochRSI_Slow_HeikinAshi.mq5 b/Indicators/MyIndicators/StochRSI_Slow_HeikinAshi.mq5 deleted file mode 100644 index db7c266..0000000 --- a/Indicators/MyIndicators/StochRSI_Slow_HeikinAshi.mq5 +++ /dev/null @@ -1,201 +0,0 @@ -//+------------------------------------------------------------------+ -//| StochRSI_Slow_HeikinAshi.mq5 | -//| Copyright 2025, xxxxxxxx | -//| | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2025, xxxxxxxx" -#property link "" -#property version "2.01" // Harmonized input parameter names -#property description "Slow Stochastic on a Heikin Ashi based RSI" - -#include - -//--- Indicator Window and Level Properties --- -#property indicator_separate_window -#property indicator_buffers 4 // %K, %D, RawK, and HA_RSI buffer -#property indicator_plots 2 -#property indicator_level1 20.0 -#property indicator_level2 80.0 -#property indicator_minimum -10.0 -#property indicator_maximum 110.0 - -//--- Plot 1: %K line (Slow) -#property indicator_label1 "HA_%K" -#property indicator_type1 DRAW_LINE -#property indicator_color1 clrLightSeaGreen -#property indicator_style1 STYLE_SOLID -#property indicator_width1 1 - -//--- Plot 2: %D line (Signal) -#property indicator_label2 "HA_%D" -#property indicator_type2 DRAW_LINE -#property indicator_color2 clrRed -#property indicator_style2 STYLE_DOT -#property indicator_width2 1 - -//--- Input Parameters --- -input int InpRSIPeriod = 14; -input int InpKPeriod = 14; -input int InpSlowingPeriod = 3; -input int InpDPeriod = 3; - -//--- Indicator Buffers --- -double BufferK[]; -double BufferD[]; -double BufferHA_RSI[]; -double BufferRawStochK[]; - -//--- Global Objects and Variables --- -int g_ExtRSIPeriod, g_ExtKPeriod, g_ExtSlowingPeriod, g_ExtDPeriod; -CHeikinAshi_RSI_Calculator *g_ha_rsi_calculator; - -//--- Forward declarations for helper functions --- -double Highest(const double &array[], int period, int current_pos); -double Lowest(const double &array[], int period, int current_pos); - -//+------------------------------------------------------------------+ -//| Custom indicator initialization function. | -//+------------------------------------------------------------------+ -int OnInit() - { - g_ExtRSIPeriod = (InpRSIPeriod < 1) ? 1 : InpRSIPeriod; - g_ExtKPeriod = (InpKPeriod < 1) ? 1 : InpKPeriod; - g_ExtSlowingPeriod = (InpSlowingPeriod < 1) ? 1 : InpSlowingPeriod; - g_ExtDPeriod = (InpDPeriod < 1) ? 1 : InpDPeriod; - - SetIndexBuffer(0, BufferK, INDICATOR_DATA); - SetIndexBuffer(1, BufferD, INDICATOR_DATA); - SetIndexBuffer(2, BufferHA_RSI, INDICATOR_CALCULATIONS); - SetIndexBuffer(3, BufferRawStochK, INDICATOR_CALCULATIONS); - - ArraySetAsSeries(BufferK, false); - ArraySetAsSeries(BufferD, false); - ArraySetAsSeries(BufferHA_RSI, false); - ArraySetAsSeries(BufferRawStochK, false); - - IndicatorSetInteger(INDICATOR_DIGITS, 2); - PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, g_ExtRSIPeriod + g_ExtKPeriod + g_ExtSlowingPeriod - 3); - PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, g_ExtRSIPeriod + g_ExtKPeriod + g_ExtSlowingPeriod + g_ExtDPeriod - 4); - IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("HA_StochRSI_Slow(%d,%d,%d,%d)", g_ExtRSIPeriod, g_ExtKPeriod, g_ExtSlowingPeriod, g_ExtDPeriod)); - - g_ha_rsi_calculator = new CHeikinAshi_RSI_Calculator(); - if(CheckPointer(g_ha_rsi_calculator) == POINTER_INVALID) - { - Print("Error creating CHeikinAshi_RSI_Calculator object"); - return(INIT_FAILED); - } - return(INIT_SUCCEEDED); - } - -//+------------------------------------------------------------------+ -//| Custom indicator deinitialization function. | -//+------------------------------------------------------------------+ -void OnDeinit(const int reason) - { - if(CheckPointer(g_ha_rsi_calculator) != POINTER_INVALID) - { - delete g_ha_rsi_calculator; - g_ha_rsi_calculator = NULL; - } - } - -//+------------------------------------------------------------------+ -//| Slow StochRSI on Heikin Ashi calculation function. | -//+------------------------------------------------------------------+ -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 start_pos = g_ExtRSIPeriod + g_ExtKPeriod + g_ExtSlowingPeriod + g_ExtDPeriod - 3; - if(rates_total <= start_pos) - return(0); - -//--- STEP 1: Calculate Heikin Ashi RSI values using our toolkit - if(!g_ha_rsi_calculator.Calculate(rates_total, g_ExtRSIPeriod, open, high, low, close, BufferHA_RSI)) - { - Print("Heikin Ashi RSI calculation failed."); - return(0); - } - -//--- STEP 2: Calculate Raw Stochastic %K on the HA_RSI buffer - int raw_k_start_pos = g_ExtRSIPeriod + g_ExtKPeriod - 2; - for(int i = raw_k_start_pos; i < rates_total; i++) - { - double highest_ha_rsi = Highest(BufferHA_RSI, g_ExtKPeriod, i); - double lowest_ha_rsi = Lowest(BufferHA_RSI, g_ExtKPeriod, i); - double range = highest_ha_rsi - lowest_ha_rsi; - if(range > 0.00001) - BufferRawStochK[i] = (BufferHA_RSI[i] - lowest_ha_rsi) / range * 100.0; - else - BufferRawStochK[i] = (i > 0) ? BufferRawStochK[i-1] : 50.0; - } - -//--- STEP 3: Calculate Slow %K (Main Line) by smoothing Raw %K - int k_slow_start_pos = g_ExtRSIPeriod + g_ExtKPeriod + g_ExtSlowingPeriod - 3; - for(int i = k_slow_start_pos; i < rates_total; i++) - { - double sum = 0; - for(int j = 0; j < g_ExtSlowingPeriod; j++) - { - sum += BufferRawStochK[i-j]; - } - BufferK[i] = sum / g_ExtSlowingPeriod; - } - -//--- STEP 4: Calculate %D (Signal Line) by smoothing Slow %K - int d_start_pos = g_ExtRSIPeriod + g_ExtKPeriod + g_ExtSlowingPeriod + g_ExtDPeriod - 4; - for(int i = d_start_pos; i < rates_total; i++) - { - double sum = 0; - for(int j = 0; j < g_ExtDPeriod; j++) - { - sum += BufferK[i-j]; - } - BufferD[i] = sum / g_ExtDPeriod; - } - - return(rates_total); - } - -//+------------------------------------------------------------------+ -//| Finds the highest value in a given period of an array. | -//+------------------------------------------------------------------+ -double Highest(const double &array[], int period, int current_pos) - { - double res = array[current_pos]; - for(int i = 1; i < period; i++) - { - int index = current_pos - i; - if(index < 0) - break; - if(res < array[index]) - res = array[index]; - } - return(res); - } - -//+------------------------------------------------------------------+ -//| Finds the lowest value in a given period of an array. | -//+------------------------------------------------------------------+ -double Lowest(const double &array[], int period, int current_pos) - { - double res = array[current_pos]; - for(int i = 1; i < period; i++) - { - int index = current_pos - i; - if(index < 0) - break; - if(res > array[index]) - res = array[index]; - } - return(res); - } -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ diff --git a/Indicators/MyIndicators/StochasticFast.md b/Indicators/MyIndicators/StochasticFast.md deleted file mode 100644 index 78389e4..0000000 --- a/Indicators/MyIndicators/StochasticFast.md +++ /dev/null @@ -1,57 +0,0 @@ -# Fast Stochastic Oscillator - -## 1. Summary (Introduction) - -The Stochastic Oscillator, developed by George C. Lane in the late 1950s, is a momentum indicator that compares a particular closing price of a security to a range of its prices over a certain period of time. The "Fast" version is the original, unsmoothed calculation of the oscillator. - -It is designed to identify overbought and oversold conditions by measuring the speed and momentum of price changes. Due to its high sensitivity, it reacts very quickly to price movements, making it a tool for traders who need to identify short-term momentum shifts. - -## 2. Mathematical Foundations and Calculation Logic - -The Fast Stochastic is the foundational calculation from which the "Slow" and "Full" versions are derived. - -### Required Components - -- **%K Period:** The main lookback period for the Stochastic calculation. -- **%D Period:** The period for the smoothing of the %K line to create the signal line. - -### Calculation Steps (Algorithm) - -1. **Calculate the Fast %K (Main Line):** This is the core of the Stochastic calculation. It measures where the current close is relative to the highest high and lowest low over the `%K Period`. This raw calculation produces the main line of the Fast Stochastic. - $\text{Fast \%K}_i = \frac{\text{Close}_i - \text{Lowest Low}_{\%K \text{ Period}}}{\text{Highest High}_{\%K \text{ Period}} - \text{Lowest Low}_{\%K \text{ Period}}} \times 100$ - Where: - - - $\text{Lowest Low}$ is the minimum low price over the `%K Period`. - - $\text{Highest High}$ is the maximum high price over the `%K Period`. - -2. **Calculate the %D (Signal Line):** The signal line is a moving average (typically a Simple Moving Average) of the Fast %K line. - $\text{\%D}_i = \text{SMA}(\text{Fast \%K}, \text{\%D Period})_i$ - -_Note: In the "Slow" Stochastic, the Fast %K line is smoothed an additional time before the %D line is calculated. In the "Fast" Stochastic, this intermediate smoothing step is omitted._ - -## 3. MQL5 Implementation Details - -Our MQL5 implementation is designed for stability, clarity, and consistency with our existing indicator toolkit. - -- **Stability via Full Recalculation:** We employ a "brute-force" full recalculation within the `OnCalculate` function. This ensures that the two-stage calculation (Price -> %K -> %D) remains stable and accurate, especially during timeframe changes or history loading. - -- **Clear, Staged Calculation:** The `OnCalculate` function is structured into clear, sequential steps, each handled by a dedicated `for` loop. This improves code readability and makes the logic easy to follow: - - 1. **Step 1:** The Fast %K line is calculated from the standard `high`, `low`, and `close` price arrays and stored in the `BufferK` plot buffer. - 2. **Step 2:** The %D signal line is calculated by applying a simple moving average with the `%D Period` to the `BufferK`. The result is stored in the `BufferD` plot buffer. - -- **Heikin Ashi Variant (`StochasticFast_HeikinAshi.mqmq5`):** - - Our toolkit also includes a Heikin Ashi version of this indicator. The calculation logic is identical, but it uses the smoothed Heikin Ashi `ha_high`, `ha_low`, and `ha_close` values as its input instead of the standard price data. - - This results in a smoother oscillator, as the input data itself is already filtered, effectively creating a hybrid between the Fast and Slow Stochastics. - -## 4. Parameters - -- **%K Period (`InpKPeriod`):** The lookback period for the Stochastic calculation (finding the highest high and lowest low). Default is `14`. -- **%D Period (`InpDPeriod`):** The smoothing period for the signal line (%D). Default is `3`. - -## 5. Usage and Interpretation - -- **Overbought/Oversold Levels:** The primary use of the Stochastic is to identify overbought (typically above 80) and oversold (typically below 20) conditions. The Fast version will enter and exit these zones very rapidly. -- **Crossovers:** The crossover of the %K line and the %D signal line is a common trade signal. A crossover of %K above %D is considered bullish, especially in oversold territory. A crossover of %K below %D is considered bearish, especially in overbought territory. -- **Divergence:** Look for divergences between the Stochastic and the price action. If the price is making a new high but the Stochastic is failing to do so (bearish divergence), it could signal weakening momentum and a potential reversal. -- **Caution:** The Fast Stochastic is highly sensitive and can produce many false signals ("whipsaws"), especially in choppy markets. It is often used by short-term traders or as a fast-reacting component in a larger trading system. For most applications, the "Slow" Stochastic is preferred due to its superior filtering of market noise. diff --git a/Indicators/MyIndicators/StochasticFast.mq5 b/Indicators/MyIndicators/StochasticFast.mq5 deleted file mode 100644 index 2099a38..0000000 --- a/Indicators/MyIndicators/StochasticFast.mq5 +++ /dev/null @@ -1,154 +0,0 @@ -//+------------------------------------------------------------------+ -//| StochasticFast.mq5 | -//| Copyright 2025, xxxxxxxx | -//| | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2025, xxxxxxxx" -#property link "" -#property version "2.00" // Refactored for stability and clarity -#property description "Fast Stochastic Oscillator" - -//--- Indicator Window and Level Properties --- -#property indicator_separate_window -#property indicator_buffers 2 // %K (Main) and %D (Signal) -#property indicator_plots 2 -#property indicator_level1 20.0 -#property indicator_level2 80.0 -#property indicator_minimum 0.0 -#property indicator_maximum 100.0 - -//--- Plot 1: %K line (Fast) -#property indicator_label1 "%K" -#property indicator_type1 DRAW_LINE -#property indicator_color1 clrLightSeaGreen -#property indicator_style1 STYLE_SOLID -#property indicator_width1 1 - -//--- Plot 2: %D line (Signal) -#property indicator_label2 "%D" -#property indicator_type2 DRAW_LINE -#property indicator_color2 clrRed -#property indicator_style2 STYLE_DOT -#property indicator_width2 1 - -//--- Input Parameters --- -input int InpKPeriod = 14; // %K Period (Stochastic period) -input int InpDPeriod = 3; // %D Period (signal line smoothing) - -//--- Indicator Buffers --- -double BufferK[]; // Plotted buffer for the main %K line -double BufferD[]; // Plotted buffer for the signal %D line - -//--- Global Variables --- -int g_ExtKPeriod, g_ExtDPeriod; - -//--- Forward declarations for helper functions --- -double Highest(const double &array[], int period, int current_pos); -double Lowest(const double &array[], int period, int current_pos); - -//+------------------------------------------------------------------+ -//| Custom indicator initialization function. | -//+------------------------------------------------------------------+ -int OnInit() - { -//--- Validate and store input periods - g_ExtKPeriod = (InpKPeriod < 1) ? 1 : InpKPeriod; - g_ExtDPeriod = (InpDPeriod < 1) ? 1 : InpDPeriod; - -//--- Map the buffers and set as non-timeseries - SetIndexBuffer(0, BufferK, INDICATOR_DATA); - SetIndexBuffer(1, BufferD, INDICATOR_DATA); - ArraySetAsSeries(BufferK, false); - ArraySetAsSeries(BufferD, false); - -//--- Set indicator display properties - IndicatorSetInteger(INDICATOR_DIGITS, 2); - PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, g_ExtKPeriod - 1); - PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, g_ExtKPeriod + g_ExtDPeriod - 2); - IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("Fast Stoch(%d,%d)", g_ExtKPeriod, g_ExtDPeriod)); - - return(INIT_SUCCEEDED); - } - -//+------------------------------------------------------------------+ -//| Fast Stochastic Oscillator calculation function. | -//+------------------------------------------------------------------+ -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[]) - { -//--- Check if there is enough historical data - int start_pos = g_ExtKPeriod + g_ExtDPeriod - 1; - if(rates_total <= start_pos) - return(0); - -//--- STEP 1: Calculate %K (Fast %K) - for(int i = g_ExtKPeriod - 1; i < rates_total; i++) - { - double highest_high = Highest(high, g_ExtKPeriod, i); - double lowest_low = Lowest(low, g_ExtKPeriod, i); - - double range = highest_high - lowest_low; - if(range > 0) - BufferK[i] = (close[i] - lowest_low) / range * 100.0; - else - BufferK[i] = (i > 0) ? BufferK[i-1] : 50.0; - } - -//--- STEP 2: Calculate %D (Signal Line) as an SMA of %K - int d_start_pos = g_ExtKPeriod + g_ExtDPeriod - 2; - for(int i = d_start_pos; i < rates_total; i++) - { - double sum = 0; - for(int j = 0; j < g_ExtDPeriod; j++) - { - sum += BufferK[i-j]; - } - BufferD[i] = sum / g_ExtDPeriod; - } - - return(rates_total); - } - -//+------------------------------------------------------------------+ -//| Finds the highest value in a given period of an array. | -//+------------------------------------------------------------------+ -double Highest(const double &array[], int period, int current_pos) - { - double res = array[current_pos]; - for(int i = 1; i < period; i++) - { - int index = current_pos - i; - if(index < 0) - break; - if(res < array[index]) - res = array[index]; - } - return(res); - } - -//+------------------------------------------------------------------+ -//| Finds the lowest value in a given period of an array. | -//+------------------------------------------------------------------+ -double Lowest(const double &array[], int period, int current_pos) - { - double res = array[current_pos]; - for(int i = 1; i < period; i++) - { - int index = current_pos - i; - if(index < 0) - break; - if(res > array[index]) - res = array[index]; - } - return(res); - } -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ diff --git a/Indicators/MyIndicators/StochasticFast_HeikinAshi.mq5 b/Indicators/MyIndicators/StochasticFast_HeikinAshi.mq5 deleted file mode 100644 index d75ca0d..0000000 --- a/Indicators/MyIndicators/StochasticFast_HeikinAshi.mq5 +++ /dev/null @@ -1,194 +0,0 @@ -//+------------------------------------------------------------------+ -//| StochasticFast_HeikinAshi.mq5 | -//| Copyright 2025, xxxxxxxx | -//| | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2025, xxxxxxxx" -#property link "" -#property version "2.00" // Refactored for full recalculation and stability -#property description "Fast Stochastic Oscillator on Heikin Ashi data" - -//--- Custom Toolkit Include --- -#include - -//--- Indicator Window and Level Properties --- -#property indicator_separate_window -#property indicator_buffers 2 // %K (Main) and %D (Signal) -#property indicator_plots 2 -#property indicator_level1 20.0 -#property indicator_level2 80.0 -#property indicator_minimum 0.0 -#property indicator_maximum 100.0 - -//--- Plot 1: %K line (Fast) -#property indicator_label1 "HA_%K" -#property indicator_type1 DRAW_LINE -#property indicator_color1 clrLightSeaGreen -#property indicator_style1 STYLE_SOLID -#property indicator_width1 1 - -//--- Plot 2: %D line (Signal) -#property indicator_label2 "HA_%D" -#property indicator_type2 DRAW_LINE -#property indicator_color2 clrRed -#property indicator_style2 STYLE_DOT -#property indicator_width2 1 - -//--- Input Parameters --- -input int InpKPeriod = 14; // %K Period (Stochastic period) -input int InpDPeriod = 3; // %D Period (signal line smoothing) - -//--- Indicator Buffers --- -double BufferHA_K[]; // Plotted buffer for the main %K line -double BufferHA_D[]; // Plotted buffer for the signal %D line - -//--- Intermediate Heikin Ashi Buffers --- -double ExtHaOpenBuffer[]; -double ExtHaHighBuffer[]; -double ExtHaLowBuffer[]; -double ExtHaCloseBuffer[]; - -//--- Global Objects and Variables --- -int g_ExtKPeriod, g_ExtDPeriod; -CHeikinAshi_Calculator *g_ha_calculator; // Pointer to our Heikin Ashi calculator - -//--- Forward declarations for helper functions --- -double Highest(const double &array[], int period, int current_pos); -double Lowest(const double &array[], int period, int current_pos); - -//+------------------------------------------------------------------+ -//| Custom indicator initialization function. | -//+------------------------------------------------------------------+ -int OnInit() - { -//--- Validate and store input periods - g_ExtKPeriod = (InpKPeriod < 1) ? 1 : InpKPeriod; - g_ExtDPeriod = (InpDPeriod < 1) ? 1 : InpDPeriod; - -//--- Map the buffers and set as non-timeseries - SetIndexBuffer(0, BufferHA_K, INDICATOR_DATA); - SetIndexBuffer(1, BufferHA_D, INDICATOR_DATA); - ArraySetAsSeries(BufferHA_K, false); - ArraySetAsSeries(BufferHA_D, false); - -//--- Set indicator display properties - IndicatorSetInteger(INDICATOR_DIGITS, 2); - PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, g_ExtKPeriod - 1); - PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, g_ExtKPeriod + g_ExtDPeriod - 2); - IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("HA_Fast_Stoch(%d,%d)", g_ExtKPeriod, g_ExtDPeriod)); - -//--- Create the calculator instance - g_ha_calculator = new CHeikinAshi_Calculator(); - if(CheckPointer(g_ha_calculator) == POINTER_INVALID) - { - Print("Error creating CHeikinAshi_Calculator object"); - return(INIT_FAILED); - } - - return(INIT_SUCCEEDED); - } - -//+------------------------------------------------------------------+ -//| Custom indicator deinitialization function. | -//+------------------------------------------------------------------+ -void OnDeinit(const int reason) - { -//--- Free the calculator object - if(CheckPointer(g_ha_calculator) != POINTER_INVALID) - { - delete g_ha_calculator; - g_ha_calculator = NULL; - } - } - -//+------------------------------------------------------------------+ -//| Fast Stochastic on Heiken Ashi calculation function. | -//+------------------------------------------------------------------+ -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[]) - { -//--- Check if there is enough historical data - if(rates_total < g_ExtKPeriod + g_ExtDPeriod - 1) - return(0); - -//--- Resize intermediate buffers - ArrayResize(ExtHaOpenBuffer, rates_total); - ArrayResize(ExtHaHighBuffer, rates_total); - ArrayResize(ExtHaLowBuffer, rates_total); - ArrayResize(ExtHaCloseBuffer, rates_total); - -//--- STEP 1: Calculate Heikin Ashi bars - g_ha_calculator.Calculate(rates_total, open, high, low, close, - ExtHaOpenBuffer, ExtHaHighBuffer, ExtHaLowBuffer, ExtHaCloseBuffer); - -//--- STEP 2: Calculate Raw %K using Heiken Ashi data - for(int i = g_ExtKPeriod - 1; i < rates_total; i++) - { - double highest_ha_high = Highest(ExtHaHighBuffer, g_ExtKPeriod, i); - double lowest_ha_low = Lowest(ExtHaLowBuffer, g_ExtKPeriod, i); - - double range = highest_ha_high - lowest_ha_low; - if(range > 0) - BufferHA_K[i] = (ExtHaCloseBuffer[i] - lowest_ha_low) / range * 100.0; - else - BufferHA_K[i] = (i > 0) ? BufferHA_K[i-1] : 50.0; - } - -//--- STEP 3: Calculate %D (Signal Line) as an SMA of %K - int d_start_pos = g_ExtKPeriod + g_ExtDPeriod - 2; - for(int i = d_start_pos; i < rates_total; i++) - { - double sum = 0; - for(int j = 0; j < g_ExtDPeriod; j++) - { - sum += BufferHA_K[i-j]; - } - BufferHA_D[i] = sum / g_ExtDPeriod; - } - - return(rates_total); - } - -//+------------------------------------------------------------------+ -//| Finds the highest value in a given period of an array. | -//+------------------------------------------------------------------+ -double Highest(const double &array[], int period, int current_pos) - { - double res = array[current_pos]; - for(int i = 1; i < period; i++) - { - int index = current_pos - i; - if(index < 0) - break; - if(res < array[index]) - res = array[index]; - } - return(res); - } - -//+------------------------------------------------------------------+ -//| Finds the lowest value in a given period of an array. | -//+------------------------------------------------------------------+ -double Lowest(const double &array[], int period, int current_pos) - { - double res = array[current_pos]; - for(int i = 1; i < period; i++) - { - int index = current_pos - i; - if(index < 0) - break; - if(res > array[index]) - res = array[index]; - } - return(res); - } -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ diff --git a/Indicators/MyIndicators/StochasticSlow.md b/Indicators/MyIndicators/StochasticSlow.md deleted file mode 100644 index 2e5c983..0000000 --- a/Indicators/MyIndicators/StochasticSlow.md +++ /dev/null @@ -1,61 +0,0 @@ -# Slow Stochastic Oscillator - -## 1. Summary (Introduction) - -The Stochastic Oscillator, developed by George C. Lane in the late 1950s, is a momentum indicator that compares a particular closing price of a security to a range of its prices over a certain period of time. The "Slow" version is the most commonly used variant, as it includes an internal smoothing mechanism that filters out the "noise" of the more volatile "Fast" Stochastic, providing clearer signals. - -Its primary purpose is to identify overbought and oversold conditions and to spot potential trend reversals through divergences and line crossovers. - -## 2. Mathematical Foundations and Calculation Logic - -The Slow Stochastic is derived from the Fast Stochastic by adding an extra layer of smoothing. - -### Required Components - -- **%K Period:** The main lookback period for the Stochastic calculation. -- **Slowing Period:** The period for the first smoothing step, which transforms the "Fast %K" into the "Slow %K". -- **%D Period:** The period for the second smoothing step, which creates the signal line (%D) from the Slow %K. - -### Calculation Steps (Algorithm) - -1. **Calculate the Raw %K (Fast %K):** This is the core of the Stochastic calculation. It measures where the current close is relative to the highest high and lowest low over the `%K Period`. - $\text{Raw \%K}_i = \frac{\text{Close}_i - \text{Lowest Low}_{\%K \text{ Period}}}{\text{Highest High}_{\%K \text{ Period}} - \text{Lowest Low}_{\%K \text{ Period}}} \times 100$ - Where: - - - $\text{Lowest Low}$ is the minimum low price over the `%K Period`. - - $\text{Highest High}$ is the maximum high price over the `%K Period`. - -2. **Calculate the Slow %K (Main Line):** This is the key step that creates the "Slow" Stochastic. The Raw %K line is smoothed, typically with a Simple Moving Average (SMA), using the `Slowing Period`. This smoothed line becomes the main `%K` line of the Slow Stochastic. - $\text{Slow \%K}_i = \text{SMA}(\text{Raw \%K}, \text{Slowing Period})_i$ - -3. **Calculate the %D (Signal Line):** The signal line is a moving average of the Slow %K line, providing an additional layer of smoothing. - $\text{Slow \%D}_i = \text{SMA}(\text{Slow \%K}, \text{\%D Period})_i$ - -## 3. MQL5 Implementation Details - -Our MQL5 implementation is designed for stability, clarity, and consistency with our existing indicator toolkit. - -- **Stability via Full Recalculation:** We employ a "brute-force" full recalculation within the `OnCalculate` function. This ensures that the multi-stage calculation (Price -> Raw %K -> Slow %K -> %D) remains stable and accurate, especially during timeframe changes or history loading. - -- **Clear, Staged Calculation:** The `OnCalculate` function is structured into clear, sequential steps, each handled by a dedicated `for` loop. This improves code readability and makes the logic easy to follow: - - 1. **Step 1:** The Raw %K (Fast %K) is calculated from the standard `high`, `low`, and `close` price arrays and stored in the `BufferRawK` calculation buffer. - 2. **Step 2:** The Slow %K (the main plot line) is calculated by applying a simple moving average with the `Slowing` period to `BufferRawK`. The result is stored in the `BufferK` plot buffer. - 3. **Step 3:** The %D signal line is calculated by applying a simple moving average with the `%D Period` to the already smoothed `BufferK`. The result is stored in the `BufferD` plot buffer. - -- **Heikin Ashi Variant (`StochasticSlow_HeikinAshi.mq5`):** - - Our toolkit also includes a Heikin Ashi version of this indicator. The calculation logic is identical, but it uses the smoothed Heikin Ashi `ha_high`, `ha_low`, and `ha_close` values as its input instead of the standard price data. - - This results in a significantly smoother oscillator, as the input data itself is already filtered. This can be useful for traders who want to focus on the primary momentum shifts and filter out market noise. - -## 4. Parameters - -- **%K Period (`InpKPeriod`):** The lookback period for the initial Stochastic calculation (finding the highest high and lowest low). Default is `5`. -- **%D Period (`InpDPeriod`):** The smoothing period for the final signal line (%D). Default is `3`. -- **Slowing (`InpSlowing`):** The smoothing period applied to the Raw %K to create the main Slow %K line. A value of `1` would effectively result in a Fast Stochastic. Default is `3`. - -## 5. Usage and Interpretation - -- **Overbought/Oversold Levels:** The primary use of the Stochastic is to identify overbought (typically above 80) and oversold (typically below 20) conditions. A move into these zones does not necessarily mean a reversal is imminent, but it indicates that the price is near the top or bottom of its recent trading range. -- **Crossovers:** The crossover of the %K line and the %D signal line is a common trade signal. A crossover of %K above %D is considered bullish, especially in oversold territory. A crossover of %K below %D is considered bearish, especially in overbought territory. -- **Divergence:** Look for divergences between the Stochastic and the price action. If the price is making a new high but the Stochastic is failing to do so (bearish divergence), it could signal weakening momentum and a potential reversal. Conversely, if the price makes a new low but the Stochastic makes a higher low (bullish divergence), it could signal a potential bottom. -- **Caution:** The Stochastic is a range-bound oscillator and performs best in sideways or choppy markets. In a strong trend, it can remain in overbought or oversold territory for extended periods, giving premature or false reversal signals. diff --git a/Indicators/MyIndicators/StochasticSlow.mq5 b/Indicators/MyIndicators/StochasticSlow.mq5 deleted file mode 100644 index 72f88a2..0000000 --- a/Indicators/MyIndicators/StochasticSlow.mq5 +++ /dev/null @@ -1,171 +0,0 @@ -//+------------------------------------------------------------------+ -//| StochasticSlow.mq5 | -//| Copyright 2025, xxxxxxxx | -//| | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2025, xxxxxxxx" -#property link "" -#property version "2.01" // Harmonized input parameter names -#property description "Slow Stochastic Oscillator" - -//--- Indicator Window and Level Properties --- -#property indicator_separate_window -#property indicator_buffers 3 // %K, %D, and Raw %K for calculation -#property indicator_plots 2 -#property indicator_level1 20.0 -#property indicator_level2 80.0 -#property indicator_minimum 0.0 -#property indicator_maximum 100.0 - -//--- Plot 1: %K line (Slow) -#property indicator_label1 "%K" -#property indicator_type1 DRAW_LINE -#property indicator_color1 clrLightSeaGreen -#property indicator_style1 STYLE_SOLID -#property indicator_width1 1 - -//--- Plot 2: %D line (Signal) -#property indicator_label2 "%D" -#property indicator_type2 DRAW_LINE -#property indicator_color2 clrRed -#property indicator_style2 STYLE_DOT -#property indicator_width2 1 - -//--- Input Parameters --- -input int InpKPeriod = 5; // %K Period -input int InpSlowingPeriod = 3; // Slowing Period -input int InpDPeriod = 3; // %D Period (signal line smoothing) - -//--- Indicator Buffers --- -double BufferK[]; // Plotted buffer for the main (Slow) %K line -double BufferD[]; // Plotted buffer for the signal %D line -double BufferRawK[]; // Calculation buffer for raw %K before slowing - -//--- Global Variables --- -int g_ExtKPeriod, g_ExtDPeriod, g_ExtSlowingPeriod; - -//--- Forward declarations for helper functions --- -double Highest(const double &array[], int period, int current_pos); -double Lowest(const double &array[], int period, int current_pos); - -//+------------------------------------------------------------------+ -//| Custom indicator initialization function. | -//+------------------------------------------------------------------+ -int OnInit() - { -//--- Validate and store input periods - g_ExtKPeriod = (InpKPeriod < 1) ? 1 : InpKPeriod; - g_ExtDPeriod = (InpDPeriod < 1) ? 1 : InpDPeriod; - g_ExtSlowingPeriod = (InpSlowingPeriod < 1) ? 1 : InpSlowingPeriod; - -//--- Map the buffers and set as non-timeseries - SetIndexBuffer(0, BufferK, INDICATOR_DATA); - SetIndexBuffer(1, BufferD, INDICATOR_DATA); - SetIndexBuffer(2, BufferRawK, INDICATOR_CALCULATIONS); - - ArraySetAsSeries(BufferK, false); - ArraySetAsSeries(BufferD, false); - ArraySetAsSeries(BufferRawK, false); - -//--- Set indicator display properties - IndicatorSetInteger(INDICATOR_DIGITS, 2); - PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, g_ExtKPeriod + g_ExtSlowingPeriod - 2); - PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, g_ExtKPeriod + g_ExtSlowingPeriod + g_ExtDPeriod - 3); - IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("Slow Stoch(%d,%d,%d)", g_ExtKPeriod, g_ExtSlowingPeriod, g_ExtDPeriod)); - - return(INIT_SUCCEEDED); - } - -//+------------------------------------------------------------------+ -//| Slow Stochastic Oscillator calculation function. | -//+------------------------------------------------------------------+ -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[]) - { -//--- Check if there is enough historical data - int start_pos = g_ExtKPeriod + g_ExtSlowingPeriod + g_ExtDPeriod - 2; - if(rates_total <= start_pos) - return(0); - -//--- STEP 1: Calculate Raw %K (Fast %K) - for(int i = g_ExtKPeriod - 1; i < rates_total; i++) - { - double highest_high = Highest(high, g_ExtKPeriod, i); - double lowest_low = Lowest(low, g_ExtKPeriod, i); - double range = highest_high - lowest_low; - if(range > 0) - BufferRawK[i] = (close[i] - lowest_low) / range * 100.0; - else - BufferRawK[i] = (i > 0) ? BufferRawK[i-1] : 50.0; - } - -//--- STEP 2: Calculate Slow %K (Main Line) by smoothing Raw %K - int k_slow_start_pos = g_ExtKPeriod + g_ExtSlowingPeriod - 2; - for(int i = k_slow_start_pos; i < rates_total; i++) - { - double sum = 0; - for(int j = 0; j < g_ExtSlowingPeriod; j++) - { - sum += BufferRawK[i-j]; - } - BufferK[i] = sum / g_ExtSlowingPeriod; - } - -//--- STEP 3: Calculate %D (Signal Line) by smoothing Slow %K - int d_start_pos = g_ExtKPeriod + g_ExtSlowingPeriod + g_ExtDPeriod - 3; - for(int i = d_start_pos; i < rates_total; i++) - { - double sum = 0; - for(int j = 0; j < g_ExtDPeriod; j++) - { - sum += BufferK[i-j]; - } - BufferD[i] = sum / g_ExtDPeriod; - } - - return(rates_total); - } - -//+------------------------------------------------------------------+ -//| Finds the highest value in a given period of an array. | -//+------------------------------------------------------------------+ -double Highest(const double &array[], int period, int current_pos) - { - double res = array[current_pos]; - for(int i = 1; i < period; i++) - { - int index = current_pos - i; - if(index < 0) - break; - if(res < array[index]) - res = array[index]; - } - return(res); - } - -//+------------------------------------------------------------------+ -//| Finds the lowest value in a given period of an array. | -//+------------------------------------------------------------------+ -double Lowest(const double &array[], int period, int current_pos) - { - double res = array[current_pos]; - for(int i = 1; i < period; i++) - { - int index = current_pos - i; - if(index < 0) - break; - if(res > array[index]) - res = array[index]; - } - return(res); - } -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ diff --git a/Indicators/MyIndicators/StochasticSlow_HeikinAshi.mq5 b/Indicators/MyIndicators/StochasticSlow_HeikinAshi.mq5 deleted file mode 100644 index c52b2b5..0000000 --- a/Indicators/MyIndicators/StochasticSlow_HeikinAshi.mq5 +++ /dev/null @@ -1,198 +0,0 @@ -//+------------------------------------------------------------------+ -//| StochasticSlow_HeikinAshi.mq5 | -//| Copyright 2025, xxxxxxxx | -//| | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2025, xxxxxxxx" -#property link "" -#property version "2.01" // Harmonized input parameter names -#property description "Slow Stochastic Oscillator on Heikin Ashi data" - -#include - -//--- Indicator Window and Level Properties --- -#property indicator_separate_window -#property indicator_buffers 3 // %K, %D, and Raw %K for calculation -#property indicator_plots 2 -#property indicator_level1 20.0 -#property indicator_level2 80.0 -#property indicator_minimum 0.0 -#property indicator_maximum 100.0 - -//--- Plot 1: %K line (Slow) -#property indicator_label1 "HA_%K" -#property indicator_type1 DRAW_LINE -#property indicator_color1 clrLightSeaGreen -#property indicator_style1 STYLE_SOLID -#property indicator_width1 1 - -//--- Plot 2: %D line (Signal) -#property indicator_label2 "HA_%D" -#property indicator_type2 DRAW_LINE -#property indicator_color2 clrRed -#property indicator_style2 STYLE_DOT -#property indicator_width2 1 - -//--- Input Parameters --- -input int InpKPeriod = 5; -input int InpSlowingPeriod = 3; -input int InpDPeriod = 3; - -//--- Indicator Buffers --- -double BufferHA_K[]; -double BufferHA_D[]; -double BufferRawK[]; - -//--- Global Objects and Variables --- -int g_ExtKPeriod, g_ExtDPeriod, g_ExtSlowingPeriod; -CHeikinAshi_Calculator *g_ha_calculator; - -//--- Forward declarations for helper functions --- -double Highest(const double &array[], int period, int current_pos); -double Lowest(const double &array[], int period, int current_pos); - -//+------------------------------------------------------------------+ -//| Custom indicator initialization function. | -//+------------------------------------------------------------------+ -int OnInit() - { - g_ExtKPeriod = (InpKPeriod < 1) ? 1 : InpKPeriod; - g_ExtDPeriod = (InpDPeriod < 1) ? 1 : InpDPeriod; - g_ExtSlowingPeriod = (InpSlowingPeriod < 1) ? 1 : InpSlowingPeriod; - - SetIndexBuffer(0, BufferHA_K, INDICATOR_DATA); - SetIndexBuffer(1, BufferHA_D, INDICATOR_DATA); - SetIndexBuffer(2, BufferRawK, INDICATOR_CALCULATIONS); - - ArraySetAsSeries(BufferHA_K, false); - ArraySetAsSeries(BufferHA_D, false); - ArraySetAsSeries(BufferRawK, false); - - IndicatorSetInteger(INDICATOR_DIGITS, 2); - PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, g_ExtKPeriod + g_ExtSlowingPeriod - 2); - PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, g_ExtKPeriod + g_ExtSlowingPeriod + g_ExtDPeriod - 3); - IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("HA_Slow_Stoch(%d,%d,%d)", g_ExtKPeriod, g_ExtSlowingPeriod, g_ExtDPeriod)); - - g_ha_calculator = new CHeikinAshi_Calculator(); - if(CheckPointer(g_ha_calculator) == POINTER_INVALID) - { - Print("Error creating CHeikinAshi_Calculator object"); - return(INIT_FAILED); - } - return(INIT_SUCCEEDED); - } - -//+------------------------------------------------------------------+ -//| Custom indicator deinitialization function. | -//+------------------------------------------------------------------+ -void OnDeinit(const int reason) - { - if(CheckPointer(g_ha_calculator) != POINTER_INVALID) - { - delete g_ha_calculator; - g_ha_calculator = NULL; - } - } - -//+------------------------------------------------------------------+ -//| Slow Stochastic on Heikin Ashi calculation function. | -//+------------------------------------------------------------------+ -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 start_pos = g_ExtKPeriod + g_ExtSlowingPeriod + g_ExtDPeriod - 2; - if(rates_total <= start_pos) - return(0); - -//--- Intermediate Heikin Ashi Buffers - double ha_open[], ha_high[], ha_low[], ha_close[]; - ArrayResize(ha_open, rates_total); - ArrayResize(ha_high, rates_total); - ArrayResize(ha_low, rates_total); - ArrayResize(ha_close, rates_total); - -//--- STEP 1: Calculate Heikin Ashi bars - g_ha_calculator.Calculate(rates_total, open, high, low, close, ha_open, ha_high, ha_low, ha_close); - -//--- STEP 2: Calculate Raw %K (Fast %K) using Heikin Ashi data - for(int i = g_ExtKPeriod - 1; i < rates_total; i++) - { - double highest_ha_high = Highest(ha_high, g_ExtKPeriod, i); - double lowest_ha_low = Lowest(ha_low, g_ExtKPeriod, i); - double range = highest_ha_high - lowest_ha_low; - if(range > 0) - BufferRawK[i] = (ha_close[i] - lowest_ha_low) / range * 100.0; - else - BufferRawK[i] = (i > 0) ? BufferRawK[i-1] : 50.0; - } - -//--- STEP 3: Calculate Slow %K (Main Line) by smoothing Raw %K - int k_slow_start_pos = g_ExtKPeriod + g_ExtSlowingPeriod - 2; - for(int i = k_slow_start_pos; i < rates_total; i++) - { - double sum = 0; - for(int j = 0; j < g_ExtSlowingPeriod; j++) - { - sum += BufferRawK[i-j]; - } - BufferHA_K[i] = sum / g_ExtSlowingPeriod; - } - -//--- STEP 4: Calculate %D (Signal Line) by smoothing Slow %K - int d_start_pos = g_ExtKPeriod + g_ExtSlowingPeriod + g_ExtDPeriod - 3; - for(int i = d_start_pos; i < rates_total; i++) - { - double sum = 0; - for(int j = 0; j < g_ExtDPeriod; j++) - { - sum += BufferHA_K[i-j]; - } - BufferHA_D[i] = sum / g_ExtDPeriod; - } - - return(rates_total); - } - -//+------------------------------------------------------------------+ -//| Finds the highest value in a given period of an array. | -//+------------------------------------------------------------------+ -double Highest(const double &array[], int period, int current_pos) - { - double res = array[current_pos]; - for(int i = 1; i < period; i++) - { - int index = current_pos - i; - if(index < 0) - break; - if(res < array[index]) - res = array[index]; - } - return(res); - } - -//+------------------------------------------------------------------+ -//| Finds the lowest value in a given period of an array. | -//+------------------------------------------------------------------+ -double Lowest(const double &array[], int period, int current_pos) - { - double res = array[current_pos]; - for(int i = 1; i < period; i++) - { - int index = current_pos - i; - if(index < 0) - break; - if(res > array[index]) - res = array[index]; - } - return(res); - } -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ diff --git a/Indicators/MyIndicators/Stochastic_Pro.md b/Indicators/MyIndicators/Stochastic_Pro.md deleted file mode 100644 index 0b31fa5..0000000 --- a/Indicators/MyIndicators/Stochastic_Pro.md +++ /dev/null @@ -1,72 +0,0 @@ -# Stochastic Pro Oscillator - -## 1. Summary (Introduction) - -The Stochastic Pro is an enhanced and highly flexible version of the classic Stochastic Oscillator. While the standard "Slow Stochastic" uses a fixed Simple Moving Average (SMA) for its smoothing steps, this "Pro" version allows the trader to select from four different moving average types for both the initial smoothing ("Slowing") and the final signal line ("%D"). - -This customization allows for fine-tuning the oscillator's responsiveness and smoothness to a degree not possible with the standard indicator. It can be configured to behave as a **classic Slow Stochastic**, replicate the **MetaTrader-specific Smoothed Stochastic**, or create entirely new, hybrid versions. - -## 2. Mathematical Foundations and Calculation Logic - -The Stochastic Pro follows the structure of the Slow Stochastic but generalizes the moving average calculations. - -### Required Components - -- **%K Period:** The lookback period for the initial Stochastic calculation. -- **Slowing Period & MA Type:** The period and MA type for the first smoothing step. -- **%D Period & MA Type:** The period and MA type for the second smoothing step (the signal line). - -### Calculation Steps (Algorithm) - -1. **Calculate the Raw %K (Fast %K):** This is the core Stochastic calculation. - $\text{Raw \%K}_i = 100 \times \frac{\text{Close}_i - \text{Lowest Low}_{\%K \text{ Period}}}{\text{Highest High}_{\%K \text{ Period}} - \text{Lowest Low}_{\%K \text{ Period}}}$ - -2. **Calculate the %K Line (Slowing):** The Raw %K line is smoothed using the selected `Slowing Period` and `Slowing MA Type`. - $\text{\%K}_i = \text{MA}(\text{Raw \%K}, \text{Slowing Period}, \text{Slowing MA Type})_i$ - -3. **Calculate the %D Line (Signal):** The signal line is a moving average of the %K line, using the selected `%D Period` and `%D MA Type`. - $\text{\%D}_i = \text{MA}(\text{\%K}, \text{\%D Period}, \text{\%D MA Type})_i$ - -## 3. MQL5 Implementation Details - -Our MQL5 implementation is a self-contained, robust, and highly flexible indicator built upon our established coding principles. - -- **Stability via Full Recalculation:** We employ a "brute-force" full recalculation within the `OnCalculate` function for maximum stability. - -- **Fully Manual MA Calculations:** To guarantee 100% accuracy and consistency across all MA types within our `non-timeseries` model, all four moving average calculations (**SMA, EMA, SMMA, LWMA**) are performed **manually**. The indicator is completely independent of the `` standard library. - - - **Robust Initialization:** All recursive MA types (EMA, SMMA) are carefully initialized with a manual Simple Moving Average (SMA). - -- **Clear, Staged Calculation:** The `OnCalculate` function is structured into clear, sequential steps, each handled by a dedicated `for` loop, making the logic easy to follow. - -- **Heikin Ashi Variant:** A "pure" Heikin Ashi version can be easily created by modifying this code to use Heikin Ashi price data as its input, providing a doubly-smoothed oscillator. - -## 4. Parameters - -- **%K Period (`InpKPeriod`):** The lookback period for the initial Stochastic calculation. Default is `5`. -- **Slowing Period (`InpSlowingPeriod`):** The period for the first smoothing step. Default is `3`. -- **Slowing MA Type (`InpSlowingMAType`):** The MA type for the first smoothing step. **Default is `MODE_SMA`**. -- **%D Period (`InpDPeriod`):** The period for the signal line smoothing. Default is `3`. -- **%D MA Type (`InpDMAType`):** The MA type for the signal line. **Default is `MODE_SMMA`**. - -### Configuration Examples - -- **Classic Slow Stochastic:** - - `Slowing MA Type`: `MODE_SMA` - - `%D MA Type`: `MODE_SMA` -- **MetaTrader Default Stochastic:** - - `Slowing MA Type`: `MODE_SMA` - - `%D MA Type`: `MODE_SMMA` -- **Fast Stochastic:** - - `Slowing Period`: `1` - - `Slowing MA Type`: `MODE_SMA` - - `%D MA Type`: `MODE_SMA` - -## 5. Usage and Interpretation - -The interpretation of the Stochastic Pro is identical to the standard Stochastic, but the signals may be faster or slower depending on the selected MA types. - -- **Overbought/Oversold Levels:** The primary use is to identify overbought (typically above 80) and oversold (typically below 20) conditions. -- **Crossovers:** The crossover of the %K line and the %D signal line is a common trade signal. A bullish crossover in oversold territory is a strong signal, and a bearish crossover in overbought territory is a strong signal. -- **Divergence:** Divergences between the oscillator and the price can signal weakening momentum and potential reversals. -- **Caution:** The Stochastic is a range-bound oscillator and performs best in sideways or choppy markets. In a strong trend, it can remain in overbought or oversold territory for extended periods. diff --git a/Indicators/MyIndicators/Stochastic_Pro.mq5 b/Indicators/MyIndicators/Stochastic_Pro.mq5 deleted file mode 100644 index d008d0f..0000000 --- a/Indicators/MyIndicators/Stochastic_Pro.mq5 +++ /dev/null @@ -1,239 +0,0 @@ -//+------------------------------------------------------------------+ -//| Stochastic_Pro.mq5 | -//| Copyright 2025, xxxxxxxx | -//| | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2025, xxxxxxxx" -#property link "" -#property version "1.00" -#property description "Stochastic Oscillator with selectable MA types for %K and %D." - -//--- Indicator Window and Plot Properties --- -#property indicator_separate_window -#property indicator_buffers 3 // %K, %D, and Raw %K for calculation -#property indicator_plots 2 -#property indicator_level1 20.0 -#property indicator_level2 80.0 -#property indicator_minimum 0.0 -#property indicator_maximum 100.0 - -//--- Plot 1: %K line -#property indicator_label1 "%K" -#property indicator_type1 DRAW_LINE -#property indicator_color1 clrLightSeaGreen -#property indicator_style1 STYLE_SOLID -#property indicator_width1 1 - -//--- Plot 2: %D line -#property indicator_label2 "%D" -#property indicator_type2 DRAW_LINE -#property indicator_color2 clrRed -#property indicator_style2 STYLE_DOT -#property indicator_width2 1 - -//--- Input Parameters --- -input int InpKPeriod = 5; -input int InpSlowingPeriod= 3; -input ENUM_MA_METHOD InpSlowingMAType= MODE_SMA; // MA type for Slowing -input int InpDPeriod = 3; -input ENUM_MA_METHOD InpDMAType = MODE_SMMA; // MA type for %D (Signal) - -//--- Indicator Buffers --- -double BufferK[]; -double BufferD[]; -double BufferRawK[]; - -//--- Global Variables --- -int g_ExtKPeriod, g_ExtDPeriod, g_ExtSlowingPeriod; - -//--- Forward declarations for helper functions --- -double Highest(const double &array[], int period, int current_pos); -double Lowest(const double &array[], int period, int current_pos); - -//+------------------------------------------------------------------+ -//| Custom indicator initialization function. | -//+------------------------------------------------------------------+ -int OnInit() - { - g_ExtKPeriod = (InpKPeriod < 1) ? 1 : InpKPeriod; - g_ExtDPeriod = (InpDPeriod < 1) ? 1 : InpDPeriod; - g_ExtSlowingPeriod = (InpSlowingPeriod < 1) ? 1 : InpSlowingPeriod; - - SetIndexBuffer(0, BufferK, INDICATOR_DATA); - SetIndexBuffer(1, BufferD, INDICATOR_DATA); - SetIndexBuffer(2, BufferRawK, INDICATOR_CALCULATIONS); - - ArraySetAsSeries(BufferK, false); - ArraySetAsSeries(BufferD, false); - ArraySetAsSeries(BufferRawK, false); - - IndicatorSetInteger(INDICATOR_DIGITS, 2); - PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, g_ExtKPeriod + g_ExtSlowingPeriod - 2); - PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, g_ExtKPeriod + g_ExtSlowingPeriod + g_ExtDPeriod - 3); - IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("Stoch Pro(%d,%d,%d)", g_ExtKPeriod, g_ExtSlowingPeriod, g_ExtDPeriod)); - - return(INIT_SUCCEEDED); - } - -//+------------------------------------------------------------------+ -//| Pro Stochastic Oscillator calculation function. | -//+------------------------------------------------------------------+ -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 start_pos = g_ExtKPeriod + g_ExtSlowingPeriod + g_ExtDPeriod - 2; - if(rates_total <= start_pos) - return(0); - -//--- STEP 1: Calculate Raw %K (Fast %K) - for(int i = g_ExtKPeriod - 1; i < rates_total; i++) - { - double highest_high = Highest(high, g_ExtKPeriod, i); - double lowest_low = Lowest(low, g_ExtKPeriod, i); - double range = highest_high - lowest_low; - if(range > 0) - BufferRawK[i] = (close[i] - lowest_low) / range * 100.0; - else - BufferRawK[i] = (i > 0) ? BufferRawK[i-1] : 50.0; - } - -//--- STEP 2: Calculate Slow %K (Main Line) by smoothing Raw %K - int k_slow_start_pos = g_ExtKPeriod + g_ExtSlowingPeriod - 2; - for(int i = k_slow_start_pos; i < rates_total; i++) - { - switch(InpSlowingMAType) - { - case MODE_EMA: - case MODE_SMMA: - if(i == k_slow_start_pos) - { - double sum=0; - for(int j=0; j0) - BufferK[i]=lwma_sum/weight_sum; - } - break; - default: // MODE_SMA - { - double sum=0; - for(int j=0; j0) - BufferD[i]=lwma_sum/weight_sum; - } - break; - default: // MODE_SMA - { - double sum=0; - for(int j=0; j array[current_pos - i]) - res = array[current_pos - i]; - } - return(res); - } -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ diff --git a/Indicators/MyIndicators/Stochastic_Pro_HeikinAshi.mq5 b/Indicators/MyIndicators/Stochastic_Pro_HeikinAshi.mq5 deleted file mode 100644 index 35531f6..0000000 --- a/Indicators/MyIndicators/Stochastic_Pro_HeikinAshi.mq5 +++ /dev/null @@ -1,270 +0,0 @@ -//+------------------------------------------------------------------+ -//| Stochastic_Pro_HeikinAshi.mq5| -//| Copyright 2025, xxxxxxxx | -//| | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2025, xxxxxxxx" -#property link "" -#property version "1.00" -#property description "Stochastic Pro Oscillator on Heikin Ashi data" - -#include - -//--- Indicator Window and Plot Properties --- -#property indicator_separate_window -#property indicator_buffers 3 // %K, %D, and Raw %K for calculation -#property indicator_plots 2 -#property indicator_level1 20.0 -#property indicator_level2 80.0 -#property indicator_minimum 0.0 -#property indicator_maximum 100.0 - -//--- Plot 1: %K line -#property indicator_label1 "HA_%K" -#property indicator_type1 DRAW_LINE -#property indicator_color1 clrLightSeaGreen -#property indicator_style1 STYLE_SOLID -#property indicator_width1 1 - -//--- Plot 2: %D line -#property indicator_label2 "HA_%D" -#property indicator_type2 DRAW_LINE -#property indicator_color2 clrRed -#property indicator_style2 STYLE_DOT -#property indicator_width2 1 - -//--- Input Parameters --- -input int InpKPeriod = 5; -input int InpSlowingPeriod= 3; -input ENUM_MA_METHOD InpSlowingMAType= MODE_SMA; -input int InpDPeriod = 3; -input ENUM_MA_METHOD InpDMAType = MODE_SMMA; - -//--- Indicator Buffers --- -double BufferK[]; -double BufferD[]; -double BufferRawK[]; - -//--- Global Objects and Variables --- -int g_ExtKPeriod, g_ExtDPeriod, g_ExtSlowingPeriod; -CHeikinAshi_Calculator *g_ha_calculator; - -//--- Forward declarations for helper functions --- -double Highest(const double &array[], int period, int current_pos); -double Lowest(const double &array[], int period, int current_pos); - -//+------------------------------------------------------------------+ -//| Custom indicator initialization function. | -//+------------------------------------------------------------------+ -int OnInit() - { - g_ExtKPeriod = (InpKPeriod < 1) ? 1 : InpKPeriod; - g_ExtDPeriod = (InpDPeriod < 1) ? 1 : InpDPeriod; - g_ExtSlowingPeriod = (InpSlowingPeriod < 1) ? 1 : InpSlowingPeriod; - - SetIndexBuffer(0, BufferK, INDICATOR_DATA); - SetIndexBuffer(1, BufferD, INDICATOR_DATA); - SetIndexBuffer(2, BufferRawK, INDICATOR_CALCULATIONS); - - ArraySetAsSeries(BufferK, false); - ArraySetAsSeries(BufferD, false); - ArraySetAsSeries(BufferRawK, false); - - IndicatorSetInteger(INDICATOR_DIGITS, 2); - PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, g_ExtKPeriod + g_ExtSlowingPeriod - 2); - PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, g_ExtKPeriod + g_ExtSlowingPeriod + g_ExtDPeriod - 3); - IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("HA_Stoch_Pro(%d,%d,%d)", g_ExtKPeriod, g_ExtSlowingPeriod, g_ExtDPeriod)); - - g_ha_calculator = new CHeikinAshi_Calculator(); - if(CheckPointer(g_ha_calculator) == POINTER_INVALID) - { - Print("Error creating CHeikinAshi_Calculator object"); - return(INIT_FAILED); - } - return(INIT_SUCCEEDED); - } - -//+------------------------------------------------------------------+ -//| Custom indicator deinitialization function. | -//+------------------------------------------------------------------+ -void OnDeinit(const int reason) - { - if(CheckPointer(g_ha_calculator) != POINTER_INVALID) - { - delete g_ha_calculator; - g_ha_calculator = NULL; - } - } - -//+------------------------------------------------------------------+ -//| Pro Stochastic on Heikin Ashi calculation function. | -//+------------------------------------------------------------------+ -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 start_pos = g_ExtKPeriod + g_ExtSlowingPeriod + g_ExtDPeriod - 2; - if(rates_total <= start_pos) - return(0); - -//--- Intermediate Heikin Ashi Buffers - double ha_open[], ha_high[], ha_low[], ha_close[]; - ArrayResize(ha_open, rates_total); - ArrayResize(ha_high, rates_total); - ArrayResize(ha_low, rates_total); - ArrayResize(ha_close, rates_total); - -//--- STEP 1: Calculate Heikin Ashi bars - g_ha_calculator.Calculate(rates_total, open, high, low, close, ha_open, ha_high, ha_low, ha_close); - -//--- STEP 2: Calculate Raw %K (Fast %K) on HA data - for(int i = g_ExtKPeriod - 1; i < rates_total; i++) - { - double highest_ha_high = Highest(ha_high, g_ExtKPeriod, i); - double lowest_ha_low = Lowest(ha_low, g_ExtKPeriod, i); - double range = highest_ha_high - lowest_ha_low; - if(range > 0) - BufferRawK[i] = (ha_close[i] - lowest_ha_low) / range * 100.0; - else - BufferRawK[i] = (i > 0) ? BufferRawK[i-1] : 50.0; - } - -//--- STEP 3: Calculate Slow %K (Main Line) by smoothing Raw %K - int k_slow_start_pos = g_ExtKPeriod + g_ExtSlowingPeriod - 2; - for(int i = k_slow_start_pos; i < rates_total; i++) - { - switch(InpSlowingMAType) - { - case MODE_EMA: - case MODE_SMMA: - if(i == k_slow_start_pos) - { - double sum=0; - for(int j=0; j0) - BufferK[i]=lwma_sum/weight_sum; - } - break; - default: // MODE_SMA - { - double sum=0; - for(int j=0; j0) - BufferD[i]=lwma_sum/weight_sum; - } - break; - default: // MODE_SMA - { - double sum=0; - for(int j=0; j array[current_pos - i]) - res = array[current_pos - i]; - } - return(res); - } -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ diff --git a/Indicators/MyIndicators/Supertrend.md b/Indicators/MyIndicators/Supertrend.md deleted file mode 100644 index e63b5fa..0000000 --- a/Indicators/MyIndicators/Supertrend.md +++ /dev/null @@ -1,85 +0,0 @@ -# Supertrend Indicator - -## 1. Summary (Introduction) - -The Supertrend indicator was developed by Olivier Seban to identify the primary trend of a financial instrument. It is a popular tool among traders due to its simplicity and clear visual representation of trend direction. Plotted directly on the price chart, the Supertrend line changes color and position based on the market's trend, acting as a dynamic level of support or resistance. - -## 2. Mathematical Foundations and Calculation Logic - -The Supertrend indicator combines a measure of volatility (Average True Range - ATR) with a central price point (typically the median price) to construct upper and lower bands. The final Supertrend line then follows one of these bands based on the current trend direction. - -### Required Components - -- **ATR (Average True Range):** A measure of market volatility. A higher ATR indicates a more volatile market. -- **Factor (Multiplier):** A user-defined multiplier that adjusts the sensitivity of the bands. A larger factor creates wider bands, resulting in fewer but potentially more reliable signals. -- **Median Price (hl2):** The central point for the bands, calculated as `(High + Low) / 2`. - -### Calculation Steps (Algorithm) - -1. **Calculate the Average True Range (ATR)** for a given period. - -2. **Calculate the Basic Upper and Lower Bands:** These are the initial, unadjusted bands around the median price. - - $$ - \text{Upper Basic Band} = \frac{\text{High} + \text{Low}}{2} + (\text{Factor} \times \text{ATR}) - $$ - - $$ - \text{Lower Basic Band} = \frac{\text{High} + \text{Low}}{2} - (\text{Factor} \times \text{ATR}) - $$ - -3. **Calculate the Final Upper and Lower Bands:** This step creates the characteristic "stair-step" appearance of the indicator. The logic ensures that the bands never move against the trend (i.e., the upper band can only move down or stay flat, and the lower band can only move up or stay flat). - - $$ - \text{Final Upper Band}_i = - \begin{cases} - \text{Upper Basic Band}_i & \text{if } \text{Upper Basic Band}_i < \text{Final Upper Band}_{i-1} \text{ or } \text{Close}_{i-1} > \text{Final Upper Band}_{i-1} \\ - \text{Final Upper Band}_{i-1} & \text{otherwise} - \end{cases} - $$ - - $$ - \text{Final Lower Band}_i = - \begin{cases} - \text{Lower Basic Band}_i & \text{if } \text{Lower Basic Band}_i > \text{Final Lower Band}_{i-1} \text{ or } \text{Close}_{i-1} < \text{Final Lower Band}_{i-1} \\ - \text{Final Lower Band}_{i-1} & \text{otherwise} - \end{cases} - $$ - -4. **Determine the Trend Direction:** The trend is determined by comparing the closing price to the opposite band. - - - If the previous trend was **up**, the trend flips to **down** if the current close crosses below the **Final Lower Band**. - - If the previous trend was **down**, the trend flips to **up** if the current close crosses above the **Final Upper Band**. - - If neither condition is met, the trend continues. - -5. **Plot the Supertrend Line:** - - If the trend is **up**, the Supertrend line is plotted at the level of the **Final Lower Band**. - - If the trend is **down**, the Supertrend line is plotted at the level of the **Final Upper Band**. - -## 3. MQL5 Implementation Details - -Our MQL5 implementation was refactored based on our core principles to ensure maximum stability and code clarity. - -- **Stability via Full Recalculation:** We employ a "brute-force" full recalculation within the `OnCalculate` function. For a state-dependent indicator like Supertrend, this approach is far more robust than using `prev_calculated` logic, as it prevents calculation errors during timeframe changes or history loading. - -- **State Management:** A dedicated calculation buffer, `BufferTrend[]`, is used to explicitly store the current trend direction (`1` for up, `-1` for down). This makes the trend-switching logic clean, readable, and less prone to errors. - -- **Robust Initialization:** The trend is explicitly initialized on the first valid bar (`i == g_ExtAtrPeriod`). The initial direction is determined by comparing the closing price to the median price (`hl2`), providing a stable starting point for the recursive logic. - -- **Visual Representation:** We opted for a "connected line" visualization for trend changes. When a trend flip occurs, the value of the previous bar's Supertrend line is overwritten to match the new bar's value. This creates a vertical line connecting the old and new trend lines, ensuring continuous visual information. - -- **Heikin Ashi Variants:** Our toolkit includes two Heikin Ashi versions of the Supertrend indicator, offering different perspectives on the trend. - - **Hybrid Version (`Supertrend_HeikinAshi.mq5`):** This version calculates the bands using the smoothed Heikin Ashi median price (`ha_hl2`) and closing price (`ha_close`) but utilizes the **standard ATR** calculated from regular candlesticks. This approach combines the smoothed trend signal of Heikin Ashi with the "true" market volatility. It may be preferred by traders looking for signals based on real volatility spikes. - - **"Pure" Version (`Supertrend_HeikinAshi_Pure.mq5`):** This version is based entirely on Heikin Ashi data. The ATR is manually calculated from the Heikin Ashi High, Low, and Close values. The result is a fully smoothed indicator where both the trend and the volatility component are filtered. This may be preferred by trend-following traders seeking a less "noisy" signal. - -## 4. Parameters - -- **ATR Period (`InpAtrPeriod`):** The lookback period for the Average True Range calculation. A shorter period makes the indicator more sensitive to recent volatility, while a longer period provides a smoother, less reactive line. Default is `10`. -- **Factor (`InpFactor`):** The multiplier applied to the ATR value. A smaller factor brings the line closer to the price, resulting in more frequent signals. A larger factor moves the line further away, filtering out minor price fluctuations and producing fewer signals. Default is `3.0`. - -## 5. Usage and Interpretation - -- **Trend Identification:** The primary use of the Supertrend is to identify the current market trend. A green line below the price indicates an uptrend, while a red line above the price indicates a downtrend. -- **Dynamic Support and Resistance:** In an uptrend, the green line often acts as a dynamic support level. In a downtrend, the red line acts as a dynamic resistance level. -- **Trade Signals:** A change in the indicator's color can be interpreted as a trade signal. A flip from red to green suggests a potential buy signal, while a flip from green to red suggests a potential sell signal. -- **Caution:** Like all trend-following indicators, Supertrend is most effective in trending markets. In sideways or ranging markets, it can produce frequent false signals ("whipsaws"). It is highly recommended to use it in conjunction with other indicators or forms of analysis for confirmation. diff --git a/Indicators/MyIndicators/Supertrend.mq5 b/Indicators/MyIndicators/Supertrend.mq5 deleted file mode 100644 index 12b3f54..0000000 --- a/Indicators/MyIndicators/Supertrend.mq5 +++ /dev/null @@ -1,169 +0,0 @@ -//+------------------------------------------------------------------+ -//| Supertrend.mq5 | -//| Copyright 2025, xxxxxxxx | -//| | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2025, xxxxxxxx" -#property link "" -#property version "2.00" // Refactored for stability and robust logic -#property description "Supertrend Indicator for trend identification" - -//--- Indicator Window and Plot Properties --- -#property indicator_chart_window -#property indicator_buffers 6 // Supertrend, Color, ATR, Upper, Lower, Trend -#property indicator_plots 1 - -//--- Plot 1: Supertrend line -#property indicator_label1 "Supertrend" -#property indicator_type1 DRAW_COLOR_LINE -#property indicator_color1 clrLimeGreen, clrTomato -#property indicator_style1 STYLE_SOLID -#property indicator_width1 2 - -//--- Input Parameters --- -input int InpAtrPeriod = 10; -input double InpFactor = 3.0; - -//--- Indicator Buffers --- -double BufferSupertrend[]; -double BufferColor[]; -double BufferATR[]; -double BufferUpperBand[]; -double BufferLowerBand[]; -double BufferTrend[]; - -//--- Global Variables --- -int g_ExtAtrPeriod; -double g_ExtFactor; -int g_handle_atr; - -//+------------------------------------------------------------------+ -//| Custom indicator initialization function. | -//+------------------------------------------------------------------+ -int OnInit() - { - g_ExtAtrPeriod = (InpAtrPeriod < 1) ? 1 : InpAtrPeriod; - g_ExtFactor = (InpFactor <= 0) ? 3.0 : InpFactor; - - SetIndexBuffer(0, BufferSupertrend, INDICATOR_DATA); - SetIndexBuffer(1, BufferColor, INDICATOR_COLOR_INDEX); - SetIndexBuffer(2, BufferATR, INDICATOR_CALCULATIONS); - SetIndexBuffer(3, BufferUpperBand, INDICATOR_CALCULATIONS); - SetIndexBuffer(4, BufferLowerBand, INDICATOR_CALCULATIONS); - SetIndexBuffer(5, BufferTrend, INDICATOR_CALCULATIONS); - - ArraySetAsSeries(BufferSupertrend, false); - ArraySetAsSeries(BufferColor, false); - ArraySetAsSeries(BufferATR, false); - ArraySetAsSeries(BufferUpperBand, false); - ArraySetAsSeries(BufferLowerBand, false); - ArraySetAsSeries(BufferTrend, false); - - g_handle_atr = iATR(_Symbol, _Period, g_ExtAtrPeriod); - if(g_handle_atr == INVALID_HANDLE) - { - Print("Error creating iATR handle."); - return(INIT_FAILED); - } - - IndicatorSetInteger(INDICATOR_DIGITS, _Digits); - PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, g_ExtAtrPeriod); - IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("Supertrend(%d, %.1f)", g_ExtAtrPeriod, g_ExtFactor)); - - return(INIT_SUCCEEDED); - } - -//+------------------------------------------------------------------+ -//| Custom indicator deinitialization function. | -//+------------------------------------------------------------------+ -void OnDeinit(const int reason) - { -//--- Release the indicator handle - IndicatorRelease(g_handle_atr); - } - -//+------------------------------------------------------------------+ -//| Supertrend calculation function. | -//+------------------------------------------------------------------+ -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 <= g_ExtAtrPeriod) - return(0); - -//--- STEP 1: Get ATR values - if(CopyBuffer(g_handle_atr, 0, 0, rates_total, BufferATR) < rates_total) - { - Print("Error copying iATR buffer data."); - } - -//--- STEP 2: Main calculation loop with robust initialization - for(int i = 1; i < rates_total; i++) - { - double hl2 = (high[i] + low[i]) / 2.0; - double atr_val = g_ExtFactor * BufferATR[i]; - - //--- Calculate basic upper and lower bands - double upper_basic = hl2 + atr_val; - double lower_basic = hl2 - atr_val; - - //--- Final upper band (stair-step logic) - if(upper_basic < BufferUpperBand[i-1] || close[i-1] > BufferUpperBand[i-1]) - BufferUpperBand[i] = upper_basic; - else - BufferUpperBand[i] = BufferUpperBand[i-1]; - - //--- Final lower band (stair-step logic) - if(lower_basic > BufferLowerBand[i-1] || close[i-1] < BufferLowerBand[i-1]) - BufferLowerBand[i] = lower_basic; - else - BufferLowerBand[i] = BufferLowerBand[i-1]; - - //--- Determine trend direction - if(i == g_ExtAtrPeriod) // Explicit trend initialization - { - if(close[i] > hl2) - BufferTrend[i] = 1; - else - BufferTrend[i] = -1; - } - else - if(i > g_ExtAtrPeriod) // Subsequent points - { - if(BufferTrend[i-1] == 1 && close[i] < BufferLowerBand[i]) - BufferTrend[i] = -1; // Trend changed to down - else - if(BufferTrend[i-1] == -1 && close[i] > BufferUpperBand[i]) - BufferTrend[i] = 1; // Trend changed to up - else - BufferTrend[i] = BufferTrend[i-1]; // Trend continues - } - - //--- Set the final Supertrend value and color, and connect lines on change - if(BufferTrend[i] == 1) // Uptrend - { - BufferSupertrend[i] = BufferLowerBand[i]; - BufferColor[i] = 0; - if(BufferTrend[i-1] == -1) - BufferSupertrend[i-1] = BufferLowerBand[i]; - } - else // Downtrend - { - BufferSupertrend[i] = BufferUpperBand[i]; - BufferColor[i] = 1; - if(BufferTrend[i-1] == 1) - BufferSupertrend[i-1] = BufferUpperBand[i]; - } - } - return(rates_total); - } -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ diff --git a/Indicators/MyIndicators/Supertrend_HeikinAshi.mq5 b/Indicators/MyIndicators/Supertrend_HeikinAshi.mq5 deleted file mode 100644 index 124baea..0000000 --- a/Indicators/MyIndicators/Supertrend_HeikinAshi.mq5 +++ /dev/null @@ -1,201 +0,0 @@ -//+------------------------------------------------------------------+ -//| Supertrend_HeikinAshi.mq5 | -//| Copyright 2025, xxxxxxxx | -//| | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2025, xxxxxxxx" -#property link "" -#property version "2.00" // Refactored for full recalculation and stability -#property description "Supertrend Indicator on Heikin Ashi data" - -#include - -//--- Indicator Window and Plot Properties --- -#property indicator_chart_window -#property indicator_buffers 6 // Supertrend, Color, ATR, Upper, Lower, Trend -#property indicator_plots 1 - -//--- Plot 1: Supertrend line -#property indicator_label1 "HA_Supertrend" -#property indicator_type1 DRAW_COLOR_LINE -#property indicator_color1 clrLimeGreen, clrTomato -#property indicator_style1 STYLE_SOLID -#property indicator_width1 2 - -//--- Input Parameters --- -input int InpAtrPeriod = 10; -input double InpFactor = 3.0; - -//--- Indicator Buffers --- -double BufferSupertrend[]; -double BufferColor[]; -double BufferATR[]; -double BufferUpperBand[]; -double BufferLowerBand[]; -double BufferTrend[]; - -//--- Intermediate Heikin Ashi Buffers --- -double ExtHaOpenBuffer[]; -double ExtHaHighBuffer[]; -double ExtHaLowBuffer[]; -double ExtHaCloseBuffer[]; - -//--- Global Objects and Variables --- -int g_ExtAtrPeriod; -double g_ExtFactor; -int g_handle_atr; -CHeikinAshi_Calculator *g_ha_calculator; // Pointer to our Heikin Ashi calculator - -//+------------------------------------------------------------------+ -//| Custom indicator initialization function. | -//+------------------------------------------------------------------+ -int OnInit() - { - g_ExtAtrPeriod = (InpAtrPeriod < 1) ? 1 : InpAtrPeriod; - g_ExtFactor = (InpFactor <= 0) ? 3.0 : InpFactor; - - SetIndexBuffer(0, BufferSupertrend, INDICATOR_DATA); - SetIndexBuffer(1, BufferColor, INDICATOR_COLOR_INDEX); - SetIndexBuffer(2, BufferATR, INDICATOR_CALCULATIONS); - SetIndexBuffer(3, BufferUpperBand, INDICATOR_CALCULATIONS); - SetIndexBuffer(4, BufferLowerBand, INDICATOR_CALCULATIONS); - SetIndexBuffer(5, BufferTrend, INDICATOR_CALCULATIONS); - - ArraySetAsSeries(BufferSupertrend, false); - ArraySetAsSeries(BufferColor, false); - ArraySetAsSeries(BufferATR, false); - ArraySetAsSeries(BufferUpperBand, false); - ArraySetAsSeries(BufferLowerBand, false); - ArraySetAsSeries(BufferTrend, false); - -// ATR is calculated on standard candles for true volatility - g_handle_atr = iATR(_Symbol, _Period, g_ExtAtrPeriod); - if(g_handle_atr == INVALID_HANDLE) - { - Print("Error creating iATR handle."); - return(INIT_FAILED); - } - - IndicatorSetInteger(INDICATOR_DIGITS, _Digits); - PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, g_ExtAtrPeriod); - PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE); // For trend change gaps - IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("HA_Supertrend(%d, %.1f)", g_ExtAtrPeriod, g_ExtFactor)); - -//--- Create the calculator instance - g_ha_calculator = new CHeikinAshi_Calculator(); - if(CheckPointer(g_ha_calculator) == POINTER_INVALID) - { - Print("Error creating CHeikinAshi_Calculator object"); - return(INIT_FAILED); - } - - return(INIT_SUCCEEDED); - } - -//+------------------------------------------------------------------+ -//| Custom indicator deinitialization function. | -//+------------------------------------------------------------------+ -void OnDeinit(const int reason) - { - if(CheckPointer(g_ha_calculator) != POINTER_INVALID) - delete g_ha_calculator; - IndicatorRelease(g_handle_atr); - } - -//+------------------------------------------------------------------+ -//| Supertrend on Heikin Ashi calculation function. | -//+------------------------------------------------------------------+ -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 <= g_ExtAtrPeriod) - return(0); - -//--- Resize intermediate buffers - ArrayResize(ExtHaOpenBuffer, rates_total); - ArrayResize(ExtHaHighBuffer, rates_total); - ArrayResize(ExtHaLowBuffer, rates_total); - ArrayResize(ExtHaCloseBuffer, rates_total); - -//--- STEP 1: Calculate Heikin Ashi bars - g_ha_calculator.Calculate(rates_total, open, high, low, close, - ExtHaOpenBuffer, ExtHaHighBuffer, ExtHaLowBuffer, ExtHaCloseBuffer); - -//--- STEP 2: Get ATR values - if(CopyBuffer(g_handle_atr, 0, 0, rates_total, BufferATR) < rates_total) - { - Print("Error copying iATR buffer data."); - } - -//--- STEP 3: Main calculation loop with robust initialization - for(int i = 1; i < rates_total; i++) - { - double ha_hl2 = (ExtHaHighBuffer[i] + ExtHaLowBuffer[i]) / 2.0; - double atr_val = g_ExtFactor * BufferATR[i]; - - double upper_basic = ha_hl2 + atr_val; - double lower_basic = ha_hl2 - atr_val; - - if(upper_basic < BufferUpperBand[i-1] || ExtHaCloseBuffer[i-1] > BufferUpperBand[i-1]) - BufferUpperBand[i] = upper_basic; - else - BufferUpperBand[i] = BufferUpperBand[i-1]; - - if(lower_basic > BufferLowerBand[i-1] || ExtHaCloseBuffer[i-1] < BufferLowerBand[i-1]) - BufferLowerBand[i] = lower_basic; - else - BufferLowerBand[i] = BufferLowerBand[i-1]; - - if(i == g_ExtAtrPeriod) - { - if(ExtHaCloseBuffer[i] > ha_hl2) - BufferTrend[i] = 1; - else - BufferTrend[i] = -1; - } - else - if(i > g_ExtAtrPeriod) - { - if(BufferTrend[i-1] == 1 && ExtHaCloseBuffer[i] < BufferLowerBand[i]) - BufferTrend[i] = -1; - else - if(BufferTrend[i-1] == -1 && ExtHaCloseBuffer[i] > BufferUpperBand[i]) - BufferTrend[i] = 1; - else - BufferTrend[i] = BufferTrend[i-1]; - } - - // --- FIX: Logic for connected lines on trend change --- - if(BufferTrend[i] == 1) // Uptrend - { - BufferSupertrend[i] = BufferLowerBand[i]; - BufferColor[i] = 0; - // If trend just changed to UP, connect the previous point - if(BufferTrend[i-1] == -1) - { - BufferSupertrend[i-1] = BufferLowerBand[i]; - } - } - else // Downtrend - { - BufferSupertrend[i] = BufferUpperBand[i]; - BufferColor[i] = 1; - // If trend just changed to DOWN, connect the previous point - if(BufferTrend[i-1] == 1) - { - BufferSupertrend[i-1] = BufferUpperBand[i]; - } - } - } - return(rates_total); - } -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ diff --git a/Indicators/MyIndicators/Supertrend_HeikinAshi_Pure.mq5 b/Indicators/MyIndicators/Supertrend_HeikinAshi_Pure.mq5 deleted file mode 100644 index 006efc3..0000000 --- a/Indicators/MyIndicators/Supertrend_HeikinAshi_Pure.mq5 +++ /dev/null @@ -1,200 +0,0 @@ -//+------------------------------------------------------------------+ -//| Supertrend_HeikinAshi_Pure.mq5 | -//| Copyright 2025, xxxxxxxx | -//| | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2025, xxxxxxxx" -#property link "" -#property version "3.00" // Pure Heikin Ashi version with manual ATR -#property description "Supertrend Indicator based entirely on Heikin Ashi data" - -#include -#include - -//--- Indicator Window and Plot Properties --- -#property indicator_chart_window -#property indicator_buffers 6 // Supertrend, Color, HA_ATR, Upper, Lower, Trend -#property indicator_plots 1 - -//--- Plot 1: Supertrend line -#property indicator_label1 "HA_Supertrend_Pure" -#property indicator_type1 DRAW_COLOR_LINE -#property indicator_color1 clrLimeGreen, clrTomato -#property indicator_style1 STYLE_SOLID -#property indicator_width1 2 - -//--- Input Parameters --- -input int InpAtrPeriod = 10; -input double InpFactor = 3.0; - -//--- Indicator Buffers --- -double BufferSupertrend[]; -double BufferColor[]; -double BufferHA_ATR[]; -double BufferUpperBand[]; -double BufferLowerBand[]; -double BufferTrend[]; - -//--- Intermediate Heikin Ashi Buffers --- -double ExtHaOpenBuffer[]; -double ExtHaHighBuffer[]; -double ExtHaLowBuffer[]; -double ExtHaCloseBuffer[]; - -//--- Global Objects and Variables --- -int g_ExtAtrPeriod; -double g_ExtFactor; -CHeikinAshi_Calculator *g_ha_calculator; // Pointer to our Heikin Ashi calculator - -//+------------------------------------------------------------------+ -//| Custom indicator initialization function. | -//+------------------------------------------------------------------+ -int OnInit() - { - g_ExtAtrPeriod = (InpAtrPeriod < 1) ? 1 : InpAtrPeriod; - g_ExtFactor = (InpFactor <= 0) ? 3.0 : InpFactor; - - SetIndexBuffer(0, BufferSupertrend, INDICATOR_DATA); - SetIndexBuffer(1, BufferColor, INDICATOR_COLOR_INDEX); - SetIndexBuffer(2, BufferHA_ATR, INDICATOR_CALCULATIONS); - SetIndexBuffer(3, BufferUpperBand, INDICATOR_CALCULATIONS); - SetIndexBuffer(4, BufferLowerBand, INDICATOR_CALCULATIONS); - SetIndexBuffer(5, BufferTrend, INDICATOR_CALCULATIONS); - - ArraySetAsSeries(BufferSupertrend, false); - ArraySetAsSeries(BufferColor, false); - ArraySetAsSeries(BufferHA_ATR, false); - ArraySetAsSeries(BufferUpperBand, false); - ArraySetAsSeries(BufferLowerBand, false); - ArraySetAsSeries(BufferTrend, false); - - IndicatorSetInteger(INDICATOR_DIGITS, _Digits); - PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, g_ExtAtrPeriod); - IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("HA_Supertrend_Pure(%d, %.1f)", g_ExtAtrPeriod, g_ExtFactor)); - -//--- Create the calculator instance - g_ha_calculator = new CHeikinAshi_Calculator(); - if(CheckPointer(g_ha_calculator) == POINTER_INVALID) - { - Print("Error creating CHeikinAshi_Calculator object"); - return(INIT_FAILED); - } - - return(INIT_SUCCEEDED); - } - -//+------------------------------------------------------------------+ -//| Custom indicator deinitialization function. | -//+------------------------------------------------------------------+ -void OnDeinit(const int reason) - { - if(CheckPointer(g_ha_calculator) != POINTER_INVALID) - delete g_ha_calculator; - } - -//+------------------------------------------------------------------+ -//| Supertrend on Heikin Ashi calculation function. | -//+------------------------------------------------------------------+ -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 <= g_ExtAtrPeriod) - return(0); - -//--- Resize intermediate buffers - ArrayResize(ExtHaOpenBuffer, rates_total); - ArrayResize(ExtHaHighBuffer, rates_total); - ArrayResize(ExtHaLowBuffer, rates_total); - ArrayResize(ExtHaCloseBuffer, rates_total); - -//--- STEP 1: Calculate Heikin Ashi bars - g_ha_calculator.Calculate(rates_total, open, high, low, close, - ExtHaOpenBuffer, ExtHaHighBuffer, ExtHaLowBuffer, ExtHaCloseBuffer); - -//--- STEP 2: Calculate Heikin Ashi True Range - double ha_tr[]; - ArrayResize(ha_tr, rates_total); - for(int i = 1; i < rates_total; i++) - { - ha_tr[i] = MathMax(ExtHaHighBuffer[i], ExtHaCloseBuffer[i-1]) - MathMin(ExtHaLowBuffer[i], ExtHaCloseBuffer[i-1]); - } - -//--- STEP 3: Calculate Heikin Ashi ATR and Supertrend in a single loop - for(int i = 1; i < rates_total; i++) - { - // --- Calculate Heikin Ashi ATR (using Wilder's smoothing) --- - if(i == g_ExtAtrPeriod) // Initialization with SMA - { - BufferHA_ATR[i] = SimpleMA(i, g_ExtAtrPeriod, ha_tr); - } - else - if(i > g_ExtAtrPeriod) // Recursive calculation - { - BufferHA_ATR[i] = (BufferHA_ATR[i-1] * (g_ExtAtrPeriod - 1) + ha_tr[i]) / g_ExtAtrPeriod; - } - - // --- Calculate Supertrend Bands and Trend --- - if(i >= g_ExtAtrPeriod) - { - double ha_hl2 = (ExtHaHighBuffer[i] + ExtHaLowBuffer[i]) / 2.0; - double atr_val = g_ExtFactor * BufferHA_ATR[i]; - - double upper_basic = ha_hl2 + atr_val; - double lower_basic = ha_hl2 - atr_val; - - if(upper_basic < BufferUpperBand[i-1] || ExtHaCloseBuffer[i-1] > BufferUpperBand[i-1]) - BufferUpperBand[i] = upper_basic; - else - BufferUpperBand[i] = BufferUpperBand[i-1]; - - if(lower_basic > BufferLowerBand[i-1] || ExtHaCloseBuffer[i-1] < BufferLowerBand[i-1]) - BufferLowerBand[i] = lower_basic; - else - BufferLowerBand[i] = BufferLowerBand[i-1]; - - if(i == g_ExtAtrPeriod) - { - if(ExtHaCloseBuffer[i] > ha_hl2) - BufferTrend[i] = 1; - else - BufferTrend[i] = -1; - } - else - { - if(BufferTrend[i-1] == 1 && ExtHaCloseBuffer[i] < BufferLowerBand[i]) - BufferTrend[i] = -1; - else - if(BufferTrend[i-1] == -1 && ExtHaCloseBuffer[i] > BufferUpperBand[i]) - BufferTrend[i] = 1; - else - BufferTrend[i] = BufferTrend[i-1]; - } - - if(BufferTrend[i] == 1) - { - BufferSupertrend[i] = BufferLowerBand[i]; - BufferColor[i] = 0; - if(BufferTrend[i-1] == -1) - BufferSupertrend[i-1] = BufferLowerBand[i]; - } - else - { - BufferSupertrend[i] = BufferUpperBand[i]; - BufferColor[i] = 1; - if(BufferTrend[i-1] == 1) - BufferSupertrend[i-1] = BufferUpperBand[i]; - } - } - } - return(rates_total); - } -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ diff --git a/Indicators/MyIndicators/Symmetric_WMA.md b/Indicators/MyIndicators/Symmetric_WMA.md deleted file mode 100644 index 2a952c7..0000000 --- a/Indicators/MyIndicators/Symmetric_WMA.md +++ /dev/null @@ -1,66 +0,0 @@ -# Symmetric Weighted Moving Average (Symmetric WMA) - -## 1. Summary (Introduction) - -The Symmetric Weighted Moving Average is a type of weighted moving average that uses a simple, triangular (or tent-shaped) weighting scheme. It is the most straightforward implementation of a symmetrical, centered smoothing filter. - -Like other symmetrical filters such as the Sine or Pascal WMA, its primary purpose is to **reduce market noise and provide a smooth representation of the price's central tendency**. It achieves this by assigning the heaviest weights to the price data in the middle of the lookback period and linearly decreasing the weights towards the ends of the period. - -The result is a smooth line that lags the price but effectively filters out insignificant fluctuations. It serves as an excellent tool for identifying the underlying smoothed trend and for mean-reversion analysis, offering a simpler alternative to more complex mathematical filters. - -## 2. Mathematical Foundations and Calculation Logic - -The Symmetric WMA calculates a weighted average where the weights form a simple triangular pattern. - -### Required Components - -- **Period (N):** The lookback period for the moving average. -- **Source Price:** The price series used for calculation (e.g., `PRICE_CLOSE`). - -### Calculation Steps (Algorithm) - -1. **Generate Symmetric Weights:** For a given period `N`, the weights are generated to form a triangle. They increase linearly from 1 to a peak at the midpoint of the period, and then decrease linearly back to 1. - - Let `midpoint = (N + 1) / 2` - - For `i` from 1 to `N`: - - If `i <= midpoint`, $Weight_i = i$ - - If `i > midpoint`, $Weight_i = N - i + 1$ - - *Example for N=5:* The weights would be `1, 2, 3, 2, 1`. - -2. **Calculate the Weighted Sum:** For each bar `t`, multiply the last `N` prices by the corresponding triangular weights. - - $\text{Weighted Sum}_t = \sum_{i=0}^{N-1} (\text{Price}_{t-i} \cdot Weight_i)$ - -3. **Calculate the Sum of Weights:** Sum all the generated triangular weights. - - $\text{Sum of Weights} = \sum_{i=0}^{N-1} Weight_i$ - -4. **Calculate the Final WMA Value:** Divide the weighted sum of prices by the sum of the weights. - - $\text{Symmetric WMA}_t = \frac{\text{Weighted Sum}_t}{\text{Sum of Weights}}$ - -This process results in a symmetrically weighted average that is centered on the data, providing a simple yet effective smoothing filter. - -## 3. MQL5 Implementation Details - -Our MQL5 implementation is a clean and robust indicator that accurately calculates the Symmetric WMA. - -- **Self-Contained, Object-Oriented Design:** The entire logic is encapsulated within a single `.mq5` file but is internally structured into a dedicated `CSymmetricWMACalculator` class. This separates the calculation logic from the indicator's buffer management, ensuring the code is clean and maintainable. - -- **Efficient Weight Generation:** The triangular weights are calculated only once during the indicator's initialization in the `Init()` method of the calculator class. The weights and their sum are stored in internal class members for efficient reuse in the main calculation loop. - -- **Stability via Full Recalculation:** In line with our core principles, the indicator employs a "brute-force" full recalculation within the `OnCalculate` function. This is the most reliable method to ensure stability and prevent any potential glitches, while keeping the code simple and robust. - -- **Correct Symmetrical Application:** The `Calculate` method applies the pre-calculated symmetrical weights directly to the price data. The weights are **not reversed**. The most recent price is multiplied by the first, smallest weight (1), and the price in the middle of the period is multiplied by the largest weight. This correctly implements the smoothing, centered nature of the filter. The inherent lag of `(Period-1)/2` bars is a mathematical property of the filter. - -## 4. Parameters - -- **Period (`InpPeriod`):** The lookback period for the moving average. A longer period results in a smoother line that is less sensitive to short-term price fluctuations. Default is `21`. -- **Source Price (`InpSourcePrice`):** The price data used for the calculation (Close, Open, High, Low, Median, etc.). Default is `PRICE_CLOSE`. - -## 5. Usage and Interpretation - -The Symmetric WMA should be interpreted as a **smoothing filter and a "mean" or "center of gravity" line**, similar to the Sine and Pascal WMAs. - -- **Noise Reduction and Trend Clarity:** The primary use of the Symmetric WMA is to filter out market noise and provide a clearer picture of the underlying price movement. Its smooth nature helps to visualize the true, smoothed path of the market. -- **Mean Reversion Signals:** The line acts as a "magnet" for the price. - - When the price moves significantly **above** the Symmetric WMA, it can be considered over-extended, increasing the probability of a reversion (downward correction) back towards the line. - - When the price moves significantly **below** the Symmetric WMA, it can be considered oversold, increasing the probability of a reversion back up towards the line. -- **Confirmation of Trend Direction:** The slope of the Symmetric WMA provides a very stable, albeit lagging, confirmation of the main trend direction. Because it is slow to turn, a change in the slope's direction is a significant event, suggesting a potential major shift in the market. -- **Caution:** Due to its inherent nature as a centered, smoothing filter, the Symmetric WMA will always lag the price. It should **not** be used for fast crossover signals in the same way as an EMA. Its strength lies in its simplicity and smoothness, making it a reliable tool for mean-reversion strategies or as a baseline in more complex systems. diff --git a/Indicators/MyIndicators/Symmetric_WMA.mq5 b/Indicators/MyIndicators/Symmetric_WMA.mq5 deleted file mode 100644 index bce845a..0000000 --- a/Indicators/MyIndicators/Symmetric_WMA.mq5 +++ /dev/null @@ -1,188 +0,0 @@ -//+------------------------------------------------------------------+ -//| Symmetric_WMA.mq5 | -//| Copyright 2025, xxxxxxxx| -//| | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2025, xxxxxxxx" -#property version "1.00" -#property description "Symmetric Weighted Moving Average. A zero-lag smoothing filter." - -#property indicator_chart_window -#property indicator_buffers 1 -#property indicator_plots 1 - -//--- Plot 1: Symmetric WMA Line -#property indicator_label1 "Symmetric WMA" -#property indicator_type1 DRAW_LINE -#property indicator_color1 clrOrange -#property indicator_style1 STYLE_SOLID -#property indicator_width1 2 - -//--- Input Parameters --- -input int InpPeriod = 21; -input ENUM_APPLIED_PRICE InpSourcePrice = PRICE_CLOSE; - -//--- Indicator Buffers --- -double BufferWMA[]; -double BufferPrice[]; - -//+------------------------------------------------------------------+ -//| CLASS: CSymmetricWMACalculator | -//| Encapsulates the logic for Symmetric Triangle weighting. | -//+------------------------------------------------------------------+ -class CSymmetricWMACalculator - { -private: - int m_period; - double m_weights[]; - double m_weight_sum; - -public: - CSymmetricWMACalculator(void); - ~CSymmetricWMACalculator(void) {}; - - bool Init(int period); - void Calculate(int rates_total, const double &price_src[], double &wma_out[]); - }; - -//+------------------------------------------------------------------+ -//| CSymmetricWMACalculator: Constructor | -//+------------------------------------------------------------------+ -CSymmetricWMACalculator::CSymmetricWMACalculator(void) : m_period(0), m_weight_sum(0) - { - } - -//+------------------------------------------------------------------+ -//| CSymmetricWMACalculator: Initialization and Weight Generation | -//+------------------------------------------------------------------+ -bool CSymmetricWMACalculator::Init(int period) - { - m_period = (period < 2) ? 2 : period; - ArrayResize(m_weights, m_period); - m_weight_sum = 0; - -//--- Generate a symmetrical, triangular weighting - int midpoint = (m_period + 1) / 2; - for(int i = 0; i < m_period; i++) - { - if(i < midpoint) - m_weights[i] = i + 1; - else - m_weights[i] = m_period - i; - - m_weight_sum += m_weights[i]; - } - - return (m_weight_sum != 0); - } - -//+------------------------------------------------------------------+ -//| CSymmetricWMACalculator: Main Calculation Method | -//+------------------------------------------------------------------+ -void CSymmetricWMACalculator::Calculate(int rates_total, const double &price_src[], double &wma_out[]) - { - if(rates_total < m_period) - return; - - for(int i = m_period - 1; i < rates_total; i++) - { - double weighted_sum = 0; - for(int j = 0; j < m_period; j++) - { - // Symmetrical weighting, use weights as generated - weighted_sum += price_src[i - j] * m_weights[j]; - } - wma_out[i] = weighted_sum / m_weight_sum; - } - } - -//--- Global calculator object --- -CSymmetricWMACalculator *g_calculator; - -//--- Forward declaration -int PriceSeries(ENUM_APPLIED_PRICE,int,const double&[],const double&[],const double&[],const double&[],double&[]); - -//+------------------------------------------------------------------+ -//| Custom indicator initialization function. | -//+------------------------------------------------------------------+ -int OnInit() - { - SetIndexBuffer(0, BufferWMA, INDICATOR_DATA); - ArraySetAsSeries(BufferWMA, false); - - g_calculator = new CSymmetricWMACalculator(); - if(CheckPointer(g_calculator) == POINTER_INVALID || !g_calculator.Init(InpPeriod)) - { - Print("Failed to initialize Symmetric WMA Calculator."); - return(INIT_FAILED); - } - - PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, InpPeriod - 1); - IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("SymmetricWMA(%d)", InpPeriod)); - - return(INIT_SUCCEEDED); - } - -//+------------------------------------------------------------------+ -//| Custom indicator deinitialization function. | -//+------------------------------------------------------------------+ -void OnDeinit(const int reason) - { - if(CheckPointer(g_calculator) != POINTER_INVALID) - delete g_calculator; - } - -//+------------------------------------------------------------------+ -//| Custom indicator iteration function. | -//+------------------------------------------------------------------+ -int OnCalculate(const int rates_total, const int, const datetime&[], const double &open[], const double &high[], const double &low[], const double &close[], const long&[], const long&[], const int&[]) - { - ArrayResize(BufferPrice, rates_total); - if(PriceSeries(InpSourcePrice, rates_total, open, high, low, close, BufferPrice) <= 0) - return 0; - - if(CheckPointer(g_calculator) != POINTER_INVALID) - { - g_calculator.Calculate(rates_total, BufferPrice, BufferWMA); - } - return(rates_total); - } - -//+------------------------------------------------------------------+ -//| Helper function to get the selected price series. | -//+------------------------------------------------------------------+ -int PriceSeries(ENUM_APPLIED_PRICE type, int rates_total, const double &open[], const double &high[], const double &low[], const double &close[], double &dest_buffer[]) - { - switch(type) - { - case PRICE_CLOSE: - ArrayCopy(dest_buffer, close, 0, 0, rates_total); - break; - case PRICE_OPEN: - ArrayCopy(dest_buffer, open, 0, 0, rates_total); - break; - case PRICE_HIGH: - ArrayCopy(dest_buffer, high, 0, 0, rates_total); - break; - case PRICE_LOW: - ArrayCopy(dest_buffer, low, 0, 0, rates_total); - break; - case PRICE_MEDIAN: - for(int i=0; i - -//--- Plot 1: RSI Price Line (Fast) -#property indicator_label1 "Price Line" -#property indicator_type1 DRAW_LINE -#property indicator_color1 clrLimeGreen -#property indicator_style1 STYLE_SOLID -#property indicator_width1 2 - -//--- Plot 2: Trade Signal Line (Slow) -#property indicator_label2 "Signal Line" -#property indicator_type2 DRAW_LINE -#property indicator_color2 clrRed -#property indicator_style2 STYLE_SOLID -#property indicator_width2 1 - -//--- Plot 3: Market Base Line (Trend) -#property indicator_label3 "Base Line" -#property indicator_type3 DRAW_LINE -#property indicator_color3 clrGold -#property indicator_style3 STYLE_SOLID -#property indicator_width3 2 - -//--- Plot 4: Upper Volatility Band -#property indicator_label4 "Upper Band" -#property indicator_type4 DRAW_LINE -#property indicator_color4 clrDodgerBlue -#property indicator_style4 STYLE_DASHDOT -#property indicator_width4 1 - -//--- Plot 5: Lower Volatility Band -#property indicator_label5 "Lower Band" -#property indicator_type5 DRAW_LINE -#property indicator_color5 clrDodgerBlue -#property indicator_style5 STYLE_DASHDOT -#property indicator_width5 1 - -//--- Input Parameters --- -input int InpRsiPeriod = 13; -input int InpPriceLinePeriod = 2; -input int InpSignalLinePeriod = 7; -input int InpBaseLinePeriod = 34; -input double InpBandsDeviation = 1.618; -input ENUM_APPLIED_PRICE InpSourcePrice = PRICE_CLOSE; - -//--- Indicator Buffers --- -double BufferPriceLine[], BufferSignalLine[], BufferBaseLine[], BufferUpperBand[], BufferLowerBand[]; - -//--- Global calculator object --- -CTDICalculator *g_calculator; - -//+------------------------------------------------------------------+ -//| Custom indicator initialization function. | -//+------------------------------------------------------------------+ -int OnInit() - { - SetIndexBuffer(0, BufferPriceLine, INDICATOR_DATA); - SetIndexBuffer(1, BufferSignalLine, INDICATOR_DATA); - SetIndexBuffer(2, BufferBaseLine, INDICATOR_DATA); - SetIndexBuffer(3, BufferUpperBand, INDICATOR_DATA); - SetIndexBuffer(4, BufferLowerBand, INDICATOR_DATA); - - ArraySetAsSeries(BufferPriceLine, false); - ArraySetAsSeries(BufferSignalLine, false); - ArraySetAsSeries(BufferBaseLine, false); - ArraySetAsSeries(BufferUpperBand, false); - ArraySetAsSeries(BufferLowerBand, false); - - g_calculator = new CTDICalculator(); - if(CheckPointer(g_calculator) == POINTER_INVALID || - !g_calculator.Init(InpRsiPeriod, InpPriceLinePeriod, InpSignalLinePeriod, InpBaseLinePeriod, InpBandsDeviation)) - { - Print("Failed to initialize TDI Calculator."); - return(INIT_FAILED); - } - - int draw_begin = InpRsiPeriod + InpPriceLinePeriod + InpBaseLinePeriod; - for(int i=0; i<5; i++) - PlotIndexSetInteger(i, PLOT_DRAW_BEGIN, draw_begin); - - IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("TDI(%d)", InpRsiPeriod)); - - return(INIT_SUCCEEDED); - } - -//+------------------------------------------------------------------+ -//| Custom indicator deinitialization function. | -//+------------------------------------------------------------------+ -void OnDeinit(const int reason) - { - if(CheckPointer(g_calculator) != POINTER_INVALID) - delete g_calculator; - } - -//+------------------------------------------------------------------+ -//| Custom indicator iteration function. | -//+------------------------------------------------------------------+ -int OnCalculate(const int rates_total, const int, const datetime&[], const double &open[], const double &high[], const double &low[], const double &close[], const long&[], const long&[], const int&[]) - { - if(CheckPointer(g_calculator) != POINTER_INVALID) - { - g_calculator.Calculate(rates_total, InpSourcePrice, open, high, low, close, - BufferPriceLine, BufferSignalLine, BufferBaseLine, BufferUpperBand, BufferLowerBand); - } - return(rates_total); - } -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ diff --git a/Indicators/MyIndicators/TDI_HeikinAshi.mq5 b/Indicators/MyIndicators/TDI_HeikinAshi.mq5 deleted file mode 100644 index bf9acf4..0000000 --- a/Indicators/MyIndicators/TDI_HeikinAshi.mq5 +++ /dev/null @@ -1,119 +0,0 @@ -//+------------------------------------------------------------------+ -//| TDI_HeikinAshi.mq5 | -//| Copyright 2025, xxxxxxxx| -//| | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2025, xxxxxxxx" -#property version "1.00" -#property description "Trader's Dynamic Index (TDI) on Heikin Ashi data." - -#property indicator_separate_window -#property indicator_buffers 5 -#property indicator_plots 5 -#property indicator_minimum 0 -#property indicator_maximum 100 -#property indicator_level1 32.0 -#property indicator_level2 50.0 -#property indicator_level3 68.0 -#property indicator_levelstyle STYLE_DOT - -#include - -//--- Plot Properties (labels changed to HA) -#property indicator_label1 "Price Line (HA)" -#property indicator_type1 DRAW_LINE -#property indicator_color1 clrLimeGreen -#property indicator_style1 STYLE_SOLID -#property indicator_width1 2 -#property indicator_label2 "Signal Line (HA)" -#property indicator_type2 DRAW_LINE -#property indicator_color2 clrRed -#property indicator_style2 STYLE_SOLID -#property indicator_width2 1 -#property indicator_label3 "Base Line (HA)" -#property indicator_type3 DRAW_LINE -#property indicator_color3 clrGold -#property indicator_style3 STYLE_SOLID -#property indicator_width3 2 -#property indicator_label4 "Upper Band (HA)" -#property indicator_type4 DRAW_LINE -#property indicator_color4 clrDodgerBlue -#property indicator_style4 STYLE_DASHDOT -#property indicator_width4 1 -#property indicator_label5 "Lower Band (HA)" -#property indicator_type5 DRAW_LINE -#property indicator_color5 clrDodgerBlue -#property indicator_style5 STYLE_DASHDOT -#property indicator_width5 1 - -//--- Input Parameters --- -input int InpRsiPeriod = 13; -input int InpPriceLinePeriod = 2; -input int InpSignalLinePeriod = 7; -input int InpBaseLinePeriod = 34; -input double InpBandsDeviation = 1.618; - -//--- Indicator Buffers --- -double BufferPriceLine[], BufferSignalLine[], BufferBaseLine[], BufferUpperBand[], BufferLowerBand[]; - -//--- Global calculator object --- -CTDICalculator_HA *g_calculator; - -//+------------------------------------------------------------------+ -//| Custom indicator initialization function. | -//+------------------------------------------------------------------+ -int OnInit() - { - SetIndexBuffer(0, BufferPriceLine, INDICATOR_DATA); - SetIndexBuffer(1, BufferSignalLine, INDICATOR_DATA); - SetIndexBuffer(2, BufferBaseLine, INDICATOR_DATA); - SetIndexBuffer(3, BufferUpperBand, INDICATOR_DATA); - SetIndexBuffer(4, BufferLowerBand, INDICATOR_DATA); - - ArraySetAsSeries(BufferPriceLine, false); - ArraySetAsSeries(BufferSignalLine, false); - ArraySetAsSeries(BufferBaseLine, false); - ArraySetAsSeries(BufferUpperBand, false); - ArraySetAsSeries(BufferLowerBand, false); - - g_calculator = new CTDICalculator_HA(); - if(CheckPointer(g_calculator) == POINTER_INVALID || - !g_calculator.Init(InpRsiPeriod, InpPriceLinePeriod, InpSignalLinePeriod, InpBaseLinePeriod, InpBandsDeviation)) - { - Print("Failed to initialize TDI HA Calculator."); - return(INIT_FAILED); - } - - int draw_begin = InpRsiPeriod + InpPriceLinePeriod + InpBaseLinePeriod; - for(int i=0; i<5; i++) - PlotIndexSetInteger(i, PLOT_DRAW_BEGIN, draw_begin); - - IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("TDI_HA(%d)", InpRsiPeriod)); - - return(INIT_SUCCEEDED); - } - -//+------------------------------------------------------------------+ -//| Custom indicator deinitialization function. | -//+------------------------------------------------------------------+ -void OnDeinit(const int reason) - { - if(CheckPointer(g_calculator) != POINTER_INVALID) - delete g_calculator; - } - -//+------------------------------------------------------------------+ -//| Custom indicator iteration function. | -//+------------------------------------------------------------------+ -int OnCalculate(const int rates_total, const int, const datetime&[], const double &open[], const double &high[], const double &low[], const double &close[], const long&[], const long&[], const int&[]) - { - if(CheckPointer(g_calculator) != POINTER_INVALID) - { - //--- The price_type parameter is ignored by the HA calculator - g_calculator.Calculate(rates_total, PRICE_CLOSE, open, high, low, close, - BufferPriceLine, BufferSignalLine, BufferBaseLine, BufferUpperBand, BufferLowerBand); - } - return(rates_total); - } -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ diff --git a/Indicators/MyIndicators/TSI.md b/Indicators/MyIndicators/TSI.md deleted file mode 100644 index 2384c82..0000000 --- a/Indicators/MyIndicators/TSI.md +++ /dev/null @@ -1,82 +0,0 @@ -# True Strength Index (TSI) and TSI Oscillator - -## 1. Summary (Introduction) - -The True Strength Index (TSI) is a momentum oscillator developed by William Blau. It was designed to provide a smoother and more reliable measure of market momentum by using a double-smoothing mechanism with Exponential Moving Averages (EMAs). The TSI fluctuates around a zero line, providing clear signals for trend direction, momentum, and overbought/oversold conditions. - -The **TSI Oscillator** is a supplementary indicator that displays the difference between the TSI line and its signal line as a histogram. It provides a clearer visual representation of the accelerating and decelerating momentum, similar to the MACD histogram. - -## 2. Mathematical Foundations and Calculation Logic - -The TSI is calculated by double-smoothing both the price momentum and the absolute price momentum, and then computing their ratio. - -### Required Components - -- **Slow Period (N_slow):** The period for the first, longer-term EMA smoothing (standard is 25). -- **Fast Period (N_fast):** The period for the second, shorter-term EMA smoothing (standard is 13). -- **Signal Period:** The period for the moving average signal line (standard is 13). -- **Source Price (P):** The price series used for the calculation (e.g., Close). - -### Calculation Steps (Algorithm) - -1. **Calculate Price Momentum (Change):** For each bar, calculate the change in price from the previous bar. - $\text{Momentum}_i = P_i - P_{i-1}$ - -2. **First EMA Smoothing (Slow Period):** Apply an `N_slow`-period EMA to both the `Momentum` and its absolute value. - $\text{EMA}_{\text{slow}}(\text{Momentum})_i = \text{EMA}(\text{Momentum}, N_{\text{slow}})_i$ - $\text{EMA}_{\text{slow}}(\text{AbsMomentum})_i = \text{EMA}(\text{Abs}(\text{Momentum}), N_{\text{slow}})_i$ - -3. **Second EMA Smoothing (Fast Period):** Apply an `N_fast`-period EMA to the results of the first smoothing step. - $\text{EMA}_{\text{fast}}(\text{EMA}_{\text{slow}}(\text{Momentum}))_i = \text{EMA}(\text{EMA}_{\text{slow}}(\text{Momentum}), N_{\text{fast}})_i$ - $\text{EMA}_{\text{fast}}(\text{EMA}_{\text{slow}}(\text{AbsMomentum}))_i = \text{EMA}(\text{EMA}_{\text{slow}}(\text{AbsMomentum}), N_{\text{fast}})_i$ - -4. **Calculate the TSI Value:** Divide the double-smoothed momentum by the double-smoothed absolute momentum and scale the result to 100. This creates the main TSI line. - $\text{TSI}_i = 100 \times \frac{\text{EMA}_{\text{fast}}(\text{EMA}_{\text{slow}}(\text{Momentum}))_i}{\text{EMA}_{\text{fast}}(\text{EMA}_{\text{slow}}(\text{AbsMomentum}))_i}$ - -5. **Calculate the Signal Line:** The signal line is a moving average of the TSI line itself. - $\text{Signal}_i = \text{MA}(\text{TSI}, \text{Signal Period})_i$ - -6. **Calculate the TSI Oscillator:** The oscillator is the difference between the TSI line and its Signal Line. - $\text{Oscillator}_i = \text{TSI}_i - \text{Signal}_i$ - -## 3. MQL5 Implementation Details - -Our MQL5 implementations are self-contained, robust, and accurate representations of the classic, double-smoothed TSI and its oscillator. - -- **Stability via Full Recalculation:** We employ a "brute-force" full recalculation within the `OnCalculate` function for maximum stability. - -- **Correct Algorithm:** Our implementation strictly follows the correct, textbook definition of the TSI, ensuring its results are consistent with other professional charting platforms like TradingView. - -- **Fully Manual EMA Calculations:** All EMA calculations are performed **manually**. Each recursive EMA calculation is carefully initialized with a **manual Simple Moving Average (SMA)** to provide a stable starting point for the calculation chain and to prevent floating-point overflows. - -- **Clear, Staged Calculation:** The `OnCalculate` function is structured into clear, sequential steps, each handled by a dedicated `for` loop, making the complex, multi-stage logic easy to follow. - -- **Flexible Signal Line:** The `TSI.mq5` indicator includes a user-configurable moving average signal line, with a robust `switch` block that correctly handles all MA types (SMA, EMA, SMMA, LWMA). - -- **Heikin Ashi Variants:** - - Both the `TSI.mq5` and `TSI_Oscillator.mq5` have "pure" Heikin Ashi counterparts. The calculation logic is identical, but they use the smoothed Heikin Ashi price data as their input for the initial momentum calculation. This results in exceptionally smooth oscillators. - -## 4. Parameters - -- **Slow Period (`InpSlowPeriod`):** The period for the first, longer-term EMA smoothing. **Default is 25.** -- **Fast Period (`InpFastPeriod`):** The period for the second, shorter-term EMA smoothing. **Default is 13.** -- **Applied Price (`InpAppliedPrice`):** The source price used for the calculation. Default is `PRICE_CLOSE`. -- **Signal Line Settings:** - - `InpSignalPeriod`: The lookback period for the signal line. **Default is 13.** - - `InpSignalMAType`: The type of moving average for the signal line. Default is `MODE_EMA`. - -## 5. Usage and Interpretation - -- **Zero Line Crossovers:** This is a primary trend signal. - - **Bullish:** A crossover of the TSI line above the zero line indicates that long-term momentum has turned positive. - - **Bearish:** A crossover below the zero line indicates that long-term momentum has turned negative. -- **Signal Line Crossovers:** These provide earlier, shorter-term momentum signals. - - **Bullish:** The TSI line crosses above its signal line. - - **Bearish:** The TSI line crosses below its signal line. -- **Overbought/Oversold Levels:** The **+25 and -25** levels are often used to identify extreme momentum. -- **Divergence:** Due to its smoothness, the TSI is excellent for spotting divergences between price and momentum, which can foreshadow reversals. -- **TSI Oscillator:** The histogram provides a clear visual of the relationship between the TSI and its signal line. - - **Histogram > 0:** The TSI is above its signal line (bullish momentum). - - **Histogram < 0:** The TSI is below its signal line (bearish momentum). - - **Growing Histogram:** Momentum is accelerating in the current direction. - - **Shrinking Histogram:** Momentum is decelerating, which can be an early warning of a potential crossover. diff --git a/Indicators/MyIndicators/TSI.mq5 b/Indicators/MyIndicators/TSI.mq5 deleted file mode 100644 index bd128ad..0000000 --- a/Indicators/MyIndicators/TSI.mq5 +++ /dev/null @@ -1,241 +0,0 @@ -//+------------------------------------------------------------------+ -//| TSI.mq5 | -//| Copyright 2025, xxxxxxxx | -//| | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2025, xxxxxxxx" -#property link "" -#property version "1.00" -#property description "True Strength Index (TSI) with a signal line." - -//--- Indicator Window and Plot Properties --- -#property indicator_separate_window -#property indicator_buffers 2 // TSI and Signal Line -#property indicator_plots 2 - -//--- Plot 1: TSI Line -#property indicator_label1 "TSI" -#property indicator_type1 DRAW_LINE -#property indicator_color1 clrDodgerBlue -#property indicator_style1 STYLE_SOLID -#property indicator_width1 1 - -//--- Plot 2: Signal Line -#property indicator_label2 "Signal" -#property indicator_type2 DRAW_LINE -#property indicator_color2 clrOrangeRed -#property indicator_style2 STYLE_DOT -#property indicator_width2 1 - -#property indicator_level1 -25.0 -#property indicator_level2 25.0 -#property indicator_level3 0.0 -#property indicator_levelstyle STYLE_DOT - -//--- Input Parameters --- -input int InpSlowPeriod = 25; // Long Length (1st smoothing) -input int InpFastPeriod = 13; // Short Length (2nd smoothing) -input ENUM_APPLIED_PRICE InpAppliedPrice = PRICE_CLOSE; // Applied Price -input group "Signal Line Settings" -input int InpSignalPeriod = 13; // Signal Line Period -input ENUM_MA_METHOD InpSignalMAType = MODE_EMA; // Signal Line MA Type - -//--- Indicator Buffers --- -double BufferTSI[]; -double BufferSignal[]; - -//--- Global Variables --- -int g_ExtSlowPeriod, g_ExtFastPeriod, g_ExtSignalPeriod; - -//+------------------------------------------------------------------+ -//| Custom indicator initialization function. | -//+------------------------------------------------------------------+ -int OnInit() - { - g_ExtSlowPeriod = (InpSlowPeriod < 1) ? 1 : InpSlowPeriod; - g_ExtFastPeriod = (InpFastPeriod < 1) ? 1 : InpFastPeriod; - g_ExtSignalPeriod = (InpSignalPeriod < 1) ? 1 : InpSignalPeriod; - - SetIndexBuffer(0, BufferTSI, INDICATOR_DATA); - SetIndexBuffer(1, BufferSignal, INDICATOR_DATA); - - ArraySetAsSeries(BufferTSI, false); - ArraySetAsSeries(BufferSignal, false); - - int tsi_draw_begin = g_ExtSlowPeriod + g_ExtFastPeriod; - PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, tsi_draw_begin); - PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, tsi_draw_begin + g_ExtSignalPeriod - 1); - IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("TSI(%d,%d,%d)", g_ExtSlowPeriod, g_ExtFastPeriod, g_ExtSignalPeriod)); - IndicatorSetInteger(INDICATOR_DIGITS, 2); - - return(INIT_SUCCEEDED); - } - -//+------------------------------------------------------------------+ -//| True Strength Index calculation function. | -//+------------------------------------------------------------------+ -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 start_pos = g_ExtSlowPeriod + g_ExtFastPeriod + g_ExtSignalPeriod; - if(rates_total <= start_pos) - return(0); - -//--- STEP 1: Prepare the source price array - double price_source[]; - ArrayResize(price_source, rates_total); - for(int i=0; i 0) - { - BufferTSI[i] = 100 * (ema2_momentum[i] / ema2_abs_momentum[i]); - } - } - -//--- STEP 6: Calculate the Signal Line - int signal_start_pos = ema2_start_pos + g_ExtSignalPeriod - 1; - for(int i = signal_start_pos; i < rates_total; i++) - { - // --- FIX: Full, robust switch block for all MA types --- - switch(InpSignalMAType) - { - case MODE_EMA: - case MODE_SMMA: - if(i == signal_start_pos) - { - double sum=0; - for(int j=0; j0) - BufferSignal[i]=lwma_sum/weight_sum; - } - break; - default: // MODE_SMA - { - double sum=0; - for(int j=0; j - -//--- Indicator Window and Plot Properties --- -#property indicator_separate_window -#property indicator_buffers 2 // TSI and Signal Line -#property indicator_plots 2 -#property indicator_type1 DRAW_LINE -#property indicator_color1 clrDodgerBlue -#property indicator_label1 "HA_TSI" -#property indicator_type2 DRAW_LINE -#property indicator_color2 clrOrangeRed -#property indicator_label2 "HA_Signal" -#property indicator_style2 STYLE_DOT -#property indicator_level1 -25.0 -#property indicator_level2 25.0 -#property indicator_level3 0.0 -#property indicator_levelstyle STYLE_DOT - -//--- Enum for selecting Heikin Ashi price source --- -enum ENUM_HA_APPLIED_PRICE - { - HA_PRICE_CLOSE, HA_PRICE_OPEN, HA_PRICE_HIGH, HA_PRICE_LOW - }; - -//--- Input Parameters --- -input int InpSlowPeriod = 25; -input int InpFastPeriod = 13; -input ENUM_HA_APPLIED_PRICE InpAppliedPrice = HA_PRICE_CLOSE; -input group "Signal Line Settings" -input int InpSignalPeriod = 13; -input ENUM_MA_METHOD InpSignalMAType = MODE_EMA; - -//--- Indicator Buffers --- -double BufferTSI[]; -double BufferSignal[]; - -//--- Global Objects and Variables --- -int g_ExtSlowPeriod, g_ExtFastPeriod, g_ExtSignalPeriod; -CHeikinAshi_Calculator *g_ha_calculator; - -//+------------------------------------------------------------------+ -//| Custom indicator initialization function. | -//+------------------------------------------------------------------+ -int OnInit() - { - g_ExtSlowPeriod = (InpSlowPeriod < 1) ? 1 : InpSlowPeriod; - g_ExtFastPeriod = (InpFastPeriod < 1) ? 1 : InpFastPeriod; - g_ExtSignalPeriod = (InpSignalPeriod < 1) ? 1 : InpSignalPeriod; - - SetIndexBuffer(0, BufferTSI, INDICATOR_DATA); - SetIndexBuffer(1, BufferSignal, INDICATOR_DATA); - - ArraySetAsSeries(BufferTSI, false); - ArraySetAsSeries(BufferSignal, false); - - int tsi_draw_begin = g_ExtSlowPeriod + g_ExtFastPeriod; - PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, tsi_draw_begin); - PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, tsi_draw_begin + g_ExtSignalPeriod - 1); - IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("HA_TSI(%d,%d,%d)", g_ExtSlowPeriod, g_ExtFastPeriod, g_ExtSignalPeriod)); - IndicatorSetInteger(INDICATOR_DIGITS, 2); - - g_ha_calculator = new CHeikinAshi_Calculator(); - if(CheckPointer(g_ha_calculator) == POINTER_INVALID) - { - Print("Error creating CHeikinAshi_Calculator object"); - return(INIT_FAILED); - } - return(INIT_SUCCEEDED); - } - -//+------------------------------------------------------------------+ -//| Custom indicator deinitialization function. | -//+------------------------------------------------------------------+ -void OnDeinit(const int reason) - { - if(CheckPointer(g_ha_calculator) != POINTER_INVALID) - { - delete g_ha_calculator; - g_ha_calculator = NULL; - } - } - -//+------------------------------------------------------------------+ -//| TSI on Heikin Ashi calculation function. | -//+------------------------------------------------------------------+ -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 start_pos = g_ExtSlowPeriod + g_ExtFastPeriod + g_ExtSignalPeriod; - if(rates_total <= start_pos) - return(0); - -//--- Intermediate Heikin Ashi Buffers - double ha_open[], ha_high[], ha_low[], ha_close[]; - ArrayResize(ha_open, rates_total); - ArrayResize(ha_high, rates_total); - ArrayResize(ha_low, rates_total); - ArrayResize(ha_close, rates_total); - -//--- STEP 1: Calculate Heikin Ashi bars - g_ha_calculator.Calculate(rates_total, open, high, low, close, ha_open, ha_high, ha_low, ha_close); - -//--- STEP 2: Prepare the Heikin Ashi source price array - double ha_price_source[]; - ArrayResize(ha_price_source, rates_total); - switch(InpAppliedPrice) - { - case HA_PRICE_OPEN: - ArrayCopy(ha_price_source, ha_open); - break; - case HA_PRICE_HIGH: - ArrayCopy(ha_price_source, ha_high); - break; - case HA_PRICE_LOW: - ArrayCopy(ha_price_source, ha_low); - break; - default: - ArrayCopy(ha_price_source, ha_close); - break; - } - -//--- STEP 3: Calculate Momentum and its Absolute Value on HA data - double momentum[], abs_momentum[]; - ArrayResize(momentum, rates_total); - ArrayResize(abs_momentum, rates_total); - for(int i=1; i 0) - { - BufferTSI[i] = 100 * (ema2_momentum[i] / ema2_abs_momentum[i]); - } - } - -//--- STEP 7: Calculate the Signal Line - int signal_start_pos = ema2_start_pos + g_ExtSignalPeriod - 1; - for(int i = signal_start_pos; i < rates_total; i++) - { - // --- FIX: Full, robust switch block for all MA types --- - switch(InpSignalMAType) - { - case MODE_EMA: - case MODE_SMMA: - if(i == signal_start_pos) - { - double sum=0; - for(int j=0; j0) - BufferSignal[i]=lwma_sum/weight_sum; - } - break; - default: // MODE_SMA - { - double sum=0; - for(int j=0; j 0) - { - buffer_tsi[i] = 100 * (ema2_momentum[i] / ema2_abs_momentum[i]); - } - } - -//--- STEP 6: Calculate the Signal Line (internal buffer) - double buffer_signal[]; - ArrayResize(buffer_signal, rates_total); - int signal_start_pos = ema2_start_pos + g_ExtSignalPeriod - 1; - for(int i = signal_start_pos; i < rates_total; i++) - { - // --- FIX: Full, robust switch block for all MA types --- - switch(InpSignalMAType) - { - case MODE_EMA: - case MODE_SMMA: - if(i == signal_start_pos) - { - double sum=0; - for(int j=0; j0) - buffer_signal[i]=lwma_sum/weight_sum; - } - break; - default: // MODE_SMA - { - double sum=0; - for(int j=0; j - -//--- Indicator Window and Plot Properties --- -#property indicator_separate_window -#property indicator_buffers 1 -#property indicator_plots 1 -#property indicator_type1 DRAW_HISTOGRAM -#property indicator_color1 clrSilver -#property indicator_width1 1 -#property indicator_label1 "HA_TSI_Osc" -#property indicator_level1 0.0 -#property indicator_levelstyle STYLE_DOT - -//--- Enum for selecting Heikin Ashi price source --- -enum ENUM_HA_APPLIED_PRICE - { - HA_PRICE_CLOSE, HA_PRICE_OPEN, HA_PRICE_HIGH, HA_PRICE_LOW - }; - -//--- Input Parameters --- -input int InpSlowPeriod = 25; -input int InpFastPeriod = 13; -input ENUM_HA_APPLIED_PRICE InpAppliedPrice = HA_PRICE_CLOSE; -input group "Signal Line Settings" -input int InpSignalPeriod = 13; -input ENUM_MA_METHOD InpSignalMAType = MODE_EMA; - -//--- Indicator Buffers --- -double BufferOscillator[]; - -//--- Global Objects and Variables --- -int g_ExtSlowPeriod, g_ExtFastPeriod, g_ExtSignalPeriod; -CHeikinAshi_Calculator *g_ha_calculator; - -//+------------------------------------------------------------------+ -//| Custom indicator initialization function. | -//+------------------------------------------------------------------+ -int OnInit() - { - g_ExtSlowPeriod = (InpSlowPeriod < 1) ? 1 : InpSlowPeriod; - g_ExtFastPeriod = (InpFastPeriod < 1) ? 1 : InpFastPeriod; - g_ExtSignalPeriod = (InpSignalPeriod < 1) ? 1 : InpSignalPeriod; - - SetIndexBuffer(0, BufferOscillator, INDICATOR_DATA); - ArraySetAsSeries(BufferOscillator, false); - - int draw_begin = g_ExtSlowPeriod + g_ExtFastPeriod + g_ExtSignalPeriod - 1; - PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, draw_begin); - IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("HA_TSI_Osc(%d,%d,%d)", g_ExtSlowPeriod, g_ExtFastPeriod, g_ExtSignalPeriod)); - IndicatorSetInteger(INDICATOR_DIGITS, 2); - - g_ha_calculator = new CHeikinAshi_Calculator(); - if(CheckPointer(g_ha_calculator) == POINTER_INVALID) - { - Print("Error creating CHeikinAshi_Calculator object"); - return(INIT_FAILED); - } - return(INIT_SUCCEEDED); - } - -//+------------------------------------------------------------------+ -//| Custom indicator deinitialization function. | -//+------------------------------------------------------------------+ -void OnDeinit(const int reason) - { - if(CheckPointer(g_ha_calculator) != POINTER_INVALID) - { - delete g_ha_calculator; - g_ha_calculator = NULL; - } - } - -//+------------------------------------------------------------------+ -//| TSI Oscillator on Heikin Ashi calculation function. | -//+------------------------------------------------------------------+ -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 start_pos = g_ExtSlowPeriod + g_ExtFastPeriod + g_ExtSignalPeriod - 1; - if(rates_total <= start_pos) - return(0); - -//--- Intermediate Heikin Ashi Buffers - double ha_open[], ha_high[], ha_low[], ha_close[]; - ArrayResize(ha_open, rates_total); - ArrayResize(ha_high, rates_total); - ArrayResize(ha_low, rates_total); - ArrayResize(ha_close, rates_total); - -//--- STEP 1: Calculate Heikin Ashi bars - g_ha_calculator.Calculate(rates_total, open, high, low, close, ha_open, ha_high, ha_low, ha_close); - -//--- STEP 2: Prepare the Heikin Ashi source price array - double ha_price_source[]; - ArrayResize(ha_price_source, rates_total); - switch(InpAppliedPrice) - { - case HA_PRICE_OPEN: - ArrayCopy(ha_price_source, ha_open); - break; - case HA_PRICE_HIGH: - ArrayCopy(ha_price_source, ha_high); - break; - case HA_PRICE_LOW: - ArrayCopy(ha_price_source, ha_low); - break; - default: - ArrayCopy(ha_price_source, ha_close); - break; - } - -//--- STEP 3: Calculate Momentum and its Absolute Value on HA data - double momentum[], abs_momentum[]; - ArrayResize(momentum, rates_total); - ArrayResize(abs_momentum, rates_total); - for(int i=1; i 0) - { - buffer_tsi[i] = 100 * (ema2_momentum[i] / ema2_abs_momentum[i]); - } - } - -//--- STEP 7: Calculate the Signal Line (internal buffer) - double buffer_signal[]; - ArrayResize(buffer_signal, rates_total); - int signal_start_pos = ema2_start_pos + g_ExtSignalPeriod - 1; - for(int i = signal_start_pos; i < rates_total; i++) - { - // --- FIX: Full, robust switch block for all MA types --- - switch(InpSignalMAType) - { - case MODE_EMA: - case MODE_SMMA: - if(i == signal_start_pos) - { - double sum=0; - for(int j=0; j0) - buffer_signal[i]=lwma_sum/weight_sum; - } - break; - default: // MODE_SMA - { - double sum=0; - for(int j=0; j g_ExtPeriod1) - { - sum_bp1 -= bp[i - g_ExtPeriod1]; - sum_tr1 -= tr[i - g_ExtPeriod1]; - } - if(i > g_ExtPeriod2) - { - sum_bp2 -= bp[i - g_ExtPeriod2]; - sum_tr2 -= tr[i - g_ExtPeriod2]; - } - if(i > g_ExtPeriod3) - { - sum_bp3 -= bp[i - g_ExtPeriod3]; - sum_tr3 -= tr[i - g_ExtPeriod3]; - } - - if(i >= g_ExtPeriod3) - { - double avg1 = (sum_tr1 > 0) ? sum_bp1 / sum_tr1 : 0; - double avg2 = (sum_tr2 > 0) ? sum_bp2 / sum_tr2 : 0; - double avg3 = (sum_tr3 > 0) ? sum_bp3 / sum_tr3 : 0; - - BufferUO[i] = 100.0 * (WEIGHT_1 * avg1 + WEIGHT_2 * avg2 + WEIGHT_3 * avg3) / TOTAL_WEIGHT; - } - } - - return(rates_total); - } -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ diff --git a/Indicators/MyIndicators/Ultimate_Oscillator_HeikinAshi.mq5 b/Indicators/MyIndicators/Ultimate_Oscillator_HeikinAshi.mq5 deleted file mode 100644 index 64c3506..0000000 --- a/Indicators/MyIndicators/Ultimate_Oscillator_HeikinAshi.mq5 +++ /dev/null @@ -1,161 +0,0 @@ -//+------------------------------------------------------------------+ -//| Ultimate_Oscillator_HeikinAshi.mq5 | -//| Copyright 2025, xxxxxxxx | -//| | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2025, xxxxxxxx" -#property link "" -#property version "1.00" -#property description "Ultimate Oscillator on Heikin Ashi data" - -#include - -//--- Indicator Window and Plot Properties --- -#property indicator_separate_window -#property indicator_buffers 1 -#property indicator_plots 1 -#property indicator_type1 DRAW_LINE -#property indicator_color1 clrDodgerBlue -#property indicator_label1 "HA_UO" -#property indicator_maximum 100.0 -#property indicator_minimum 0.0 -#property indicator_level1 30.0 -#property indicator_level2 50.0 -#property indicator_level3 70.0 -#property indicator_levelstyle STYLE_DOT - -//--- Input Parameters --- -input int InpPeriod1 = 7; // Fast Period -input int InpPeriod2 = 14; // Middle Period -input int InpPeriod3 = 28; // Slow Period - -//--- Indicator Buffers --- -double BufferUO[]; - -//--- Global Objects and Variables --- -int g_ExtPeriod1, g_ExtPeriod2, g_ExtPeriod3; -const double WEIGHT_1 = 4.0; -const double WEIGHT_2 = 2.0; -const double WEIGHT_3 = 1.0; -const double TOTAL_WEIGHT = WEIGHT_1 + WEIGHT_2 + WEIGHT_3; -CHeikinAshi_Calculator *g_ha_calculator; - -//+------------------------------------------------------------------+ -//| Custom indicator initialization function. | -//+------------------------------------------------------------------+ -int OnInit() - { - g_ExtPeriod1 = (InpPeriod1 < 1) ? 1 : InpPeriod1; - g_ExtPeriod2 = (InpPeriod2 < 1) ? 1 : InpPeriod2; - g_ExtPeriod3 = (InpPeriod3 < 1) ? 1 : InpPeriod3; - - SetIndexBuffer(0, BufferUO, INDICATOR_DATA); - ArraySetAsSeries(BufferUO, false); - - PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, g_ExtPeriod3); - IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("HA_UO(%d,%d,%d)", g_ExtPeriod1, g_ExtPeriod2, g_ExtPeriod3)); - IndicatorSetInteger(INDICATOR_DIGITS, 2); - - g_ha_calculator = new CHeikinAshi_Calculator(); - if(CheckPointer(g_ha_calculator) == POINTER_INVALID) - { - Print("Error creating CHeikinAshi_Calculator object"); - return(INIT_FAILED); - } - return(INIT_SUCCEEDED); - } - -//+------------------------------------------------------------------+ -//| Custom indicator deinitialization function. | -//+------------------------------------------------------------------+ -void OnDeinit(const int reason) - { - if(CheckPointer(g_ha_calculator) != POINTER_INVALID) - { - delete g_ha_calculator; - g_ha_calculator = NULL; - } - } - -//+------------------------------------------------------------------+ -//| Ultimate Oscillator on Heikin Ashi calculation function. | -//+------------------------------------------------------------------+ -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 <= g_ExtPeriod3) - return(0); - -//--- Intermediate Heikin Ashi Buffers - double ha_open[], ha_high[], ha_low[], ha_close[]; - ArrayResize(ha_open, rates_total); - ArrayResize(ha_high, rates_total); - ArrayResize(ha_low, rates_total); - ArrayResize(ha_close, rates_total); - -//--- STEP 1: Calculate Heikin Ashi bars - g_ha_calculator.Calculate(rates_total, open, high, low, close, ha_open, ha_high, ha_low, ha_close); - -//--- STEP 2, 3: Calculate BP and TR on HA data - double bp[], tr[]; - ArrayResize(bp, rates_total); - ArrayResize(tr, rates_total); - for(int i=1; i g_ExtPeriod1) - { - sum_bp1 -= bp[i - g_ExtPeriod1]; - sum_tr1 -= tr[i - g_ExtPeriod1]; - } - if(i > g_ExtPeriod2) - { - sum_bp2 -= bp[i - g_ExtPeriod2]; - sum_tr2 -= tr[i - g_ExtPeriod2]; - } - if(i > g_ExtPeriod3) - { - sum_bp3 -= bp[i - g_ExtPeriod3]; - sum_tr3 -= tr[i - g_ExtPeriod3]; - } - - if(i >= g_ExtPeriod3) - { - double avg1 = (sum_tr1 > 0) ? sum_bp1 / sum_tr1 : 0; - double avg2 = (sum_tr2 > 0) ? sum_bp2 / sum_tr2 : 0; - double avg3 = (sum_tr3 > 0) ? sum_bp3 / sum_tr3 : 0; - - BufferUO[i] = 100.0 * (WEIGHT_1 * avg1 + WEIGHT_2 * avg2 + WEIGHT_3 * avg3) / TOTAL_WEIGHT; - } - } - - return(rates_total); - } -//+------------------------------------------------------------------+``` -//+------------------------------------------------------------------+ diff --git a/Indicators/MyIndicators/VIDYA.md b/Indicators/MyIndicators/VIDYA.md deleted file mode 100644 index 93c962e..0000000 --- a/Indicators/MyIndicators/VIDYA.md +++ /dev/null @@ -1,65 +0,0 @@ -# Variable Index Dynamic Average (VIDYA) - -## 1. Summary (Introduction) - -The Variable Index Dynamic Average (VIDYA) is an adaptive moving average developed by Tushar Chande. It was designed to automatically adjust its smoothing speed based on market momentum, making it more responsive in trending markets and smoother in sideways markets. - -Unlike a standard Exponential Moving Average (EMA) which uses a fixed smoothing constant, VIDYA uses the Chande Momentum Oscillator (CMO) to dynamically alter this constant. When momentum is high, VIDYA speeds up and hugs the price more closely. When momentum wanes, it slows down, filtering out more noise. - -## 2. Mathematical Foundations and Calculation Logic - -VIDYA is a modified Exponential Moving Average where the smoothing factor is multiplied by the absolute value of the Chande Momentum Oscillator (CMO). - -### Required Components - -- **EMA Period (N):** The base period for the EMA smoothing calculation. -- **CMO Period (M):** The lookback period for the Chande Momentum Oscillator. -- **Source Price (P):** The price series used for the calculation (e.g., Close). - -### Calculation Steps (Algorithm) - -1. **Calculate the Chande Momentum Oscillator (CMO):** The CMO measures momentum by summing up positive and negative price changes over a period `M`. - $\text{Sum Up}_i = \sum \text{Positive Changes over M periods}$ - $\text{Sum Down}_i = \sum \text{Negative Changes over M periods}$ - $\text{CMO}_i = \frac{\text{Sum Up}_i - \text{Sum Down}_i}{\text{Sum Up}_i + \text{Sum Down}_i}$ - The CMO oscillates between -1 and +1. - -2. **Calculate the VIDYA:** The VIDYA is calculated recursively, similar to an EMA. - - First, define the standard EMA smoothing factor, `alpha`: - $\alpha = \frac{2}{N + 1}$ - - Then, calculate the VIDYA for each bar: - $\text{VIDYA}_i = (P_i \times \alpha \times \text{Abs}(\text{CMO}_i)) + (\text{VIDYA}_{i-1} \times (1 - \alpha \times \text{Abs}(\text{CMO}_i)))$ - -The key is the `alpha * Abs(CMO)` term. When momentum is high, `Abs(CMO)` is close to 1, and VIDYA behaves like a standard EMA. When momentum is low, `Abs(CMO)` is close to 0, which dramatically increases the smoothing and makes the VIDYA line flatten out. - -## 3. MQL5 Implementation Details - -Our MQL5 implementation was refactored to be a completely self-contained, robust, and accurate indicator. - -- **Stability via Full Recalculation:** We employ a "brute-force" full recalculation within the `OnCalculate` function. This is our standard practice for indicators with recursive logic to ensure maximum stability. - -- **Robust Initialization:** The recursive VIDYA calculation is carefully initialized to prevent floating-point overflows. The **first valid value** of the VIDYA line is calculated using a **manual Simple Moving Average (SMA)** on the source price data. This provides a stable starting point for all subsequent recursive calculations. - -- **Self-Contained Logic:** The indicator is completely self-contained. It does not use external handles. The source price is prepared internally using a `switch` block that handles all `ENUM_APPLIED_PRICE` types, and the CMO is calculated via a dedicated helper function. - -- **Clear, Staged Calculation:** The `OnCalculate` function is structured into clear, sequential steps: - - 1. **Step 1:** A `price_source[]` array is prepared based on the user's input. - 2. **Step 2:** A single, efficient `for` loop handles the entire VIDYA calculation, including the robust initialization step and the subsequent recursive calculations. - -- **Heikin Ashi Variant (`VIDYA_HeikinAshi.mq5`):** - - Our toolkit also includes a "pure" Heikin Ashi version. The calculation logic is identical, but it uses the smoothed Heikin Ashi price data as the input for both the VIDYA and the underlying CMO calculation. - - **Behavioral Note:** This version can appear _more responsive_ than the standard version in strong trends. This is because the smoothed Heikin Ashi data produces a very clean, high-momentum signal for the CMO, causing the `Abs(CMO)` value to stay near 1. This keeps the VIDYA at maximum speed, allowing it to closely track the already-smoothed Heikin Ashi trend. - -## 4. Parameters - -- **CMO Period (`InpPeriodCMO`):** The lookback period for the Chande Momentum Oscillator, which determines the sensitivity of the speed adjustment. Default is `9`. -- **EMA Period (`InpPeriodEMA`):** The base period for the EMA smoothing. This defines the "slowest" speed of the indicator when momentum is high. Default is `12`. -- **Applied Price (`InpAppliedPrice`):** The source price used for the calculation (e.g., `PRICE_CLOSE`). - -## 5. Usage and Interpretation - -- **Trend Identification:** VIDYA is used as an adaptive trend line. When the price is above the VIDYA and the line is rising, the trend is bullish. When the price is below the line and it is falling, the trend is bearish. -- **Crossover Signals:** Crossovers of the price and the VIDYA line can be used as trade signals. Because it adapts its speed, these signals can be faster than a standard EMA in trending markets and less frequent in ranging markets. -- **Trend Filter:** The key advantage of VIDYA is its ability to flatten out during periods of low momentum (sideways markets). A flat VIDYA line is a clear signal to avoid trend-following strategies. When the line begins to angle up or down sharply, it indicates that momentum is returning to the market. -- **Caution:** While adaptive, VIDYA is still a lagging indicator. It is a tool for trend confirmation and filtering, not for precise market timing. diff --git a/Indicators/MyIndicators/VIDYA.mq5 b/Indicators/MyIndicators/VIDYA.mq5 deleted file mode 100644 index 8e8d96f..0000000 --- a/Indicators/MyIndicators/VIDYA.mq5 +++ /dev/null @@ -1,158 +0,0 @@ -//+------------------------------------------------------------------+ -//| VIDYA.mq5 | -//| Copyright 2025, xxxxxxxx | -//| | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2025, xxxxxxxx" -#property link "" -#property version "1.00" -#property description "Variable Index Dynamic Average by Tushar Chande" - -//--- Indicator Window and Plot Properties --- -#property indicator_chart_window -#property indicator_buffers 1 -#property indicator_plots 1 -#property indicator_type1 DRAW_LINE -#property indicator_color1 clrRed -#property indicator_style1 STYLE_SOLID -#property indicator_width1 1 -#property indicator_label1 "VIDYA" - -//--- Input Parameters --- -input int InpPeriodCMO = 9; // Chande Momentum Oscillator Period -input int InpPeriodEMA = 12; // EMA Period for smoothing -input ENUM_APPLIED_PRICE InpAppliedPrice = PRICE_CLOSE; // Applied Price - -//--- Indicator Buffers --- -double BufferVIDYA[]; - -//--- Global Variables --- -int g_ExtPeriodCMO; -int g_ExtPeriodEMA; - -//--- Forward declarations --- -double CalculateCMO(int position, int period, const double &price_array[]); - -//+------------------------------------------------------------------+ -//| Custom indicator initialization function. | -//+------------------------------------------------------------------+ -int OnInit() - { - g_ExtPeriodCMO = (InpPeriodCMO < 1) ? 1 : InpPeriodCMO; - g_ExtPeriodEMA = (InpPeriodEMA < 1) ? 1 : InpPeriodEMA; - - SetIndexBuffer(0, BufferVIDYA, INDICATOR_DATA); - ArraySetAsSeries(BufferVIDYA, false); - - int draw_begin = g_ExtPeriodCMO + g_ExtPeriodEMA; - PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, draw_begin); - IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("VIDYA(%d,%d)", g_ExtPeriodCMO, g_ExtPeriodEMA)); - IndicatorSetInteger(INDICATOR_DIGITS, _Digits); - - return(INIT_SUCCEEDED); - } - -//+------------------------------------------------------------------+ -//| Variable Index Dynamic Average calculation function. | -//+------------------------------------------------------------------+ -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 start_pos = g_ExtPeriodCMO + g_ExtPeriodEMA; - if(rates_total <= start_pos) - return(0); - -//--- STEP 1: Prepare the source price array - double price_source[]; - ArrayResize(price_source, rates_total); - for(int i=0; i start_pos) - { - // --- Recursive Calculation Step --- - double cmo = MathAbs(CalculateCMO(i, g_ExtPeriodCMO, price_source)); - BufferVIDYA[i] = price_source[i] * alpha * cmo + BufferVIDYA[i-1] * (1 - alpha * cmo); - } - } - - return(rates_total); - } - -//+------------------------------------------------------------------+ -//| Calculates Chande Momentum Oscillator (CMO) for a given position | -//+------------------------------------------------------------------+ -double CalculateCMO(int position, int period, const double &price_array[]) - { - if(position < period) - return 0.0; - - double sum_up = 0.0; - double sum_down = 0.0; - - for(int i = 0; i < period; i++) - { - double diff = price_array[position - i] - price_array[position - i - 1]; - if(diff > 0.0) - sum_up += diff; - else - sum_down += (-diff); - } - - if(sum_up + sum_down == 0.0) - return 0.0; - - return (sum_up - sum_down) / (sum_up + sum_down); - } -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ diff --git a/Indicators/MyIndicators/VIDYA_HeikinAshi.mq5 b/Indicators/MyIndicators/VIDYA_HeikinAshi.mq5 deleted file mode 100644 index 2b26aeb..0000000 --- a/Indicators/MyIndicators/VIDYA_HeikinAshi.mq5 +++ /dev/null @@ -1,187 +0,0 @@ -//+------------------------------------------------------------------+ -//| VIDYA_HeikinAshi.mq5| -//| Copyright 2025, xxxxxxxx | -//| | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2025, xxxxxxxx" -#property link "" -#property version "1.00" -#property description "Variable Index Dynamic Average on Heikin Ashi data" - -#include - -//--- Indicator Window and Plot Properties --- -#property indicator_chart_window -#property indicator_buffers 1 -#property indicator_plots 1 -#property indicator_type1 DRAW_LINE -#property indicator_color1 clrRed -#property indicator_style1 STYLE_SOLID -#property indicator_width1 1 -#property indicator_label1 "HA_VIDYA" - -//--- Enum for selecting Heikin Ashi price source --- -enum ENUM_HA_APPLIED_PRICE - { - HA_PRICE_CLOSE, // Heikin Ashi Close - HA_PRICE_OPEN, // Heikin Ashi Open - HA_PRICE_HIGH, // Heikin Ashi High - HA_PRICE_LOW, // Heikin Ashi Low - }; - -//--- Input Parameters --- -input int InpPeriodCMO = 9; // Chande Momentum Oscillator Period -input int InpPeriodEMA = 12; // EMA Period for smoothing -input ENUM_HA_APPLIED_PRICE InpAppliedPrice = HA_PRICE_CLOSE; // Heikin Ashi Applied Price - -//--- Indicator Buffers --- -double BufferHA_VIDYA[]; - -//--- Global Objects and Variables --- -int g_ExtPeriodCMO; -int g_ExtPeriodEMA; -CHeikinAshi_Calculator *g_ha_calculator; - -//--- Forward declarations --- -double CalculateCMO(int position, int period, const double &price_array[]); - -//+------------------------------------------------------------------+ -//| Custom indicator initialization function. | -//+------------------------------------------------------------------+ -int OnInit() - { - g_ExtPeriodCMO = (InpPeriodCMO < 1) ? 1 : InpPeriodCMO; - g_ExtPeriodEMA = (InpPeriodEMA < 1) ? 1 : InpPeriodEMA; - - SetIndexBuffer(0, BufferHA_VIDYA, INDICATOR_DATA); - ArraySetAsSeries(BufferHA_VIDYA, false); - - int draw_begin = g_ExtPeriodCMO + g_ExtPeriodEMA; - PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, draw_begin); - IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("HA_VIDYA(%d,%d)", g_ExtPeriodCMO, g_ExtPeriodEMA)); - IndicatorSetInteger(INDICATOR_DIGITS, _Digits); - - g_ha_calculator = new CHeikinAshi_Calculator(); - if(CheckPointer(g_ha_calculator) == POINTER_INVALID) - { - Print("Error creating CHeikinAshi_Calculator object"); - return(INIT_FAILED); - } - - return(INIT_SUCCEEDED); - } - -//+------------------------------------------------------------------+ -//| Custom indicator deinitialization function. | -//+------------------------------------------------------------------+ -void OnDeinit(const int reason) - { - if(CheckPointer(g_ha_calculator) != POINTER_INVALID) - { - delete g_ha_calculator; - g_ha_calculator = NULL; - } - } - -//+------------------------------------------------------------------+ -//| VIDYA on Heikin Ashi calculation function. | -//+------------------------------------------------------------------+ -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 start_pos = g_ExtPeriodCMO + g_ExtPeriodEMA; - if(rates_total <= start_pos) - return(0); - -//--- Intermediate Heikin Ashi Buffers - double ha_open[], ha_high[], ha_low[], ha_close[]; - ArrayResize(ha_open, rates_total); - ArrayResize(ha_high, rates_total); - ArrayResize(ha_low, rates_total); - ArrayResize(ha_close, rates_total); - -//--- STEP 1: Calculate Heikin Ashi bars - g_ha_calculator.Calculate(rates_total, open, high, low, close, ha_open, ha_high, ha_low, ha_close); - -//--- STEP 2: Prepare the Heikin Ashi source price array - double ha_price_source[]; - ArrayResize(ha_price_source, rates_total); - switch(InpAppliedPrice) - { - case HA_PRICE_OPEN: - ArrayCopy(ha_price_source, ha_open); - break; - case HA_PRICE_HIGH: - ArrayCopy(ha_price_source, ha_high); - break; - case HA_PRICE_LOW: - ArrayCopy(ha_price_source, ha_low); - break; - default: - ArrayCopy(ha_price_source, ha_close); - break; - } - -//--- STEP 3: Main calculation loop - double alpha = 2.0 / (g_ExtPeriodEMA + 1.0); - - for(int i = 1; i < rates_total; i++) - { - // --- Initialization Step with SMA --- - if(i == start_pos) - { - double sum = 0; - for(int j=0; j start_pos) - { - // --- Recursive Calculation Step --- - double cmo = MathAbs(CalculateCMO(i, g_ExtPeriodCMO, ha_price_source)); - BufferHA_VIDYA[i] = ha_price_source[i] * alpha * cmo + BufferHA_VIDYA[i-1] * (1 - alpha * cmo); - } - } - - return(rates_total); - } - -//+------------------------------------------------------------------+ -//| Calculates Chande Momentum Oscillator (CMO) for a given position | -//+------------------------------------------------------------------+ -double CalculateCMO(int position, int period, const double &price_array[]) - { - if(position < period) - return 0.0; - - double sum_up = 0.0; - double sum_down = 0.0; - - for(int i = 0; i < period; i++) - { - double diff = price_array[position - i] - price_array[position - i - 1]; - if(diff > 0.0) - sum_up += diff; - else - sum_down += (-diff); - } - - if(sum_up + sum_down == 0.0) - return 0.0; - - return (sum_up - sum_down) / (sum_up + sum_down); - } -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ diff --git a/Indicators/MyIndicators/VIDYA_TrendActivity.md b/Indicators/MyIndicators/VIDYA_TrendActivity.md deleted file mode 100644 index e13adba..0000000 --- a/Indicators/MyIndicators/VIDYA_TrendActivity.md +++ /dev/null @@ -1,66 +0,0 @@ -# VIDYA Trend Activity - -## 1. Summary (Introduction) - -The VIDYA Trend Activity is a custom-built "meta-indicator" designed to measure the directional strength and activity of the Variable Index Dynamic Average (VIDYA). While the VIDYA line itself shows the trend, this oscillator quantifies _how trendy_ the market is according to the VIDYA's behavior. - -Developed as part of our indicator toolkit, its primary purpose is to act as a **trend filter**. It generates high values when the VIDYA is moving decisively in one direction (indicating a strong trend) and low values when the VIDYA line flattens out (indicating a sideways, ranging, or choppy market). It helps traders to visually distinguish between trending and non-trending environments. - -## 2. Mathematical Foundations and Calculation Logic - -This indicator analyzes the behavior of two underlying indicators, VIDYA and ATR, to produce a final, normalized oscillator. - -### Required Components - -- **VIDYA:** The underlying adaptive moving average. Its slope is the primary input. -- **ATR (Average True Range):** Used as a normalization factor to make the indicator's output comparable across different instruments and timeframes. -- **Smoothing Period:** A final smoothing period for the oscillator output. - -### Calculation Steps (Algorithm) - -1. **Calculate VIDYA:** First, the standard VIDYA is calculated for the chart based on its own parameters (CMO Period, EMA Period). - -2. **Calculate ATR:** Separately, the standard Wilder's ATR is calculated. - -3. **Calculate Raw Activity:** For each bar, the indicator measures the rate of change (slope) of the VIDYA line and normalizes it by the market's current volatility (ATR). This produces a raw, unbounded value representing the trend's relative strength. - $\text{Raw Activity}_i = \frac{\text{Abs}(\text{VIDYA}_i - \text{VIDYA}_{i-1})}{\text{ATR}_i}$ - -4. **Normalize with Arctan:** To solve the problem of scale across different timeframes, the `Raw Activity` value is passed through the inverse tangent (`Arctan`) function and then scaled to a consistent `0..1` range. The `Arctan` function elegantly maps any positive input into a predictable range, making the indicator robust on any timeframe. - $\text{Scaled Activity}_i = \frac{\text{Arctan}(\text{Raw Activity}_i)}{\pi/2}$ - -5. **Final Smoothing:** The `Scaled Activity` values are smoothed with a Simple Moving Average (SMA) to create the final, plotted histogram. - $\text{Final Activity}_i = \text{SMA}(\text{Scaled Activity}, \text{Smoothing Period})_i$ - -## 3. MQL5 Implementation Details - -Our MQL5 implementation is a completely self-contained indicator that internally calculates all its required components based on our established robust principles. - -- **Stability via Full Recalculation:** The indicator employs a "brute-force" full recalculation within the `OnCalculate` function to ensure maximum stability and prevent calculation errors. - -- **Internal Calculators:** The indicator does not use any external handles. It contains the full, robust, and manually implemented logic for calculating both the **VIDYA** (with its underlying CMO) and the **ATR**. All recursive calculations are carefully initialized to prevent floating-point overflows. - -- **Robust Normalization:** The use of the `MathArctan` function for normalization is a key feature. It ensures that the indicator's output remains consistent and comparable across all instruments and timeframes, from M1 to Weekly, solving the scaling issues that simpler normalization methods face. - -- **Optimized Visualization:** The indicator's vertical scale is programmatically set to a `0.0` to `0.5` range. Our analysis showed that the vast majority of significant signals occur within this range. This "zooms in" on the most relevant area of activity, making the visual output much clearer and easier to interpret. - -- **Heikin Ashi Variant (`VIDYA_TrendActivity_HeikinAshi.mq5`):** - - Our toolkit also includes a "pure" Heikin Ashi version. The calculation logic is identical, but all its inputs (VIDYA, CMO, and ATR) are derived from the smoothed Heikin Ashi price data. - - This results in an extremely smooth trend activity filter, ideal for traders using a full Heikin Ashi-based system. - -## 4. Parameters - -- **VIDYA Settings:** - - `InpPeriodCMO`: The period for the underlying Chande Momentum Oscillator. - - `InpPeriodEMA`: The base period for the underlying VIDYA. - - `InpAppliedPrice`: The source price for the underlying VIDYA. -- **Activity Calculation Settings:** - - `InpAtrPeriod`: The period for the ATR used in normalization. - - `InpSmoothingPeriod`: The period for the final SMA smoothing of the oscillator. - -## 5. Usage and Interpretation - -- **Trend Filter:** This is the indicator's primary function. A trader can establish a threshold (e.g., 0.1 or 0.2). - - **Activity > Threshold:** The market is considered to be in a **trending phase**. Trend-following strategies (e.g., using Supertrend, moving average crossovers) are more likely to be effective. - - **Activity < Threshold:** The market is considered to be in a **ranging or consolidating phase**. Mean-reversion strategies (e.g., using Bollinger Bands, oscillators) may be more appropriate. -- **Identifying Trend Exhaustion:** A sharp decline in the activity histogram after a strong trend can signal that momentum is waning and the trend may be nearing exhaustion or entering a consolidation phase. -- **Confirming Breakouts:** A spike in the activity histogram accompanying a price breakout from a range can provide strong confirmation that the breakout has momentum behind it. diff --git a/Indicators/MyIndicators/VIDYA_TrendActivity.mq5 b/Indicators/MyIndicators/VIDYA_TrendActivity.mq5 deleted file mode 100644 index bc8bea0..0000000 --- a/Indicators/MyIndicators/VIDYA_TrendActivity.mq5 +++ /dev/null @@ -1,222 +0,0 @@ -//+------------------------------------------------------------------+ -//| VIDYA_TrendActivity.mq5 | -//| Copyright 2025, xxxxxxxx | -//| | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2025, xxxxxxxx" -#property link "" -#property version "4.03" // Adjusted vertical scale -#property description "Measures the trend activity (slope) of a VIDYA line using Arctan normalization." -#property description "High values suggest a trending market, low values suggest a flat/ranging market." - -//--- Indicator Window and Plot Properties --- -#property indicator_separate_window -#property indicator_buffers 1 -#property indicator_plots 1 -#property indicator_type1 DRAW_HISTOGRAM -#property indicator_color1 clrDodgerBlue -#property indicator_width1 2 -#property indicator_label1 "Activity" -#property indicator_minimum 0.0 -#property indicator_maximum 0.5 // Adjusted for better visualization - -//--- Input Parameters --- -input group "VIDYA Settings" -input int InpPeriodCMO = 9; -input int InpPeriodEMA = 12; -input ENUM_APPLIED_PRICE InpAppliedPrice = PRICE_CLOSE; -input group "Activity Calculation Settings" -input int InpAtrPeriod = 14; -input int InpSmoothingPeriod = 5; // Final smoothing period for the oscillator - -//--- Indicator Buffers --- -double BufferActivity[]; - -//--- Global Variables --- -int g_ExtPeriodCMO, g_ExtPeriodEMA, g_ExtAtrPeriod, g_ExtSmoothingPeriod; -double g_M_PI_2; - -//--- Forward declarations --- -double CalculateCMO(int position, int period, const double &price_array[]); - -//+------------------------------------------------------------------+ -//| Custom indicator initialization function. | -//+------------------------------------------------------------------+ -int OnInit() - { - g_ExtPeriodCMO = (InpPeriodCMO < 1) ? 1 : InpPeriodCMO; - g_ExtPeriodEMA = (InpPeriodEMA < 1) ? 1 : InpPeriodEMA; - g_ExtAtrPeriod = (InpAtrPeriod < 1) ? 1 : InpAtrPeriod; - g_ExtSmoothingPeriod = (InpSmoothingPeriod < 1) ? 1 : InpSmoothingPeriod; - g_M_PI_2 = M_PI / 2.0; - - SetIndexBuffer(0, BufferActivity, INDICATOR_DATA); - ArraySetAsSeries(BufferActivity, false); - - int draw_begin = g_ExtPeriodCMO + g_ExtPeriodEMA + g_ExtAtrPeriod + g_ExtSmoothingPeriod; - PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, draw_begin); - IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("VIDYA Activity(%d,%d,%d,%d)", g_ExtPeriodCMO, g_ExtPeriodEMA, g_ExtAtrPeriod, g_ExtSmoothingPeriod)); - IndicatorSetInteger(INDICATOR_DIGITS, 4); - -//--- Programmatically set the vertical scale for better visualization - IndicatorSetDouble(INDICATOR_MINIMUM, 0.0); - IndicatorSetDouble(INDICATOR_MAXIMUM, 0.5); - - return(INIT_SUCCEEDED); - } - -//+------------------------------------------------------------------+ -//| VIDYA Trend Activity calculation function. | -//+------------------------------------------------------------------+ -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 start_pos = g_ExtPeriodCMO + g_ExtPeriodEMA + g_ExtAtrPeriod + g_ExtSmoothingPeriod; - if(rates_total <= start_pos) - return(0); - -//--- STEP 1: Prepare the source price array for VIDYA - double price_source[]; - ArrayResize(price_source, rates_total); - for(int i=0; i vidya_start_pos) - { - double cmo = MathAbs(CalculateCMO(i, g_ExtPeriodCMO, price_source)); - buffer_vidya[i] = price_source[i] * alpha * cmo + buffer_vidya[i-1] * (1 - alpha * cmo); - } - } - -//--- STEP 3: Calculate ATR - double buffer_atr[]; - ArrayResize(buffer_atr, rates_total); - double tr[]; - ArrayResize(tr, rates_total); - for(int i = 1; i < rates_total; i++) - { - tr[i] = MathMax(high[i], close[i-1]) - MathMin(low[i], close[i-1]); - } - for(int i = 1; i < rates_total; i++) - { - if(i == g_ExtAtrPeriod) - { - double sum_tr = 0; - for(int j = 1; j <= g_ExtAtrPeriod; j++) - sum_tr += tr[j]; - buffer_atr[i] = sum_tr / g_ExtAtrPeriod; - } - else - if(i > g_ExtAtrPeriod) - { - buffer_atr[i] = (buffer_atr[i-1] * (g_ExtAtrPeriod - 1) + tr[i]) / g_ExtAtrPeriod; - } - } - -//--- STEP 4: Calculate Raw Activity and Scale it using MathArctan - double scaled_activity[]; - ArrayResize(scaled_activity, rates_total); - for(int i = vidya_start_pos + 1; i < rates_total; i++) - { - if(buffer_atr[i] > 0) - { - double raw_activity = MathAbs(buffer_vidya[i] - buffer_vidya[i-1]) / buffer_atr[i]; - scaled_activity[i] = MathArctan(raw_activity) / g_M_PI_2; - } - } - -//--- STEP 5: Calculate Final Oscillator (SMA of Scaled Activity) - double sum = 0; - int final_start_pos = vidya_start_pos + g_ExtSmoothingPeriod; - for(int i = vidya_start_pos + 1; i < rates_total; i++) - { - sum += scaled_activity[i]; - if(i >= final_start_pos) - { - if(i > final_start_pos) - { - sum -= scaled_activity[i - g_ExtSmoothingPeriod]; - } - BufferActivity[i] = sum / g_ExtSmoothingPeriod; - } - } - - return(rates_total); - } - -//+------------------------------------------------------------------+ -//| Calculates Chande Momentum Oscillator (CMO) for a given position | -//+------------------------------------------------------------------+ -double CalculateCMO(int position, int period, const double &price_array[]) - { - if(position < period) - return 0.0; - - double sum_up = 0.0; - double sum_down = 0.0; - - for(int i = 0; i < period; i++) - { - double diff = price_array[position - i] - price_array[position - i - 1]; - if(diff > 0.0) - sum_up += diff; - else - sum_down += (-diff); - } - - if(sum_up + sum_down == 0.0) - return 0.0; - - return (sum_up - sum_down) / (sum_up + sum_down); - } -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ diff --git a/Indicators/MyIndicators/VIDYA_TrendActivity_HeikinAshi.mq5 b/Indicators/MyIndicators/VIDYA_TrendActivity_HeikinAshi.mq5 deleted file mode 100644 index 2993333..0000000 --- a/Indicators/MyIndicators/VIDYA_TrendActivity_HeikinAshi.mq5 +++ /dev/null @@ -1,251 +0,0 @@ -//+------------------------------------------------------------------+ -//| VIDYA_TrendActivity_HeikinAshi.mq5| -//| Copyright 2025, xxxxxxxx | -//| | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2025, xxxxxxxx" -#property link "" -#property version "2.00" // Adjusted vertical scale -#property description "Measures the trend activity of a Heikin Ashi VIDYA line using Arctan normalization." -#property description "High values suggest a trending market, low values suggest a flat/ranging market." - -#include - -//--- Indicator Window and Plot Properties --- -#property indicator_separate_window -#property indicator_buffers 1 -#property indicator_plots 1 -#property indicator_type1 DRAW_HISTOGRAM -#property indicator_color1 clrDodgerBlue -#property indicator_width1 2 -#property indicator_label1 "HA_Activity" -#property indicator_minimum 0.0 -#property indicator_maximum 0.5 // Adjusted for better visualization - -//--- Enum for selecting Heikin Ashi price source --- -enum ENUM_HA_APPLIED_PRICE - { - HA_PRICE_CLOSE, // Heikin Ashi Close - HA_PRICE_OPEN, // Heikin Ashi Open - HA_PRICE_HIGH, // Heikin Ashi High - HA_PRICE_LOW, // Heikin Ashi Low - }; - -//--- Input Parameters --- -input group "VIDYA Settings" -input int InpPeriodCMO = 9; -input int InpPeriodEMA = 12; -input ENUM_HA_APPLIED_PRICE InpAppliedPrice = HA_PRICE_CLOSE; -input group "Activity Calculation Settings" -input int InpAtrPeriod = 14; -input int InpSmoothingPeriod = 5; - -//--- Indicator Buffers --- -double BufferActivity[]; - -//--- Global Objects and Variables --- -int g_ExtPeriodCMO, g_ExtPeriodEMA, g_ExtAtrPeriod, g_ExtSmoothingPeriod; -double g_M_PI_2; -CHeikinAshi_Calculator *g_ha_calculator; - -//--- Forward declarations --- -double CalculateCMO(int position, int period, const double &price_array[]); - -//+------------------------------------------------------------------+ -//| Custom indicator initialization function. | -//+------------------------------------------------------------------+ -int OnInit() - { - g_ExtPeriodCMO = (InpPeriodCMO < 1) ? 1 : InpPeriodCMO; - g_ExtPeriodEMA = (InpPeriodEMA < 1) ? 1 : InpPeriodEMA; - g_ExtAtrPeriod = (InpAtrPeriod < 1) ? 1 : InpAtrPeriod; - g_ExtSmoothingPeriod = (InpSmoothingPeriod < 1) ? 1 : InpSmoothingPeriod; - g_M_PI_2 = M_PI / 2.0; - - SetIndexBuffer(0, BufferActivity, INDICATOR_DATA); - ArraySetAsSeries(BufferActivity, false); - - int draw_begin = g_ExtPeriodCMO + g_ExtPeriodEMA + g_ExtAtrPeriod + g_ExtSmoothingPeriod; - PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, draw_begin); - IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("HA VIDYA Activity(%d,%d,%d,%d)", g_ExtPeriodCMO, g_ExtPeriodEMA, g_ExtAtrPeriod, g_ExtSmoothingPeriod)); - IndicatorSetInteger(INDICATOR_DIGITS, 4); - -//--- Programmatically set the vertical scale for better visualization - IndicatorSetDouble(INDICATOR_MINIMUM, 0.0); - IndicatorSetDouble(INDICATOR_MAXIMUM, 0.5); - - g_ha_calculator = new CHeikinAshi_Calculator(); - if(CheckPointer(g_ha_calculator) == POINTER_INVALID) - { - Print("Error creating CHeikinAshi_Calculator object"); - return(INIT_FAILED); - } - - return(INIT_SUCCEEDED); - } - -//+------------------------------------------------------------------+ -//| Custom indicator deinitialization function. | -//+------------------------------------------------------------------+ -void OnDeinit(const int reason) - { - if(CheckPointer(g_ha_calculator) != POINTER_INVALID) - { - delete g_ha_calculator; - g_ha_calculator = NULL; - } - } - -//+------------------------------------------------------------------+ -//| VIDYA Trend Activity on Heikin Ashi calculation function. | -//+------------------------------------------------------------------+ -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 start_pos = g_ExtPeriodCMO + g_ExtPeriodEMA + g_ExtAtrPeriod + g_ExtSmoothingPeriod; - if(rates_total <= start_pos) - return(0); - -//--- Intermediate Heikin Ashi Buffers - double ha_open[], ha_high[], ha_low[], ha_close[]; - ArrayResize(ha_open, rates_total); - ArrayResize(ha_high, rates_total); - ArrayResize(ha_low, rates_total); - ArrayResize(ha_close, rates_total); - -//--- STEP 1: Calculate Heikin Ashi bars - g_ha_calculator.Calculate(rates_total, open, high, low, close, ha_open, ha_high, ha_low, ha_close); - -//--- STEP 2: Prepare the Heikin Ashi source price array for VIDYA - double ha_price_source[]; - ArrayResize(ha_price_source, rates_total); - switch(InpAppliedPrice) - { - case HA_PRICE_OPEN: - ArrayCopy(ha_price_source, ha_open); - break; - case HA_PRICE_HIGH: - ArrayCopy(ha_price_source, ha_high); - break; - case HA_PRICE_LOW: - ArrayCopy(ha_price_source, ha_low); - break; - default: - ArrayCopy(ha_price_source, ha_close); - break; - } - -//--- STEP 3: Calculate Heikin Ashi VIDYA - double buffer_vidya[]; - ArrayResize(buffer_vidya, rates_total); - double alpha = 2.0 / (g_ExtPeriodEMA + 1.0); - int vidya_start_pos = g_ExtPeriodCMO + g_ExtPeriodEMA; - - for(int i = 1; i < rates_total; i++) - { - if(i == vidya_start_pos) - { - double sum = 0; - for(int j=0; j vidya_start_pos) - { - double cmo = MathAbs(CalculateCMO(i, g_ExtPeriodCMO, ha_price_source)); - buffer_vidya[i] = ha_price_source[i] * alpha * cmo + buffer_vidya[i-1] * (1 - alpha * cmo); - } - } - -//--- STEP 4: Calculate Heikin Ashi ATR - double buffer_atr[]; - ArrayResize(buffer_atr, rates_total); - double ha_tr[]; - ArrayResize(ha_tr, rates_total); - for(int i = 1; i < rates_total; i++) - { - ha_tr[i] = MathMax(ha_high[i], ha_close[i-1]) - MathMin(ha_low[i], ha_close[i-1]); - } - for(int i = 1; i < rates_total; i++) - { - if(i == g_ExtAtrPeriod) - { - double sum_tr = 0; - for(int j = 1; j <= g_ExtAtrPeriod; j++) - sum_tr += ha_tr[j]; - buffer_atr[i] = sum_tr / g_ExtAtrPeriod; - } - else - if(i > g_ExtAtrPeriod) - { - buffer_atr[i] = (buffer_atr[i-1] * (g_ExtAtrPeriod - 1) + ha_tr[i]) / g_ExtAtrPeriod; - } - } - -//--- STEP 5: Calculate Raw Activity and Scale it using MathArctan - double scaled_activity[]; - ArrayResize(scaled_activity, rates_total); - for(int i = vidya_start_pos + 1; i < rates_total; i++) - { - if(buffer_atr[i] > 0) - { - double raw_activity = MathAbs(buffer_vidya[i] - buffer_vidya[i-1]) / buffer_atr[i]; - scaled_activity[i] = MathArctan(raw_activity) / g_M_PI_2; - } - } - -//--- STEP 6: Calculate Final Oscillator (SMA of Scaled Activity) - double sum = 0; - int final_start_pos = vidya_start_pos + g_ExtSmoothingPeriod; - for(int i = vidya_start_pos + 1; i < rates_total; i++) - { - sum += scaled_activity[i]; - if(i >= final_start_pos) - { - if(i > final_start_pos) - { - sum -= scaled_activity[i - g_ExtSmoothingPeriod]; - } - BufferActivity[i] = sum / g_ExtSmoothingPeriod; - } - } - - return(rates_total); - } - -//+------------------------------------------------------------------+ -//| Calculates Chande Momentum Oscillator (CMO) for a given position | -//+------------------------------------------------------------------+ -double CalculateCMO(int position, int period, const double &price_array[]) - { - if(position < period) - return 0.0; - - double sum_up = 0.0; - double sum_down = 0.0; - - for(int i = 0; i < period; i++) - { - double diff = price_array[position - i] - price_array[position - i - 1]; - if(diff > 0.0) - sum_up += diff; - else - sum_down += (-diff); - } - - if(sum_up + sum_down == 0.0) - return 0.0; - - return (sum_up - sum_down) / (sum_up + sum_down); - } -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ diff --git a/Indicators/MyIndicators/WPR.md b/Indicators/MyIndicators/WPR.md deleted file mode 100644 index baca7fa..0000000 --- a/Indicators/MyIndicators/WPR.md +++ /dev/null @@ -1,56 +0,0 @@ -# Williams' Percent Range (%R) - -## 1. Summary (Introduction) - -Williams' Percent Range, or %R, is a momentum oscillator developed by Larry Williams. It is very similar to the Stochastic Oscillator, but it is plotted on an inverted scale from 0 to -100. Its primary purpose is to identify overbought and oversold conditions in the market. - -The indicator measures the current closing price in relation to the highest high and lowest low over a specified lookback period. It shows where the current price is relative to the recent trading range, helping traders to spot potential exhaustion points in a trend. - -## 2. Mathematical Foundations and Calculation Logic - -The %R formula is straightforward and compares the current close to the recent high-low range. - -### Required Components - -- **Period (N):** The lookback period for the calculation (e.g., 14). -- **Price Data:** The `High`, `Low`, and `Close` of each bar. - -### Calculation Steps (Algorithm) - -1. **Find the Highest High and Lowest Low:** For each bar, determine the highest high and lowest low over the last `N` periods. - $\text{Highest High}_N = \text{Max}(\text{High}, N)_i$ - $\text{Lowest Low}_N = \text{Min}(\text{Low}, N)_i$ - -2. **Calculate the Williams %R:** Apply the main formula. - $\text{\%R}_i = -100 \times \frac{\text{Highest High}_N - \text{Close}_i}{\text{Highest High}_N - \text{Lowest Low}_N}$ - -The result is a value between 0 and -100. A reading close to 0 means the price is closing near the top of its recent range (overbought), while a reading close to -100 means the price is closing near the bottom of its range (oversold). - -## 3. MQL5 Implementation Details - -Our MQL5 implementation is a self-contained, robust, and clear representation of the Williams %R indicator. - -- **Stability via Full Recalculation:** We employ a "brute-force" full recalculation within the `OnCalculate` function. As a non-recursive indicator, this is a simple and highly stable approach. - -- **Self-Contained Logic:** The indicator is completely self-contained. It does not use any external indicator handles (like `iWPR`). All calculations are performed manually within the `OnCalculate` function using the price data provided. - -- **Reusable Helper Functions:** The calculation of the highest high and lowest low is performed by our standard, reusable `Highest()` and `Lowest()` helper functions, ensuring consistency across our entire indicator toolkit. - -- **Clear, Staged Calculation:** The `OnCalculate` function uses a single, efficient `for` loop to calculate the %R for each bar. The logic is clear and directly follows the mathematical definition of the indicator. - -- **Heikin Ashi Variants:** - - **`WPR_HeikinAshi.mq5`:** Our toolkit includes a Heikin Ashi version of this indicator. The calculation logic is identical, but it uses the smoothed Heikin Ashi `ha_high`, `ha_low`, and `ha_close` values as its input. This results in a smoother oscillator that reflects the momentum of the underlying Heikin Ashi trend. - - **`WPRMA_HeikinAshi.mq5`:** We also have a version that adds a moving average signal line to the Heikin Ashi WPR, providing an additional layer of smoothing and potential crossover signals. - -## 4. Parameters - -- **WPR Period (`InpWPRPeriod`):** The lookback period for the indicator. Larry Williams' original recommendation and the most common value is `14`. - -## 5. Usage and Interpretation - -- **Overbought/Oversold Levels:** The primary use of %R is to identify overbought and oversold conditions. - - **Overbought:** Readings between **0 and -20** are considered overbought. This suggests that the price is near the top of its recent range and may be due for a pullback. - - **Oversold:** Readings between **-80 and -100** are considered oversold. This suggests that the price is near the bottom of its recent range and may be due for a bounce. -- **Divergence:** Look for divergences between the %R and the price action. A bearish divergence (higher price highs, lower %R highs) can signal weakening bullish momentum. A bullish divergence (lower price lows, higher %R lows) can signal weakening bearish momentum. -- **Momentum Failure:** A common signal is when the %R enters the overbought zone, pulls back, and then fails to re-enter the overbought zone on a subsequent price rally. This "momentum failure" can be an early sign of a trend reversal. -- **Caution:** Like all oscillators, %R can remain in overbought or oversold territory for extended periods during a strong trend. It is not a standalone signal for buying or selling but a tool to gauge momentum within a broader market context. diff --git a/Indicators/MyIndicators/WPR.mq5 b/Indicators/MyIndicators/WPR.mq5 deleted file mode 100644 index d1be5ad..0000000 --- a/Indicators/MyIndicators/WPR.mq5 +++ /dev/null @@ -1,121 +0,0 @@ -//+------------------------------------------------------------------+ -//| WPR.mq5 | -//| Copyright 2025, xxxxxxxx | -//| | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2025, xxxxxxxx" -#property link "" -#property version "2.00" // Refactored for stability and clarity -#property description "Larry Williams' Percent Range" - -//--- Indicator Window and Level Properties --- -#property indicator_separate_window -#property indicator_level1 -20.0 -#property indicator_level2 -80.0 -#property indicator_levelstyle STYLE_DOT -#property indicator_levelcolor clrSilver -#property indicator_levelwidth 1 -#property indicator_maximum 0.0 -#property indicator_minimum -100.0 - -//--- Buffers and Plots --- -#property indicator_buffers 1 -#property indicator_plots 1 - -//--- Plot 1: WPR line -#property indicator_type1 DRAW_LINE -#property indicator_color1 clrDodgerBlue -#property indicator_label1 "WPR" - -//--- Input Parameters --- -input int InpWPRPeriod = 14; // Period for WPR calculation - -//--- Indicator Buffers --- -double BufferWPR[]; - -//--- Global Variables --- -int g_ExtWPRPeriod; - -//--- Forward declarations for helper functions --- -double Highest(const double &array[], int period, int current_pos); -double Lowest(const double &array[], int period, int current_pos); - -//+------------------------------------------------------------------+ -//| Custom indicator initialization function. | -//+------------------------------------------------------------------+ -int OnInit() - { - g_ExtWPRPeriod = (InpWPRPeriod < 1) ? 1 : InpWPRPeriod; - - SetIndexBuffer(0, BufferWPR, INDICATOR_DATA); - ArraySetAsSeries(BufferWPR, false); - - PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, g_ExtWPRPeriod - 1); - IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("WPR(%d)", g_ExtWPRPeriod)); - IndicatorSetInteger(INDICATOR_DIGITS, 2); - - return(INIT_SUCCEEDED); - } - -//+------------------------------------------------------------------+ -//| Williams’ Percent Range calculation function. | -//+------------------------------------------------------------------+ -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 < g_ExtWPRPeriod) - return(0); - -//--- Main calculation loop - for(int i = g_ExtWPRPeriod - 1; i < rates_total; i++) - { - double highest_high = Highest(high, g_ExtWPRPeriod, i); - double lowest_low = Lowest(low, g_ExtWPRPeriod, i); - double range = highest_high - lowest_low; - - if(range > 0) - BufferWPR[i] = -100.0 * (highest_high - close[i]) / range; - else - BufferWPR[i] = (i > 0) ? BufferWPR[i-1] : -50.0; // Avoid division by zero - } - - return(rates_total); - } - -//+------------------------------------------------------------------+ -//| Finds the highest value in a given period of an array. | -//+------------------------------------------------------------------+ -double Highest(const double &array[], int period, int current_pos) - { - double res = array[current_pos]; - for(int i = 1; i < period; i++) - { - if(res < array[current_pos - i]) - res = array[current_pos - i]; - } - return(res); - } - -//+------------------------------------------------------------------+ -//| Finds the lowest value in a given period of an array. | -//+------------------------------------------------------------------+ -double Lowest(const double &array[], int period, int current_pos) - { - double res = array[current_pos]; - for(int i = 1; i < period; i++) - { - if(res > array[current_pos - i]) - res = array[current_pos - i]; - } - return(res); - } -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ diff --git a/Indicators/MyIndicators/WPRMA_HeikinAshi.mq5 b/Indicators/MyIndicators/WPRMA_HeikinAshi.mq5 deleted file mode 100644 index a7f0948..0000000 --- a/Indicators/MyIndicators/WPRMA_HeikinAshi.mq5 +++ /dev/null @@ -1,227 +0,0 @@ -//+------------------------------------------------------------------+ -//| WPRMA_HeikinAshi.mq5 | -//| Copyright 2025, xxxxxxxx (Based on MetaQuotes WPR) | -//| | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2025, xxxxxxxx" -#property link "" -#property version "2.02" // Reverted to robust manual MA calculation -#property description "WPR on Heikin Ashi candles, with a Moving Average." - -// --- Standard and Custom Includes --- -#include // For SimpleMA and LinearWeightedMA single-value functions -#include - -//--- Indicator Window and Level Properties --- -#property indicator_separate_window -#property indicator_level1 -20.0 -#property indicator_level2 -80.0 -#property indicator_levelstyle STYLE_DOT -#property indicator_levelcolor clrSilver -#property indicator_levelwidth 1 -#property indicator_maximum 0.0 -#property indicator_minimum -100.0 - -//--- Buffers and Plots --- -#property indicator_buffers 2 // WPRMA and the raw WPR -#property indicator_plots 2 - -//--- Plot 1: WPR MA line (smoothed) -#property indicator_label1 "HA_WPRMA" -#property indicator_type1 DRAW_LINE -#property indicator_color1 clrRed - -//--- Plot 2: WPR line (raw) -#property indicator_label2 "HA_WPR" -#property indicator_type2 DRAW_LINE -#property indicator_color2 clrDodgerBlue - -//--- Input Parameters --- -input int InpWPRPeriod = 14; // Period for WPR calculation -input int InpMAPeriod = 14; // Period for Moving Average -input ENUM_MA_METHOD InpMAMethod = MODE_SMA; // Method for Moving Average - -//--- Indicator Buffers --- -double BufferHA_WPRMA[]; // Buffer for the smoothed WPR line -double BufferHA_WPR[]; // Buffer for the raw Heikin Ashi WPR line - -//--- Intermediate Heikin Ashi Buffers --- -double ExtHaOpenBuffer[]; -double ExtHaHighBuffer[]; -double ExtHaLowBuffer[]; -double ExtHaCloseBuffer[]; - -//--- Global Objects and Variables --- -int g_ExtWPRPeriod; -int g_ExtMAPeriod; -CHeikinAshi_Calculator *g_ha_calculator; // Pointer to our Heikin Ashi calculator - -//--- Forward declarations for helper functions --- -double Highest(const double &array[], int period, int current_pos); -double Lowest(const double &array[], int period, int current_pos); - -//+------------------------------------------------------------------+ -//| Custom indicator initialization function. | -//+------------------------------------------------------------------+ -int OnInit() - { -//--- Validate and store input periods - g_ExtWPRPeriod = (InpWPRPeriod < 1) ? 1 : InpWPRPeriod; - g_ExtMAPeriod = (InpMAPeriod < 1) ? 1 : InpMAPeriod; - -//--- Map the buffers - SetIndexBuffer(0, BufferHA_WPRMA, INDICATOR_DATA); - SetIndexBuffer(1, BufferHA_WPR, INDICATOR_DATA); - -//--- Set buffers to non-timeseries for stable calculation - ArraySetAsSeries(BufferHA_WPRMA, false); - ArraySetAsSeries(BufferHA_WPR, false); - -//--- Set indicator properties - PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, g_ExtWPRPeriod + g_ExtMAPeriod - 2); - PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, g_ExtWPRPeriod - 1); - IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("HA_WPRMA(%d, %d)", g_ExtWPRPeriod, g_ExtMAPeriod)); - IndicatorSetInteger(INDICATOR_DIGITS, 2); - -//--- Create the calculator instance - g_ha_calculator = new CHeikinAshi_Calculator(); - if(CheckPointer(g_ha_calculator) == POINTER_INVALID) - { - Print("Error creating CHeikinAshi_Calculator object"); - return(INIT_FAILED); - } - - return(INIT_SUCCEEDED); - } - -//+------------------------------------------------------------------+ -//| Custom indicator deinitialization function. | -//+------------------------------------------------------------------+ -void OnDeinit(const int reason) - { -//--- Free the calculator object to prevent memory leaks - if(CheckPointer(g_ha_calculator) != POINTER_INVALID) - { - delete g_ha_calculator; - g_ha_calculator = NULL; - } - } - -//+------------------------------------------------------------------+ -//| Williams’ Percent Range on Heikin Ashi with MA. | -//+------------------------------------------------------------------+ -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[]) - { -//--- Check if there is enough historical data for the first calculation - if(rates_total < g_ExtWPRPeriod) - return(0); - -//--- Resize intermediate buffers to match the available bars - ArrayResize(ExtHaOpenBuffer, rates_total); - ArrayResize(ExtHaHighBuffer, rates_total); - ArrayResize(ExtHaLowBuffer, rates_total); - ArrayResize(ExtHaCloseBuffer, rates_total); - -//--- STEP 1: Calculate Heikin Ashi bars using our toolkit (full recalculation) - g_ha_calculator.Calculate(rates_total, open, high, low, close, - ExtHaOpenBuffer, ExtHaHighBuffer, ExtHaLowBuffer, ExtHaCloseBuffer); - -//--- STEP 2: Calculate the raw WPR based on the Heikin Ashi results - for(int i = g_ExtWPRPeriod - 1; i < rates_total; i++) - { - double max_ha_high = Highest(ExtHaHighBuffer, g_ExtWPRPeriod, i); - double min_ha_low = Lowest(ExtHaLowBuffer, g_ExtWPRPeriod, i); - if(max_ha_high != min_ha_low) - BufferHA_WPR[i] = - (max_ha_high - ExtHaCloseBuffer[i]) * 100.0 / (max_ha_high - min_ha_low); - else - BufferHA_WPR[i] = (i > 0) ? BufferHA_WPR[i-1] : -50.0; - } - -//--- STEP 3: Calculate the Moving Average on the raw WPR buffer using a manual loop - int ma_start_pos = g_ExtWPRPeriod + g_ExtMAPeriod - 2; - for(int i = ma_start_pos; i < rates_total; i++) - { - switch(InpMAMethod) - { - case MODE_EMA: - // --- Special handling for EMA --- - if(i == ma_start_pos) // First EMA value is an SMA - { - BufferHA_WPRMA[i] = SimpleMA(i, g_ExtMAPeriod, BufferHA_WPR); - } - else // Subsequent EMA values are calculated recursively - { - double pr = 2.0 / (g_ExtMAPeriod + 1.0); - BufferHA_WPRMA[i] = BufferHA_WPR[i] * pr + BufferHA_WPRMA[i-1] * (1.0 - pr); - } - break; - - case MODE_SMMA: - if(i == ma_start_pos) // First SMMA value is an SMA - { - BufferHA_WPRMA[i] = SimpleMA(i, g_ExtMAPeriod, BufferHA_WPR); - } - else // Subsequent SMMA values are calculated recursively - { - BufferHA_WPRMA[i] = (BufferHA_WPRMA[i-1] * (g_ExtMAPeriod - 1) + BufferHA_WPR[i]) / g_ExtMAPeriod; - } - break; - - case MODE_LWMA: - BufferHA_WPRMA[i] = LinearWeightedMA(i, g_ExtMAPeriod, BufferHA_WPR); - break; - - default: // MODE_SMA - BufferHA_WPRMA[i] = SimpleMA(i, g_ExtMAPeriod, BufferHA_WPR); - break; - } - } - -//--- Return value of rates_total to signal a full recalculation - return(rates_total); - } - -//+------------------------------------------------------------------+ -//| Finds the highest value in a given period of an array. | -//+------------------------------------------------------------------+ -double Highest(const double &array[], int period, int current_pos) - { - double res = array[current_pos]; - for(int i = 1; i < period; i++) - { - int index = current_pos - i; - if(index < 0) - break; - if(res < array[index]) - res = array[index]; - } - return(res); - } - -//+------------------------------------------------------------------+ -//| Finds the lowest value in a given period of an array. | -//+------------------------------------------------------------------+ -double Lowest(const double &array[], int period, int current_pos) - { - double res = array[current_pos]; - for(int i = 1; i < period; i++) - { - int index = current_pos - i; - if(index < 0) - break; - if(res > array[index]) - res = array[index]; - } - return(res); - } -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+ diff --git a/Indicators/MyIndicators/WPR_HeikinAshi.mq5 b/Indicators/MyIndicators/WPR_HeikinAshi.mq5 deleted file mode 100644 index 291047c..0000000 --- a/Indicators/MyIndicators/WPR_HeikinAshi.mq5 +++ /dev/null @@ -1,181 +0,0 @@ -//+------------------------------------------------------------------+ -//| WPR_HeikinAshi.mq5 | -//| Copyright 2025, xxxxxxxx (Based on MetaQuotes WPR) | -//| | -//+------------------------------------------------------------------+ -#property copyright "Copyright 2025, xxxxxxxx" -#property link "" -#property version "3.00" // Refactored for stability and new calculator -#property description "Larry Williams' Percent Range based on Heikin Ashi candles" - -//--- Custom Toolkit Include --- -#include - -//--- Indicator Window and Level Properties --- -#property indicator_separate_window -#property indicator_level1 -20.0 -#property indicator_level2 -80.0 -#property indicator_levelstyle STYLE_DOT -#property indicator_levelcolor clrSilver -#property indicator_levelwidth 1 -#property indicator_maximum 0.0 -#property indicator_minimum -100.0 - -//--- Buffers and Plots --- -#property indicator_buffers 1 // Only one buffer is needed for the WPR line -#property indicator_plots 1 - -//--- Plot 1: WPR line -#property indicator_type1 DRAW_LINE -#property indicator_color1 clrDodgerBlue -#property indicator_label1 "HA_WPR" - -//--- Input Parameters --- -input int InpWPRPeriod=14; // Period for WPR calculation - -//--- Indicator Buffers --- -double BufferHA_WPR[]; // The final WPR values for plotting - -//--- Intermediate Heikin Ashi Buffers --- -double ExtHaOpenBuffer[]; -double ExtHaHighBuffer[]; -double ExtHaLowBuffer[]; -double ExtHaCloseBuffer[]; - -//--- Global Objects and Variables --- -int g_ExtPeriodWPR; -CHeikinAshi_Calculator *g_ha_calculator; // Pointer to our Heikin Ashi calculator - -//--- Forward declarations for helper functions --- -double Highest(const double &array[], int period, int current_pos); -double Lowest(const double &array[], int period, int current_pos); - -//+------------------------------------------------------------------+ -//| Custom indicator initialization function. | -//+------------------------------------------------------------------+ -int OnInit() - { -//--- Validate and store the WPR period - g_ExtPeriodWPR = (InpWPRPeriod < 1) ? 1 : InpWPRPeriod; - -//--- Map the buffer to the indicator's internal memory - SetIndexBuffer(0, BufferHA_WPR, INDICATOR_DATA); -//--- Set buffer as non-timeseries for stable calculation - ArraySetAsSeries(BufferHA_WPR, false); - -//--- Set indicator properties - PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, g_ExtPeriodWPR - 1); - IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("HA_WPR(%d)", g_ExtPeriodWPR)); - IndicatorSetInteger(INDICATOR_DIGITS, 2); - -//--- Create the calculator instance - g_ha_calculator = new CHeikinAshi_Calculator(); - if(CheckPointer(g_ha_calculator) == POINTER_INVALID) - { - Print("Error creating CHeikinAshi_Calculator object"); - return(INIT_FAILED); - } - - return(INIT_SUCCEEDED); - } - -//+------------------------------------------------------------------+ -//| Custom indicator deinitialization function. | -//+------------------------------------------------------------------+ -void OnDeinit(const int reason) - { -//--- Free the calculator object to prevent memory leaks - if(CheckPointer(g_ha_calculator) != POINTER_INVALID) - { - delete g_ha_calculator; - g_ha_calculator = NULL; - } - } - -//+------------------------------------------------------------------+ -//| Williams’ Percent Range on Heikin Ashi. | -//+------------------------------------------------------------------+ -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[]) - { -//--- Check if there is enough historical data for the first calculation - if(rates_total < g_ExtPeriodWPR) - return(0); - -//--- Resize intermediate buffers to match the available bars - ArrayResize(ExtHaOpenBuffer, rates_total); - ArrayResize(ExtHaHighBuffer, rates_total); - ArrayResize(ExtHaLowBuffer, rates_total); - ArrayResize(ExtHaCloseBuffer, rates_total); - -//--- STEP 1: Calculate Heikin Ashi bars using our toolkit (full recalculation) - g_ha_calculator.Calculate(rates_total, open, high, low, close, - ExtHaOpenBuffer, ExtHaHighBuffer, ExtHaLowBuffer, ExtHaCloseBuffer); - -//--- STEP 2: Calculate WPR based on the Heikin Ashi results -// Start from the first bar that has enough preceding data for the WPR period - for(int i = g_ExtPeriodWPR - 1; i < rates_total; i++) - { - // Find the highest HA_High and lowest HA_Low over the WPR period - double max_ha_high = Highest(ExtHaHighBuffer, g_ExtPeriodWPR, i); - double min_ha_low = Lowest(ExtHaLowBuffer, g_ExtPeriodWPR, i); - - // Calculate WPR using the current HA_Close - if(max_ha_high != min_ha_low) - BufferHA_WPR[i] = - (max_ha_high - ExtHaCloseBuffer[i]) * 100.0 / (max_ha_high - min_ha_low); - else - // If max high equals min low, avoid division by zero - BufferHA_WPR[i] = (i > 0) ? BufferHA_WPR[i-1] : -50.0; - } - -//--- Return value of rates_total to signal a full recalculation - return(rates_total); - } - -//+------------------------------------------------------------------+ -//| Finds the highest value in a given period of an array. | -//+------------------------------------------------------------------+ -double Highest(const double &array[], int period, int current_pos) - { - double res = array[current_pos]; -//--- Loop backwards from the current position for 'period' bars - for(int i = 1; i < period; i++) - { - int index = current_pos - i; - if(index < 0) - break; // Stop if we go out of bounds - - if(res < array[index]) - res = array[index]; - } - return(res); - } - -//+------------------------------------------------------------------+ -//| Finds the lowest value in a given period of an array. | -//+------------------------------------------------------------------+ -double Lowest(const double &array[], int period, int current_pos) - { - double res = array[current_pos]; -//--- Loop backwards from the current position for 'period' bars - for(int i = 1; i < period; i++) - { - int index = current_pos - i; - if(index < 0) - break; // Stop if we go out of bounds - - if(res > array[index]) - res = array[index]; - } - return(res); - } -//+------------------------------------------------------------------+ -//+------------------------------------------------------------------+