stock-bot/apps/stock/orchestrator/examples/trace-short-positions.ts
2025-07-03 18:33:15 -04:00

188 lines
No EOL
6.5 KiB
TypeScript

import { BacktestEngine } from '../src/backtest/BacktestEngine';
import { StrategyManager } from '../src/strategies/StrategyManager';
import { StorageService } from '../src/services/StorageService';
import { ModeManager } from '../src/core/ModeManager';
import { MarketDataService } from '../src/services/MarketDataService';
import { ExecutionService } from '../src/services/ExecutionService';
import { IServiceContainer } from '@stock-bot/di';
async function traceShortPositions() {
let orderCount = 0;
let fillCount = 0;
const orderTracker: any[] = [];
const fillTracker: any[] = [];
// Create service container with detailed logging
const container: IServiceContainer = {
logger: {
info: (msg: string, ...args: any[]) => {
// Log all order and fill events
if (msg.includes('order') || msg.includes('Order') ||
msg.includes('fill') || msg.includes('Fill') ||
msg.includes('position') || msg.includes('Position')) {
console.log('[INFO]', msg, ...args);
}
// Track order submissions
if (msg.includes('Submitting order')) {
orderCount++;
const orderData = args[0];
orderTracker.push({
count: orderCount,
symbol: orderData.symbol,
side: orderData.side,
quantity: orderData.quantity,
type: orderData.type
});
console.log(`\n🔵 ORDER #${orderCount}:`, orderData.side.toUpperCase(), orderData.symbol);
}
// Track fills
if (msg.includes('Order filled')) {
fillCount++;
const fillData = args[0];
fillTracker.push({
count: fillCount,
orderId: fillData.orderId,
symbol: fillData.symbol,
side: fillData.side,
price: fillData.price,
quantity: fillData.quantity
});
console.log(`\n🟢 FILL #${fillCount}:`, fillData.side.toUpperCase(), fillData.symbol, '@', fillData.price);
}
},
error: console.error,
warn: () => {},
debug: () => {},
} as any,
custom: {}
};
// Initialize services
const storageService = new StorageService();
const marketDataService = new MarketDataService(container);
const executionService = new ExecutionService(container);
const modeManager = new ModeManager(container, marketDataService, executionService, storageService);
const strategyManager = new StrategyManager(container);
container.custom = {
MarketDataService: marketDataService,
ExecutionService: executionService,
ModeManager: modeManager,
StorageService: storageService
};
// Listen to strategy events
strategyManager.on('signal', (signal: any) => {
console.log('\n🎯 STRATEGY SIGNAL:', signal);
});
// Initialize backtest mode
await modeManager.initializeMode({
mode: 'backtest',
startDate: '2023-06-01T00:00:00Z',
endDate: '2023-09-01T00:00:00Z', // 3 months
speed: 'max',
symbols: ['AAPL'],
initialCapital: 100000,
dataFrequency: '1d',
strategy: 'sma-crossover'
});
// Create backtest engine
const backtestEngine = new BacktestEngine(container, storageService, strategyManager);
// Configure backtest
const config = {
mode: 'backtest' as const,
name: 'Short Position Trace',
strategy: 'sma-crossover',
symbols: ['AAPL'],
startDate: '2023-06-01T00:00:00Z',
endDate: '2023-09-01T00:00:00Z',
initialCapital: 100000,
commission: 0.001,
slippage: 0.0001,
dataFrequency: '1d' as const,
speed: 'max' as const
};
console.log('=== TRACING SHORT POSITION FLOW ===\n');
try {
const result = await backtestEngine.runBacktest(config);
console.log('\n=== ORDER/FILL TRACKING SUMMARY ===');
console.log(`Total orders submitted: ${orderCount}`);
console.log(`Total fills executed: ${fillCount}`);
// Analyze order flow
let buyOrders = 0;
let sellOrders = 0;
orderTracker.forEach(order => {
if (order.side === 'buy') buyOrders++;
else sellOrders++;
});
console.log(`\nOrder breakdown:`);
console.log(`- BUY orders: ${buyOrders}`);
console.log(`- SELL orders: ${sellOrders}`);
// Check for short positions
console.log('\n=== LOOKING FOR SHORT PATTERNS ===');
console.log('(A short position starts with a SELL and closes with a BUY)\n');
let potentialShorts = 0;
for (let i = 0; i < orderTracker.length - 1; i++) {
if (orderTracker[i].side === 'sell') {
// Look for subsequent buy to close
for (let j = i + 1; j < orderTracker.length; j++) {
if (orderTracker[j].side === 'buy' && orderTracker[j].symbol === orderTracker[i].symbol) {
potentialShorts++;
console.log(`Potential short trade found:`);
console.log(` Open: Order #${orderTracker[i].count} (SELL)`);
console.log(` Close: Order #${orderTracker[j].count} (BUY)`);
break;
}
}
}
}
console.log(`\nPotential short trades identified: ${potentialShorts}`);
// Final results
console.log('\n=== BACKTEST RESULTS ===');
console.log(`Total closed trades: ${result.metrics.totalTrades}`);
let longTrades = 0;
let shortTrades = 0;
result.trades.forEach((trade, i) => {
const tradeType = trade.side === 'buy' ? 'LONG' : 'SHORT';
if (trade.side === 'buy') longTrades++;
else shortTrades++;
console.log(`\nTrade ${i + 1} (${tradeType}):`);
console.log(` Entry: ${trade.entryDate} @ $${trade.entryPrice.toFixed(2)}`);
console.log(` Exit: ${trade.exitDate} @ $${trade.exitPrice.toFixed(2)}`);
console.log(` P&L: $${trade.pnl.toFixed(2)}`);
});
console.log('\n=== FINAL SUMMARY ===');
console.log(`Long trades recorded: ${longTrades}`);
console.log(`Short trades recorded: ${shortTrades}`);
console.log(`Expected short trades (from order flow): ${potentialShorts}`);
if (shortTrades < potentialShorts) {
console.log('\n❌ ISSUE: Not all short trades were recorded in closed trades!');
console.log('This suggests the Rust core trade matching logic may have an issue.');
}
} catch (error) {
console.error('Trace failed:', error);
}
}
// Run the trace
traceShortPositions().catch(console.error);