fixed test strat
This commit is contained in:
parent
6cf3179092
commit
8a9a4bc336
12 changed files with 1301 additions and 8 deletions
113
apps/stock/orchestrator/examples/debug-position-tracking.ts
Normal file
113
apps/stock/orchestrator/examples/debug-position-tracking.ts
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
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 debugPositionTracking() {
|
||||
// Create service container with detailed logging
|
||||
const container: IServiceContainer = {
|
||||
logger: {
|
||||
info: (msg: string, ...args: any[]) => console.log('[INFO]', msg, ...args),
|
||||
error: (msg: string, ...args: any[]) => console.error('[ERROR]', msg, ...args),
|
||||
warn: (msg: string, ...args: any[]) => console.warn('[WARN]', msg, ...args),
|
||||
debug: (msg: string, ...args: any[]) => console.log('[DEBUG]', msg, ...args),
|
||||
} 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);
|
||||
|
||||
// Set services in container
|
||||
container.custom = {
|
||||
MarketDataService: marketDataService,
|
||||
ExecutionService: executionService,
|
||||
ModeManager: modeManager,
|
||||
StorageService: storageService
|
||||
};
|
||||
|
||||
// Initialize backtest mode with full config
|
||||
await modeManager.initializeMode({
|
||||
mode: 'backtest',
|
||||
startDate: '2023-06-01T00:00:00Z',
|
||||
endDate: '2023-09-01T00:00:00Z', // Just 3 months for debugging
|
||||
speed: 'max',
|
||||
symbols: ['AAPL'],
|
||||
initialCapital: 100000,
|
||||
dataFrequency: '1d',
|
||||
strategy: 'sma-crossover'
|
||||
});
|
||||
|
||||
// Create backtest engine
|
||||
const backtestEngine = new BacktestEngine(container, storageService, strategyManager);
|
||||
|
||||
// Listen to strategy events for debugging
|
||||
strategyManager.on('order', (orderEvent: any) => {
|
||||
console.log('\n📊 STRATEGY ORDER EVENT:', orderEvent);
|
||||
});
|
||||
|
||||
// Configure backtest
|
||||
const config = {
|
||||
mode: 'backtest' as const,
|
||||
name: 'Position Tracking Debug',
|
||||
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('Starting position tracking debug...\n');
|
||||
|
||||
try {
|
||||
const result = await backtestEngine.runBacktest(config);
|
||||
|
||||
console.log('\n=== FINAL RESULTS ===');
|
||||
console.log(`Total Trades: ${result.metrics.totalTrades}`);
|
||||
console.log(`Win Rate: ${result.metrics.winRate.toFixed(2)}%`);
|
||||
|
||||
console.log('\n=== TRADE DETAILS ===');
|
||||
let buyCount = 0;
|
||||
let sellCount = 0;
|
||||
|
||||
result.trades.forEach((trade, i) => {
|
||||
console.log(`\nTrade ${i + 1}:`);
|
||||
console.log(` Symbol: ${trade.symbol}`);
|
||||
console.log(` Side: ${trade.side}`);
|
||||
console.log(` Entry: ${trade.entryDate} @ $${trade.entryPrice.toFixed(2)}`);
|
||||
console.log(` Exit: ${trade.exitDate} @ $${trade.exitPrice.toFixed(2)}`);
|
||||
console.log(` Quantity: ${trade.quantity}`);
|
||||
console.log(` P&L: $${trade.pnl.toFixed(2)}`);
|
||||
|
||||
if (trade.side === 'buy') buyCount++;
|
||||
else if (trade.side === 'sell') sellCount++;
|
||||
});
|
||||
|
||||
console.log(`\n=== TRADE SIDE SUMMARY ===`);
|
||||
console.log(`Buy trades: ${buyCount}`);
|
||||
console.log(`Sell trades: ${sellCount}`);
|
||||
|
||||
// Check final positions
|
||||
console.log('\n=== FINAL POSITIONS ===');
|
||||
result.positions.forEach(pos => {
|
||||
console.log(`${pos.symbol}: ${pos.quantity} shares @ avg $${pos.averagePrice.toFixed(2)}`);
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Debug failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Run the debug
|
||||
debugPositionTracking().catch(console.error);
|
||||
129
apps/stock/orchestrator/examples/debug-rust-short-trades.ts
Normal file
129
apps/stock/orchestrator/examples/debug-rust-short-trades.ts
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
import { TradingEngine } from '@stock-bot/core';
|
||||
|
||||
async function debugRustShortTrades() {
|
||||
// Create engine config for backtest mode
|
||||
const engineConfig = {
|
||||
startTime: new Date('2023-01-01').getTime(),
|
||||
endTime: new Date('2023-02-01').getTime(),
|
||||
speedMultiplier: 0
|
||||
};
|
||||
|
||||
console.log('=== RUST CORE SHORT TRADE DEBUG ===\n');
|
||||
|
||||
console.log('1. Creating TradingEngine in backtest mode...');
|
||||
const engine = new TradingEngine('backtest', engineConfig);
|
||||
|
||||
// Simulate opening a short position
|
||||
console.log('\n2. Submitting SELL order to open short position...');
|
||||
const sellOrder = {
|
||||
id: 'sell-order-001',
|
||||
symbol: 'TEST',
|
||||
side: 'sell',
|
||||
quantity: 100,
|
||||
orderType: 'market',
|
||||
timeInForce: 'DAY'
|
||||
};
|
||||
const sellOrderId = engine.submitOrder(sellOrder);
|
||||
console.log(` Sell order ID: ${sellOrderId}`);
|
||||
|
||||
// Process the sell fill
|
||||
console.log('\n3. Processing SELL fill...');
|
||||
const sellFillResult = engine.processFillWithMetadata(
|
||||
'TEST', // symbol
|
||||
50.0, // price
|
||||
100, // quantity
|
||||
'sell', // side
|
||||
0.1, // commission
|
||||
sellOrderId, // orderId
|
||||
'debug-strategy' // strategyId
|
||||
);
|
||||
console.log(` Fill result: ${sellFillResult}`);
|
||||
|
||||
// Check positions
|
||||
console.log('\n4. Checking positions after SELL...');
|
||||
const positionsAfterSell = engine.getPosition('TEST');
|
||||
console.log(' Position:', positionsAfterSell);
|
||||
|
||||
// Check open trades
|
||||
const openTradesAfterSell = JSON.parse(engine.getOpenTrades());
|
||||
console.log(' Open trades:', openTradesAfterSell.length);
|
||||
if (openTradesAfterSell.length > 0) {
|
||||
console.log(' First open trade:', openTradesAfterSell[0]);
|
||||
}
|
||||
|
||||
// Check closed trades
|
||||
const closedTradesAfterSell = JSON.parse(engine.getClosedTrades());
|
||||
console.log(' Closed trades:', closedTradesAfterSell.length);
|
||||
|
||||
// Now close the short with a buy order
|
||||
console.log('\n5. Submitting BUY order to close short position...');
|
||||
const buyOrder = {
|
||||
id: 'buy-order-001',
|
||||
symbol: 'TEST',
|
||||
side: 'buy',
|
||||
quantity: 100,
|
||||
orderType: 'market',
|
||||
timeInForce: 'DAY'
|
||||
};
|
||||
const buyOrderId = engine.submitOrder(buyOrder);
|
||||
console.log(` Buy order ID: ${buyOrderId}`);
|
||||
|
||||
// Process the buy fill
|
||||
console.log('\n6. Processing BUY fill...');
|
||||
const buyFillResult = engine.processFillWithMetadata(
|
||||
'TEST', // symbol
|
||||
48.0, // price (profit on short)
|
||||
100, // quantity
|
||||
'buy', // side
|
||||
0.1, // commission
|
||||
buyOrderId, // orderId
|
||||
'debug-strategy' // strategyId
|
||||
);
|
||||
console.log(` Fill result: ${buyFillResult}`);
|
||||
|
||||
// Check positions after closing
|
||||
console.log('\n7. Checking positions after BUY...');
|
||||
const positionsAfterBuy = engine.getPosition('TEST');
|
||||
console.log(' Position:', positionsAfterBuy);
|
||||
|
||||
// Check open trades after closing
|
||||
const openTradesAfterBuy = JSON.parse(engine.getOpenTrades());
|
||||
console.log(' Open trades:', openTradesAfterBuy.length);
|
||||
|
||||
// Check closed trades after closing - THIS IS WHERE WE SHOULD SEE THE SHORT TRADE
|
||||
const closedTradesAfterBuy = JSON.parse(engine.getClosedTrades());
|
||||
console.log(' Closed trades:', closedTradesAfterBuy.length);
|
||||
|
||||
if (closedTradesAfterBuy.length > 0) {
|
||||
console.log('\n8. Closed trade details:');
|
||||
closedTradesAfterBuy.forEach((trade: any, i: number) => {
|
||||
console.log(` Trade ${i + 1}:`);
|
||||
console.log(` ID: ${trade.id}`);
|
||||
console.log(` Side: ${trade.side}`);
|
||||
console.log(` Entry: ${trade.entry_price} @ ${trade.entry_time}`);
|
||||
console.log(` Exit: ${trade.exit_price} @ ${trade.exit_time}`);
|
||||
console.log(` P&L: ${trade.pnl} (${trade.pnl_percent}%)`);
|
||||
console.log(` Quantity: ${trade.quantity}`);
|
||||
});
|
||||
} else {
|
||||
console.log('\n❌ ERROR: No closed trades found! Short trade was not recorded.');
|
||||
}
|
||||
|
||||
// Also check trade history
|
||||
console.log('\n9. Trade history:');
|
||||
const tradeHistory = JSON.parse(engine.getTradeHistory());
|
||||
tradeHistory.forEach((trade: any, i: number) => {
|
||||
console.log(` Trade ${i + 1}: ${trade.side} ${trade.quantity} @ ${trade.price}`);
|
||||
});
|
||||
|
||||
// Check totals
|
||||
console.log('\n10. Summary:');
|
||||
console.log(` Total trades: ${engine.getTradeCount()}`);
|
||||
console.log(` Closed trades: ${engine.getClosedTradeCount()}`);
|
||||
const [realizedPnl, unrealizedPnl] = engine.getTotalPnl();
|
||||
console.log(` Realized P&L: ${realizedPnl}`);
|
||||
console.log(` Unrealized P&L: ${unrealizedPnl}`);
|
||||
}
|
||||
|
||||
// Run the debug
|
||||
debugRustShortTrades().catch(console.error);
|
||||
161
apps/stock/orchestrator/examples/force-both-trade-types.ts
Normal file
161
apps/stock/orchestrator/examples/force-both-trade-types.ts
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
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';
|
||||
|
||||
// Modify the data generation to ensure we get both golden and death crosses
|
||||
function generateMockDataWithBothCrosses() {
|
||||
const data = [];
|
||||
const startDate = new Date('2023-01-01');
|
||||
let price = 150;
|
||||
|
||||
// Create 365 days of data with clear trends
|
||||
for (let i = 0; i < 365; i++) {
|
||||
const date = new Date(startDate);
|
||||
date.setDate(date.getDate() + i);
|
||||
|
||||
// Create alternating trends every ~30 days
|
||||
const cycleDay = i % 60;
|
||||
if (cycleDay < 30) {
|
||||
// Uptrend - will create golden crosses
|
||||
price += Math.random() * 2 - 0.5; // Bias upward
|
||||
} else {
|
||||
// Downtrend - will create death crosses
|
||||
price -= Math.random() * 2 - 0.5; // Bias downward
|
||||
}
|
||||
|
||||
// Add some volatility
|
||||
const dayChange = (Math.random() - 0.5) * 4;
|
||||
price = Math.max(100, Math.min(200, price + dayChange));
|
||||
|
||||
data.push({
|
||||
timestamp: date.toISOString(),
|
||||
open: price - Math.random() * 2,
|
||||
high: price + Math.random() * 2,
|
||||
low: price - Math.random() * 2,
|
||||
close: price,
|
||||
volume: Math.floor(Math.random() * 10000000) + 5000000
|
||||
});
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
async function forceBothTradeTypes() {
|
||||
// Create service container with minimal logging
|
||||
const container: IServiceContainer = {
|
||||
logger: {
|
||||
info: (msg: string, ...args: any[]) => {
|
||||
if (msg.includes('cross detected') || msg.includes('Generated') || msg.includes('Position update')) {
|
||||
console.log('[INFO]', msg, ...args);
|
||||
}
|
||||
},
|
||||
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
|
||||
};
|
||||
|
||||
// Override the mock data generation
|
||||
const originalGenerateMockData = marketDataService.generateMockData;
|
||||
marketDataService.generateMockData = function(symbol: string, startDate: string, endDate: string) {
|
||||
console.log('Generating mock data with forced crossovers...');
|
||||
return generateMockDataWithBothCrosses();
|
||||
};
|
||||
|
||||
// Initialize backtest mode
|
||||
await modeManager.initializeMode({
|
||||
mode: 'backtest',
|
||||
startDate: '2023-01-01T00:00:00Z',
|
||||
endDate: '2024-01-01T00:00:00Z',
|
||||
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: 'Force Both Trade Types',
|
||||
strategy: 'sma-crossover',
|
||||
symbols: ['AAPL'],
|
||||
startDate: '2023-01-01T00:00:00Z',
|
||||
endDate: '2024-01-01T00:00:00Z',
|
||||
initialCapital: 100000,
|
||||
commission: 0.001,
|
||||
slippage: 0.0001,
|
||||
dataFrequency: '1d' as const,
|
||||
speed: 'max' as const
|
||||
};
|
||||
|
||||
console.log('=== TESTING WITH FORCED CROSSOVERS ===\n');
|
||||
|
||||
try {
|
||||
const result = await backtestEngine.runBacktest(config);
|
||||
|
||||
console.log('\n=== BACKTEST COMPLETE ===');
|
||||
console.log(`Total Trades: ${result.metrics.totalTrades}`);
|
||||
|
||||
// Analyze trades
|
||||
let longTrades = 0;
|
||||
let shortTrades = 0;
|
||||
|
||||
result.trades.forEach((trade) => {
|
||||
if (trade.side === 'buy') {
|
||||
longTrades++;
|
||||
console.log(`\nLONG trade found:`);
|
||||
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)}`);
|
||||
} else {
|
||||
shortTrades++;
|
||||
console.log(`\nSHORT trade found:`);
|
||||
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: ${longTrades}`);
|
||||
console.log(`SHORT trades: ${shortTrades}`);
|
||||
console.log(`Total trades: ${result.metrics.totalTrades}`);
|
||||
|
||||
if (longTrades > 0 && shortTrades > 0) {
|
||||
console.log('\n✅ SUCCESS: Both long and short trades are working!');
|
||||
} else {
|
||||
console.log('\n❌ ISSUE: Missing trade types');
|
||||
if (longTrades === 0) console.log(' - No long trades found');
|
||||
if (shortTrades === 0) console.log(' - No short trades found');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Test failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Run the test
|
||||
forceBothTradeTypes().catch(console.error);
|
||||
99
apps/stock/orchestrator/examples/show-order-flow.ts
Normal file
99
apps/stock/orchestrator/examples/show-order-flow.ts
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
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 showOrderFlow() {
|
||||
// Create service container
|
||||
const container: IServiceContainer = {
|
||||
logger: {
|
||||
info: (msg: string, ...args: any[]) => {
|
||||
// Only log order-related messages
|
||||
if (msg.includes('order') || msg.includes('Order') || msg.includes('Filling') || msg.includes('cross detected')) {
|
||||
console.log('[INFO]', msg, ...args);
|
||||
}
|
||||
},
|
||||
error: (msg: string, ...args: any[]) => console.error('[ERROR]', msg, ...args),
|
||||
warn: (msg: string, ...args: any[]) => {},
|
||||
debug: (msg: string, ...args: any[]) => {},
|
||||
} 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);
|
||||
|
||||
// Set services in container
|
||||
container.custom = {
|
||||
MarketDataService: marketDataService,
|
||||
ExecutionService: executionService,
|
||||
ModeManager: modeManager,
|
||||
StorageService: storageService
|
||||
};
|
||||
|
||||
// Initialize backtest mode
|
||||
await modeManager.initializeMode({
|
||||
mode: 'backtest',
|
||||
startDate: '2023-07-01T00:00:00Z',
|
||||
endDate: '2023-08-01T00:00:00Z', // Just 1 month
|
||||
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: 'Order Flow Demo',
|
||||
strategy: 'sma-crossover',
|
||||
symbols: ['AAPL'],
|
||||
startDate: '2023-07-01T00:00:00Z',
|
||||
endDate: '2023-08-01T00:00:00Z',
|
||||
initialCapital: 100000,
|
||||
commission: 0.001,
|
||||
slippage: 0.0001,
|
||||
dataFrequency: '1d' as const,
|
||||
speed: 'max' as const
|
||||
};
|
||||
|
||||
console.log('\n=== ORDER FLOW DEMONSTRATION ===\n');
|
||||
console.log('This will show the actual BUY and SELL orders being generated and executed:\n');
|
||||
|
||||
try {
|
||||
const result = await backtestEngine.runBacktest(config);
|
||||
|
||||
console.log('\n=== COMPLETED TRADES (Round-trips) ===');
|
||||
console.log('Note: Each trade below represents a BUY order (entry) + SELL order (exit):\n');
|
||||
|
||||
result.trades.forEach((trade, i) => {
|
||||
console.log(`Trade ${i + 1}:`);
|
||||
console.log(` Opened with: BUY order on ${trade.entryDate} @ $${trade.entryPrice.toFixed(2)}`);
|
||||
console.log(` Closed with: SELL order on ${trade.exitDate} @ $${trade.exitPrice.toFixed(2)}`);
|
||||
console.log(` Trade type: ${trade.side === 'buy' ? 'LONG' : 'SHORT'} position`);
|
||||
console.log(` P&L: $${trade.pnl.toFixed(2)} (${trade.pnlPercent.toFixed(2)}%)\n`);
|
||||
});
|
||||
|
||||
console.log('Summary:');
|
||||
console.log(`- Total completed trades: ${result.metrics.totalTrades}`);
|
||||
console.log(`- Each trade = 1 BUY order + 1 SELL order`);
|
||||
console.log(`- Total orders executed: ${result.metrics.totalTrades * 2}`);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Run the demo
|
||||
showOrderFlow().catch(console.error);
|
||||
103
apps/stock/orchestrator/examples/test-short-trades.ts
Normal file
103
apps/stock/orchestrator/examples/test-short-trades.ts
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
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 testShortTrades() {
|
||||
// Create service container
|
||||
const container: IServiceContainer = {
|
||||
logger: {
|
||||
info: () => {},
|
||||
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
|
||||
};
|
||||
|
||||
// Initialize backtest mode
|
||||
await modeManager.initializeMode({
|
||||
mode: 'backtest',
|
||||
startDate: '2023-01-01T00:00:00Z',
|
||||
endDate: '2024-01-01T00:00:00Z',
|
||||
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 Trade Test',
|
||||
strategy: 'sma-crossover',
|
||||
symbols: ['AAPL'],
|
||||
startDate: '2023-01-01T00:00:00Z',
|
||||
endDate: '2024-01-01T00:00:00Z',
|
||||
initialCapital: 100000,
|
||||
commission: 0.001,
|
||||
slippage: 0.0001,
|
||||
dataFrequency: '1d' as const,
|
||||
speed: 'max' as const
|
||||
};
|
||||
|
||||
console.log('Testing short trade recording...\n');
|
||||
|
||||
try {
|
||||
const result = await backtestEngine.runBacktest(config);
|
||||
|
||||
console.log('=== BACKTEST RESULTS ===');
|
||||
console.log(`Total Trades: ${result.metrics.totalTrades}`);
|
||||
console.log(`Win Rate: ${result.metrics.winRate.toFixed(2)}%`);
|
||||
console.log(`Total Return: ${result.metrics.totalReturn.toFixed(2)}%`);
|
||||
|
||||
// Count long vs short trades
|
||||
let longTrades = 0;
|
||||
let shortTrades = 0;
|
||||
|
||||
console.log('\n=== TRADE BREAKDOWN ===');
|
||||
result.trades.forEach((trade, i) => {
|
||||
const tradeType = trade.side === 'buy' ? 'LONG' : 'SHORT';
|
||||
if (trade.side === 'buy') longTrades++;
|
||||
else shortTrades++;
|
||||
|
||||
console.log(`Trade ${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)} (${trade.pnlPercent.toFixed(2)}%)`);
|
||||
console.log('');
|
||||
});
|
||||
|
||||
console.log('=== TRADE TYPE SUMMARY ===');
|
||||
console.log(`Long trades: ${longTrades}`);
|
||||
console.log(`Short trades: ${shortTrades}`);
|
||||
console.log(`Total trades: ${result.metrics.totalTrades}`);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Test failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Run the test
|
||||
testShortTrades().catch(console.error);
|
||||
188
apps/stock/orchestrator/examples/trace-short-positions.ts
Normal file
188
apps/stock/orchestrator/examples/trace-short-positions.ts
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
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);
|
||||
133
apps/stock/orchestrator/examples/verify-both-trade-types.ts
Normal file
133
apps/stock/orchestrator/examples/verify-both-trade-types.ts
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
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 verifyBothTradeTypes() {
|
||||
// Create service container
|
||||
const container: IServiceContainer = {
|
||||
logger: {
|
||||
info: console.log,
|
||||
error: console.error,
|
||||
warn: console.warn,
|
||||
debug: console.log,
|
||||
} 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
|
||||
};
|
||||
|
||||
// Initialize backtest mode
|
||||
await modeManager.initializeMode({
|
||||
mode: 'backtest',
|
||||
startDate: '2023-01-01T00:00:00Z',
|
||||
endDate: '2024-01-01T00:00:00Z',
|
||||
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: 'Trade Type Verification',
|
||||
strategy: 'sma-crossover',
|
||||
symbols: ['AAPL'],
|
||||
startDate: '2023-01-01T00:00:00Z',
|
||||
endDate: '2024-01-01T00:00:00Z',
|
||||
initialCapital: 100000,
|
||||
commission: 0.001,
|
||||
slippage: 0.0001,
|
||||
dataFrequency: '1d' as const,
|
||||
speed: 'max' as const
|
||||
};
|
||||
|
||||
console.log('=== VERIFYING BOTH LONG AND SHORT TRADES ===\n');
|
||||
|
||||
try {
|
||||
const result = await backtestEngine.runBacktest(config);
|
||||
|
||||
console.log('=== BACKTEST COMPLETE ===');
|
||||
console.log(`Total Trades: ${result.metrics.totalTrades}`);
|
||||
console.log(`Win Rate: ${result.metrics.winRate.toFixed(2)}%`);
|
||||
console.log(`Total Return: ${result.metrics.totalReturn.toFixed(2)}%`);
|
||||
|
||||
// Analyze trades
|
||||
let longTrades = 0;
|
||||
let shortTrades = 0;
|
||||
let longPnL = 0;
|
||||
let shortPnL = 0;
|
||||
|
||||
console.log('\n=== DETAILED TRADE ANALYSIS ===');
|
||||
result.trades.forEach((trade, i) => {
|
||||
const isLong = trade.side === 'buy';
|
||||
const tradeType = isLong ? 'LONG' : 'SHORT';
|
||||
|
||||
if (isLong) {
|
||||
longTrades++;
|
||||
longPnL += trade.pnl;
|
||||
} else {
|
||||
shortTrades++;
|
||||
shortPnL += trade.pnl;
|
||||
}
|
||||
|
||||
console.log(`\nTrade ${i + 1}:`);
|
||||
console.log(` Type: ${tradeType} position`);
|
||||
console.log(` Opening side: ${trade.side.toUpperCase()}`);
|
||||
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)} (${trade.pnlPercent.toFixed(2)}%)`);
|
||||
|
||||
// Explain the trade flow
|
||||
if (isLong) {
|
||||
console.log(` Order flow: BUY ${trade.quantity} shares → SELL ${trade.quantity} shares`);
|
||||
} else {
|
||||
console.log(` Order flow: SELL ${trade.quantity} shares → BUY ${trade.quantity} shares`);
|
||||
}
|
||||
});
|
||||
|
||||
console.log('\n=== SUMMARY BY TRADE TYPE ===');
|
||||
console.log(`LONG trades: ${longTrades}`);
|
||||
console.log(` - Total P&L from longs: $${longPnL.toFixed(2)}`);
|
||||
console.log(` - Average P&L per long: $${longTrades > 0 ? (longPnL / longTrades).toFixed(2) : '0.00'}`);
|
||||
|
||||
console.log(`\nSHORT trades: ${shortTrades}`);
|
||||
console.log(` - Total P&L from shorts: $${shortPnL.toFixed(2)}`);
|
||||
console.log(` - Average P&L per short: $${shortTrades > 0 ? (shortPnL / shortTrades).toFixed(2) : '0.00'}`);
|
||||
|
||||
console.log(`\nTotal trades: ${result.metrics.totalTrades}`);
|
||||
|
||||
if (longTrades === 0) {
|
||||
console.log('\n⚠️ WARNING: No long trades found!');
|
||||
}
|
||||
if (shortTrades === 0) {
|
||||
console.log('\n⚠️ WARNING: No short trades found!');
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Test failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Run the verification
|
||||
verifyBothTradeTypes().catch(console.error);
|
||||
Loading…
Add table
Add a link
Reference in a new issue