diff --git a/Indicators/MyIndicators/RSI_Oscillator.mq5 b/Indicators/MyIndicators/RSI_Oscillator.mq5 index a80fc77..1ad7f28 100644 --- a/Indicators/MyIndicators/RSI_Oscillator.mq5 +++ b/Indicators/MyIndicators/RSI_Oscillator.mq5 @@ -1,60 +1,88 @@ //+------------------------------------------------------------------+ //| RSI_Oscillator.mq5 | -//| Copyright 2025, xxxxxxxx | +//| Copyright 2025, xxxxxxxx| //| | //+------------------------------------------------------------------+ #property copyright "Copyright 2025, xxxxxxxx" -#property link "" -#property version "1.00" -#property description "RSI Oscillator (Histogram of RSI vs Signal Line)" +#property version "3.00" +#property description "RSI Oscillator (Histogram of RSI vs Signal Line) with selectable price source." -//--- 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_width1 2 #property indicator_label1 "RSI Oscillator" #property indicator_level1 0.0 #property indicator_levelstyle STYLE_DOT +#include + +//--- Custom Enum for Price Source, including Heikin Ashi +enum ENUM_APPLIED_PRICE_HA_ALL + { +//--- Heikin Ashi Prices + PRICE_HA_CLOSE = -1, + PRICE_HA_OPEN = -2, + PRICE_HA_HIGH = -3, + PRICE_HA_LOW = -4, + PRICE_HA_MEDIAN = -5, + PRICE_HA_TYPICAL = -6, + PRICE_HA_WEIGHTED = -7, +//--- Standard Prices + PRICE_CLOSE_STD = PRICE_CLOSE, + PRICE_OPEN_STD = PRICE_OPEN, + PRICE_HIGH_STD = PRICE_HIGH, + PRICE_LOW_STD = PRICE_LOW, + PRICE_MEDIAN_STD = PRICE_MEDIAN, + PRICE_TYPICAL_STD = PRICE_TYPICAL, + PRICE_WEIGHTED_STD = PRICE_WEIGHTED + }; + //--- Input Parameters --- -input int InpPeriodRSI = 14; -input ENUM_APPLIED_PRICE InpAppliedPrice = PRICE_CLOSE; -input group "Signal Line Settings" -input int InpPeriodMA = 14; -input ENUM_MA_METHOD InpMethod = MODE_SMA; +input int InpPeriodRSI = 14; +input ENUM_APPLIED_PRICE_HA_ALL InpSourcePrice = PRICE_CLOSE_STD; +input group "Signal Line Settings" +input int InpPeriodMA = 14; +input ENUM_MA_METHOD InpMethodMA = MODE_SMA; //--- Indicator Buffers --- double BufferOscillator[]; -//--- Global Variables --- -int g_ExtPeriodRSI, g_ExtPeriodMA; -int g_handle_rsi; +//--- Global calculator object --- +CRSIProCalculator *g_calculator; //+------------------------------------------------------------------+ //| Custom indicator initialization function. | //+------------------------------------------------------------------+ int OnInit() { - g_ExtPeriodRSI = (InpPeriodRSI < 1) ? 1 : InpPeriodRSI; - g_ExtPeriodMA = (InpPeriodMA < 1) ? 1 : InpPeriodMA; - SetIndexBuffer(0, BufferOscillator, INDICATOR_DATA); ArraySetAsSeries(BufferOscillator, false); - int draw_begin = g_ExtPeriodRSI + g_ExtPeriodMA - 1; - PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, draw_begin); - IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("RSI Osc(%d,%d)", g_ExtPeriodRSI, g_ExtPeriodMA)); - IndicatorSetInteger(INDICATOR_DIGITS, 2); - - g_handle_rsi = iRSI(_Symbol, _Period, g_ExtPeriodRSI, InpAppliedPrice); - if(g_handle_rsi == INVALID_HANDLE) + if(InpSourcePrice <= PRICE_HA_CLOSE) { - Print("Error creating iRSI handle."); + g_calculator = new CRSIProCalculator_HA(); + IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("RSI Osc HA(%d,%d)", InpPeriodRSI, InpPeriodMA)); + } + else + { + g_calculator = new CRSIProCalculator(); + IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("RSI Osc(%d,%d)", InpPeriodRSI, InpPeriodMA)); + } + +//--- We pass a dummy deviation value (0.0) as it's not used for the oscillator + if(CheckPointer(g_calculator) == POINTER_INVALID || + !g_calculator.Init(InpPeriodRSI, InpPeriodMA, InpMethodMA, 0.0)) + { + Print("Failed to initialize RSI Pro Calculator for Oscillator."); return(INIT_FAILED); } + + PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, InpPeriodRSI + InpPeriodMA - 1); + IndicatorSetInteger(INDICATOR_DIGITS, 2); + return(INIT_SUCCEEDED); } @@ -63,91 +91,39 @@ int OnInit() //+------------------------------------------------------------------+ void OnDeinit(const int reason) { - IndicatorRelease(g_handle_rsi); + if(CheckPointer(g_calculator) != POINTER_INVALID) + delete g_calculator; } //+------------------------------------------------------------------+ -//| RSI Oscillator calculation function. | +//| Custom indicator iteration 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 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&[]) { - int start_pos = g_ExtPeriodRSI + g_ExtPeriodMA - 1; - if(rates_total <= start_pos) - return(0); + if(CheckPointer(g_calculator) == POINTER_INVALID) + return 0; -//--- Internal Buffers for calculation --- - double buffer_rsi[], buffer_signal[]; - ArrayResize(buffer_rsi, rates_total); - ArrayResize(buffer_signal, rates_total); +//--- Step 1: Use the Pro calculator to get the core RSI and MA values + double rsi_buffer[], ma_buffer[], dummy_upper[], dummy_lower[]; + ArrayResize(rsi_buffer, rates_total); + ArrayResize(ma_buffer, rates_total); + ArrayResize(dummy_upper, rates_total); + ArrayResize(dummy_lower, rates_total); -//--- STEP 1: Get RSI values - if(CopyBuffer(g_handle_rsi, 0, 0, rates_total, buffer_rsi) < rates_total) - { - Print("Error copying RSI buffer data."); - } + ENUM_APPLIED_PRICE price_type; + if(InpSourcePrice <= PRICE_HA_CLOSE) + price_type = (ENUM_APPLIED_PRICE)(-(int)InpSourcePrice); + else + price_type = (ENUM_APPLIED_PRICE)InpSourcePrice; -//--- STEP 2: Calculate the Signal Line (MA of RSI) + g_calculator.Calculate(rates_total, price_type, open, high, low, close, + rsi_buffer, ma_buffer, dummy_upper, dummy_lower); + +//--- Step 2: Calculate the final Oscillator value (RSI - MA) + int start_pos = InpPeriodRSI + InpPeriodMA - 1; for(int i = start_pos; i < rates_total; i++) { - switch(InpMethod) - { - case MODE_EMA: - case MODE_SMMA: - if(i == 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