#![cfg(feature = "portfolio")]
#![allow(clippy::inconsistent_digit_grouping)]
use nanobook::Symbol;
use nanobook::portfolio::{CostModel, Portfolio, Position};
#[test]
fn market_value_does_not_panic_on_large_quantity_times_price() {
let sym = Symbol::new("FZ0");
let mut pos = Position::new(sym);
pos.apply_fill(2_000_000_000, 5_000_000_000);
let mv = pos.market_value(5_000_000_000);
assert!(
mv == i64::MAX || mv == i64::MIN,
"expected saturation to i64 extreme, got {mv}"
);
}
#[test]
fn unrealized_pnl_does_not_panic_on_large_inputs() {
let sym = Symbol::new("FZ0");
let mut pos = Position::new(sym);
pos.apply_fill(2_000_000_000, 5_000_000_000);
let _pnl = pos.unrealized_pnl(6_000_000_000);
}
#[test]
fn apply_fill_does_not_panic_on_overflow() {
let sym = Symbol::new("FZ0");
let mut pos = Position::new(sym);
pos.apply_fill(1_000_000_000, 1_000_000_000);
pos.apply_fill(1_000_000_000, 1_000_000_000);
assert!(pos.quantity > 0);
}
#[test]
fn replays_crash_artifact_330fb9() {
let cost_model = CostModel {
commission_bps: 0.0,
slippage_bps: 0.0,
min_commission: 0,
};
let mut portfolio = Portfolio::new(1_000_000_000_000, cost_model);
let sym = Symbol::new("FZ0");
portfolio.rebalance_simple(&[(sym, 1.0)], &[(sym, 1_000_000_00)]);
portfolio.rebalance_simple(&[(sym, 1.0)], &[(sym, 100_000_000_00)]);
}
#[test]
fn total_equity_does_not_panic_on_large_holdings() {
let cost_model = CostModel {
commission_bps: 0.0,
slippage_bps: 0.0,
min_commission: 0,
};
let mut portfolio = Portfolio::new(i64::MAX / 2, cost_model);
let sym_a = Symbol::new("FZ0");
let sym_b = Symbol::new("FZ1");
portfolio.rebalance_simple(
&[(sym_a, 0.5), (sym_b, 0.5)],
&[(sym_a, 1_000_000_00), (sym_b, 1_000_000_00)],
);
portfolio.rebalance_simple(
&[(sym_a, 0.5), (sym_b, 0.5)],
&[(sym_a, 100_000_000_00), (sym_b, 100_000_000_00)],
);
}
#[test]
fn rebalance_simple_does_not_panic_on_negative_extremes() {
let cost_model = CostModel {
commission_bps: 100.0,
slippage_bps: 100.0,
min_commission: 0,
};
let mut portfolio = Portfolio::new(1_000_000_000_000, cost_model);
let sym = Symbol::new("FZ0");
for (weight, price) in [
(1.0_f64, 1_000_000_00_i64),
(0.0, 100_000_000_00),
(1.0, 1_000),
(0.5, 1_000_000_000_00),
] {
portfolio.rebalance_simple(&[(sym, weight)], &[(sym, price)]);
}
}