added more functions

This commit is contained in:
Bojan Kucera 2025-06-04 20:01:39 -04:00
parent a1c82ae0b8
commit cca9ac03dd
8 changed files with 1563 additions and 2 deletions

View file

@ -517,3 +517,116 @@ export function calculateYangZhangVolatility(
return Math.sqrt(yangZhangVariance * annualizationFactor);
}
/**
* Parkinson volatility estimator
*/
export function parkinsonVolatility(
ohlcv: OHLCVData[],
annualizationFactor: number = 252
): number {
if (ohlcv.length < 2) return 0;
const sum = ohlcv
.slice(1)
.reduce((acc, curr) => {
const range = Math.log(curr.high / curr.low);
return acc + range * range;
}, 0);
return Math.sqrt((sum / (ohlcv.length - 1)) * annualizationFactor);
}
/**
* Calculate Implied Volatility using Black-Scholes model (simplified)
*/
export function calculateImpliedVolatility(
optionPrice: number,
spotPrice: number,
strikePrice: number,
timeToExpiry: number,
riskFreeRate: number,
optionType: 'call' | 'put',
maxIterations: number = 100,
tolerance: number = 1e-6
): number {
// Bisection method for implied volatility calculation
let low = 0.01;
let high = 5.0;
let impliedVol = 0.0;
for (let i = 0; i < maxIterations; i++) {
impliedVol = (low + high) / 2;
const modelPrice = blackScholes(spotPrice, strikePrice, timeToExpiry, impliedVol, riskFreeRate, optionType);
const diff = optionPrice - modelPrice;
if (Math.abs(diff) < tolerance) {
return impliedVol;
}
if (diff > 0) {
low = impliedVol;
} else {
high = impliedVol;
}
}
return impliedVol; // Return best estimate if no convergence
}
/**
* Black-Scholes option pricing model
*/
function blackScholes(
spotPrice: number,
strikePrice: number,
timeToExpiry: number,
volatility: number,
riskFreeRate: number,
optionType: 'call' | 'put'
): number {
const d1 = (Math.log(spotPrice / strikePrice) + (riskFreeRate + 0.5 * volatility * volatility) * timeToExpiry) / (volatility * Math.sqrt(timeToExpiry));
const d2 = d1 - volatility * Math.sqrt(timeToExpiry);
if (optionType === 'call') {
return spotPrice * normalCDF(d1) - strikePrice * Math.exp(-riskFreeRate * timeToExpiry) * normalCDF(d2);
} else {
return strikePrice * Math.exp(-riskFreeRate * timeToExpiry) * normalCDF(-d2) - spotPrice * normalCDF(-d1);
}
}
/**
* Normal cumulative distribution function
*/
function normalCDF(x: number): number {
const a1 = 0.254829592;
const a2 = -0.284496736;
const a3 = 1.421060743;
const a4 = -1.453152027;
const a5 = 1.061405429;
const p = 0.3275911;
const sign = x < 0 ? -1 : 1;
const absX = Math.abs(x);
const t = 1 / (1 + p * absX);
const y = 1 - (a1 * t + a2 * t * t + a3 * t * t * t + a4 * t * t * t * t + a5 * t * t * t * t * t) * Math.exp(-absX * absX / 2);
return 0.5 * (1 + sign * y);
}
/**
* Forecast volatility using EWMA
*/
export function forecastVolatilityEWMA(
volatilities: number[],
lambda: number = 0.94,
forecastHorizon: number = 1
): number {
if (volatilities.length === 0) {
return 0;
}
let forecast = volatilities[volatilities.length - 1];
for (let i = 0; i < forecastHorizon; i++) {
forecast = lambda * forecast + (1 - lambda) * forecast; // Using the last value as the long-term average
}
return forecast;
}