453 lines
17 KiB
MQL5
453 lines
17 KiB
MQL5
//+------------------------------------------------------------------+
| |||
//| 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
| |||
}
| |||
//+------------------------------------------------------------------+
|