work on calculations

This commit is contained in:
Bojan Kucera 2025-06-04 18:16:16 -04:00
parent 3d910a13e0
commit ab7ef2b678
20 changed files with 1343 additions and 222 deletions

View file

@ -52,9 +52,9 @@ export interface MarketRegime {
}
/**
* Calculate Volume Weighted Average Price (VWAP)
* Volume Weighted Average Price (VWAP)
*/
export function calculateVWAP(ohlcv: OHLCVData[]): number[] {
export function VWAP(ohlcv: OHLCVData[]): number[] {
if (ohlcv.length === 0) return [];
const vwap: number[] = [];
@ -73,9 +73,9 @@ export function calculateVWAP(ohlcv: OHLCVData[]): number[] {
}
/**
* Calculate Time Weighted Average Price (TWAP)
* Time Weighted Average Price (TWAP)
*/
export function calculateTWAP(prices: number[], timeWeights?: number[]): number {
export function TWAP(prices: number[], timeWeights?: number[]): number {
if (prices.length === 0) return 0;
if (!timeWeights) {
@ -93,9 +93,9 @@ export function calculateTWAP(prices: number[], timeWeights?: number[]): number
}
/**
* Calculate market impact of trades
* market impact of trades
*/
export function calculateMarketImpact(
export function MarketImpact(
trades: Array<{ price: number; volume: number; side: 'buy' | 'sell'; timestamp: Date }>,
benchmarkPrice: number
): {
@ -138,9 +138,9 @@ export function calculateMarketImpact(
}
/**
* Calculate liquidity metrics
* liquidity metrics
*/
export function calculateLiquidityMetrics(
export function LiquidityMetrics(
ohlcv: OHLCVData[],
bidPrices: number[],
askPrices: number[],
@ -209,13 +209,13 @@ export function identifyMarketRegime(
const prices = recentData.map(candle => candle.close);
const volumes = recentData.map(candle => candle.volume);
// Calculate returns and volatility
// returns and volatility
const returns = [];
for (let i = 1; i < prices.length; i++) {
returns.push((prices[i] - prices[i - 1]) / prices[i - 1]);
}
const volatility = calculateVolatility(returns);
const volatility = Volatility(returns);
const averageVolume = volumes.reduce((sum, vol) => sum + vol, 0) / volumes.length;
// Trend analysis
@ -258,9 +258,9 @@ export function identifyMarketRegime(
}
/**
* Calculate order book imbalance
* order book imbalance
*/
export function calculateOrderBookImbalance(
export function OrderBookImbalance(
bidPrices: number[],
askPrices: number[],
bidSizes: number[],
@ -285,9 +285,9 @@ export function calculateOrderBookImbalance(
}
/**
* Calculate intraday patterns
* intraday patterns
*/
export function calculateIntradayPatterns(
export function IntradayPatterns(
ohlcv: OHLCVData[]
): {
hourlyReturns: { [hour: number]: number };
@ -312,7 +312,7 @@ export function calculateIntradayPatterns(
hourlyData[hour].volumes.push(ohlcv[i].volume);
}
// Calculate statistics for each hour
// statistics for each hour
const hourlyReturns: { [hour: number]: number } = {};
const hourlyVolatility: { [hour: number]: number } = {};
const hourlyVolume: { [hour: number]: number } = {};
@ -323,13 +323,13 @@ export function calculateIntradayPatterns(
hourlyReturns[hour] = data.returns.length > 0 ?
data.returns.reduce((sum, ret) => sum + ret, 0) / data.returns.length : 0;
hourlyVolatility[hour] = calculateVolatility(data.returns);
hourlyVolatility[hour] = Volatility(data.returns);
hourlyVolume[hour] = data.volumes.length > 0 ?
data.volumes.reduce((sum, vol) => sum + vol, 0) / data.volumes.length : 0;
}
// Calculate 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;
@ -346,9 +346,9 @@ export function calculateIntradayPatterns(
}
/**
* Calculate price discovery metrics
* price discovery metrics
*/
export function calculatePriceDiscovery(
export function PriceDiscovery(
prices1: number[], // Prices from market 1
prices2: number[] // Prices from market 2
): {
@ -366,7 +366,7 @@ export function calculatePriceDiscovery(
};
}
// Calculate returns
// returns
const returns1 = [];
const returns2 = [];
@ -375,20 +375,20 @@ export function calculatePriceDiscovery(
returns2.push((prices2[i] - prices2[i - 1]) / prices2[i - 1]);
}
// Calculate correlations with lags
const correlation0 = calculateCorrelation(returns1, returns2);
// correlations with lags
const correlation0 = Correlation(returns1, returns2);
const correlation1 = returns1.length > 1 ?
calculateCorrelation(returns1.slice(1), returns2.slice(0, -1)) : 0;
Correlation(returns1.slice(1), returns2.slice(0, -1)) : 0;
const correlationMinus1 = returns1.length > 1 ?
calculateCorrelation(returns1.slice(0, -1), returns2.slice(1)) : 0;
Correlation(returns1.slice(0, -1), returns2.slice(1)) : 0;
// Price lead-lag (simplified)
const priceLeadLag = correlation1 - correlationMinus1;
// Information shares (simplified Hasbrouck methodology)
const variance1 = calculateVariance(returns1);
const variance2 = calculateVariance(returns2);
const covariance = calculateCovariance(returns1, returns2);
const variance1 = Variance(returns1);
const variance2 = Variance(returns2);
const covariance = Covariance(returns1, returns2);
const totalVariance = variance1 + variance2 + 2 * covariance;
const informationShare1 = totalVariance > 0 ? (variance1 + covariance) / totalVariance : 0.5;
@ -406,9 +406,9 @@ export function calculatePriceDiscovery(
}
/**
* Calculate market stress indicators
* market stress indicators
*/
export function calculateMarketStress(
export function MarketStress(
ohlcv: OHLCVData[],
lookbackPeriod: number = 20
): {
@ -438,12 +438,12 @@ export function calculateMarketStress(
}
// Volatility stress
const volatility = calculateVolatility(returns);
const volatility = Volatility(returns);
const volatilityStress = Math.min(1, volatility / 0.05); // Normalize to 5% daily vol
// Liquidity stress (volume-based)
const averageVolume = volumes.reduce((sum, vol) => sum + vol, 0) / volumes.length;
const volumeVariability = calculateVolatility(volumes.map(vol => vol / averageVolume));
const volumeVariability = Volatility(volumes.map(vol => vol / averageVolume));
const liquidityStress = Math.min(1, volumeVariability);
// Correlation stress (simplified - would need multiple assets)
@ -467,9 +467,82 @@ export function calculateMarketStress(
};
}
/**
* realized spread
*/
export function RealizedSpread(
trades: Array<{ price: number; side: 'buy' | 'sell'; timestamp: Date }>,
midPrices: number[],
timeWindow: number = 5 // minutes
): number {
if (trades.length === 0 || midPrices.length === 0) return 0;
let totalSpread = 0;
let count = 0;
for (const trade of trades) {
// Find corresponding mid price
const midPrice = midPrices[0]; // Simplified - should match by timestamp
const spread = trade.side === 'buy' ?
2 * (trade.price - midPrice) :
2 * (midPrice - trade.price);
totalSpread += spread;
count++;
}
return count > 0 ? totalSpread / count : 0;
}
/**
* implementation shortfall
*/
export function ImplementationShortfall(
decisionPrice: number,
executionPrices: number[],
volumes: number[],
commissions: number[],
marketImpact: number[]
): {
totalShortfall: number;
delayComponent: number;
marketImpactComponent: number;
timingComponent: number;
commissionComponent: number;
} {
if (executionPrices.length !== volumes.length) {
throw new Error('Execution prices and volumes must have same length');
}
const totalVolume = volumes.reduce((sum, vol) => sum + vol, 0);
const weightedExecutionPrice = executionPrices.reduce((sum, price, i) =>
sum + price * volumes[i], 0) / totalVolume;
const totalCommissions = commissions.reduce((sum, comm) => sum + comm, 0);
const totalMarketImpact = marketImpact.reduce((sum, impact, i) =>
sum + impact * volumes[i], 0);
const delayComponent = weightedExecutionPrice - decisionPrice;
const marketImpactComponent = totalMarketImpact / totalVolume;
const timingComponent = 0; // Simplified - would need benchmark price evolution
const commissionComponent = totalCommissions / totalVolume;
const totalShortfall = delayComponent + marketImpactComponent +
timingComponent + commissionComponent;
return {
totalShortfall,
delayComponent,
marketImpactComponent,
timingComponent,
commissionComponent
};
}
// Helper functions
function calculateVolatility(returns: number[]): number {
function Volatility(returns: number[]): number {
if (returns.length < 2) return 0;
const mean = returns.reduce((sum, ret) => sum + ret, 0) / returns.length;
@ -478,7 +551,7 @@ function calculateVolatility(returns: number[]): number {
return Math.sqrt(variance);
}
function calculateCorrelation(x: number[], y: number[]): number {
function Correlation(x: number[], y: number[]): number {
if (x.length !== y.length || x.length < 2) return 0;
const n = x.length;
@ -503,14 +576,14 @@ function calculateCorrelation(x: number[], y: number[]): number {
return denominator > 0 ? numerator / denominator : 0;
}
function calculateVariance(values: number[]): number {
function Variance(values: number[]): number {
if (values.length < 2) return 0;
const mean = values.reduce((sum, val) => sum + val, 0) / values.length;
return values.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / (values.length - 1);
}
function calculateCovariance(x: number[], y: number[]): number {
function Covariance(x: number[], y: number[]): number {
if (x.length !== y.length || x.length < 2) return 0;
const n = x.length;