use rust_decimal_macros::dec;
use rustledger_booking::book;
use rustledger_core::{
Amount, BookingMethod, CostNumber, CostSpec, Directive, Posting, PriceAnnotation, Transaction,
};
fn generate(accounts: usize, lots: usize) -> Vec<Directive> {
let date = rustledger_core::naive_date(2024, 1, 1).unwrap();
let mut d = Vec::with_capacity(accounts * lots * 2);
for k in 0..accounts {
let stock = format!("Assets:Stock{k}");
for i in 0..lots {
let price = dec!(100) + rust_decimal::Decimal::from(i as i64);
let buy = Transaction::new(date, "buy")
.with_synthesized_posting(
Posting::new(stock.clone(), Amount::new(dec!(1), "AAPL")).with_cost(
CostSpec::empty()
.with_number(CostNumber::PerUnit { value: price })
.with_currency("USD"),
),
)
.with_synthesized_posting(Posting::new("Assets:Cash", Amount::new(-price, "USD")));
d.push(Directive::Transaction(buy));
}
for i in 0..lots {
let price = dec!(150) + rust_decimal::Decimal::from(i as i64);
let sell = Transaction::new(date, "sell")
.with_synthesized_posting(
Posting::new(stock.clone(), Amount::new(dec!(-1), "AAPL"))
.with_cost(CostSpec::empty())
.with_price(PriceAnnotation::unit(Amount::new(price, "USD"))),
)
.with_synthesized_posting(Posting::new("Assets:Cash", Amount::new(price, "USD")))
.with_synthesized_posting(Posting::auto("Income:Gains"));
d.push(Directive::Transaction(sell));
}
}
d
}
fn main() {
let mut a = std::env::args().skip(1);
let accounts: usize = a.next().and_then(|s| s.parse().ok()).unwrap_or(30);
let lots: usize = a.next().and_then(|s| s.parse().ok()).unwrap_or(100);
let iters: usize = a.next().and_then(|s| s.parse().ok()).unwrap_or(5);
let directives = generate(accounts, lots);
let mut sink = 0usize;
let mut failed = 0usize;
for _ in 0..iters {
let r = book(std::hint::black_box(&directives), BookingMethod::Fifo);
sink = sink.wrapping_add(r.booked.len());
failed = r.failed.len();
}
eprintln!(
"booking profile: {accounts} accts x {lots} lots (buys+sells) x {iters} iters; \
dirs={} booked_sink={sink} failed/iter={failed}",
directives.len()
);
assert_eq!(
failed, 0,
"{failed} bookings failed for these args; the profile would not reflect \
the steady-state booking path — adjust accounts/lots so all bookings succeed"
);
}