stock-bot/apps/stock/orchestrator/examples/advanced-risk-management.ts
2025-07-04 11:24:27 -04:00

272 lines
No EOL
10 KiB
TypeScript

/**
* Advanced Risk Management Examples
* Demonstrates orderbook analytics, portfolio risk, and bet sizing
*/
import { OrderbookAnalyzer, RiskAnalyzer, TradingEngine } from '@stock-bot/engine';
import { getLogger } from '@stock-bot/logger';
const logger = getLogger('AdvancedRiskExample');
// Example 1: Orderbook Analytics
async function orderbookAnalyticsExample() {
console.log('\n=== Orderbook Analytics Example ===');
const engine = new TradingEngine('paper', { startingCapital: 100000 });
const obAnalyzer = new OrderbookAnalyzer();
// Update orderbook with some data
const symbol = 'AAPL';
engine.updateQuote(symbol, 149.95, 150.05, 1000, 1200);
engine.updateQuote(symbol, 149.90, 150.10, 800, 900);
engine.updateQuote(symbol, 149.85, 150.15, 600, 700);
// Get orderbook snapshot
const snapshotJson = engine.getOrderbookSnapshot(symbol, 10);
const snapshot = JSON.parse(snapshotJson);
// Analyze orderbook
const analyticsJson = obAnalyzer.analyzeOrderbook(snapshotJson);
const analytics = JSON.parse(analyticsJson);
console.log('Orderbook Analytics:');
console.log(` Spread: $${analytics.spread.toFixed(2)} (${analytics.spread_bps.toFixed(1)} bps)`);
console.log(` Mid Price: $${analytics.mid_price.toFixed(2)}`);
console.log(` Micro Price: $${analytics.micro_price.toFixed(2)}`);
console.log(` Imbalance: ${(analytics.imbalance * 100).toFixed(1)}%`);
console.log(` Liquidity Score: ${analytics.liquidity_score.toFixed(2)}`);
// Calculate liquidity profile
const profileJson = obAnalyzer.calculateLiquidityProfile(snapshotJson);
const profile = JSON.parse(profileJson);
console.log('\nLiquidity Profile:');
console.log(` Total Bid Depth: $${profile.total_bid_depth.toFixed(2)}`);
console.log(` Total Ask Depth: $${profile.total_ask_depth.toFixed(2)}`);
// Calculate market impact for a $10,000 buy order
const impactJson = obAnalyzer.calculateMarketImpact(snapshotJson, 10000, true);
const impact = JSON.parse(impactJson);
console.log('\nMarket Impact ($10k buy):');
console.log(` Avg Execution Price: $${impact.avg_execution_price.toFixed(2)}`);
console.log(` Price Impact: ${(impact.price_impact * 100).toFixed(2)}%`);
console.log(` Slippage: $${impact.slippage.toFixed(2)}`);
console.log(` Levels Consumed: ${impact.levels_consumed}`);
}
// Example 2: Portfolio Risk Analysis
async function portfolioRiskExample() {
console.log('\n=== Portfolio Risk Analysis Example ===');
const riskAnalyzer = new RiskAnalyzer(100000, 0.02, 252); // $100k, 2% risk, 252 days lookback
// Update historical returns for portfolio symbols
const symbols = ['AAPL', 'GOOGL', 'MSFT', 'AMZN', 'META'];
// Simulate some returns data (in practice, load from historical data)
for (const symbol of symbols) {
const returns = generateRandomReturns(252);
riskAnalyzer.updateReturns(symbol, returns);
}
// Current positions
const positions = [
{ symbol: 'AAPL', quantity: 100, avgPrice: 150 },
{ symbol: 'GOOGL', quantity: 50, avgPrice: 140 },
{ symbol: 'MSFT', quantity: 75, avgPrice: 380 },
{ symbol: 'AMZN', quantity: 40, avgPrice: 170 },
{ symbol: 'META', quantity: 60, avgPrice: 480 }
];
// Current prices
const prices = {
AAPL: 155,
GOOGL: 145,
MSFT: 390,
AMZN: 175,
META: 490
};
// Calculate portfolio risk
const riskJson = riskAnalyzer.calculatePortfolioRisk(
JSON.stringify(positions.map(p => [p.symbol, p.quantity, p.avgPrice])),
JSON.stringify(prices)
);
const risk = JSON.parse(riskJson);
console.log('Portfolio Risk Metrics:');
console.log(` VaR (95%): $${risk.total_var_95.toFixed(2)}`);
console.log(` VaR (99%): $${risk.total_var_99.toFixed(2)}`);
console.log(` CVaR (95%): $${risk.total_cvar_95.toFixed(2)}`);
console.log('\nConcentration Metrics:');
console.log(` Herfindahl Index: ${risk.concentration_risk.herfindahl_index.toFixed(3)}`);
console.log(` Effective Positions: ${risk.concentration_risk.effective_number_of_positions.toFixed(1)}`);
console.log(` Top 5 Concentration: ${(risk.concentration_risk.top_5_concentration * 100).toFixed(1)}%`);
console.log('\nCorrelation Analysis:');
console.log(` Average Correlation: ${risk.correlation_matrix.average_correlation.toFixed(3)}`);
console.log(` Max Correlation: ${risk.correlation_matrix.max_correlation[0]} vs ${risk.correlation_matrix.max_correlation[1]} = ${risk.correlation_matrix.max_correlation[2].toFixed(3)}`);
console.log(` Clustering Score: ${risk.correlation_matrix.clustering_score.toFixed(3)}`);
console.log('\nStress Test Results:');
for (const [scenario, loss] of Object.entries(risk.stress_test_results)) {
console.log(` ${scenario}: $${(loss as number).toFixed(2)}`);
}
}
// Example 3: Dynamic Bet Sizing
async function betSizingExample() {
console.log('\n=== Dynamic Bet Sizing Example ===');
const riskAnalyzer = new RiskAnalyzer(100000, 0.02, 252);
// Scenario 1: Strong signal in trending market
console.log('\nScenario 1: Strong Signal, Trending Market');
let positionSize = riskAnalyzer.calculatePositionSize(
0.8, // signal_strength
0.9, // signal_confidence
0.015, // volatility (1.5% daily)
0.8, // liquidity_score
0.02, // current_drawdown (2%)
150, // price
145, // stop_loss
'trending'
);
let size = JSON.parse(positionSize);
console.log(` Shares: ${size.shares}`);
console.log(` Notional Value: $${size.notional_value.toFixed(2)}`);
console.log(` % of Capital: ${(size.percent_of_capital * 100).toFixed(2)}%`);
console.log(' Adjustments:');
for (const adj of size.adjustments) {
console.log(` ${adj.reason}: ${adj.factor.toFixed(2)}x`);
}
// Scenario 2: Weak signal in high volatility
console.log('\nScenario 2: Weak Signal, High Volatility');
positionSize = riskAnalyzer.calculatePositionSize(
0.3, // signal_strength
0.5, // signal_confidence
0.03, // volatility (3% daily)
0.6, // liquidity_score
0.15, // current_drawdown (15%)
150, // price
null, // no stop_loss
'high_volatility'
);
size = JSON.parse(positionSize);
console.log(` Shares: ${size.shares}`);
console.log(` Notional Value: $${size.notional_value.toFixed(2)}`);
console.log(` % of Capital: ${(size.percent_of_capital * 100).toFixed(2)}%`);
// Calculate optimal stop loss
const supportLevels = [148, 145, 142, 140];
const optimalStop = riskAnalyzer.calculateOptimalStopLoss(
150, // entry_price
0.015, // volatility
supportLevels,
2.5, // atr
true // is_long
);
console.log(`\nOptimal Stop Loss: $${optimalStop.toFixed(2)}`);
}
// Example 4: Integrated Risk Management in Trading
async function integratedTradingExample() {
console.log('\n=== Integrated Risk Management Example ===');
const engine = new TradingEngine('backtest', {
startTime: Date.now() - 30 * 24 * 60 * 60 * 1000, // 30 days ago
endTime: Date.now(),
speedMultiplier: 1
});
const riskAnalyzer = new RiskAnalyzer(100000, 0.02, 252);
const obAnalyzer = new OrderbookAnalyzer();
// Simulate a trading decision
const symbol = 'AAPL';
// 1. Check orderbook liquidity
engine.updateQuote(symbol, 149.95, 150.05, 5000, 5500);
const snapshot = engine.getOrderbookSnapshot(symbol, 10);
const analytics = JSON.parse(obAnalyzer.analyzeOrderbook(snapshot));
console.log('Pre-trade Analysis:');
console.log(` Liquidity Score: ${analytics.liquidity_score.toFixed(2)}`);
console.log(` Spread: ${analytics.spread_bps.toFixed(1)} bps`);
console.log(` Orderbook Imbalance: ${(analytics.imbalance * 100).toFixed(1)}%`);
// 2. Calculate position size based on current conditions
const positionSizeJson = riskAnalyzer.calculatePositionSize(
0.7, // signal_strength
0.8, // signal_confidence
0.018, // volatility
analytics.liquidity_score, // from orderbook
0.05, // current_drawdown
150, // price
147, // stop_loss
'trending'
);
const positionSize = JSON.parse(positionSizeJson);
console.log(`\nPosition Sizing:`);
console.log(` Recommended Shares: ${positionSize.shares}`);
console.log(` Risk-Adjusted Size: ${(positionSize.risk_adjusted_size * 100).toFixed(2)}%`);
// 3. Check market impact before placing order
const orderValue = positionSize.shares * 150;
const impact = JSON.parse(obAnalyzer.calculateMarketImpact(snapshot, orderValue, true));
console.log(`\nExpected Market Impact:`);
console.log(` Price Impact: ${(impact.price_impact * 100).toFixed(3)}%`);
console.log(` Expected Fill Price: $${impact.avg_execution_price.toFixed(2)}`);
// 4. Risk check
const riskCheck = engine.checkRisk({
id: '123',
symbol: symbol,
side: 'buy',
quantity: positionSize.shares,
orderType: 'market',
timeInForce: 'DAY'
});
const riskResult = JSON.parse(riskCheck);
console.log(`\nRisk Check: ${riskResult.passed ? 'PASSED' : 'FAILED'}`);
if (!riskResult.passed) {
console.log(' Violations:', riskResult.violations);
}
}
// Helper function to generate random returns
function generateRandomReturns(length: number): number[] {
const returns: number[] = [];
for (let i = 0; i < length; i++) {
// Generate returns with mean 0.0005 (0.05%) and std dev 0.02 (2%)
const return_ = (Math.random() - 0.5) * 0.04 + 0.0005;
returns.push(return_);
}
return returns;
}
// Run all examples
async function runExamples() {
try {
await orderbookAnalyticsExample();
await portfolioRiskExample();
await betSizingExample();
await integratedTradingExample();
} catch (error) {
console.error('Error running examples:', error);
}
}
// Execute if running directly
if (require.main === module) {
runExamples();
}