Files
mql5/Indicators/MyIndicators/RSI_HeikenAshi.mq5
T
2025-08-11 11:48:42 +02:00

231 lines
8.1 KiB
Plaintext

//+------------------------------------------------------------------+
//| RSI_HeikenAshi.mq5 |
//| Copyright 2024, Your Name (Based on MetaQuotes RSI) |
//| |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, Your Name"
#property link ""
#property version "1.00"
#property description "RSI calculated on Heiken Ashi Close prices, with a Moving Average."
//--- Indicator settings
#property indicator_separate_window
#property indicator_minimum 0
#property indicator_maximum 100
#property indicator_level1 30.0
#property indicator_level2 50.0
#property indicator_level3 70.0
//--- Buffers and Plots
#property indicator_buffers 5 // HA_RSI_MA, HA_RSI, Pos, Neg, HA_Close (all calculations)
#property indicator_plots 2 // We only plot HA_RSI_MA and HA_RSI
//--- Plot 1: RSI MA line (smoothed)
#property indicator_label1 "HA_RSIMA"
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrDodgerBlue
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
//--- Plot 2: RSI line (raw)
#property indicator_label2 "HA_RSI"
#property indicator_type2 DRAW_LINE
#property indicator_color2 clrGreen
#property indicator_style2 STYLE_SOLID
#property indicator_width2 1
//--- Input parameters
input int InpPeriodRSI = 14; // RSI Period
input int InpPeriodMA = 14; // MA Period
input ENUM_MA_METHOD InpMethodMA = MODE_SMA; // MA Method
//--- Indicator Buffers
// Plotted buffers
double BufferHARSI_MA[]; // Smoothed Heiken Ashi RSI
double BufferHARSI[]; // Raw Heiken Ashi RSI
// Calculation buffers
double BufferPos[]; // For RSI calculation (average gain)
double BufferNeg[]; // For RSI calculation (average loss)
double BufferHAClose[]; // To store Heiken Ashi Close prices
//--- Global variables
int ExtPeriodRSI;
int ExtPeriodMA;
//--- Include for MA calculations
#include <MovingAverages.mqh>
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- Validate inputs
ExtPeriodRSI = (InpPeriodRSI < 1) ? 1 : InpPeriodRSI;
ExtPeriodMA = (InpPeriodMA < 1) ? 1 : InpPeriodMA;
//--- Indicator buffers mapping
SetIndexBuffer(0, BufferHARSI_MA, INDICATOR_DATA);
SetIndexBuffer(1, BufferHARSI, INDICATOR_DATA);
SetIndexBuffer(2, BufferPos, INDICATOR_CALCULATIONS);
SetIndexBuffer(3, BufferNeg, INDICATOR_CALCULATIONS);
SetIndexBuffer(4, BufferHAClose, INDICATOR_CALCULATIONS);
//--- Set accuracy
IndicatorSetInteger(INDICATOR_DIGITS, 2);
//--- Set drawing start positions
PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, ExtPeriodRSI + ExtPeriodMA);
PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, ExtPeriodRSI);
//--- Set labels for DataWindow
PlotIndexSetString(0, PLOT_LABEL, "HA_RSIMA");
PlotIndexSetString(1, PLOT_LABEL, "HA_RSI");
//--- Set indicator short name
IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("HA_RSI(%d, %d)", ExtPeriodRSI, ExtPeriodMA));
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator 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 data
if(rates_total < ExtPeriodRSI)
return(0);
//====== STEP 1: CALCULATE HEIKEN ASHI BARS ======
double ha_open, ha_close;
// Calculate the very first HA bar
ha_open = (open[0] + close[0]) / 2.0;
ha_close = (open[0] + high[0] + low[0] + close[0]) / 4.0;
BufferHAClose[0] = ha_close;
// Loop to calculate all HA bars
for(int i = 1; i < rates_total; i++)
{
// Previous HA values are needed
double prev_ha_open = ha_open;
double prev_ha_close = ha_close;
// Calculate current HA values
ha_close = (open[i] + high[i] + low[i] + close[i]) / 4.0;
ha_open = (prev_ha_open + prev_ha_close) / 2.0;
// We only need the HA Close for RSI, so we store it in our buffer
BufferHAClose[i] = ha_close;
}
//====== STEP 2: CALCULATE RSI BASED ON HEIKEN ASHI CLOSE PRICES ======
// This part is adapted from the standard RSI indicator code
int start_pos;
if(prev_calculated > 0)
start_pos = prev_calculated - 1;
else
start_pos = 0;
// --- First-time calculation setup ---
if(start_pos == 0)
{
double sum_pos = 0.0;
double sum_neg = 0.0;
// Initialize first period values to zero
for(int i = 0; i < ExtPeriodRSI; i++)
{
BufferHARSI[i] = 0.0;
BufferPos[i] = 0.0;
BufferNeg[i] = 0.0;
}
// Calculate initial sums for the first visible RSI value
for(int i = 1; i <= ExtPeriodRSI; i++)
{
double diff = BufferHAClose[i] - BufferHAClose[i-1];
sum_pos += (diff > 0 ? diff : 0);
sum_neg += (diff < 0 ? -diff : 0);
}
// Calculate first visible value
BufferPos[ExtPeriodRSI] = sum_pos / ExtPeriodRSI;
BufferNeg[ExtPeriodRSI] = sum_neg / ExtPeriodRSI;
if(BufferNeg[ExtPeriodRSI] != 0.0)
BufferHARSI[ExtPeriodRSI] = 100.0 - (100.0 / (1.0 + BufferPos[ExtPeriodRSI] / BufferNeg[ExtPeriodRSI]));
else
BufferHARSI[ExtPeriodRSI] = (BufferPos[ExtPeriodRSI] != 0.0) ? 100.0 : 50.0;
// Set the starting position for the main loop
start_pos = ExtPeriodRSI + 1;
}
// --- Main RSI calculation loop ---
for(int i = start_pos; i < rates_total; i++)
{
double diff = BufferHAClose[i] - BufferHAClose[i-1];
BufferPos[i] = (BufferPos[i-1] * (ExtPeriodRSI - 1) + (diff > 0.0 ? diff : 0.0)) / ExtPeriodRSI;
BufferNeg[i] = (BufferNeg[i-1] * (ExtPeriodRSI - 1) + (diff < 0.0 ? -diff : 0.0)) / ExtPeriodRSI;
if(BufferNeg[i] != 0.0)
BufferHARSI[i] = 100.0 - 100.0 / (1.0 + BufferPos[i] / BufferNeg[i]);
else
BufferHARSI[i] = (BufferPos[i] != 0.0) ? 100.0 : 50.0;
}
//====== STEP 3: CALCULATE MOVING AVERAGE ON THE HEIKEN ASHI RSI BUFFER ======
// We use the robust manual loop from our final RSIMA indicator
if(rates_total < ExtPeriodRSI + ExtPeriodMA)
return(rates_total); // Not enough data for MA yet
// Determine starting bar for MA calculation
if(prev_calculated > 0)
start_pos = prev_calculated - 1;
else
start_pos = ExtPeriodRSI + ExtPeriodMA - 2;
// Loop through bars that need MA calculation
for(int i = start_pos; i < rates_total; i++)
{
if(i < ExtPeriodRSI + ExtPeriodMA - 2)
{
BufferHARSI_MA[i] = EMPTY_VALUE;
continue;
}
switch(InpMethodMA)
{
case MODE_EMA:
BufferHARSI_MA[i] = ExponentialMA(i, ExtPeriodMA, BufferHARSI_MA[i-1], BufferHARSI);
break;
case MODE_SMMA:
BufferHARSI_MA[i] = SmoothedMA(i, ExtPeriodMA, BufferHARSI_MA[i-1], BufferHARSI);
break;
case MODE_LWMA:
BufferHARSI_MA[i] = LinearWeightedMA(i, ExtPeriodMA, BufferHARSI);
break;
default: // MODE_SMA
BufferHARSI_MA[i] = SimpleMA(i, ExtPeriodMA, BufferHARSI);
break;
}
}
return(rates_total);
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+