added trade-tracking and example rust strats
This commit is contained in:
parent
0a4702d12a
commit
3a7557c8f4
15 changed files with 2108 additions and 29 deletions
274
test-rust-strategies.js
Normal file
274
test-rust-strategies.js
Normal file
|
|
@ -0,0 +1,274 @@
|
|||
#!/usr/bin/env bun
|
||||
|
||||
import { BacktestEngine } from './apps/stock/core/index.js';
|
||||
|
||||
// Test configuration
|
||||
const config = {
|
||||
name: 'Native Rust Strategies Test',
|
||||
symbols: ['AA', 'AAS'],
|
||||
startDate: '2024-01-01T00:00:00Z',
|
||||
endDate: '2024-01-31T00:00:00Z',
|
||||
initialCapital: 100000,
|
||||
commission: 0.001,
|
||||
slippage: 0.0001,
|
||||
dataFrequency: '1d',
|
||||
};
|
||||
|
||||
// Create the Rust engine
|
||||
const engine = new BacktestEngine(config);
|
||||
|
||||
// Test different native Rust strategies
|
||||
console.log('Testing native Rust strategies...\n');
|
||||
|
||||
// 1. Test Mean Reversion Strategy
|
||||
console.log('1. Mean Reversion Strategy');
|
||||
engine.addNativeStrategy(
|
||||
'mean_reversion',
|
||||
'Mean Reversion AA/AAS',
|
||||
'mean-rev-1',
|
||||
{
|
||||
lookbackPeriod: 20,
|
||||
entryThreshold: 2.0,
|
||||
positionSize: 1000,
|
||||
}
|
||||
);
|
||||
|
||||
// Generate synthetic market data with mean-reverting characteristics
|
||||
const testData = [];
|
||||
const startDate = new Date('2024-01-01');
|
||||
|
||||
for (let i = 0; i < 30; i++) {
|
||||
const date = new Date(startDate);
|
||||
date.setDate(date.getDate() + i);
|
||||
|
||||
// AA: Mean-reverting around 100
|
||||
const aaMean = 100;
|
||||
const aaPrice = aaMean + Math.sin(i / 5) * 10 + (Math.random() - 0.5) * 5;
|
||||
|
||||
// AAS: Mean-reverting around 50
|
||||
const aasMean = 50;
|
||||
const aasPrice = aasMean + Math.sin(i / 5) * 5 + (Math.random() - 0.5) * 2.5;
|
||||
|
||||
testData.push({
|
||||
symbol: 'AA',
|
||||
timestamp: date.getTime(),
|
||||
type: 'bar',
|
||||
open: aaPrice - 0.5,
|
||||
high: aaPrice + 0.5,
|
||||
low: aaPrice - 1,
|
||||
close: aaPrice,
|
||||
volume: 1000000,
|
||||
vwap: aaPrice,
|
||||
});
|
||||
|
||||
testData.push({
|
||||
symbol: 'AAS',
|
||||
timestamp: date.getTime(),
|
||||
type: 'bar',
|
||||
open: aasPrice - 0.25,
|
||||
high: aasPrice + 0.25,
|
||||
low: aasPrice - 0.5,
|
||||
close: aasPrice,
|
||||
volume: 500000,
|
||||
vwap: aasPrice,
|
||||
});
|
||||
}
|
||||
|
||||
console.log(`Loading ${testData.length} market data points...`);
|
||||
engine.loadMarketData(testData);
|
||||
|
||||
// Run the backtest
|
||||
console.log('Running mean reversion backtest...');
|
||||
try {
|
||||
const resultJson = engine.run();
|
||||
const result = JSON.parse(resultJson);
|
||||
|
||||
console.log('\nResults:');
|
||||
console.log('Total trades:', result.trades?.length || 0);
|
||||
console.log('Win rate:', result.metrics.win_rate?.toFixed(2) + '%');
|
||||
console.log('Profit factor:', result.metrics.profit_factor?.toFixed(2));
|
||||
console.log('Total PnL:', '$' + result.metrics.total_pnl?.toFixed(2));
|
||||
console.log('Final equity:', '$' + result.equity_curve[result.equity_curve.length - 1]?.[1].toFixed(2));
|
||||
|
||||
// Show some trades
|
||||
if (result.trades && result.trades.length > 0) {
|
||||
console.log('\nFirst few trades:');
|
||||
result.trades.slice(0, 5).forEach((trade, i) => {
|
||||
console.log(` ${i + 1}. ${trade.symbol} ${trade.side} @ $${trade.price.toFixed(2)}`);
|
||||
});
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Backtest failed:', error);
|
||||
}
|
||||
|
||||
console.log('\n' + '='.repeat(50) + '\n');
|
||||
|
||||
// 2. Test Momentum Strategy
|
||||
console.log('2. Momentum Strategy');
|
||||
|
||||
// Create a new engine for momentum strategy
|
||||
const engine2 = new BacktestEngine(config);
|
||||
|
||||
engine2.addNativeStrategy(
|
||||
'momentum',
|
||||
'Momentum Trading',
|
||||
'momentum-1',
|
||||
{
|
||||
lookbackPeriod: 10,
|
||||
momentumThreshold: 5.0,
|
||||
positionSize: 1000,
|
||||
}
|
||||
);
|
||||
|
||||
// Generate trending market data
|
||||
const trendData = [];
|
||||
for (let i = 0; i < 30; i++) {
|
||||
const date = new Date(startDate);
|
||||
date.setDate(date.getDate() + i);
|
||||
|
||||
// AA: Uptrend
|
||||
const aaPrice = 100 + i * 2 + (Math.random() - 0.5) * 2;
|
||||
|
||||
// AAS: Downtrend then uptrend
|
||||
const aasPrice = i < 15
|
||||
? 50 - i * 1 + (Math.random() - 0.5) * 1
|
||||
: 35 + (i - 15) * 1.5 + (Math.random() - 0.5) * 1;
|
||||
|
||||
trendData.push({
|
||||
symbol: 'AA',
|
||||
timestamp: date.getTime(),
|
||||
type: 'bar',
|
||||
open: aaPrice - 0.5,
|
||||
high: aaPrice + 0.5,
|
||||
low: aaPrice - 1,
|
||||
close: aaPrice,
|
||||
volume: 1000000,
|
||||
vwap: aaPrice,
|
||||
});
|
||||
|
||||
trendData.push({
|
||||
symbol: 'AAS',
|
||||
timestamp: date.getTime(),
|
||||
type: 'bar',
|
||||
open: aasPrice - 0.25,
|
||||
high: aasPrice + 0.25,
|
||||
low: aasPrice - 0.5,
|
||||
close: aasPrice,
|
||||
volume: 500000,
|
||||
vwap: aasPrice,
|
||||
});
|
||||
}
|
||||
|
||||
engine2.loadMarketData(trendData);
|
||||
|
||||
console.log('Running momentum backtest...');
|
||||
try {
|
||||
const resultJson = engine2.run();
|
||||
const result = JSON.parse(resultJson);
|
||||
|
||||
console.log('\nResults:');
|
||||
console.log('Total trades:', result.trades?.length || 0);
|
||||
console.log('Win rate:', result.metrics.win_rate?.toFixed(2) + '%');
|
||||
console.log('Profit factor:', result.metrics.profit_factor?.toFixed(2));
|
||||
console.log('Total PnL:', '$' + result.metrics.total_pnl?.toFixed(2));
|
||||
console.log('Final equity:', '$' + result.equity_curve[result.equity_curve.length - 1]?.[1].toFixed(2));
|
||||
|
||||
} catch (error) {
|
||||
console.error('Backtest failed:', error);
|
||||
}
|
||||
|
||||
console.log('\n' + '='.repeat(50) + '\n');
|
||||
|
||||
// 3. Test Pairs Trading Strategy
|
||||
console.log('3. Pairs Trading Strategy');
|
||||
|
||||
const engine3 = new BacktestEngine(config);
|
||||
|
||||
engine3.addNativeStrategy(
|
||||
'pairs_trading',
|
||||
'Pairs Trading AA/AAS',
|
||||
'pairs-1',
|
||||
{
|
||||
pairA: 'AA',
|
||||
pairB: 'AAS',
|
||||
lookbackPeriod: 20,
|
||||
entryThreshold: 2.0,
|
||||
positionSize: 1000,
|
||||
}
|
||||
);
|
||||
|
||||
// Generate correlated market data with spread deviations
|
||||
const pairsData = [];
|
||||
for (let i = 0; i < 30; i++) {
|
||||
const date = new Date(startDate);
|
||||
date.setDate(date.getDate() + i);
|
||||
|
||||
// Base prices
|
||||
const basePrice = 100 + Math.sin(i / 10) * 5;
|
||||
|
||||
// Spread oscillates around 50
|
||||
const spread = 50 + Math.sin(i / 3) * 10 + (Math.random() - 0.5) * 2;
|
||||
|
||||
const aaPrice = basePrice;
|
||||
const aasPrice = basePrice - spread;
|
||||
|
||||
pairsData.push({
|
||||
symbol: 'AA',
|
||||
timestamp: date.getTime(),
|
||||
type: 'bar',
|
||||
open: aaPrice - 0.5,
|
||||
high: aaPrice + 0.5,
|
||||
low: aaPrice - 1,
|
||||
close: aaPrice,
|
||||
volume: 1000000,
|
||||
vwap: aaPrice,
|
||||
});
|
||||
|
||||
pairsData.push({
|
||||
symbol: 'AAS',
|
||||
timestamp: date.getTime(),
|
||||
type: 'bar',
|
||||
open: aasPrice - 0.25,
|
||||
high: aasPrice + 0.25,
|
||||
low: aasPrice - 0.5,
|
||||
close: aasPrice,
|
||||
volume: 500000,
|
||||
vwap: aasPrice,
|
||||
});
|
||||
}
|
||||
|
||||
engine3.loadMarketData(pairsData);
|
||||
|
||||
console.log('Running pairs trading backtest...');
|
||||
try {
|
||||
const resultJson = engine3.run();
|
||||
const result = JSON.parse(resultJson);
|
||||
|
||||
console.log('\nResults:');
|
||||
console.log('Total trades:', result.trades?.length || 0);
|
||||
console.log('Win rate:', result.metrics.win_rate?.toFixed(2) + '%');
|
||||
console.log('Profit factor:', result.metrics.profit_factor?.toFixed(2));
|
||||
console.log('Total PnL:', '$' + result.metrics.total_pnl?.toFixed(2));
|
||||
console.log('Final equity:', '$' + result.equity_curve[result.equity_curve.length - 1]?.[1].toFixed(2));
|
||||
|
||||
// Show paired trades
|
||||
if (result.trades && result.trades.length > 0) {
|
||||
console.log('\nPairs trades (showing pairs):');
|
||||
for (let i = 0; i < result.trades.length && i < 6; i += 2) {
|
||||
const trade1 = result.trades[i];
|
||||
const trade2 = result.trades[i + 1];
|
||||
if (trade2) {
|
||||
console.log(` Pair ${Math.floor(i/2) + 1}: ${trade1.symbol} ${trade1.side} @ $${trade1.price.toFixed(2)}, ${trade2.symbol} ${trade2.side} @ $${trade2.price.toFixed(2)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Backtest failed:', error);
|
||||
}
|
||||
|
||||
console.log('\n' + '='.repeat(50));
|
||||
console.log('\nNative Rust strategies test complete!');
|
||||
console.log('\nThese strategies run at microsecond speeds in Rust,');
|
||||
console.log('perfect for high-frequency trading and production use.');
|
||||
Loading…
Add table
Add a link
Reference in a new issue