Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Garch addition #14

Open
wants to merge 4 commits into
base: garch
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 23 additions & 7 deletions timeseries/fit.q
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,29 @@ ts.ARCH.fit:{[resid;lags]
resid:"f"$resid;
// cast endog to floating value
sqresid:resid*resid;
// Using the resid errorrs calculate coefficients
// fit using an AR model
coeff:ts.i.estimateParams[sqresid;();sqresid;`p`q`tr!lags,0,1b];
// Get lagged values needed for future predictions
resid:neg[lags]#sqresid;
// return dictionary with required info for predictions
keyVals:`params`tr_param`p_param`resid;
params:(coeff;coeff[0];1_coeff;resid);
keyVals!params
coeff:ts.i.ARCH.updCoeffs[sqresid;coeff;lags];
lagvals:neg[lags]#sqresid;
keyvals:`params`tr_param`p_param`lags;
params:(coeff;1#coeff;neg[lags]#coeff;lagvals);
keyvals!params
}

// @kind function
// @category modelFit
// @fileoverview Fit a Generalized AutoRegressive Conditional Heteroscedasticity model (ARCH)
// @param resid {num[]} Residual errors from fitted time series model
// @param lags {integer} The number/order of time lags of the model
// @param error {integer} The number/order of error to account for
// @return {dict} All information required to use a fit model for the prediction of
// new values based on incoming data
ts.GARCH.fit:{[resid;lags;error]
if[error~0;:ts.ARCH.fit[resid;lags],enlist[`q_param]!enlist ()];
// cast to floating value
resid:"f"$resid;
// cast endog to floating value
sqresid:resid*resid;
// cast endog to floating value
ts.i.GARCH.model[sqresid;`p`q`tr!lags,error,1b]
}
20 changes: 17 additions & 3 deletions timeseries/predict.q
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,21 @@ ts.SARIMA.predict:{[mdl;exog;len]
// Predict future volatility using an ARCH model
/. r > list of predicted values
ts.ARCH.predict:{[mdl;len]
ts.i.dictCheck[mdl;ts.i.ARCH.keyList;"mdl"];
// predict and return future values
last{x>count y 1}[len;]ts.i.ARCH.singlePredict[mdl`params]/(mdl`resid;())
mdl,:enlist[`exog_param]!enlist();
ts.AR.predict[mdl;();len]
}

// @kind function
// @category modelPredict
// @fileoverview Predictions based on a Generalized AutoRegressive Conditional Heteroskedasticity
// model (GARCH)
// @param mdl {dict} model parameters returned from fitting of an appropriate model
// @param len {integer} number of values to be predicted
// @return {float[]} list of predicted values
// Predict future volatility using an ARCH model
/. r > list of predicted values
ts.GARCH.predict:{[mdl;len]
if[()~mdl`q_param;:ts.ARCH.predict[mdl;len]];
mdl,:enlist[`exog_param]!enlist();
ts.i.predictFunction[mdl;();len;ts.i.GARCH.singlePredict]
}
141 changes: 138 additions & 3 deletions timeseries/utils.q
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,27 @@ ts.i.SARMA.model:{[endog;exog;params]
modelKeys!modelParams
}

// @private
// @kind function
// @category fitUtility
// @fileoverview GARCH model generation
// @param endog {num[]} Endogenous variable (time-series) from which to build a model
// this is the target variable from which a value is to be predicted
// @param params {dict} parameter sets used to fit the SARMA model
// @return {dict} dictionary containing all information required to make predictions
// using an SARMA based model
ts.i.GARCH.model:{[endog;params]
n:1+max params`p`q;
errCoeff:ts.i.estimateErrorCoeffs[endog;();params;n];
coeffs:abs ts.i.GARCH.coefficients[endog;errCoeff[`errors]`err;errCoeff`coeffs;params];
// update p param if q>p for future prediction
params[`p]:max params`p`q;
GARCHparams:ts.i.ARMA.parameters[endog;coeffs;params;errCoeff`errors;n];
modelKeys:`params`tr_param`p_param`q_param`lags`resid`estresid`pred_dict;
modelParams:(coeffs(::;params[`tr]-1)),GARCHparams;
modelKeys!modelParams
}

// @private
// @kind function
// @category fitUtility
Expand Down Expand Up @@ -178,12 +199,100 @@ ts.i.SARMA.coefficients:{[endog;exog;resid;coeff;params]
];
// normal arima vals
vals:(exog;lagVal;residVal;seasLag;seasResid);
params[`norm_mat]:(,'/)m#'vals;
optD:`xk`args!(coeff;params);
params[`norm_mat]:(,'/)m#'vals;
// use optimizer function to improve SARMA coefficients
.ml.optimize.BFGS[ts.i.SARMA.maxLikelihood;coeff;params;::]`xVals
}

// @private
// @kind function
// @category fitUtility
// @fileoverview Estimate coefficients as starting points to calculate the GARCH coeffs
// @param endog {num[]} Endogenous variable (time-series) from which to build a model
// this is the target variable from which a value is to be predicted
// @param resid {num[][]} residual errors estimated using i.estimateErrorCoeffs
// @param coeff {num[][]} Estimated coefficients for ARMA model using OLS
// @param params {dict} Information on seasonal and non seasonal lags to be accounted for
// @return {dict} updated optimized coefficients for SARMA model
ts.i.GARCH.coefficients:{[endog;errors;coeff;params]
// Create lagged matrices for the endogenous variable and residual errors
endogm:ts.i.lagMatrix[endog ;max params`p`q];
resid :ts.i.lagMatrix[errors;params`q];
// Collect the data needed for estimation
vals:(endogm;resid);
// How many data points are required
m:neg min raze(count[endog]-params[`p]),count[errors]-params[`q];
x:(,'/)m#'vals;
// If required add a trend line variable
x:1f,'x;
y:m#endog;
params[`y]:y;
params[`x]:x;
.ml.optimize.BFGS[ts.i.GARCH.maxLikelihood;coeff;params;::]`xVals
}

// @private
// @kind function
// @category fitUtility
// @fileoverview Use maximum likelihood to update coefficients
// @param endog {num[]} Endogenous variable (time-series) from which to build a model
// this is the target variable from which a value is to be predicted
// @param coeff {num[][]} Estimated coefficients for ARMA model using OLS
// @param lag {int} Number of lag values to include
// @return {dict} updated optimized coefficients for ARMA model
ts.i.ARCH.updCoeffs:{[endog;coeff;lag]
// Create lagged matrices for the endogenous variable and residual errors
endogm:enlist ts.i.lagMatrix[endog;lag];
m:neg count[endog]-lag;
x:1f,'(,'/)m#'endogm;
y:m#endog;
params:`x`y!(x;y);
abs .ml.optimize.BFGS[ts.i.ARCH.maxLikelihood;coeff;params;::]`xVals
}

// @private
// @kind function
// @category fitUtility
// @fileoverview Calculation of the errors in calculation of the ARCH coefficients
// @param params {dict} Parameters required for calculation of ARCH coefficients
// @param dict {dict} Additional parameters required in calculation
// @return {float} returns the square root of the summed, squared errors
ts.i.ARCH.maxLikelihood:{[coeff;dict]
preds:dict[`x] mmu abs coeff;
sqrt sum n*n:preds-dict`y
}

// @private
// @kind function
// @category fitUtility
// @fileoverview Calculation of the errors in calculation of the GARCH coefficients
// @param params {dict} Parameters required for calculation of GARCH coefficients
// @param dict {dict} Additional parameters required in calculation
// @return {float} returns the square root of the summed, squared errors
ts.i.GARCH.maxLikelihood:{[params;dict]
updParams:ts.i.GARCH.preproc[params;dict];
preds:dict[`x] mmu updParams;
// calculate error
sqrt sum n*n:preds-dict`y
}

// @private
// @kind function
// @category fitUtility
// @fileoverview Prepare parameters to be used for prediction
// @param params {dict} Parameters required for calculation of GARCH coefficients
// @param dict {dict} Additional parameters required in calculation
// @return {float} information required for prediction
ts.i.GARCH.preproc:{[params;dict]
params:abs params;
trend:first params;
pVar:dict[`p]#1_params;
qVar:neg[dict`q]#params;
m:til max dict`p`q;
pVarUpd:(0^pVar[m])+0^qVar[m];
trend,pVarUpd,neg qVar
}

// @private
// @kind function
// @category fitUtility
Expand Down Expand Up @@ -256,7 +365,7 @@ ts.i.AR.keyList :`params`tr_param`exog_param`p_param`lags
ts.i.ARMA.keyList :ts.i.AR.keyList,`q_param`resid`estresid`pred_dict
ts.i.ARIMA.keyList :ts.i.ARMA.keyList,`origd
ts.i.SARIMA.keyList:ts.i.ARIMA.keyList,`origs`P_param`Q_param
ts.i.ARCH.keyList :`params`tr_param`p_param`resid
ts.i.ARCH.keyList :`params`tr_param`p_param`lags

// @private
// @kind function
Expand Down Expand Up @@ -318,6 +427,7 @@ ts.i.ARMA.singlePredict:{[params;exog;dict;pvals;estresid]
((1_pvals[0]),pred;pvals[1];pvals[2],pred)
}


// @private
// @kind function
// @category predictUtility
Expand Down Expand Up @@ -463,6 +573,31 @@ ts.i.ARCH.singlePredict:{[params;pvals]
((1_pvals 0),predict;pvals[1],predict)
}


// GARCH predict functions

// @private
// @kind function
// @category predictUtility
// @fileoverview predict a single ARCH value
// @param params {num[]} model parameters retrieved from initial fit model
// @param exog {tab} exogenous variables, are additional variables which
// may be accounted for to improve the model
// @param dict {dict} additional information which can dictate the behaviour
// when making a prediction
// @param pvals {num[]} previously predicted values
// @param estresid {num[]} estimates of the residual errors
// @return {num[]} information required for the prediction of a set of ARMA values
ts.i.GARCH.singlePredict:{[params;exog;dict;pvals;estresid]
normmat:raze#[neg[dict`p];pvals[0]],pvals[1];
updParams:ts.i.GARCH.preproc[params;dict];
pred:updParams[0] + normmat mmu 1_updParams;
estvals:pvals[0];
pvals[1]:(1_pvals[1]),pred-mmu[estresid;estvals];
((1_pvals[0]),pred;pvals[1];pvals[2],pred)
}


// Akaike Information Criterion

// @private
Expand Down