added more functions

This commit is contained in:
Bojan Kucera 2025-06-04 19:27:11 -04:00
parent a53d8d13ca
commit a1c82ae0b8
7 changed files with 648 additions and 177 deletions

View file

@ -326,10 +326,9 @@ export function IntradayPatterns(
hourlyVolume[hour] = data.volumes.length > 0 ?
data.volumes.reduce((sum, vol) => sum + vol, 0) / data.volumes.length : 0;
}
// opening gap and closing drift
// opening gap and closing drift
const openingGap = ohlcv.length > 1 ?
(ohlcv[0].open - ohlcv[0].close) / ohlcv[0].close : 0;
(ohlcv[1].open - ohlcv[0].close) / ohlcv[0].close : 0;
const lastCandle = ohlcv[ohlcv.length - 1];
const closingDrift = (lastCandle.close - lastCandle.open) / lastCandle.open;
@ -536,6 +535,136 @@ export function ImplementationShortfall(
};
}
/**
* Amihud Illiquidity Measure (price impact per unit of volume)
*/
export function amihudIlliquidity(
ohlcv: OHLCVData[],
lookbackPeriod: number = 252
): number {
if (ohlcv.length < lookbackPeriod) return 0;
const recentData = ohlcv.slice(-lookbackPeriod);
let illiquiditySum = 0;
let validDays = 0;
for (const candle of recentData) {
if (candle.volume > 0) {
const dailyReturn = Math.abs((candle.close - candle.open) / candle.open);
const dollarVolume = candle.volume * candle.close;
if (dollarVolume > 0) {
illiquiditySum += dailyReturn / dollarVolume;
validDays++;
}
}
}
return validDays > 0 ? (illiquiditySum / validDays) * 1000000 : 0; // Scale to millions
}
/**
* Roll's Spread Estimator (effective spread from serial covariance)
*/
export function rollSpreadEstimator(prices: number[]): number {
if (prices.length < 3) return 0;
// Calculate price changes
const priceChanges: number[] = [];
for (let i = 1; i < prices.length; i++) {
priceChanges.push(prices[i] - prices[i - 1]);
}
// Calculate serial covariance
let covariance = 0;
for (let i = 1; i < priceChanges.length; i++) {
covariance += priceChanges[i] * priceChanges[i - 1];
}
covariance /= (priceChanges.length - 1);
// Roll's estimator: spread = 2 * sqrt(-covariance)
const spread = covariance < 0 ? 2 * Math.sqrt(-covariance) : 0;
return spread;
}
/**
* Kyle's Lambda (price impact coefficient)
*/
export function kyleLambda(
priceChanges: number[],
orderFlow: number[] // Signed order flow (positive for buys, negative for sells)
): number {
if (priceChanges.length !== orderFlow.length || priceChanges.length < 2) return 0;
// Calculate regression: priceChange = lambda * orderFlow + error
const n = priceChanges.length;
const meanPrice = priceChanges.reduce((sum, p) => sum + p, 0) / n;
const meanFlow = orderFlow.reduce((sum, f) => sum + f, 0) / n;
let numerator = 0;
let denominator = 0;
for (let i = 0; i < n; i++) {
const priceDeviation = priceChanges[i] - meanPrice;
const flowDeviation = orderFlow[i] - meanFlow;
numerator += priceDeviation * flowDeviation;
denominator += flowDeviation * flowDeviation;
}
return denominator > 0 ? numerator / denominator : 0;
}
/**
* Probability of Informed Trading (PIN) - simplified version
*/
export function probabilityInformedTrading(
buyVolumes: number[],
sellVolumes: number[],
period: number = 20
): number {
if (buyVolumes.length !== sellVolumes.length || buyVolumes.length < period) return 0;
const recentBuys = buyVolumes.slice(-period);
const recentSells = sellVolumes.slice(-period);
let totalImbalance = 0;
let totalVolume = 0;
for (let i = 0; i < period; i++) {
const imbalance = Math.abs(recentBuys[i] - recentSells[i]);
const volume = recentBuys[i] + recentSells[i];
totalImbalance += imbalance;
totalVolume += volume;
}
// Simplified PIN estimate based on order imbalance
return totalVolume > 0 ? totalImbalance / totalVolume : 0;
}
/**
* Herfindahl-Hirschman Index for Volume Concentration
*/
export function volumeConcentrationHHI(
exchanges: Array<{ name: string; volume: number }>
): number {
if (exchanges.length === 0) return 0;
const totalVolume = exchanges.reduce((sum, exchange) => sum + exchange.volume, 0);
if (totalVolume === 0) return 0;
let hhi = 0;
for (const exchange of exchanges) {
const marketShare = exchange.volume / totalVolume;
hhi += marketShare * marketShare;
}
return hhi * 10000; // Scale to 0-10000 range
}
// Helper functions
function calculateVolatility(returns: number[]): number {