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
|
|
@ -14,7 +14,7 @@ use crate::{
|
|||
|
||||
use super::{
|
||||
BacktestConfig, BacktestState, EventQueue, BacktestEvent, EventType,
|
||||
Strategy, Signal, SignalType, BacktestResult,
|
||||
Strategy, Signal, SignalType, BacktestResult, TradeTracker,
|
||||
};
|
||||
|
||||
pub struct BacktestEngine {
|
||||
|
|
@ -38,6 +38,9 @@ pub struct BacktestEngine {
|
|||
|
||||
// Price tracking
|
||||
last_prices: HashMap<String, f64>,
|
||||
|
||||
// Trade tracking
|
||||
trade_tracker: TradeTracker,
|
||||
}
|
||||
|
||||
impl BacktestEngine {
|
||||
|
|
@ -67,6 +70,7 @@ impl BacktestEngine {
|
|||
profitable_trades: 0,
|
||||
total_pnl: 0.0,
|
||||
last_prices: HashMap::new(),
|
||||
trade_tracker: TradeTracker::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -394,6 +398,9 @@ impl BacktestEngine {
|
|||
// Record the fill with symbol and side information
|
||||
self.state.write().record_fill(order.symbol.clone(), order.side, fill.clone());
|
||||
|
||||
// Track trades
|
||||
self.trade_tracker.process_fill(&order.symbol, order.side, &fill);
|
||||
|
||||
// Update cash
|
||||
let cash_change = match order.side {
|
||||
crate::Side::Buy => -(fill.quantity * fill.price + fill.commission),
|
||||
|
|
@ -410,6 +417,13 @@ impl BacktestEngine {
|
|||
}
|
||||
}
|
||||
|
||||
eprintln!("Fill processed: {} {} @ {} (side: {:?})",
|
||||
fill.quantity, order.symbol, fill.price, order.side);
|
||||
eprintln!("Current position after fill: {}",
|
||||
self.position_tracker.get_position(&order.symbol)
|
||||
.map(|p| p.quantity)
|
||||
.unwrap_or(0.0));
|
||||
|
||||
// Update metrics
|
||||
self.total_trades += 1;
|
||||
if update.resulting_position.realized_pnl > 0.0 {
|
||||
|
|
@ -470,24 +484,43 @@ impl BacktestEngine {
|
|||
let total_pnl = realized_pnl + unrealized_pnl;
|
||||
let total_return = (total_pnl / self.config.initial_capital) * 100.0;
|
||||
|
||||
// Get completed trades from trade tracker for metrics
|
||||
let completed_trades = self.trade_tracker.get_completed_trades();
|
||||
|
||||
// Calculate metrics from completed trades
|
||||
let completed_trade_count = completed_trades.len();
|
||||
let profitable_trades = completed_trades.iter().filter(|t| t.pnl > 0.0).count();
|
||||
let total_wins: f64 = completed_trades.iter().filter(|t| t.pnl > 0.0).map(|t| t.pnl).sum();
|
||||
let total_losses: f64 = completed_trades.iter().filter(|t| t.pnl < 0.0).map(|t| t.pnl.abs()).sum();
|
||||
let avg_win = if profitable_trades > 0 { total_wins / profitable_trades as f64 } else { 0.0 };
|
||||
let avg_loss = if completed_trade_count > profitable_trades {
|
||||
total_losses / (completed_trade_count - profitable_trades) as f64
|
||||
} else { 0.0 };
|
||||
let profit_factor = if total_losses > 0.0 { total_wins / total_losses } else { 0.0 };
|
||||
|
||||
// For the API, return all fills (not just completed trades)
|
||||
// This shows all trading activity
|
||||
let all_fills = state.completed_trades.clone();
|
||||
let total_trades = all_fills.len();
|
||||
|
||||
BacktestResult {
|
||||
config: self.config.clone(),
|
||||
metrics: super::BacktestMetrics {
|
||||
total_return,
|
||||
total_trades: self.total_trades,
|
||||
profitable_trades: self.profitable_trades,
|
||||
win_rate: if self.total_trades > 0 {
|
||||
(self.profitable_trades as f64 / self.total_trades as f64) * 100.0
|
||||
total_trades,
|
||||
profitable_trades,
|
||||
win_rate: if completed_trade_count > 0 {
|
||||
(profitable_trades as f64 / completed_trade_count as f64) * 100.0
|
||||
} else { 0.0 },
|
||||
profit_factor: 0.0, // TODO: Calculate properly
|
||||
profit_factor,
|
||||
sharpe_ratio: 0.0, // TODO: Calculate properly
|
||||
max_drawdown: 0.0, // TODO: Calculate properly
|
||||
total_pnl,
|
||||
avg_win: 0.0, // TODO: Calculate properly
|
||||
avg_loss: 0.0, // TODO: Calculate properly
|
||||
avg_win,
|
||||
avg_loss,
|
||||
},
|
||||
equity_curve: state.equity_curve.clone(),
|
||||
trades: state.completed_trades.clone(),
|
||||
trades: all_fills,
|
||||
final_positions: self.position_tracker.get_all_positions()
|
||||
.into_iter()
|
||||
.map(|p| (p.symbol.clone(), p))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue