#[non_exhaustive]pub struct Position {Show 15 fields
pub side: PositionSide,
pub entry_timestamp: i64,
pub entry_price: f64,
pub quantity: f64,
pub entry_quantity: f64,
pub entry_commission: f64,
pub entry_transaction_tax: f64,
pub entry_signal: Signal,
pub dividend_income: f64,
pub unreinvested_dividends: f64,
pub scale_in_count: usize,
pub partial_close_count: usize,
pub bracket_stop_loss_pct: Option<f64>,
pub bracket_take_profit_pct: Option<f64>,
pub bracket_trailing_stop_pct: Option<f64>,
}Expand description
An open position
Fields (Non-exhaustive)§
This struct is marked as non-exhaustive
Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.side: PositionSidePosition direction
entry_timestamp: i64Entry timestamp
entry_price: f64Entry price (after slippage)
quantity: f64Number of shares/units
entry_quantity: f64Number of shares/units at entry (before any dividend reinvestment).
entry_commission: f64Entry commission paid
entry_transaction_tax: f64Transaction tax paid on entry (long entries and short covers only).
entry_signal: SignalSignal that triggered entry
dividend_income: f64Accumulated dividend income received while this position was open.
Added to trade P&L on close. Zero when dividends are not supplied to the engine or when the position receives no dividends.
unreinvested_dividends: f64Dividend income that was NOT reinvested (i.e. remains as cash). Used internally for correct cash-accounting.
scale_in_count: usizeNumber of times this position has been scaled into (pyramid adds).
Starts at 0 (initial entry). Incremented by
Position::scale_in on each successful add.
partial_close_count: usizeNumber of partial closes executed so far.
Used to assign a monotonically increasing Trade::scale_sequence
to each Trade returned by Position::partial_close.
bracket_stop_loss_pct: Option<f64>Per-trade stop-loss percentage override.
Populated from Signal::bracket_stop_loss_pct when the position is
opened. Takes precedence over BacktestConfig::stop_loss_pct when
Some. None means fall back to the config-level default.
bracket_take_profit_pct: Option<f64>Per-trade take-profit percentage override.
Populated from Signal::bracket_take_profit_pct when the position is
opened. Takes precedence over BacktestConfig::take_profit_pct when
Some.
bracket_trailing_stop_pct: Option<f64>Per-trade trailing stop percentage override.
Populated from Signal::bracket_trailing_stop_pct when the position
is opened. Takes precedence over BacktestConfig::trailing_stop_pct
when Some.
Implementations§
Source§impl Position
impl Position
Sourcepub fn new(
side: PositionSide,
entry_timestamp: i64,
entry_price: f64,
quantity: f64,
entry_commission: f64,
entry_signal: Signal,
) -> Self
pub fn new( side: PositionSide, entry_timestamp: i64, entry_price: f64, quantity: f64, entry_commission: f64, entry_signal: Signal, ) -> Self
Create a new position.
Sourcepub fn current_value(&self, current_price: f64) -> f64
pub fn current_value(&self, current_price: f64) -> f64
Net contribution of this position to portfolio equity at current_price.
Sign convention (important): returns a positive value for long
positions and a negative value for short positions. The negative
short value is deliberate: when the engine opens a short it credits
cash with the sale proceeds (cash += entry_price × quantity), so
the correct running equity is cash + current_value(price). As the
price falls the negative value grows less negative, and the net equity
rises — exactly the expected profit behaviour for a short.
If you need the raw notional exposure (always positive), use
self.quantity * current_price directly.
Sourcepub fn unrealized_pnl(&self, current_price: f64) -> f64
pub fn unrealized_pnl(&self, current_price: f64) -> f64
Calculate unrealized P&L at given price (before exit commission)
Sourcepub fn unrealized_return_pct(&self, current_price: f64) -> f64
pub fn unrealized_return_pct(&self, current_price: f64) -> f64
Calculate unrealized return percentage
Sourcepub fn is_profitable(&self, current_price: f64) -> bool
pub fn is_profitable(&self, current_price: f64) -> bool
Check if position is profitable at given price
Sourcepub fn credit_dividend(&mut self, income: f64, close_price: f64, reinvest: bool)
pub fn credit_dividend(&mut self, income: f64, close_price: f64, reinvest: bool)
Credit dividend cashflow to this position.
income must be pre-signed by the caller:
- Long positions receive dividends → pass
+per_share × quantity - Short positions owe dividends to the stock lender → pass
-(per_share × quantity)
The engine’s credit_dividends helper handles this negation
automatically. Passing an unsigned (always-positive) value to a short
position would incorrectly record dividend income instead of a
liability.
When reinvest is true, only positive income is reinvested
into additional units (long-side reinvestment only).
Sourcepub fn scale_in(
&mut self,
fill_price: f64,
additional_qty: f64,
commission: f64,
entry_tax: f64,
)
pub fn scale_in( &mut self, fill_price: f64, additional_qty: f64, commission: f64, entry_tax: f64, )
Add shares to this position (pyramid / scale-in).
Updates the weighted-average entry_price and entry_quantity to reflect
the blended cost basis and increments scale_in_count. The caller is
responsible for debiting the entry cost from available cash and for applying
slippage/spread to fill_price before calling this method.
§Arguments
fill_price– Adjusted entry price for the new shares.additional_qty– Number of shares to add. No-op if<= 0.0.commission– Commission paid for this add (already applied to cash).entry_tax– Transaction tax for this add (already applied to cash).
Sourcepub fn partial_close(
&mut self,
fraction: f64,
exit_ts: i64,
exit_price: f64,
commission: f64,
exit_tax: f64,
signal: Signal,
) -> Trade
pub fn partial_close( &mut self, fraction: f64, exit_ts: i64, exit_price: f64, commission: f64, exit_tax: f64, signal: Signal, ) -> Trade
Partially close this position and return a completed Trade.
Closes fraction of the current position quantity, allocating a
proportional share of accumulated entry costs and dividend income to the
trade P&L. The remaining position stays open with reduced quantity,
dividend balances, and entry cost bases.
Trade::is_partial is true for all trades returned by this method.
For a full close prefer Position::close_with_tax, which sets
is_partial = false. The engine’s scale_out_position delegates
fraction >= 1.0 to close_position for exactly this reason.
The caller is responsible for updating cash from the returned trade’s exit proceeds.
§Arguments
fraction– Portion of current quantity to close (0.0..=1.0).exit_ts– Timestamp of the fill.exit_price– Adjusted exit price (after slippage/spread).commission– Exit-side commission for this close.exit_tax– Exit-side transaction tax for this close.signal– Signal that triggered the partial exit.
Trait Implementations§
Source§impl<'de> Deserialize<'de> for Position
impl<'de> Deserialize<'de> for Position
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Auto Trait Implementations§
impl Freeze for Position
impl RefUnwindSafe for Position
impl Send for Position
impl Sync for Position
impl Unpin for Position
impl UnsafeUnpin for Position
impl UnwindSafe for Position
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more