work on calculations
This commit is contained in:
parent
3d910a13e0
commit
ab7ef2b678
20 changed files with 1343 additions and 222 deletions
|
|
@ -352,38 +352,51 @@ export function estimateHestonParameters(
|
|||
): HestonParameters {
|
||||
const n = returns.length;
|
||||
|
||||
if (n < 10) {
|
||||
throw new Error('Need at least 10 observations for Heston parameter estimation');
|
||||
}
|
||||
|
||||
// Initial parameter estimates
|
||||
let kappa = 2.0; // Mean reversion speed
|
||||
let theta = 0.04; // Long-term variance
|
||||
let sigma = 0.3; // Vol of vol
|
||||
let sigma = 0.3; // Volatility of variance
|
||||
let rho = -0.5; // Correlation
|
||||
let v0 = 0.04; // Initial variance
|
||||
|
||||
// Calculate sample statistics for initialization
|
||||
const meanReturn = returns.reduce((sum, r) => sum + r, 0) / n;
|
||||
const sampleVariance = returns.reduce((sum, r) => sum + Math.pow(r - meanReturn, 2), 0) / (n - 1);
|
||||
|
||||
theta = sampleVariance;
|
||||
v0 = sampleVariance;
|
||||
|
||||
let logLikelihood = -Infinity;
|
||||
|
||||
for (let iter = 0; iter < maxIterations; iter++) {
|
||||
const variances: number[] = [v0];
|
||||
let newLogLikelihood = 0;
|
||||
|
||||
// Euler discretization of Heston model
|
||||
const dt = 1 / 252; // Daily time step
|
||||
let currentVariance = v0;
|
||||
|
||||
for (let t = 1; t < n; t++) {
|
||||
const prevVar = Math.max(variances[t - 1], 1e-8);
|
||||
const sqrtVar = Math.sqrt(prevVar);
|
||||
const dt = 1.0; // Assuming daily data
|
||||
const prevReturn = returns[t - 1];
|
||||
|
||||
// Simulate variance process (simplified)
|
||||
const dW2 = Math.random() - 0.5; // Should be proper random normal
|
||||
const newVar = prevVar + kappa * (theta - prevVar) * dt + sigma * sqrtVar * Math.sqrt(dt) * dW2;
|
||||
variances.push(Math.max(newVar, 1e-8));
|
||||
// Euler discretization of variance process
|
||||
const dW1 = Math.random() - 0.5; // Simplified random shock
|
||||
const dW2 = rho * dW1 + Math.sqrt(1 - rho * rho) * (Math.random() - 0.5);
|
||||
|
||||
// Calculate likelihood contribution
|
||||
const expectedReturn = 0; // Assuming zero drift for simplicity
|
||||
const variance = prevVar;
|
||||
const actualReturn = returns[t];
|
||||
const varianceChange = kappa * (theta - currentVariance) * dt +
|
||||
sigma * Math.sqrt(Math.max(currentVariance, 0)) * dW2;
|
||||
|
||||
newLogLikelihood -= 0.5 * (Math.log(2 * Math.PI) + Math.log(variance) +
|
||||
Math.pow(actualReturn - expectedReturn, 2) / variance);
|
||||
currentVariance = Math.max(currentVariance + varianceChange, 0.001);
|
||||
|
||||
// Log-likelihood contribution (simplified)
|
||||
const expectedReturn = meanReturn;
|
||||
const variance = currentVariance;
|
||||
|
||||
if (variance > 0) {
|
||||
newLogLikelihood -= 0.5 * Math.log(2 * Math.PI * variance);
|
||||
newLogLikelihood -= 0.5 * Math.pow(returns[t] - expectedReturn, 2) / variance;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for convergence
|
||||
|
|
@ -393,12 +406,13 @@ export function estimateHestonParameters(
|
|||
|
||||
logLikelihood = newLogLikelihood;
|
||||
|
||||
// Simple parameter update (in practice, use proper optimization)
|
||||
kappa = Math.max(0.1, Math.min(10, kappa + 0.01));
|
||||
theta = Math.max(0.001, Math.min(1, theta + 0.001));
|
||||
sigma = Math.max(0.01, Math.min(2, sigma + 0.01));
|
||||
rho = Math.max(-0.99, Math.min(0.99, rho + 0.01));
|
||||
v0 = Math.max(0.001, Math.min(1, v0 + 0.001));
|
||||
// Simple parameter updates (in practice, use maximum likelihood estimation)
|
||||
const learningRate = 0.001;
|
||||
kappa = Math.max(0.1, Math.min(10, kappa + learningRate));
|
||||
theta = Math.max(0.001, Math.min(1, theta + learningRate));
|
||||
sigma = Math.max(0.01, Math.min(2, sigma + learningRate));
|
||||
rho = Math.max(-0.99, Math.min(0.99, rho + learningRate * 0.1));
|
||||
v0 = Math.max(0.001, Math.min(1, v0 + learningRate));
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
@ -458,3 +472,48 @@ export function calculateVolatilityRisk(
|
|||
volatilityVolatility
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix Yang-Zhang volatility calculation
|
||||
*/
|
||||
export function calculateYangZhangVolatility(
|
||||
ohlcv: OHLCVData[],
|
||||
annualizationFactor: number = 252
|
||||
): number {
|
||||
if (ohlcv.length < 2) {
|
||||
throw new Error('Need at least 2 observations for Yang-Zhang volatility calculation');
|
||||
}
|
||||
|
||||
const n = ohlcv.length;
|
||||
let overnightSum = 0;
|
||||
let openToCloseSum = 0;
|
||||
let rogersSatchellSum = 0;
|
||||
|
||||
for (let i = 1; i < n; i++) {
|
||||
const prev = ohlcv[i - 1];
|
||||
const curr = ohlcv[i];
|
||||
|
||||
// Overnight return (close to open)
|
||||
const overnight = Math.log(curr.open / prev.close);
|
||||
overnightSum += overnight * overnight;
|
||||
|
||||
// Open to close return
|
||||
const openToClose = Math.log(curr.close / curr.open);
|
||||
openToCloseSum += openToClose * openToClose;
|
||||
|
||||
// Rogers-Satchell component
|
||||
const logHighOpen = Math.log(curr.high / curr.open);
|
||||
const logHighClose = Math.log(curr.high / curr.close);
|
||||
const logLowOpen = Math.log(curr.low / curr.open);
|
||||
const logLowClose = Math.log(curr.low / curr.close);
|
||||
rogersSatchellSum += logHighOpen * logHighClose + logLowOpen * logLowClose;
|
||||
}
|
||||
|
||||
// Yang-Zhang estimator
|
||||
const k = 0.34 / (1.34 + (n + 1) / (n - 1)); // Drift adjustment factor
|
||||
const yangZhangVariance = overnightSum / (n - 1) +
|
||||
k * openToCloseSum / (n - 1) +
|
||||
(1 - k) * rogersSatchellSum / (n - 1);
|
||||
|
||||
return Math.sqrt(yangZhangVariance * annualizationFactor);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue