/// @module std::finance::backtest::state
/// Backtest State Types
///
/// Core state types for backtesting simulations using the high-performance
/// simulation engine (simulate() and simulate_correlated()).
// ===== Backtest State =====
/// Core state tracked during a backtest simulation
/// All monetary values are in account currency
pub type BacktestState = {
// Portfolio state
cash: number; // Available cash
position: number; // Current position size (positive = long, negative = short)
entry_price: number; // Average entry price of current position
equity: number; // Total equity (cash + position value)
// Trade statistics
trades: number; // Total number of completed trades
wins: number; // Number of winning trades
losses: number; // Number of losing trades
// Drawdown tracking
peak_equity: number; // Highest equity achieved
max_drawdown: number; // Maximum drawdown seen (as decimal, e.g., 0.15 = 15%)
// P&L tracking
total_pnl: number; // Total realized P&L
unrealized_pnl: number; // Unrealized P&L on open position
};
/// Create initial backtest state with given capital
pub fn initial_state(capital = 100000.0) {
{
cash: capital,
position: 0.0,
entry_price: 0.0,
equity: capital,
trades: 0,
wins: 0,
losses: 0,
peak_equity: capital,
max_drawdown: 0.0,
total_pnl: 0.0,
unrealized_pnl: 0.0
}
}
// ===== Order Types =====
/// Order request generated by strategy
pub type Order = {
side: string; // "buy" | "sell"
quantity: number; // Number of units
price: number; // Limit price (0 for market order)
order_type: string; // "market" | "limit" | "stop"
stop_loss: number; // Stop loss price (0 = none)
take_profit: number; // Take profit price (0 = none)
};
/// Create a market buy order
pub fn market_buy(quantity, stop_loss = 0.0, take_profit = 0.0) {
{
side: "buy",
quantity: quantity,
price: 0.0,
order_type: "market",
stop_loss: stop_loss,
take_profit: take_profit
}
}
/// Create a market sell order
pub fn market_sell(quantity, stop_loss = 0.0, take_profit = 0.0) {
{
side: "sell",
quantity: quantity,
price: 0.0,
order_type: "market",
stop_loss: stop_loss,
take_profit: take_profit
}
}
/// Create a limit buy order
pub fn limit_buy(quantity, price, stop_loss = 0.0, take_profit = 0.0) {
{
side: "buy",
quantity: quantity,
price: price,
order_type: "limit",
stop_loss: stop_loss,
take_profit: take_profit
}
}
/// Create a limit sell order
pub fn limit_sell(quantity, price, stop_loss = 0.0, take_profit = 0.0) {
{
side: "sell",
quantity: quantity,
price: price,
order_type: "limit",
stop_loss: stop_loss,
take_profit: take_profit
}
}
// ===== Position Helpers =====
/// Check if we have a long position
pub fn is_long(state) {
state.position > 0
}
/// Check if we have a short position
pub fn is_short(state) {
state.position < 0
}
/// Check if we have no position
pub fn is_flat(state) {
state.position == 0
}
/// Get absolute position size
pub fn position_size(state) {
abs(state.position)
}
/// Calculate current win rate (0-1)
pub fn win_rate(state) {
if state.trades == 0 {
0.0
} else {
state.wins / state.trades
}
}
/// Calculate profit factor (gross profit / gross loss)
/// Returns infinity representation (999999) if no losses
pub fn profit_factor(state) {
// Note: Would need separate gross_profit/gross_loss tracking
// This is a simplified version based on win/loss counts
if state.losses == 0 {
999999.0
} else if state.wins == 0 {
0.0
} else {
state.wins / state.losses
}
}