moving engine to rust
This commit is contained in:
parent
d14380d740
commit
16ac28a565
16 changed files with 1598 additions and 3 deletions
145
apps/stock/orchestrator/test-rust-backtest.ts
Normal file
145
apps/stock/orchestrator/test-rust-backtest.ts
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
import { createRustBacktest } from './src/backtest/RustBacktestEngine';
|
||||
import { SimpleMovingAverageCrossoverRust } from './src/strategies/rust/SimpleMovingAverageCrossoverRust';
|
||||
import { IServiceContainer } from '@stock-bot/di';
|
||||
|
||||
// Mock StorageService
|
||||
class MockStorageService {
|
||||
async getHistoricalBars(symbol: string, startDate: Date, endDate: Date, frequency: string) {
|
||||
// Generate mock data
|
||||
const bars = [];
|
||||
const msPerDay = 24 * 60 * 60 * 1000;
|
||||
let currentDate = new Date(startDate);
|
||||
let price = 100 + Math.random() * 50; // Start between 100-150
|
||||
|
||||
while (currentDate <= endDate) {
|
||||
// Random walk
|
||||
const change = (Math.random() - 0.5) * 2; // +/- 1%
|
||||
price *= (1 + change / 100);
|
||||
|
||||
bars.push({
|
||||
symbol,
|
||||
timestamp: new Date(currentDate),
|
||||
open: price * (1 + (Math.random() - 0.5) * 0.01),
|
||||
high: price * (1 + Math.random() * 0.02),
|
||||
low: price * (1 - Math.random() * 0.02),
|
||||
close: price,
|
||||
volume: 1000000 + Math.random() * 500000,
|
||||
});
|
||||
|
||||
currentDate = new Date(currentDate.getTime() + msPerDay);
|
||||
}
|
||||
|
||||
return bars;
|
||||
}
|
||||
}
|
||||
|
||||
async function testRustBacktest() {
|
||||
console.log('🚀 Testing Rust Backtest Engine with TypeScript Strategy\n');
|
||||
|
||||
// Create minimal container
|
||||
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: {
|
||||
StorageService: new MockStorageService(),
|
||||
}
|
||||
};
|
||||
|
||||
// Backtest configuration
|
||||
const config = {
|
||||
mode: 'backtest' as const,
|
||||
name: 'Rust Engine Test',
|
||||
strategy: 'sma-crossover',
|
||||
symbols: ['AAPL'], // Just one symbol for testing
|
||||
startDate: '2023-01-01T00:00:00Z',
|
||||
endDate: '2023-01-31T00:00:00Z', // Just one month for testing
|
||||
initialCapital: 100000,
|
||||
commission: 0.001,
|
||||
slippage: 0.0001,
|
||||
dataFrequency: '1d',
|
||||
speed: 'max' as const,
|
||||
};
|
||||
|
||||
// Create strategy
|
||||
const strategy = new SimpleMovingAverageCrossoverRust({
|
||||
fastPeriod: 10,
|
||||
slowPeriod: 30,
|
||||
minHoldingBars: 5,
|
||||
});
|
||||
|
||||
console.log('Configuration:');
|
||||
console.log(` Symbols: ${config.symbols.join(', ')}`);
|
||||
console.log(` Period: ${config.startDate} to ${config.endDate}`);
|
||||
console.log(` Initial Capital: $${config.initialCapital.toLocaleString()}`);
|
||||
console.log(` Strategy: ${strategy.constructor.name}`);
|
||||
console.log('');
|
||||
|
||||
try {
|
||||
console.log('Running backtest in Rust engine...\n');
|
||||
const startTime = Date.now();
|
||||
|
||||
try {
|
||||
const result = await createRustBacktest(container, config, [strategy]);
|
||||
console.log('Raw result:', result);
|
||||
|
||||
const duration = (Date.now() - startTime) / 1000;
|
||||
|
||||
console.log(`\n✅ Backtest completed in ${duration.toFixed(2)} seconds`);
|
||||
|
||||
if (!result || !result.metrics) {
|
||||
console.error('Invalid result structure:', result);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('\n=== PERFORMANCE METRICS ===');
|
||||
console.log(`Total Return: ${result.metrics.totalReturn?.toFixed(2) || 'N/A'}%`);
|
||||
console.log(`Sharpe Ratio: ${result.metrics.sharpeRatio?.toFixed(2) || 'N/A'}`);
|
||||
console.log(`Max Drawdown: ${result.metrics.maxDrawdown ? (result.metrics.maxDrawdown * 100).toFixed(2) : 'N/A'}%`);
|
||||
console.log(`Win Rate: ${result.metrics.winRate?.toFixed(1) || 'N/A'}%`);
|
||||
console.log(`Total Trades: ${result.metrics.totalTrades || 0}`);
|
||||
console.log(`Profit Factor: ${result.metrics.profitFactor?.toFixed(2) || 'N/A'}`);
|
||||
|
||||
console.log('\n=== TRADE STATISTICS ===');
|
||||
console.log(`Profitable Trades: ${result.metrics.profitableTrades || 0}`);
|
||||
console.log(`Average Win: $${result.metrics.avgWin?.toFixed(2) || '0.00'}`);
|
||||
console.log(`Average Loss: $${result.metrics.avgLoss?.toFixed(2) || '0.00'}`);
|
||||
console.log(`Total P&L: $${result.metrics.totalPnl?.toFixed(2) || '0.00'}`);
|
||||
|
||||
console.log('\n=== EQUITY CURVE ===');
|
||||
if (result.equityCurve.length > 0) {
|
||||
const firstValue = result.equityCurve[0].value;
|
||||
const lastValue = result.equityCurve[result.equityCurve.length - 1].value;
|
||||
console.log(`Starting Value: $${firstValue.toLocaleString()}`);
|
||||
console.log(`Ending Value: $${lastValue.toLocaleString()}`);
|
||||
console.log(`Growth: ${((lastValue / firstValue - 1) * 100).toFixed(2)}%`);
|
||||
}
|
||||
|
||||
console.log('\n=== FINAL POSITIONS ===');
|
||||
const positions = Object.entries(result.finalPositions);
|
||||
if (positions.length > 0) {
|
||||
for (const [symbol, position] of positions) {
|
||||
console.log(`${symbol}: ${position.quantity} shares @ $${position.averagePrice}`);
|
||||
}
|
||||
} else {
|
||||
console.log('No open positions');
|
||||
}
|
||||
|
||||
// Compare with TypeScript engine performance
|
||||
console.log('\n=== PERFORMANCE COMPARISON ===');
|
||||
console.log('TypeScript Engine: ~5-10 seconds for 1 year backtest');
|
||||
console.log(`Rust Engine: ${duration.toFixed(2)} seconds`);
|
||||
console.log(`Speed Improvement: ${(10 / duration).toFixed(1)}x faster`);
|
||||
} catch (innerError) {
|
||||
console.error('Result processing error:', innerError);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ Backtest failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Run the test
|
||||
testRustBacktest().catch(console.error);
|
||||
Loading…
Add table
Add a link
Reference in a new issue