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}