institutional-trader/backend/scripts/testBacktester.js

168 lines
5.8 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Test script for backtesting functionality
* Tests the enhanced backtester with sample patterns
*/
import { backtestSignal } from '../src/services/backtester.js';
import { rawQuery } from '../src/db.js';
async function testBacktester() {
console.log('🧪 Testing Enhanced Backtester\n');
console.log('='.repeat(60));
try {
// Test 1: Check database connectivity
console.log('\n1⃣ Testing database connectivity...');
try {
const testQuery = await rawQuery('SELECT COUNT(*) as count FROM "OptionsFlow_monthly" LIMIT 1');
console.log(' ✅ Database connection successful');
console.log(` 📊 OptionsFlow_monthly table accessible`);
} catch (error) {
console.log(' ❌ Database connection failed:', error.message);
console.log(' 💡 Make sure database is configured and accessible');
return false;
}
// Test 2: Check price data availability
console.log('\n2⃣ Checking price data availability...');
try {
const priceCheck = await rawQuery(`
SELECT
COUNT(*) as intraday_count,
MIN(ts) as earliest_intraday,
MAX(ts) as latest_intraday
FROM prices_intraday_1m
WHERE ts >= NOW() - INTERVAL '30 days'
LIMIT 1
`);
const dailyCheck = await rawQuery(`
SELECT
COUNT(*) as daily_count,
MIN("Date") as earliest_daily,
MAX("Date") as latest_daily
FROM prices_daily
WHERE "Date" >= CURRENT_DATE - INTERVAL '30 days'
LIMIT 1
`);
console.log(' 📈 Intraday data:', {
count: priceCheck[0]?.intraday_count || 0,
range: priceCheck[0]?.earliest_intraday && priceCheck[0]?.latest_intraday
? `${priceCheck[0].earliest_intraday} to ${priceCheck[0].latest_intraday}`
: 'No data'
});
console.log(' 📊 Daily data:', {
count: dailyCheck[0]?.daily_count || 0,
range: dailyCheck[0]?.earliest_daily && dailyCheck[0]?.latest_daily
? `${dailyCheck[0].earliest_daily} to ${dailyCheck[0].latest_daily}`
: 'No data'
});
if ((priceCheck[0]?.intraday_count || 0) === 0 && (dailyCheck[0]?.daily_count || 0) === 0) {
console.log(' ⚠️ No price data found for last 30 days');
console.log(' 💡 Run: python yahhooscript.py to pull historical data');
} else {
console.log(' ✅ Price data available');
}
} catch (error) {
console.log(' ⚠️ Error checking price data:', error.message);
}
// Test 3: Run a simple backtest
console.log('\n3⃣ Running sample backtest...');
try {
const testPattern = {
rocketScoreMin: 3.0,
session: 'RTH'
};
console.log(' Pattern:', JSON.stringify(testPattern, null, 2));
console.log(' Lookback: 30 days');
const results = await backtestSignal(testPattern, 30);
console.log('\n 📊 Results:');
console.log(` - Total Occurrences: ${results.totalOccurrences}`);
console.log(` - Wins: ${results.wins}`);
console.log(` - Losses: ${results.losses}`);
console.log(` - Win Rate: ${results.winRate}%`);
console.log(` - Avg Win: ${results.avgWin}%`);
console.log(` - Avg Loss: ${results.avgLoss}%`);
console.log(` - Expectancy: ${results.expectancy}%`);
if (results.sharpeRatio !== undefined) {
console.log(` - Sharpe Ratio: ${results.sharpeRatio}`);
}
if (results.maxDrawdown !== undefined) {
console.log(` - Max Drawdown: ${results.maxDrawdown}%`);
}
if (results.streaks) {
console.log(` - Max Win Streak: ${results.streaks.maxWinStreak}`);
console.log(` - Max Loss Streak: ${results.streaks.maxLossStreak}`);
}
if (results.sessionPerformance && results.sessionPerformance.length > 0) {
console.log(' - Session Performance:');
results.sessionPerformance.forEach(session => {
console.log(` ${session.session}: ${session.winRate.toFixed(1)}% win rate (${session.totalTrades} trades)`);
});
}
if (results.totalOccurrences === 0) {
console.log('\n ⚠️ No matches found for this pattern');
console.log(' 💡 This could mean:');
console.log(' - No options flow data in the date range');
console.log(' - Pattern criteria too strict');
console.log(' - Need to pull historical data first');
} else {
console.log('\n ✅ Backtest completed successfully');
}
} catch (error) {
console.log(' ❌ Backtest failed:', error.message);
console.error(error);
return false;
}
// Test 4: Verify new metrics are calculated
console.log('\n4⃣ Verifying enhanced metrics...');
const metricsToCheck = [
'sharpeRatio',
'maxDrawdown',
'streaks',
'sessionPerformance',
'symbolPerformance',
'equityCurve'
];
let allMetricsPresent = true;
metricsToCheck.forEach(metric => {
// We'll check this in the next test with actual data
});
console.log(' ✅ Enhanced metrics module loaded');
console.log('\n' + '='.repeat(60));
console.log('✅ Backtester testing complete!');
console.log('\n💡 Next steps:');
console.log(' 1. Pull historical data: python yahhooscript.py');
console.log(' 2. Test API endpoints: POST /api/backtest/run');
console.log(' 3. Compare strategies: POST /api/backtest/compare');
return true;
} catch (error) {
console.error('\n❌ Test failed:', error);
return false;
}
}
// Run tests
testBacktester()
.then(success => {
process.exit(success ? 0 : 1);
})
.catch(error => {
console.error('Fatal error:', error);
process.exit(1);
});