mql5/Include/Escape/VolatilityManager.mqh

453 lines
17 KiB
MQL5
Raw Permalink Normal View History

2025-08-05 01:57:33 -04:00
//+------------------------------------------------------------------+
//| VolatilityManager.mqh |
//| Copyright 2025, EscapeEA Team |
//| https://www.escapeea.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, EscapeEA Team"
#property link "https://www.escapeea.com"
#property version "1.00"
#property strict
#include <Escape/Common/ErrorHandler.mqh>
//+------------------------------------------------------------------+
//| Volatility Calculation Methods |
//+------------------------------------------------------------------+
enum ENUM_VOLATILITY_METHOD
{
VOL_ATR, // Average True Range
VOL_STD_DEV, // Standard Deviation
VOL_PARKINSON, // Parkinson's volatility
VOL_GK, // Garman-Klass volatility
VOL_RS, // Rogers-Satchell volatility
VOL_YZ // Yang-Zhang volatility
};
//+------------------------------------------------------------------+
//| Volatility Manager Class |
//+------------------------------------------------------------------+
class CVolatilityManager
{
private:
// Configuration
ENUM_TIMEFRAMES m_timeframe; // Default timeframe for calculations
int m_period; // Default period for calculations
ENUM_VOLATILITY_METHOD m_method; // Default calculation method
// State
bool m_initialized; // Initialization flag
// Cache
double m_lastValues[]; // Cache of last calculated values
datetime m_lastUpdate; // Last update time
public:
//--- Constructor/Destructor
CVolatilityManager(void);
~CVolatilityManager(void);
//--- Initialization
bool Initialize(void);
void Shutdown(void);
//--- Volatility Calculation
double GetVolatility(const string symbol, const ENUM_TIMEFRAMES timeframe, const int period,
const ENUM_VOLATILITY_METHOD method, const int shift=0);
double GetCurrentVolatility(const string symbol, const ENUM_TIMEFRAMES timeframe,
const int period, const ENUM_VOLATILITY_METHOD method);
double GetAverageVolatility(const string symbol, const ENUM_TIMEFRAMES timeframe,
const int period, const int bars, const ENUM_VOLATILITY_METHOD method);
//--- Configuration
void SetDefaultTimeframe(const ENUM_TIMEFRAMES timeframe) { m_timeframe = timeframe; }
void SetDefaultPeriod(const int period) { m_period = period; }
void SetDefaultMethod(const ENUM_VOLATILITY_METHOD method) { m_method = method; }
private:
//--- Calculation Methods
double CalculateATR(const string symbol, const int period, const int shift);
double CalculateStdDev(const string symbol, const int period, const int shift);
double CalculateParkinson(const string symbol, const int period, const int shift);
double CalculateGarmanKlass(const string symbol, const int period, const int shift);
double CalculateRogersSatchell(const string symbol, const int period, const int shift);
double CalculateYangZhang(const string symbol, const int period, const int shift);
//--- Helper Methods
void UpdateCache(const string symbol, const ENUM_TIMEFRAMES timeframe,
const int period, const ENUM_VOLATILITY_METHOD method);
string GenerateCacheKey(const string symbol, const ENUM_TIMEFRAMES timeframe,
const int period, const ENUM_VOLATILITY_METHOD method) const;
double GetCachedValue(const string key);
void SetCachedValue(const string key, const double value);
};
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
CVolatilityManager::CVolatilityManager(void) :
m_timeframe(PERIOD_CURRENT),
m_period(14),
m_method(VOL_ATR),
m_initialized(false),
m_lastUpdate(0)
{
ArrayResize(m_lastValues, 0);
}
//+------------------------------------------------------------------+
//| Destructor |
//+------------------------------------------------------------------+
CVolatilityManager::~CVolatilityManager(void)
{
Shutdown();
}
//+------------------------------------------------------------------+
//| Initialize the volatility manager |
//+------------------------------------------------------------------+
bool CVolatilityManager::Initialize(void)
{
if(m_initialized)
return true;
// Initialize any required resources
m_initialized = true;
return true;
}
//+------------------------------------------------------------------+
//| Shutdown the volatility manager |
//+------------------------------------------------------------------+
void CVolatilityManager::Shutdown(void)
{
if(!m_initialized)
return;
// Clean up resources
ArrayFree(m_lastValues);
m_initialized = false;
}
//+------------------------------------------------------------------+
//| Get volatility using specified parameters |
//+------------------------------------------------------------------+
double CVolatilityManager::GetVolatility(const string symbol, const ENUM_TIMEFRAMES timeframe,
const int period, const ENUM_VOLATILITY_METHOD method, const int shift)
{
// Check for valid parameters
if(period <= 0)
{
CErrorHandler::HandleError(ERR_INVALID_PARAMETER, "Invalid period: " + IntegerToString(period));
return 0.0;
}
// Use default values if not specified
ENUM_TIMEFRAMES tf = (timeframe == PERIOD_CURRENT) ? m_timeframe : timeframe;
int p = (period <= 0) ? m_period : period;
ENUM_VOLATILITY_METHOD m = (method == -1) ? m_method : method;
// Calculate volatility based on selected method
double volatility = 0.0;
switch(m)
{
case VOL_ATR:
volatility = CalculateATR(symbol, p, shift);
break;
case VOL_STD_DEV:
volatility = CalculateStdDev(symbol, p, shift);
break;
case VOL_PARKINSON:
volatility = CalculateParkinson(symbol, p, shift);
break;
case VOL_GK:
volatility = CalculateGarmanKlass(symbol, p, shift);
break;
case VOL_RS:
volatility = CalculateRogersSatchell(symbol, p, shift);
break;
case VOL_YZ:
volatility = CalculateYangZhang(symbol, p, shift);
break;
default:
CErrorHandler::HandleError(ERR_INVALID_PARAMETER, "Unknown volatility method: " + IntegerToString(m));
break;
}
return volatility;
}
//+------------------------------------------------------------------+
//| Get current volatility |
//+------------------------------------------------------------------+
double CVolatilityManager::GetCurrentVolatility(const string symbol, const ENUM_TIMEFRAMES timeframe,
const int period, const ENUM_VOLATILITY_METHOD method)
{
return GetVolatility(symbol, timeframe, period, method, 0);
}
//+------------------------------------------------------------------+
//| Get average volatility over a number of bars |
//+------------------------------------------------------------------+
double CVolatilityManager::GetAverageVolatility(const string symbol, const ENUM_TIMEFRAMES timeframe,
const int period, const int bars, const ENUM_VOLATILITY_METHOD method)
{
if(bars <= 0)
{
CErrorHandler::HandleError(ERR_INVALID_PARAMETER, "Invalid number of bars: " + IntegerToString(bars));
return 0.0;
}
double sum = 0.0;
int count = 0;
// Calculate average volatility over the specified number of bars
for(int i = 0; i < bars; i++)
{
double vol = GetVolatility(symbol, timeframe, period, method, i);
if(vol > 0)
{
sum += vol;
count++;
}
}
return (count > 0) ? sum / count : 0.0;
}
//+------------------------------------------------------------------+
//| Calculate Average True Range (ATR) |
//+------------------------------------------------------------------+
double CVolatilityManager::CalculateATR(const string symbol, const int period, const int shift)
{
double atr = iATR(symbol, m_timeframe, period, shift);
if(atr == 0)
{
CErrorHandler::HandleError(ERR_INDICATOR_CALCULATION, "Failed to calculate ATR for " + symbol);
return 0.0;
}
return atr;
}
//+------------------------------------------------------------------+
//| Calculate Standard Deviation |
//+------------------------------------------------------------------+
double CVolatilityManager::CalculateStdDev(const string symbol, const int period, const int shift)
{
double close[];
ArraySetAsSeries(close, true);
// Get close prices
if(CopyClose(symbol, m_timeframe, shift, period, close) != period)
{
CErrorHandler::HandleError(ERR_HISTORY_NOT_FOUND, "Failed to get close prices for " + symbol);
return 0.0;
}
// Calculate mean
double sum = 0.0;
for(int i = 0; i < period; i++)
sum += close[i];
double mean = sum / period;
// Calculate variance
double variance = 0.0;
for(int i = 0; i < period; i++)
variance += MathPow(close[i] - mean, 2);
variance /= period;
// Standard deviation is the square root of variance
return MathSqrt(variance);
}
//+------------------------------------------------------------------+
//| Calculate Parkinson Volatility |
//+------------------------------------------------------------------+
double CVolatilityManager::CalculateParkinson(const string symbol, const int period, const int shift)
{
double high[], low[];
ArraySetAsSeries(high, true);
ArraySetAsSeries(low, true);
// Get high and low prices
if(CopyHigh(symbol, m_timeframe, shift, period, high) != period ||
CopyLow(symbol, m_timeframe, shift, period, low) != period)
{
CErrorHandler::HandleError(ERR_HISTORY_NOT_FOUND, "Failed to get price data for Parkinson");
return 0.0;
}
// Calculate Parkinson volatility
double sum = 0.0;
for(int i = 0; i < period; i++)
{
if(high[i] > 0 && low[i] > 0)
sum += MathLog(high[i] / low[i]) * MathLog(high[i] / low[i]);
}
return MathSqrt(sum / (4 * period * MathLog(2)));
}
//+------------------------------------------------------------------+
//| Calculate Garman-Klass Volatility |
//+------------------------------------------------------------------+
double CVolatilityManager::CalculateGarmanKlass(const string symbol, const int period, const int shift)
{
double open[], high[], low[], close[];
ArraySetAsSeries(open, true);
ArraySetAsSeries(high, true);
ArraySetAsSeries(low, true);
ArraySetAsSeries(close, true);
// Get price data
if(CopyOpen(symbol, m_timeframe, shift, period, open) != period ||
CopyHigh(symbol, m_timeframe, shift, period, high) != period ||
CopyLow(symbol, m_timeframe, shift, period, low) != period ||
CopyClose(symbol, m_timeframe, shift, period, close) != period)
{
CErrorHandler::HandleError(ERR_HISTORY_NOT_FOUND, "Failed to get price data for Garman-Klass");
return 0.0;
}
// Calculate Garman-Klass volatility
double sum = 0.0;
for(int i = 0; i < period; i++)
{
if(open[i] > 0 && high[i] > 0 && low[i] > 0 && close[i] > 0)
{
double u = MathLog(high[i] / open[i]);
double d = MathLog(low[i] / open[i]);
double c = MathLog(close[i] / open[i]);
sum += 0.511 * (u - d) * (u - d) - 0.019 * (c * (u + d) - 2 * u * d) - 0.383 * c * c;
}
}
return MathSqrt(sum / period);
}
//+------------------------------------------------------------------+
//| Calculate Rogers-Satchell Volatility |
//+------------------------------------------------------------------+
double CVolatilityManager::CalculateRogersSatchell(const string symbol, const int period, const int shift)
{
double open[], high[], low[], close[];
ArraySetAsSeries(open, true);
ArraySetAsSeries(high, true);
ArraySetAsSeries(low, true);
ArraySetAsSeries(close, true);
// Get price data
if(CopyOpen(symbol, m_timeframe, shift, period, open) != period ||
CopyHigh(symbol, m_timeframe, shift, period, high) != period ||
CopyLow(symbol, m_timeframe, shift, period, low) != period ||
CopyClose(symbol, m_timeframe, shift, period, close) != period)
{
CErrorHandler::HandleError(ERR_HISTORY_NOT_FOUND, "Failed to get price data for Rogers-Satchell");
return 0.0;
}
// Calculate Rogers-Satchell volatility
double sum = 0.0;
for(int i = 0; i < period; i++)
{
if(open[i] > 0 && high[i] > 0 && low[i] > 0 && close[i] > 0)
{
double u = MathLog(high[i] / open[i]);
double d = MathLog(low[i] / open[i]);
double c = MathLog(close[i] / open[i]);
sum += u * (u - c) + d * (d - c);
}
}
return MathSqrt(sum / period);
}
//+------------------------------------------------------------------+
//| Calculate Yang-Zhang Volatility |
//+------------------------------------------------------------------+
double CVolatilityManager::CalculateYangZhang(const string symbol, const int period, const int shift)
{
double open[], close[];
ArraySetAsSeries(open, true);
ArraySetAsSeries(close, true);
// Get open and close prices
if(CopyOpen(symbol, m_timeframe, shift, period, open) != period ||
CopyClose(symbol, m_timeframe, shift-1, period+1, close) != period+1)
{
CErrorHandler::HandleError(ERR_HISTORY_NOT_FOUND, "Failed to get price data for Yang-Zhang");
return 0.0;
}
// Calculate Yang-Zhang volatility
double sum_var = 0.0;
double sum_mean = 0.0;
for(int i = 0; i < period; i++)
{
if(open[i] > 0 && close[i] > 0 && close[i+1] > 0)
{
double o = MathLog(open[i] / close[i+1]);
double c = MathLog(close[i] / open[i]);
double u = MathLog(high[i] / open[i]);
double d = MathLog(low[i] / open[i]);
double rs = u * (u - c) + d * (d - c);
double o_c = o * o;
double c_c = c * c;
sum_var += 0.511 * rs - 0.019 * (c * (u + d) - 2 * u * d) - 0.383 * c_c;
sum_mean += o_c;
}
}
double k = 0.34 / (1.34 + (period + 1) / (period - 1));
return MathSqrt(sum_var / period + k * sum_mean / (period - 1));
}
//+------------------------------------------------------------------+
//| Update the cache with latest values |
//+------------------------------------------------------------------+
void CVolatilityManager::UpdateCache(const string symbol, const ENUM_TIMEFRAMES timeframe,
const int period, const ENUM_VOLATILITY_METHOD method)
{
// Implementation for caching would go here
// This is a placeholder for actual caching logic
}
//+------------------------------------------------------------------+
//| Generate a cache key |
//+------------------------------------------------------------------+
string CVolatilityManager::GenerateCacheKey(const string symbol, const ENUM_TIMEFRAMES timeframe,
const int period, const ENUM_VOLATILITY_METHOD method) const
{
return symbol + "_" + IntegerToString(timeframe) + "_" + IntegerToString(period) + "_" + IntegerToString(method);
}
//+------------------------------------------------------------------+
//| Get a value from cache |
//+------------------------------------------------------------------+
double CVolatilityManager::GetCachedValue(const string key)
{
// Implementation for getting cached values would go here
// This is a placeholder for actual caching logic
return 0.0;
}
//+------------------------------------------------------------------+
//| Set a value in cache |
//+------------------------------------------------------------------+
void CVolatilityManager::SetCachedValue(const string key, const double value)
{
// Implementation for setting cached values would go here
// This is a placeholder for actual caching logic
}
//+------------------------------------------------------------------+