Files
mql5/Indicators/MyIndicators/WPRMA_HeikenAshi.mq5
T
2025-08-12 18:07:35 +02:00

200 lines
15 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//+------------------------------------------------------------------+
//| WPRMA_HeikenAshi.mq5 |
//| Copyright 2025, xxxxxxxx (Based on MetaQuotes WPR) |
//| |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, xxxxxxxx"
#property link ""
#property version "1.00"
#property description "WPR on Heiken Ashi candles, with a Moving Average."
// --- Standard and Custom Includes ---
#include <MovingAverages.mqh>
#include <MyIncludes\HA_Tools.mqh>
//--- 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 Heiken Ashi WPR line
//--- Global Objects and Variables ---
int ExtWPRPeriod;
int ExtMAPeriod;
CHA_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. |
//+------------------------------------------------------------------+
void OnInit()
{
//--- Validate and store input periods
ExtWPRPeriod = (InpWPRPeriod < 1) ? 1 : InpWPRPeriod;
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, ExtWPRPeriod + ExtMAPeriod - 2);
PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, ExtWPRPeriod - 1);
IndicatorSetString(INDICATOR_SHORTNAME, StringFormat("HA_WPRMA(%d, %d)", ExtWPRPeriod, ExtMAPeriod));
IndicatorSetInteger(INDICATOR_DIGITS, 2);
}
//+------------------------------------------------------------------+
//| Williams Percent Range on Heiken 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[])
{
if(rates_total < ExtWPRPeriod)
return(0);
// STEP 1: Calculate Heiken Ashi (full recalculation)
if(!g_ha_calculator.Calculate(rates_total, 0, open, high, low, close))
return(0);
// STEP 2: Calculate WPR
for(int i = ExtWPRPeriod - 1; i < rates_total; i++)
{
double max_ha_high = Highest(g_ha_calculator.ha_high, ExtWPRPeriod, i);
double min_ha_low = Lowest(g_ha_calculator.ha_low, ExtWPRPeriod, i);
if(max_ha_high != min_ha_low)
BufferHA_WPR[i] = - (max_ha_high - g_ha_calculator.ha_close[i]) * 100.0 / (max_ha_high - min_ha_low);
else
BufferHA_WPR[i] = (i > 0) ? BufferHA_WPR[i-1] : -50.0;
}
// STEP 3: Calculate Moving Average (with EMA/SMMA fix)
if(rates_total < ExtWPRPeriod + ExtMAPeriod - 1)
return(rates_total);
for(int i = 1; i < rates_total; i++)
{
if(i < ExtWPRPeriod + ExtMAPeriod - 2)
{
BufferHA_WPRMA[i] = EMPTY_VALUE;
continue;
}
// --- Calculate the MA value for the current bar 'i' ---
switch(InpMAMethod)
{
case MODE_EMA:
// --- Special handling for EMA ---
if(i == ExtWPRPeriod + ExtMAPeriod - 2) // First EMA value is an SMA
{
BufferHA_WPRMA[i] = SimpleMA(i, ExtMAPeriod, BufferHA_WPR);
}
else // Subsequent EMA values are calculated recursively
{
double pr = 2.0 / (ExtMAPeriod + 1.0);
BufferHA_WPRMA[i] = BufferHA_WPR[i] * pr + BufferHA_WPRMA[i-1] * (1.0 - pr);
}
break;
case MODE_SMMA:
if(i == ExtWPRPeriod + ExtMAPeriod - 2) // First SMMA value is an SMA
{
BufferHA_WPRMA[i] = SimpleMA(i, ExtMAPeriod, BufferHA_WPR);
}
else // Subsequent SMMA values are calculated recursively
{
BufferHA_WPRMA[i] = (BufferHA_WPRMA[i-1] * (ExtMAPeriod - 1) + BufferHA_WPR[i]) / ExtMAPeriod;
}
break;
case MODE_LWMA:
BufferHA_WPRMA[i] = LinearWeightedMA(i, ExtMAPeriod, BufferHA_WPR);
break;
default: // MODE_SMA
BufferHA_WPRMA[i] = SimpleMA(i, ExtMAPeriod, BufferHA_WPR);
break;
}
}
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);
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+