mirror of
https://github.com/softwaredevelop/mql5.git
synced 2026-08-19 15:28:06 +00:00
231 lines
8.1 KiB
Plaintext
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);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//+------------------------------------------------------------------+
|