finished initial backtest / engine

This commit is contained in:
Boki 2025-07-03 12:49:22 -04:00
parent 55b4ca78c9
commit c106a719e8
18 changed files with 1571 additions and 180 deletions

View file

@ -0,0 +1,151 @@
#!/usr/bin/env bun
/**
* Test SMA strategy directly to debug trading
*/
import { SimpleMovingAverageCrossover } from './src/strategies/examples/SimpleMovingAverageCrossover';
import { getLogger } from '@stock-bot/logger';
async function testSMAStrategy() {
console.log('=== Testing SMA Strategy Trading ===\n');
const logger = getLogger('test');
const config = {
id: 'test-sma',
name: 'Test SMA',
enabled: true,
symbols: ['AAPL'],
allocation: 1.0
};
const strategy = new SimpleMovingAverageCrossover(config, null, null);
let signalCount = 0;
let orderCount = 0;
const orders: any[] = [];
strategy.on('signal', (signal) => {
signalCount++;
console.log(`\n📊 Signal #${signalCount}:`, {
type: signal.type,
symbol: signal.symbol,
strength: signal.strength,
reason: signal.reason
});
});
strategy.on('order', (order) => {
orderCount++;
orders.push(order);
console.log(`\n📈 Order #${orderCount}:`, order);
});
await strategy.start();
// Generate clear pattern: downtrend then uptrend
console.log('Generating market data with clear trend changes...\n');
// Phase 1: Stable around 100 for first 10 days
for (let i = 0; i < 10; i++) {
const price = 100 + Math.sin(i * 0.5) * 2;
await strategy.onMarketData({
type: 'bar',
data: {
symbol: 'AAPL',
open: price,
high: price + 1,
low: price - 1,
close: price,
volume: 1000000,
timestamp: Date.now() + i * 86400000
}
});
}
// Phase 2: Clear downtrend from 100 to 80 (days 11-30)
for (let i = 10; i < 30; i++) {
const price = 100 - (i - 10); // Falls by $1 per day
await strategy.onMarketData({
type: 'bar',
data: {
symbol: 'AAPL',
open: price,
high: price + 0.5,
low: price - 0.5,
close: price,
volume: 1000000,
timestamp: Date.now() + i * 86400000
}
});
}
// Phase 3: Clear uptrend from 80 to 110 (days 31-60)
for (let i = 30; i < 60; i++) {
const price = 80 + (i - 30); // Rises by $1 per day
await strategy.onMarketData({
type: 'bar',
data: {
symbol: 'AAPL',
open: price,
high: price + 0.5,
low: price - 0.5,
close: price,
volume: 1000000,
timestamp: Date.now() + i * 86400000
}
});
// Simulate position update after first buy
if (i === 45 && orders.length > 0) {
console.log('\n🔄 Simulating position update after buy order...');
await strategy.onOrderUpdate({
orderId: 'test-order-1',
symbol: 'AAPL',
side: 'buy',
status: 'filled',
fills: [{
quantity: orders[0].quantity,
price: 95
}]
});
}
}
// Phase 4: Another downtrend from 110 to 90 (days 61-80)
for (let i = 60; i < 80; i++) {
const price = 110 - (i - 60); // Falls by $1 per day
if (i % 5 === 0) {
console.log(`\nDay ${i + 1}: Price = $${price}`);
}
await strategy.onMarketData({
type: 'bar',
data: {
symbol: 'AAPL',
open: price,
high: price + 0.5,
low: price - 0.5,
close: price,
volume: 1000000,
timestamp: Date.now() + i * 86400000
}
});
}
await strategy.stop();
console.log('\n=== Test Results ===');
console.log(`Total signals generated: ${signalCount}`);
console.log(`Total orders generated: ${orderCount}`);
console.log(`\nExpected behavior:`);
console.log(`- Golden cross around day 40-45 (when 10 SMA crosses above 20 SMA)`);
console.log(`- Death cross around day 70-75 (when 10 SMA crosses below 20 SMA)`);
const perf = strategy.getPerformance();
console.log('\nStrategy performance:', perf);
}
testSMAStrategy().catch(console.error);