196 lines
6.3 KiB
MQL5
196 lines
6.3 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| ConditionalVolatility_forecaster.mq5 |
|
|
//| Copyright 2025, MetaQuotes Ltd. |
|
|
//| https://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2025, MetaQuotes Ltd."
|
|
#property link "https://www.mql5.com"
|
|
#property version "1.00"
|
|
#include<VolatilityModels\Arch\Univariate\mean.mqh>
|
|
#property indicator_separate_window
|
|
#property indicator_buffers 2
|
|
#property indicator_plots 2
|
|
//--- plot Forecast
|
|
#property indicator_label1 "Forecast"
|
|
#property indicator_type1 DRAW_LINE
|
|
#property indicator_color1 clrRed
|
|
#property indicator_style1 STYLE_DOT
|
|
#property indicator_width1 1
|
|
//--- plot Mean
|
|
#property indicator_label2 "Vol_Zscore"
|
|
#property indicator_type2 DRAW_LINE
|
|
#property indicator_color2 clrLimeGreen
|
|
#property indicator_style2 STYLE_SOLID
|
|
#property indicator_width2 1
|
|
//--- input parameters
|
|
input int BarsToDraw = 50;
|
|
input int HistoryLen = 200;
|
|
input double Num_Stds = 1.5;
|
|
input double ScaleFactor=100.;
|
|
input ENUM_MEAN_MODEL MeanModel = MEAN_CONSTANT;
|
|
input bool MeanConstant = false;
|
|
input string MeanLags ="";
|
|
input ENUM_VOLATILITY_MODEL VolatilityModel = VOL_TARCH;
|
|
input ulong _P_ = 1;
|
|
input ulong _O_ = 1;
|
|
input ulong _Q_ = 1;
|
|
input int Volatility_Seed = 0;
|
|
input ENUM_DISTRIBUTION_MODEL ErrorDistribution = DIST_NORMAL;
|
|
input int Distribution_Seed = 0;
|
|
//--- indicator buffers
|
|
double ForecastBuffer[];
|
|
double ThresholdBuffer[];
|
|
double VolZscoreBuffer[];
|
|
vector returns = vector::Zeros(HistoryLen);
|
|
ArchParameters spec;
|
|
HARX* full_model;
|
|
//+------------------------------------------------------------------+
|
|
//| Custom indicator initialization function |
|
|
//+------------------------------------------------------------------+
|
|
int OnInit()
|
|
{
|
|
if(HistoryLen<30)
|
|
{
|
|
Print("Invalid input value for HistoryLen");
|
|
return INIT_FAILED;
|
|
}
|
|
//--- indicator buffers mapping
|
|
SetIndexBuffer(0,ForecastBuffer,INDICATOR_DATA);
|
|
SetIndexBuffer(1,VolZscoreBuffer,INDICATOR_DATA);
|
|
//---
|
|
PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,BarsToDraw);
|
|
PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,BarsToDraw);
|
|
//---
|
|
IndicatorSetInteger(INDICATOR_LEVELS,2);
|
|
IndicatorSetDouble(INDICATOR_LEVELVALUE,0,Num_Stds);
|
|
IndicatorSetDouble(INDICATOR_LEVELVALUE,1,-1.0);
|
|
//---
|
|
spec.mean_model_type = MeanModel;
|
|
if(StringLen(MeanLags))
|
|
{
|
|
string lag_info[];
|
|
int nlags = StringSplit(MeanLags,StringGetCharacter(",",0),lag_info);
|
|
if(nlags>0)
|
|
{
|
|
for(uint i = 0; i<uint(nlags); ++i)
|
|
{
|
|
if(StringLen(lag_info[i])>0)
|
|
{
|
|
if(spec.mean_lags.Resize(spec.mean_lags.Size()+1,3))
|
|
spec.mean_lags[spec.mean_lags.Size()-1] = StringToDouble(lag_info[i]);
|
|
else
|
|
{
|
|
Print(" error ", GetLastError());
|
|
return INIT_FAILED;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
spec.vol_rng_seed = Volatility_Seed;
|
|
spec.garch_o = _O_;
|
|
spec.garch_p = _P_;
|
|
spec.garch_q = _Q_;
|
|
spec.dist_type = ErrorDistribution;
|
|
spec.dist_rng_seed = Distribution_Seed;
|
|
|
|
switch(MeanModel)
|
|
{
|
|
case MEAN_CONSTANT:
|
|
full_model = new ConstantMean();
|
|
break;
|
|
case MEAN_ZERO:
|
|
full_model = new ZeroMean();
|
|
break;
|
|
case MEAN_AR:
|
|
full_model = new AR();
|
|
break;
|
|
default:
|
|
full_model = new ConstantMean();
|
|
break;
|
|
}
|
|
|
|
if(CheckPointer(full_model)==POINTER_INVALID)
|
|
return INIT_FAILED;
|
|
|
|
switch(VolatilityModel)
|
|
{
|
|
case VOL_GJR_GARCH:
|
|
spec.vol_model_type = VOL_GJR_GARCH;
|
|
break;
|
|
case VOL_TARCH:
|
|
spec.vol_model_type = VOL_TARCH;
|
|
break;
|
|
default:
|
|
spec.vol_model_type = VOL_GARCH;
|
|
break;
|
|
}
|
|
|
|
return(INIT_SUCCEEDED);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Custom indicator deinitialization |
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason)
|
|
{
|
|
if(CheckPointer(full_model)==POINTER_DYNAMIC)
|
|
delete full_model;
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
//| Custom indicator iteration function |
|
|
//+------------------------------------------------------------------+
|
|
int OnCalculate(const int32_t rates_total,
|
|
const int32_t 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 int32_t &spread[])
|
|
{
|
|
//---
|
|
int32_t limit;
|
|
static datetime last_time;
|
|
if(time[rates_total-1]==last_time)
|
|
return rates_total;
|
|
else
|
|
last_time = time[rates_total-1];
|
|
if(prev_calculated<=0)
|
|
limit = rates_total - int32_t(fabs(BarsToDraw));
|
|
else
|
|
limit = prev_calculated - 1;
|
|
for(int32_t shift = limit; shift<rates_total; ++shift)
|
|
{
|
|
int from = shift - fabs(HistoryLen);
|
|
for(int32_t i = from; i<(shift); ++i)
|
|
returns[i-(from)] = log(close[i]/close[i-1]);
|
|
returns*=fabs(ScaleFactor);
|
|
spec.observations = returns;
|
|
if(!full_model.initialize(spec))
|
|
{
|
|
Print(" initialization error ");
|
|
return 0;
|
|
}
|
|
ArchModelResult result = full_model.fit(ScaleFactor);
|
|
ulong size = result.conditional_volatility.Size();
|
|
if(!size)
|
|
{
|
|
Print(" model fit error ");
|
|
return 0;
|
|
}
|
|
|
|
ArchForecast forecast = full_model.forecast();
|
|
ForecastBuffer[shift] = (spec.vol_model_type!=VOL_TARCH)?sqrt(forecast.variance[0,0]):forecast.variance[0,0];
|
|
VolZscoreBuffer[shift] = (ForecastBuffer[shift] - result.conditional_volatility.Mean())/result.conditional_volatility.Std();
|
|
}
|
|
|
|
//--- return value of prev_calculated for next call
|
|
return(rates_total);
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|