pub struct PositionLedger { /* private fields */ }Expand description
A multi-symbol ledger tracking positions and a cash balance.
Implementations§
Source§impl PositionLedger
impl PositionLedger
Sourcepub fn new(initial_cash: Decimal) -> Self
pub fn new(initial_cash: Decimal) -> Self
Creates a new PositionLedger with the given initial cash balance.
Sourcepub fn apply_fill(&mut self, fill: Fill) -> Result<(), FinError>
pub fn apply_fill(&mut self, fill: Fill) -> Result<(), FinError>
Applies a fill to the appropriate position and updates cash.
§Errors
Returns FinError::InsufficientFunds if a buy would require more cash than available.
Sourcepub fn position(&self, symbol: &Symbol) -> Option<&Position>
pub fn position(&self, symbol: &Symbol) -> Option<&Position>
Returns the position for symbol, or None if no position exists.
Sourcepub fn has_position(&self, symbol: &Symbol) -> bool
pub fn has_position(&self, symbol: &Symbol) -> bool
Returns true if the ledger is tracking symbol (even if flat).
Sourcepub fn positions(&self) -> impl Iterator<Item = &Position>
pub fn positions(&self) -> impl Iterator<Item = &Position>
Returns an iterator over all tracked positions (including flat ones).
Sourcepub fn open_positions(&self) -> impl Iterator<Item = &Position>
pub fn open_positions(&self) -> impl Iterator<Item = &Position>
Returns an iterator over positions with non-zero quantity.
Sourcepub fn flat_positions(&self) -> impl Iterator<Item = &Position>
pub fn flat_positions(&self) -> impl Iterator<Item = &Position>
Returns an iterator over flat (zero-quantity) positions.
Sourcepub fn long_positions(&self) -> impl Iterator<Item = &Position>
pub fn long_positions(&self) -> impl Iterator<Item = &Position>
Returns an iterator over long (positive-quantity) positions.
Sourcepub fn short_positions(&self) -> impl Iterator<Item = &Position>
pub fn short_positions(&self) -> impl Iterator<Item = &Position>
Returns an iterator over short (negative-quantity) positions.
Sourcepub fn symbols(&self) -> impl Iterator<Item = &Symbol>
pub fn symbols(&self) -> impl Iterator<Item = &Symbol>
Returns an iterator over the symbols being tracked by this ledger.
Sourcepub fn open_symbols(&self) -> impl Iterator<Item = &Symbol>
pub fn open_symbols(&self) -> impl Iterator<Item = &Symbol>
Returns an iterator over symbols that have a non-flat (open) position.
Sourcepub fn total_long_exposure(&self) -> Decimal
pub fn total_long_exposure(&self) -> Decimal
Returns the sum of |quantity| × avg_cost for all long (positive quantity) positions.
Represents the notional value invested on the long side.
Sourcepub fn total_short_exposure(&self) -> Decimal
pub fn total_short_exposure(&self) -> Decimal
Returns the sum of |quantity| × avg_cost for all short (negative quantity) positions.
Represents the notional value of the short exposure.
Sourcepub fn symbols_sorted(&self) -> Vec<&Symbol>
pub fn symbols_sorted(&self) -> Vec<&Symbol>
Returns a sorted Vec of all tracked symbols in lexicographic order.
Useful when deterministic output ordering is required (e.g. reports, snapshots).
Sourcepub fn position_count(&self) -> usize
pub fn position_count(&self) -> usize
Returns the total number of symbols tracked by this ledger (open and flat).
Sourcepub fn deposit(&mut self, amount: Decimal)
pub fn deposit(&mut self, amount: Decimal)
Deposits amount into the cash balance (increases cash).
§Panics
Does not panic; accepts any Decimal including negative (use withdraw for cleaner API).
Sourcepub fn withdraw(&mut self, amount: Decimal) -> Result<(), FinError>
pub fn withdraw(&mut self, amount: Decimal) -> Result<(), FinError>
Withdraws amount from the cash balance.
§Errors
Returns FinError::InsufficientFunds if amount > self.cash.
Sourcepub fn open_position_count(&self) -> usize
pub fn open_position_count(&self) -> usize
Returns the number of non-flat (open) positions.
Sourcepub fn long_count(&self) -> usize
pub fn long_count(&self) -> usize
Returns the number of long (positive quantity) open positions.
Sourcepub fn short_count(&self) -> usize
pub fn short_count(&self) -> usize
Returns the number of short (negative quantity) open positions.
Sourcepub fn net_exposure(&self) -> Decimal
pub fn net_exposure(&self) -> Decimal
Returns the net signed quantity exposure across all positions.
Long positions contribute positive values; short positions contribute negative values. A result near zero indicates a roughly delta-neutral portfolio.
Sourcepub fn net_market_exposure(
&self,
prices: &HashMap<String, Price>,
) -> Option<Decimal>
pub fn net_market_exposure( &self, prices: &HashMap<String, Price>, ) -> Option<Decimal>
Net market exposure using current prices: sum of (quantity × price) across all positions.
Long positions contribute positive values; short positions contribute negative values.
Prices missing from prices are skipped.
Returns None if no open positions have prices available.
Sourcepub fn gross_exposure(&self) -> Decimal
pub fn gross_exposure(&self) -> Decimal
Returns the gross (absolute) quantity exposure across all positions.
Sums |quantity| for every position regardless of direction.
Sourcepub fn open_count(&self) -> usize
pub fn open_count(&self) -> usize
Returns a reference to the open position with the largest absolute quantity.
Returns None when there are no open (non-flat) positions.
Returns the number of positions with non-zero quantity.
Sourcepub fn largest_position(&self) -> Option<&Position>
pub fn largest_position(&self) -> Option<&Position>
Returns a reference to the open position with the largest absolute quantity.
Returns None if there are no open (non-flat) positions.
Sourcepub fn total_market_value(
&self,
prices: &HashMap<String, Price>,
) -> Result<Decimal, FinError>
pub fn total_market_value( &self, prices: &HashMap<String, Price>, ) -> Result<Decimal, FinError>
Returns the total market value of all open positions given a price map.
§Errors
Returns FinError::PositionNotFound if a non-flat position has no price in prices.
Sourcepub fn position_weights(
&self,
prices: &HashMap<String, Price>,
) -> Vec<(Symbol, Decimal)>
pub fn position_weights( &self, prices: &HashMap<String, Price>, ) -> Vec<(Symbol, Decimal)>
Returns each open position’s market value as a fraction of total market value.
Returns a Vec<(Symbol, Decimal)> where the second element is [0, 1].
Flat positions are excluded. Returns an empty vec if total market value is zero
or if prices lacks an entry for an open position (graceful skip).
Sourcepub fn realized_pnl_total(&self) -> Decimal
pub fn realized_pnl_total(&self) -> Decimal
Returns the total realized P&L across all positions.
Sourcepub fn unrealized_pnl_total(
&self,
prices: &HashMap<String, Price>,
) -> Result<Decimal, FinError>
pub fn unrealized_pnl_total( &self, prices: &HashMap<String, Price>, ) -> Result<Decimal, FinError>
Returns the total unrealized P&L given a map of current prices.
§Errors
Returns FinError::PositionNotFound if a non-flat position has no price in prices.
Sourcepub fn realized_pnl(&self, symbol: &Symbol) -> Option<Decimal>
pub fn realized_pnl(&self, symbol: &Symbol) -> Option<Decimal>
Returns the realized P&L for symbol, or None if the symbol is not tracked.
Sourcepub fn net_pnl(
&self,
prices: &HashMap<String, Price>,
) -> Result<Decimal, FinError>
pub fn net_pnl( &self, prices: &HashMap<String, Price>, ) -> Result<Decimal, FinError>
Returns total net P&L: realized_pnl_total + unrealized_pnl_total(prices).
§Errors
Returns FinError::PositionNotFound if a non-flat position has no price in prices.
Sourcepub fn equity(
&self,
prices: &HashMap<String, Price>,
) -> Result<Decimal, FinError>
pub fn equity( &self, prices: &HashMap<String, Price>, ) -> Result<Decimal, FinError>
Returns total equity: cash + sum(unrealized P&L of open positions).
§Errors
Returns FinError::PositionNotFound if a position has no price in prices.
Sourcepub fn net_liquidation_value(
&self,
prices: &HashMap<String, Price>,
) -> Result<Decimal, FinError>
pub fn net_liquidation_value( &self, prices: &HashMap<String, Price>, ) -> Result<Decimal, FinError>
Returns the net liquidation value: cash + sum(market_value of each open position).
Market value of a position = quantity × current_price. This differs from
equity which adds unrealized P&L rather than raw market value.
§Errors
Returns FinError::PositionNotFound if a position has no price in prices.
Sourcepub fn pnl_by_symbol(
&self,
prices: &HashMap<String, Price>,
) -> Result<HashMap<Symbol, Decimal>, FinError>
pub fn pnl_by_symbol( &self, prices: &HashMap<String, Price>, ) -> Result<HashMap<Symbol, Decimal>, FinError>
Returns the gross exposure: sum of |quantity × price| across all open positions.
Returns unrealized P&L per symbol as a HashMap.
§Errors
Returns FinError::PositionNotFound if a non-flat position has no price in prices.
Sourcepub fn delta_neutral_check(
&self,
prices: &HashMap<String, Price>,
) -> Result<bool, FinError>
pub fn delta_neutral_check( &self, prices: &HashMap<String, Price>, ) -> Result<bool, FinError>
Returns true if the portfolio is approximately delta-neutral.
Delta-neutral: |net_exposure| / gross_exposure < 0.01 (within 1%).
Returns true when there are no open positions.
§Errors
Returns FinError::PositionNotFound if a non-flat position has no price in prices.
Sourcepub fn allocation_pct(
&self,
symbol: &Symbol,
prices: &HashMap<String, Price>,
) -> Result<Option<Decimal>, FinError>
pub fn allocation_pct( &self, symbol: &Symbol, prices: &HashMap<String, Price>, ) -> Result<Option<Decimal>, FinError>
Returns the allocation percentage of a symbol within the total portfolio value.
allocation = |qty * price| / total_market_value * 100.
Returns None if the symbol has no open position, the price is not provided,
or total market value is zero.
§Errors
Returns crate::error::FinError::PositionNotFound if symbol is unknown.
Sourcepub fn positions_sorted_by_pnl(
&self,
prices: &HashMap<String, Price>,
) -> Vec<&Position>
pub fn positions_sorted_by_pnl( &self, prices: &HashMap<String, Price>, ) -> Vec<&Position>
Returns open positions sorted descending by unrealized PnL.
Positions not in prices are assigned a PnL of zero for sorting purposes.
Sourcepub fn top_n_positions<'a>(
&'a self,
n: usize,
prices: &HashMap<String, Price>,
) -> Vec<&'a Position>
pub fn top_n_positions<'a>( &'a self, n: usize, prices: &HashMap<String, Price>, ) -> Vec<&'a Position>
Returns the top n open positions sorted by absolute market value descending.
Positions missing from prices are assigned market value of zero and sink to the bottom.
Sourcepub fn concentration(
&self,
prices: &HashMap<String, Price>,
) -> Result<Option<Decimal>, FinError>
pub fn concentration( &self, prices: &HashMap<String, Price>, ) -> Result<Option<Decimal>, FinError>
Returns the Herfindahl-Hirschman Index of position weights (0–1).
HHI = Σ(weight_i²) where weight_i = |mv_i| / gross_exposure.
Values near 1 indicate high concentration (single dominant position);
near 1/n indicate equal distribution. Returns None when no open positions.
§Errors
Returns FinError::PositionNotFound if a non-flat position has no price in prices.
Sourcepub fn margin_used(
&self,
prices: &HashMap<String, Price>,
margin_rate: Decimal,
) -> Result<Decimal, FinError>
pub fn margin_used( &self, prices: &HashMap<String, Price>, margin_rate: Decimal, ) -> Result<Decimal, FinError>
Returns the margin required: gross_exposure × margin_rate.
§Errors
Returns FinError::PositionNotFound if a non-flat position has no price in prices.
Sourcepub fn flat_count(&self) -> usize
pub fn flat_count(&self) -> usize
Returns the count of tracked positions with zero quantity (flat positions).
Sourcepub fn smallest_position(&self) -> Option<&Position>
pub fn smallest_position(&self) -> Option<&Position>
Returns the open position with the smallest absolute quantity.
Returns None if there are no open (non-flat) positions.
Sourcepub fn most_profitable_symbol(
&self,
prices: &HashMap<String, Price>,
) -> Option<&Symbol>
pub fn most_profitable_symbol( &self, prices: &HashMap<String, Price>, ) -> Option<&Symbol>
Returns the symbol with the highest unrealized PnL given current prices.
Returns None if there are no open positions or the price map is empty.
Sourcepub fn least_profitable_symbol(
&self,
prices: &HashMap<String, Price>,
) -> Option<&Symbol>
pub fn least_profitable_symbol( &self, prices: &HashMap<String, Price>, ) -> Option<&Symbol>
Returns the symbol with the lowest (most negative) unrealized PnL given current prices.
Returns None if there are no open positions or the price map is empty.
Sourcepub fn total_commission_paid(&self) -> Decimal
pub fn total_commission_paid(&self) -> Decimal
Returns the cumulative commissions paid across all fills processed by this ledger.
Sourcepub fn symbols_with_pnl(
&self,
prices: &HashMap<String, Price>,
) -> Vec<(&Symbol, Decimal)>
pub fn symbols_with_pnl( &self, prices: &HashMap<String, Price>, ) -> Vec<(&Symbol, Decimal)>
Returns all open positions as (Symbol, unrealized_pnl) sorted by PnL descending.
Symbols without a price entry in prices are skipped.
Sourcepub fn concentration_pct(
&self,
symbol: &Symbol,
prices: &HashMap<String, Price>,
) -> Option<Decimal>
pub fn concentration_pct( &self, symbol: &Symbol, prices: &HashMap<String, Price>, ) -> Option<Decimal>
Returns the fraction of total portfolio value held in a single symbol (as a percentage).
concentration = market_value(symbol) / total_market_value * 100.
Returns None if the symbol is not found, price is missing, or total value is zero.
Sourcepub fn all_flat(&self) -> bool
pub fn all_flat(&self) -> bool
Returns true if all registered positions are flat (zero quantity).
Sourcepub fn long_exposure(&self, prices: &HashMap<String, Price>) -> Decimal
pub fn long_exposure(&self, prices: &HashMap<String, Price>) -> Decimal
Total market value of all long (positive quantity) positions.
Skips any symbol not present in prices. Returns Decimal::ZERO when there are no longs.
Sourcepub fn short_exposure(&self, prices: &HashMap<String, Price>) -> Decimal
pub fn short_exposure(&self, prices: &HashMap<String, Price>) -> Decimal
Total market value of all short (negative quantity) positions.
Skips any symbol not present in prices. Returns Decimal::ZERO when there are no shorts.
Sourcepub fn net_delta(&self, prices: &HashMap<String, Price>) -> Decimal
pub fn net_delta(&self, prices: &HashMap<String, Price>) -> Decimal
Signed net market value: long_exposure - short_exposure.
Positive = net long; negative = net short; zero = balanced or flat.
Sourcepub fn avg_cost_basis(&self, symbol: &Symbol) -> Option<Decimal>
pub fn avg_cost_basis(&self, symbol: &Symbol) -> Option<Decimal>
Returns the average cost basis for symbol, or None if the position is flat or unknown.
Sourcepub fn active_symbols(&self) -> Vec<&Symbol>
pub fn active_symbols(&self) -> Vec<&Symbol>
Returns a list of symbols that currently have a non-flat (open) position.
Sourcepub fn symbol_count(&self) -> usize
pub fn symbol_count(&self) -> usize
Returns the total number of symbols tracked by this ledger (including flat positions).
Sourcepub fn realized_pnl_by_symbol(&self) -> Vec<(Symbol, Decimal)>
pub fn realized_pnl_by_symbol(&self) -> Vec<(Symbol, Decimal)>
Returns the realized P&L for every symbol that has a non-zero realized P&L, sorted descending by value.
Symbols with zero realized P&L are excluded.
Sourcepub fn top_losers<'a>(
&'a self,
n: usize,
prices: &HashMap<String, Price>,
) -> Vec<&'a Position>
pub fn top_losers<'a>( &'a self, n: usize, prices: &HashMap<String, Price>, ) -> Vec<&'a Position>
Returns up to n open positions with the worst (most negative) unrealized P&L.
Positions missing from prices receive an unrealized PnL of zero.
Returns an empty slice when n == 0 or no open positions exist.
Sourcepub fn flat_symbols(&self) -> Vec<&Symbol>
pub fn flat_symbols(&self) -> Vec<&Symbol>
Returns the symbols that currently have flat (zero-quantity) positions, sorted lexicographically.
Sourcepub fn max_unrealized_loss(
&self,
prices: &HashMap<String, Price>,
) -> Option<Decimal>
pub fn max_unrealized_loss( &self, prices: &HashMap<String, Price>, ) -> Option<Decimal>
Largest unrealized loss among all open positions.
Returns None if there are no open positions or all unrealized PnLs are non-negative.
Sourcepub fn largest_winner<'a>(
&'a self,
prices: &HashMap<String, Price>,
) -> Option<&'a Position>
pub fn largest_winner<'a>( &'a self, prices: &HashMap<String, Price>, ) -> Option<&'a Position>
Returns the position with the largest positive unrealized P&L at the given prices.
Returns None if there are no open positions or no position has a positive unrealized PnL.
Sourcepub fn largest_loser<'a>(
&'a self,
prices: &HashMap<String, Price>,
) -> Option<&'a Position>
pub fn largest_loser<'a>( &'a self, prices: &HashMap<String, Price>, ) -> Option<&'a Position>
Returns the position with the largest negative unrealized P&L at the given prices.
Returns None if there are no open positions or no position has a negative unrealized PnL.
Sourcepub fn gross_market_exposure(&self, prices: &HashMap<String, Price>) -> Decimal
pub fn gross_market_exposure(&self, prices: &HashMap<String, Price>) -> Decimal
Returns the gross market exposure: sum of absolute market values across all open positions.
Sourcepub fn largest_position_pct(
&self,
prices: &HashMap<String, Price>,
) -> Option<Decimal>
pub fn largest_position_pct( &self, prices: &HashMap<String, Price>, ) -> Option<Decimal>
Returns the largest single-position market value as a percentage of total gross exposure.
Returns None if there are no open positions or total exposure is zero.
Sourcepub fn unrealized_pnl_pct(
&self,
prices: &HashMap<String, Price>,
) -> Option<Decimal>
pub fn unrealized_pnl_pct( &self, prices: &HashMap<String, Price>, ) -> Option<Decimal>
Total unrealized P&L as a percentage of total cost basis.
upnl_pct = unrealized_pnl_total / total_cost_basis × 100
Returns None if total cost basis is zero.
Sourcepub fn symbols_up<'a>(
&'a self,
prices: &HashMap<String, Price>,
) -> Vec<&'a Symbol>
pub fn symbols_up<'a>( &'a self, prices: &HashMap<String, Price>, ) -> Vec<&'a Symbol>
Returns the symbols of all open positions with positive unrealized P&L at prices.
A position is “up” if unrealized_pnl > 0 at the given prices.
Sourcepub fn symbols_down<'a>(
&'a self,
prices: &HashMap<String, Price>,
) -> Vec<&'a Symbol>
pub fn symbols_down<'a>( &'a self, prices: &HashMap<String, Price>, ) -> Vec<&'a Symbol>
Returns the symbols of all open positions with negative unrealized P&L at prices.
A position is “down” if unrealized_pnl < 0 at the given prices.
Sourcepub fn largest_unrealized_gain<'a>(
&'a self,
prices: &HashMap<String, Price>,
) -> Option<&'a Position>
pub fn largest_unrealized_gain<'a>( &'a self, prices: &HashMap<String, Price>, ) -> Option<&'a Position>
Returns the open position with the largest positive unrealized P&L at prices.
Alias for PositionLedger::largest_winner with a more descriptive name.
Returns None if no positions have positive unrealized PnL.
Sourcepub fn avg_realized_pnl_per_symbol(&self) -> Option<Decimal>
pub fn avg_realized_pnl_per_symbol(&self) -> Option<Decimal>
Average realized P&L per symbol across all positions (including flat ones).
Returns None if there are no positions.
Sourcepub fn win_rate(&self) -> Option<Decimal>
pub fn win_rate(&self) -> Option<Decimal>
Win rate: fraction of positions with strictly positive realized P&L, as a percentage.
Only positions that have been at least partially closed (non-zero realized PnL activity) are considered; positions with zero realized P&L are treated as losses.
Returns None if there are no positions.
Sourcepub fn net_pnl_excluding(
&self,
exclude: &Symbol,
prices: &HashMap<String, Price>,
) -> Result<Decimal, FinError>
pub fn net_pnl_excluding( &self, exclude: &Symbol, prices: &HashMap<String, Price>, ) -> Result<Decimal, FinError>
Total P&L (realized + unrealized) excluding a specific symbol.
Useful for single-symbol attribution analysis.
Returns Err if any open position’s price is missing from prices.
Sourcepub fn long_short_ratio(
&self,
prices: &HashMap<String, Price>,
) -> Option<Decimal>
pub fn long_short_ratio( &self, prices: &HashMap<String, Price>, ) -> Option<Decimal>
Ratio of total long market exposure to total absolute short market exposure.
long_short_ratio = long_exposure / |short_exposure|
Returns None if there is no short exposure or short_exposure is zero.
Sourcepub fn position_count_by_direction(&self) -> (usize, usize)
pub fn position_count_by_direction(&self) -> (usize, usize)
Returns (long_count, short_count) — the number of open long and short positions.
Sourcepub fn max_position_age_bars(&self, current_bar: usize) -> Option<usize>
pub fn max_position_age_bars(&self, current_bar: usize) -> Option<usize>
Returns the age in bars of the oldest open position.
Returns None if there are no open positions or no position has an open bar set.
Sourcepub fn avg_position_age_bars(&self, current_bar: usize) -> Option<Decimal>
pub fn avg_position_age_bars(&self, current_bar: usize) -> Option<Decimal>
Returns the mean age in bars of all open positions.
Returns None if there are no open positions.
Sourcepub fn hhi_concentration(
&self,
prices: &HashMap<String, Price>,
) -> Option<Decimal>
pub fn hhi_concentration( &self, prices: &HashMap<String, Price>, ) -> Option<Decimal>
Herfindahl-Hirschman Index (HHI) of portfolio concentration by market value.
HHI = Σ(weight_i²) where weight_i = |market_value_i| / total_gross_exposure. Range [0, 1]: 0 = perfectly diversified, 1 = entirely in one position.
Returns None if there are no open positions or total gross exposure is zero.
Sourcepub fn long_short_pnl_ratio(
&self,
prices: &HashMap<String, Price>,
) -> Option<Decimal>
pub fn long_short_pnl_ratio( &self, prices: &HashMap<String, Price>, ) -> Option<Decimal>
Ratio of total long unrealized P&L to absolute total short unrealized P&L.
Values > 1 mean longs are outperforming; values < 1 mean shorts are leading.
Returns None if short PnL is zero or no short prices are available.
Sourcepub fn unrealized_pnl_by_symbol(
&self,
prices: &HashMap<String, Price>,
) -> HashMap<String, Decimal>
pub fn unrealized_pnl_by_symbol( &self, prices: &HashMap<String, Price>, ) -> HashMap<String, Decimal>
Unrealized P&L for each open position, keyed by symbol string.
Positions absent from prices are omitted from the result.
Sourcepub fn portfolio_beta(
&self,
prices: &HashMap<String, Price>,
betas: &HashMap<String, f64>,
) -> Option<f64>
pub fn portfolio_beta( &self, prices: &HashMap<String, Price>, betas: &HashMap<String, f64>, ) -> Option<f64>
Portfolio-level beta: sum of (weight * beta) for each open position.
betas maps symbol string to the symbol’s beta coefficient.
Positions with unknown beta or missing from prices are skipped.
Returns None if total market value is zero or no betas are available.
Sourcepub fn total_notional(&self, prices: &HashMap<String, Price>) -> Option<Decimal>
pub fn total_notional(&self, prices: &HashMap<String, Price>) -> Option<Decimal>
Returns the total notional value: sum of |quantity| × price for all open positions.
Positions absent from prices are skipped. Returns None if no open positions
have a matching price.
Sourcepub fn max_unrealized_pnl(
&self,
prices: &HashMap<String, Price>,
) -> Option<Decimal>
pub fn max_unrealized_pnl( &self, prices: &HashMap<String, Price>, ) -> Option<Decimal>
Returns the largest unrealized gain (most positive unrealized P&L) among open positions.
Returns None if no open positions have a matching price, or all unrealized P&Ls are
non-positive.
Sourcepub fn realized_pnl_rank(&self, symbol: &Symbol) -> Option<usize>
pub fn realized_pnl_rank(&self, symbol: &Symbol) -> Option<usize>
Returns the 1-based rank (1 = best) of symbol’s realized P&L among all symbols
that have non-zero realized P&L.
Returns None if symbol has no realized P&L or if it is not found.
Sourcepub fn open_positions_vec(&self) -> Vec<&Position>
pub fn open_positions_vec(&self) -> Vec<&Position>
Returns a Vec of references to all open (non-flat) positions, sorted by symbol.
Sourcepub fn symbols_with_pnl_above(&self, threshold: Decimal) -> Vec<Symbol>
pub fn symbols_with_pnl_above(&self, threshold: Decimal) -> Vec<Symbol>
Returns all symbols whose realized P&L strictly exceeds threshold.
Results are sorted by realized P&L descending.
Sourcepub fn net_long_short_count(&self) -> (usize, usize)
pub fn net_long_short_count(&self) -> (usize, usize)
Returns (long_count, short_count) of currently open (non-flat) positions.
Sourcepub fn largest_open_position(&self) -> Option<&Symbol>
pub fn largest_open_position(&self) -> Option<&Symbol>
Returns the symbol of the open position with the largest absolute quantity.
Returns None if there are no open positions.
Sourcepub fn exposure_by_direction(
&self,
prices: &HashMap<String, Price>,
) -> (Decimal, Decimal)
pub fn exposure_by_direction( &self, prices: &HashMap<String, Price>, ) -> (Decimal, Decimal)
Market exposure broken down by direction: (long_exposure, short_exposure).
Both values are positive (abs). Positions not in prices contribute zero.
Sourcepub fn total_realized_pnl(&self) -> Decimal
pub fn total_realized_pnl(&self) -> Decimal
Returns the sum of realized P&L across all positions in this ledger.
Sourcepub fn count_with_pnl_below(&self, threshold: Decimal) -> usize
pub fn count_with_pnl_below(&self, threshold: Decimal) -> usize
Returns the number of positions whose realized P&L is strictly below threshold.
Sourcepub fn is_net_long(&self) -> bool
pub fn is_net_long(&self) -> bool
Returns true if the sum of all position quantities is positive (net long exposure).
Sourcepub fn total_unrealized_pnl(&self, prices: &HashMap<String, Price>) -> Decimal
pub fn total_unrealized_pnl(&self, prices: &HashMap<String, Price>) -> Decimal
Total unrealized P&L across all open positions that have a price available.
Positions absent from prices contribute zero.
Sourcepub fn symbols_flat(&self) -> Vec<&Symbol>
pub fn symbols_flat(&self) -> Vec<&Symbol>
Returns symbols that have a flat (zero-quantity) position in this ledger, sorted.
Sourcepub fn avg_unrealized_pnl_pct(
&self,
prices: &HashMap<String, Price>,
) -> Option<Decimal>
pub fn avg_unrealized_pnl_pct( &self, prices: &HashMap<String, Price>, ) -> Option<Decimal>
Returns the average unrealized P&L percentage across all open positions.
Each position’s unrealized PnL % is unrealized_pnl / (avg_price * qty).abs() * 100.
Returns None if there are no open positions with valid prices.
Sourcepub fn max_drawdown_symbol<'a>(
&'a self,
prices: &HashMap<String, Price>,
) -> Option<&'a Symbol>
pub fn max_drawdown_symbol<'a>( &'a self, prices: &HashMap<String, Price>, ) -> Option<&'a Symbol>
Returns the symbol with the worst (most negative) unrealized P&L.
Returns None if there are no open positions or none have a price in prices.
Sourcepub fn avg_unrealized_pnl(
&self,
prices: &HashMap<String, Price>,
) -> Option<Decimal>
pub fn avg_unrealized_pnl( &self, prices: &HashMap<String, Price>, ) -> Option<Decimal>
Average unrealized P&L across all open positions that have a price in prices.
Returns None if there are no open positions with prices available.
Sourcepub fn position_symbols(&self) -> Vec<&Symbol>
pub fn position_symbols(&self) -> Vec<&Symbol>
Returns a sorted Vec of all symbols tracked by this ledger (open or closed).
Sourcepub fn count_profitable(&self) -> usize
pub fn count_profitable(&self) -> usize
Returns the count of positions with strictly positive realized P&L.
Sourcepub fn count_losing(&self) -> usize
pub fn count_losing(&self) -> usize
Returns the count of positions with strictly negative realized P&L.
Sourcepub fn top_n_by_exposure<'a>(
&'a self,
prices: &HashMap<String, Price>,
n: usize,
) -> Vec<(&'a Symbol, Decimal)>
pub fn top_n_by_exposure<'a>( &'a self, prices: &HashMap<String, Price>, n: usize, ) -> Vec<(&'a Symbol, Decimal)>
Returns the top n open positions by absolute notional exposure (|qty * price|),
sorted descending. Positions without a price in prices are excluded.
Sourcepub fn has_open_positions(&self) -> bool
pub fn has_open_positions(&self) -> bool
Returns true if there is at least one non-flat position.
Sourcepub fn long_symbols(&self) -> Vec<&Symbol>
pub fn long_symbols(&self) -> Vec<&Symbol>
Symbols with a strictly positive (long) quantity.
Sourcepub fn short_symbols(&self) -> Vec<&Symbol>
pub fn short_symbols(&self) -> Vec<&Symbol>
Symbols with a strictly negative (short) quantity.
Sourcepub fn concentration_ratio(
&self,
prices: &HashMap<String, Price>,
) -> Option<f64>
pub fn concentration_ratio( &self, prices: &HashMap<String, Price>, ) -> Option<f64>
Herfindahl-Hirschman Index of notional exposure: Σ w_i² where w_i = |notional_i| / Σ|notional|.
Returns 1.0 (full concentration) for a single position.
Returns None if there are no open positions with available prices.
Sourcepub fn min_unrealized_pnl(
&self,
prices: &HashMap<String, Price>,
) -> Option<Decimal>
pub fn min_unrealized_pnl( &self, prices: &HashMap<String, Price>, ) -> Option<Decimal>
Minimum unrealized P&L across all open positions.
Returns None if there are no open positions with a known price.
Sourcepub fn pct_long(&self) -> Option<Decimal>
pub fn pct_long(&self) -> Option<Decimal>
Percentage of non-flat positions that are long (quantity > 0).
Returns None if there are no open positions.
Sourcepub fn pct_short(&self) -> Option<Decimal>
pub fn pct_short(&self) -> Option<Decimal>
Percentage of non-flat positions that are short (quantity < 0).
Returns None if there are no open positions.
Sourcepub fn realized_pnl_total_abs(&self) -> Decimal
pub fn realized_pnl_total_abs(&self) -> Decimal
Sum of absolute values of all realized P&L across positions.
Sourcepub fn average_entry_price(&self, symbol: &Symbol) -> Option<Price>
pub fn average_entry_price(&self, symbol: &Symbol) -> Option<Price>
Average entry price for a symbol’s current position.
Returns None if the symbol is not tracked or the position is flat.
Sourcepub fn net_quantity(&self) -> Decimal
pub fn net_quantity(&self) -> Decimal
Net sum of all position quantities across all symbols.
Sourcepub fn max_long_notional(
&self,
prices: &HashMap<String, Price>,
) -> Option<Decimal>
pub fn max_long_notional( &self, prices: &HashMap<String, Price>, ) -> Option<Decimal>
Maximum notional exposure (|qty * price|) of any single long position.
Returns None if no long positions have a price in prices.
Sourcepub fn max_short_notional(
&self,
prices: &HashMap<String, Price>,
) -> Option<Decimal>
pub fn max_short_notional( &self, prices: &HashMap<String, Price>, ) -> Option<Decimal>
Maximum notional exposure (|qty * price|) of any single short position.
Returns None if no short positions have a price in prices.
Sourcepub fn max_realized_pnl(&self) -> Option<(&Symbol, Decimal)>
pub fn max_realized_pnl(&self) -> Option<(&Symbol, Decimal)>
Symbol with the highest realized P&L.
Returns None if no positions have been tracked.
Sourcepub fn min_realized_pnl(&self) -> Option<(&Symbol, Decimal)>
pub fn min_realized_pnl(&self) -> Option<(&Symbol, Decimal)>
Symbol with the lowest (most negative) realized P&L.
Returns None if no positions have been tracked.
Sourcepub fn avg_holding_bars(&self, current_bar: usize) -> Option<f64>
pub fn avg_holding_bars(&self, current_bar: usize) -> Option<f64>
Average holding duration in bars for all open positions.
Uses current_bar - p.open_bar for each open position.
Returns None if there are no open positions.
Sourcepub fn symbols_with_unrealized_loss(
&self,
prices: &HashMap<String, Price>,
) -> Vec<&Symbol>
pub fn symbols_with_unrealized_loss( &self, prices: &HashMap<String, Price>, ) -> Vec<&Symbol>
Symbols of open positions that currently have a negative unrealized P&L.
Sourcepub fn avg_long_entry_price(&self) -> Option<Decimal>
pub fn avg_long_entry_price(&self) -> Option<Decimal>
Volume-weighted average entry price across all open long positions. Returns None if
there are no long positions.
Sourcepub fn avg_short_entry_price(&self) -> Option<Decimal>
pub fn avg_short_entry_price(&self) -> Option<Decimal>
Volume-weighted average entry price across all open short positions. Returns None if
there are no short positions.
Trait Implementations§
Source§impl Clone for PositionLedger
impl Clone for PositionLedger
Source§fn clone(&self) -> PositionLedger
fn clone(&self) -> PositionLedger
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more