nautilus_model/events/position/
changed.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2025 Nautech Systems Pty Ltd. All rights reserved.
3//  https://nautechsystems.io
4//
5//  Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6//  You may not use this file except in compliance with the License.
7//  You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9//  Unless required by applicable law or agreed to in writing, software
10//  distributed under the License is distributed on an "AS IS" BASIS,
11//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12//  See the License for the specific language governing permissions and
13//  limitations under the License.
14// -------------------------------------------------------------------------------------------------
15
16use nautilus_core::{UnixNanos, UUID4};
17
18use crate::{
19    enums::{OrderSide, PositionSide},
20    events::OrderFilled,
21    identifiers::{AccountId, ClientOrderId, InstrumentId, PositionId, StrategyId, TraderId},
22    position::Position,
23    types::{Currency, Money, Price, Quantity},
24};
25
26/// Represents an event where a position has changed.
27#[repr(C)]
28#[derive(Clone, PartialEq, Debug)]
29pub struct PositionChanged {
30    /// The trader ID associated with the event.
31    pub trader_id: TraderId,
32    /// The strategy ID associated with the event.
33    pub strategy_id: StrategyId,
34    /// The instrument ID associated with the event.
35    pub instrument_id: InstrumentId,
36    /// The position ID associated with the event.
37    pub position_id: PositionId,
38    /// The account ID associated with the position.
39    pub account_id: AccountId,
40    /// The client order ID for the order which opened the position.
41    pub opening_order_id: ClientOrderId,
42    /// The position entry order side.
43    pub entry: OrderSide,
44    /// The position side.
45    pub side: PositionSide,
46    /// The current signed quantity (positive for position side `LONG`, negative for `SHORT`).
47    pub signed_qty: f64,
48    /// The current open quantity.
49    pub quantity: Quantity,
50    /// The peak directional quantity reached by the position.
51    pub peak_quantity: Quantity,
52    /// The last fill quantity for the position.
53    pub last_qty: Quantity,
54    /// The last fill price for the position.
55    pub last_px: Price,
56    /// The position quote currency.
57    pub currency: Currency,
58    /// The average open price.
59    pub avg_px_open: f64,
60    /// The average close price.
61    pub avg_px_close: Option<f64>,
62    /// The realized return for the position.
63    pub realized_return: f64,
64    /// The realized PnL for the position (including commissions).
65    pub realized_pnl: Option<Money>,
66    /// The unrealized PnL for the position (including commissions).
67    pub unrealized_pnl: Money,
68    /// The unique identifier for the event.
69    pub event_id: UUID4,
70    /// UNIX timestamp (nanoseconds) when the position was opened.
71    pub ts_opened: UnixNanos,
72    /// UNIX timestamp (nanoseconds) when the event occurred.
73    pub ts_event: UnixNanos,
74    /// UNIX timestamp (nanoseconds) when the event was initialized.
75    pub ts_init: UnixNanos,
76}
77
78impl PositionChanged {
79    pub fn create(
80        position: &Position,
81        fill: &OrderFilled,
82        event_id: UUID4,
83        ts_init: UnixNanos,
84    ) -> PositionChanged {
85        PositionChanged {
86            trader_id: position.trader_id,
87            strategy_id: position.strategy_id,
88            instrument_id: position.instrument_id,
89            position_id: position.id,
90            account_id: position.account_id,
91            opening_order_id: position.opening_order_id,
92            entry: position.entry,
93            side: position.side,
94            signed_qty: position.signed_qty,
95            quantity: position.quantity,
96            peak_quantity: position.peak_qty,
97            last_qty: fill.last_qty,
98            last_px: fill.last_px,
99            currency: position.quote_currency,
100            avg_px_open: position.avg_px_open,
101            avg_px_close: position.avg_px_close,
102            realized_return: position.realized_return,
103            realized_pnl: position.realized_pnl,
104            unrealized_pnl: Money::new(0.0, position.quote_currency),
105            event_id,
106            ts_opened: position.ts_opened,
107            ts_event: fill.ts_event,
108            ts_init,
109        }
110    }
111}