ibapi/accounts/mod.rs
1//! # Account Management
2//!
3//! This module provides functionality for managing positions and profit and loss (PnL)
4//! information in a trading system. It includes structures and implementations for:
5//!
6//! - Position tracking
7//! - Daily, unrealized, and realized PnL calculations
8//! - Family code management
9//! - Real-time PnL updates for individual positions
10//!
11
12// Common implementation modules
13mod common;
14
15// Domain types
16pub mod types;
17
18use crate::contracts::Contract;
19use serde::{Deserialize, Serialize};
20
21// Public types - always available regardless of feature flags
22
23#[derive(Debug, Default, Serialize, Deserialize)]
24/// Account information as it appears in the TWS' Account Summary Window
25pub struct AccountSummary {
26 /// The account identifier.
27 pub account: String,
28 /// The account's attribute.
29 pub tag: String,
30 /// The account's attribute's value.
31 pub value: String,
32 /// The currency in which the value is expressed.
33 pub currency: String,
34}
35
36/// Constants for account summary tags used in account summary requests.
37/// These tags define which account information fields to retrieve.
38pub struct AccountSummaryTags {}
39
40impl AccountSummaryTags {
41 /// Identifies the account type (e.g. cash, margin, IRA).
42 pub const ACCOUNT_TYPE: &'static str = "AccountType";
43 /// Net liquidation value of the account including cash and positions.
44 pub const NET_LIQUIDATION: &'static str = "NetLiquidation";
45 /// Total cash across currencies converted to the base currency.
46 pub const TOTAL_CASH_VALUE: &'static str = "TotalCashValue";
47 /// Settled cash available for trading.
48 pub const SETTLED_CASH: &'static str = "SettledCash";
49 /// Accrued cash such as interest or dividends due.
50 pub const ACCRUED_CASH: &'static str = "AccruedCash";
51 /// Maximum capital available to open new positions.
52 pub const BUYING_POWER: &'static str = "BuyingPower";
53 /// Equity with loan value after margin calculations.
54 pub const EQUITY_WITH_LOAN_VALUE: &'static str = "EquityWithLoanValue";
55 /// Equity with loan value recorded on the previous trading day.
56 pub const PREVIOUS_EQUITY_WITH_LOAN_VALUE: &'static str = "PreviousEquityWithLoanValue";
57 /// Gross market value of all positions.
58 pub const GROSS_POSITION_VALUE: &'static str = "GrossPositionValue";
59 /// Regulation-T equity available in the account.
60 pub const REQ_T_EQUITY: &'static str = "RegTEquity";
61 /// Regulation-T margin requirement.
62 pub const REQ_T_MARGIN: &'static str = "RegTMargin";
63 /// Special Memorandum Account value as defined by Regulation-T.
64 pub const SMA: &'static str = "SMA";
65 /// Initial margin requirement for current positions.
66 pub const INIT_MARGIN_REQ: &'static str = "InitMarginReq";
67 /// Maintenance margin requirement for current positions.
68 pub const MAINT_MARGIN_REQ: &'static str = "MaintMarginReq";
69 /// Funds currently available for trading.
70 pub const AVAILABLE_FUNDS: &'static str = "AvailableFunds";
71 /// Excess liquidity above maintenance requirements.
72 pub const EXCESS_LIQUIDITY: &'static str = "ExcessLiquidity";
73 /// Cushion percentage representing excess liquidity scaled by equity.
74 pub const CUSHION: &'static str = "Cushion";
75 /// Full initial margin requirement across all related accounts.
76 pub const FULL_INIT_MARGIN_REQ: &'static str = "FullInitMarginReq";
77 /// Full maintenance margin requirement across all related accounts.
78 pub const FULL_MAINT_MARGIN_REQ: &'static str = "FullMaintMarginReq";
79 /// Full funds available for trading across all related accounts.
80 pub const FULL_AVAILABLE_FUNDS: &'static str = "FullAvailableFunds";
81 /// Full excess liquidity across all related accounts.
82 pub const FULL_EXCESS_LIQUIDITY: &'static str = "FullExcessLiquidity";
83 /// Estimated time of the next margin change event.
84 pub const LOOK_AHEAD_NEXT_CHANGE: &'static str = "LookAheadNextChange";
85 /// Projected initial margin requirement at the next change.
86 pub const LOOK_AHEAD_INIT_MARGIN_REQ: &'static str = "LookAheadInitMarginReq";
87 /// Projected maintenance margin requirement at the next change.
88 pub const LOOK_AHEAD_MAINT_MARGIN_REQ: &'static str = "LookAheadMaintMarginReq";
89 /// Projected funds available for trading at the next change.
90 pub const LOOK_AHEAD_AVAILABLE_FUNDS: &'static str = "LookAheadAvailableFunds";
91 /// Projected excess liquidity at the next change.
92 pub const LOOK_AHEAD_EXCESS_LIQUIDITY: &'static str = "LookAheadExcessLiquidity";
93 /// Highest pending warning severity for the account.
94 pub const HIGHEST_SEVERITY: &'static str = "HighestSeverity";
95 /// Day trades remaining before hitting the PDT limit.
96 pub const DAY_TRADES_REMAINING: &'static str = "DayTradesRemaining";
97 /// Effective account leverage based on net liquidation.
98 pub const LEVERAGE: &'static str = "Leverage";
99
100 /// Convenience slice containing every supported account summary tag.
101 pub const ALL: &'static [&'static str] = &[
102 Self::ACCOUNT_TYPE,
103 Self::NET_LIQUIDATION,
104 Self::TOTAL_CASH_VALUE,
105 Self::SETTLED_CASH,
106 Self::ACCRUED_CASH,
107 Self::BUYING_POWER,
108 Self::EQUITY_WITH_LOAN_VALUE,
109 Self::PREVIOUS_EQUITY_WITH_LOAN_VALUE,
110 Self::GROSS_POSITION_VALUE,
111 Self::REQ_T_EQUITY,
112 Self::REQ_T_MARGIN,
113 Self::SMA,
114 Self::INIT_MARGIN_REQ,
115 Self::MAINT_MARGIN_REQ,
116 Self::AVAILABLE_FUNDS,
117 Self::EXCESS_LIQUIDITY,
118 Self::CUSHION,
119 Self::FULL_INIT_MARGIN_REQ,
120 Self::FULL_MAINT_MARGIN_REQ,
121 Self::FULL_AVAILABLE_FUNDS,
122 Self::FULL_EXCESS_LIQUIDITY,
123 Self::LOOK_AHEAD_NEXT_CHANGE,
124 Self::LOOK_AHEAD_INIT_MARGIN_REQ,
125 Self::LOOK_AHEAD_MAINT_MARGIN_REQ,
126 Self::LOOK_AHEAD_AVAILABLE_FUNDS,
127 Self::LOOK_AHEAD_EXCESS_LIQUIDITY,
128 Self::HIGHEST_SEVERITY,
129 Self::DAY_TRADES_REMAINING,
130 Self::LEVERAGE,
131 ];
132}
133
134/// Result of an account summary request emitted by the [Client](crate::client::Client).
135#[derive(Debug)]
136pub enum AccountSummaryResult {
137 /// Summary of account details such as net liquidation, cash balance, etc.
138 Summary(AccountSummary),
139 /// End marker for a batch of account summaries
140 End,
141}
142
143/// Aggregated profit and loss metrics for the entire account.
144#[derive(Debug, Default, Serialize, Deserialize)]
145pub struct PnL {
146 /// DailyPnL for the position
147 pub daily_pnl: f64,
148 /// UnrealizedPnL total unrealized PnL for the position (since inception) updating in real time.
149 pub unrealized_pnl: Option<f64>,
150 /// RealizedPnL is the realized PnL for the position.
151 pub realized_pnl: Option<f64>,
152}
153
154/// Real-time profit and loss metrics for a single position.
155#[derive(Debug, Default, Serialize, Deserialize)]
156pub struct PnLSingle {
157 /// Current size of the position
158 pub position: f64,
159 /// DailyPnL for the position
160 pub daily_pnl: f64,
161 /// UnrealizedPnL is the total unrealized PnL for the position (since inception) updating in real time
162 pub unrealized_pnl: f64,
163 /// RealizedPnL is the realized PnL for the position.
164 pub realized_pnl: f64,
165 /// Current market value of the position
166 pub value: f64,
167}
168
169/// Open position held within the account.
170#[derive(Debug, Default, Clone, Serialize, Deserialize)]
171pub struct Position {
172 /// Account holding position
173 pub account: String,
174 /// Contract
175 pub contract: Contract,
176 /// Number of shares held
177 pub position: f64,
178 /// Average cost of shares
179 pub average_cost: f64,
180}
181
182/// Messages emitted while streaming position updates.
183#[allow(clippy::large_enum_variant)]
184#[derive(Debug)]
185pub enum PositionUpdate {
186 /// Update for a position in the account
187 Position(Position),
188 /// Indicates all positions have been transmitted
189 PositionEnd,
190}
191
192/// Messages emitted while streaming model-code scoped position updates.
193#[allow(clippy::large_enum_variant)]
194#[derive(Debug)]
195pub enum PositionUpdateMulti {
196 /// Position update scoped to a specific account/model code pair.
197 Position(PositionMulti),
198 /// Indicates all positions have been transmitted.
199 PositionEnd,
200}
201
202/// Position scoped to a specific account and model code.
203#[derive(Debug, Default, Clone, Serialize, Deserialize)]
204pub struct PositionMulti {
205 /// Account holding position
206 pub account: String,
207 /// Contract
208 pub contract: Contract,
209 /// Number of shares held
210 pub position: f64,
211 /// Average cost of shares
212 pub average_cost: f64,
213 /// Model code for the position
214 pub model_code: String,
215}
216
217/// Family code assigned to a group of accounts.
218#[derive(Debug, Default, PartialEq, Serialize, Deserialize)]
219pub struct FamilyCode {
220 /// Account ID for the account family
221 pub account_id: String,
222 /// Account family code
223 pub family_code: String,
224}
225
226/// Account update events delivered while streaming high-level account data.
227#[allow(clippy::large_enum_variant)]
228#[derive(Debug)]
229pub enum AccountUpdate {
230 /// Key/value update describing an account metric.
231 AccountValue(AccountValue),
232 /// Update describing a position's valuation data.
233 PortfolioValue(AccountPortfolioValue),
234 /// Timestamp indicating when the account snapshot was generated.
235 UpdateTime(AccountUpdateTime),
236 /// Indicates the end of the account update stream.
237 End,
238}
239
240/// Single account value update emitted by the API.
241#[derive(Debug, Default, Serialize, Deserialize)]
242pub struct AccountValue {
243 /// Key describing the value
244 pub key: String,
245 /// Value corresponding to the key
246 pub value: String,
247 /// Currency of the value
248 pub currency: String,
249 /// Account ID (optional)
250 pub account: Option<String>,
251}
252
253/// Aggregated valuation details for a single contract within the account.
254#[derive(Debug, Default, PartialEq, Serialize, Deserialize)]
255pub struct AccountPortfolioValue {
256 /// Contract for the position
257 pub contract: Contract,
258 /// Number of shares held
259 pub position: f64,
260 /// Current market price of the contract
261 pub market_price: f64,
262 /// Current market value of the position (shares * market price)
263 pub market_value: f64,
264 /// Average cost per share
265 pub average_cost: f64,
266 /// Unrealized profit and loss
267 pub unrealized_pnl: f64,
268 /// Realized profit and loss
269 pub realized_pnl: f64,
270 /// Account holding the position
271 pub account: Option<String>,
272}
273
274/// Timestamp wrapper for account update streams.
275#[derive(Debug, Default, PartialEq, Serialize, Deserialize)]
276pub struct AccountUpdateTime {
277 /// Timestamp of the last account update
278 pub timestamp: String,
279}
280
281/// Account update events scoped to an account/model code pair.
282#[derive(Debug, PartialEq)]
283pub enum AccountUpdateMulti {
284 /// Key/value update for a specific account/model code pair.
285 AccountMultiValue(AccountMultiValue),
286 /// Indicates the end of the scoped account update stream.
287 End,
288}
289
290/// Key/value pair returned for a specific account/model code pair.
291#[derive(Debug, Default, PartialEq, Serialize, Deserialize)]
292pub struct AccountMultiValue {
293 /// Account ID
294 pub account: String,
295 /// Model code
296 pub model_code: String,
297 /// Key describing the value
298 pub key: String,
299 /// Value corresponding to the key
300 pub value: String,
301 /// Currency of the value
302 pub currency: String,
303}
304
305// Feature-specific implementations
306#[cfg(feature = "sync")]
307mod sync;
308
309#[cfg(feature = "async")]
310mod r#async;
311
312/// Blocking account management API implemented on top of the synchronous client.
313#[cfg(feature = "sync")]
314pub mod blocking {
315 pub use super::sync::{
316 account_summary, account_updates, account_updates_multi, family_codes, managed_accounts, pnl, pnl_single, positions, positions_multi,
317 server_time,
318 };
319}
320
321#[cfg(all(feature = "sync", not(feature = "async")))]
322pub use sync::{
323 account_summary, account_updates, account_updates_multi, family_codes, managed_accounts, pnl, pnl_single, positions, positions_multi, server_time,
324};
325
326#[cfg(feature = "async")]
327pub use r#async::{
328 account_summary, account_updates, account_updates_multi, family_codes, managed_accounts, pnl, pnl_single, positions, positions_multi, server_time,
329};