ib_flex/types/
extended.rs

1//! Extended FLEX statement types for v0.2.0+
2//!
3//! This module contains additional types beyond the core v0.1.0 types.
4//! These include account information, NAV changes, performance summaries,
5//! fee details, and more comprehensive trading data.
6
7use chrono::NaiveDate;
8use rust_decimal::Decimal;
9use serde::{Deserialize, Serialize};
10
11use super::common::{AssetCategory, OptionAction, TransferType};
12use crate::parsers::xml_utils::{
13    deserialize_flex_date, deserialize_optional_date, deserialize_optional_decimal,
14};
15
16/// Account information and metadata
17#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
18pub struct AccountInformation {
19    /// Account ID
20    #[serde(rename = "@accountId")]
21    pub account_id: String,
22
23    /// Account type
24    #[serde(rename = "@accountType", default)]
25    pub account_type: Option<String>,
26
27    /// Account alias
28    #[serde(rename = "@acctAlias", default)]
29    pub acct_alias: Option<String>,
30
31    /// Currency
32    #[serde(rename = "@currency", default)]
33    pub currency: Option<String>,
34
35    /// Account name
36    #[serde(rename = "@name", default)]
37    pub name: Option<String>,
38
39    /// Master account
40    #[serde(rename = "@masterName", default)]
41    pub master_name: Option<String>,
42}
43
44/// Change in portfolio NAV (Net Asset Value)
45#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
46pub struct ChangeInNAV {
47    /// Account ID
48    #[serde(rename = "@accountId")]
49    pub account_id: String,
50
51    /// From date
52    #[serde(rename = "@fromDate", deserialize_with = "deserialize_flex_date")]
53    pub from_date: NaiveDate,
54
55    /// To date
56    #[serde(rename = "@toDate", deserialize_with = "deserialize_flex_date")]
57    pub to_date: NaiveDate,
58
59    /// Starting value
60    #[serde(rename = "@startingValue")]
61    pub starting_value: Decimal,
62
63    /// Transfers (deposits/withdrawals)
64    #[serde(
65        rename = "@transfers",
66        default,
67        deserialize_with = "deserialize_optional_decimal"
68    )]
69    pub transfers: Option<Decimal>,
70
71    /// Mark-to-market P&L
72    #[serde(
73        rename = "@mtmPlusRealizedPnl",
74        default,
75        deserialize_with = "deserialize_optional_decimal"
76    )]
77    pub mtm_plus_realized_pnl: Option<Decimal>,
78
79    /// Realized P&L
80    #[serde(
81        rename = "@realizedPnl",
82        default,
83        deserialize_with = "deserialize_optional_decimal"
84    )]
85    pub realized_pnl: Option<Decimal>,
86
87    /// Unrealized P&L
88    #[serde(
89        rename = "@unrealizedPnl",
90        default,
91        deserialize_with = "deserialize_optional_decimal"
92    )]
93    pub unrealized_pnl: Option<Decimal>,
94
95    /// Ending value
96    #[serde(rename = "@endingValue")]
97    pub ending_value: Decimal,
98}
99
100/// Equity summary by report date in base currency
101#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
102pub struct EquitySummaryByReportDateInBase {
103    /// Account ID
104    #[serde(rename = "@accountId")]
105    pub account_id: String,
106
107    /// Report date
108    #[serde(rename = "@reportDate", deserialize_with = "deserialize_flex_date")]
109    pub report_date: NaiveDate,
110
111    /// Cash
112    #[serde(
113        rename = "@cash",
114        default,
115        deserialize_with = "deserialize_optional_decimal"
116    )]
117    pub cash: Option<Decimal>,
118
119    /// Stock value
120    #[serde(
121        rename = "@stock",
122        default,
123        deserialize_with = "deserialize_optional_decimal"
124    )]
125    pub stock: Option<Decimal>,
126
127    /// Options value
128    #[serde(
129        rename = "@options",
130        default,
131        deserialize_with = "deserialize_optional_decimal"
132    )]
133    pub options: Option<Decimal>,
134
135    /// Bonds value
136    #[serde(
137        rename = "@bonds",
138        default,
139        deserialize_with = "deserialize_optional_decimal"
140    )]
141    pub bonds: Option<Decimal>,
142
143    /// Total
144    #[serde(rename = "@total")]
145    pub total: Decimal,
146}
147
148/// Cash report by currency
149#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
150pub struct CashReportCurrency {
151    /// Account ID
152    #[serde(rename = "@accountId")]
153    pub account_id: String,
154
155    /// Currency
156    #[serde(rename = "@currency")]
157    pub currency: String,
158
159    /// From date
160    #[serde(rename = "@fromDate", deserialize_with = "deserialize_flex_date")]
161    pub from_date: NaiveDate,
162
163    /// To date
164    #[serde(rename = "@toDate", deserialize_with = "deserialize_flex_date")]
165    pub to_date: NaiveDate,
166
167    /// Starting cash
168    #[serde(rename = "@startingCash")]
169    pub starting_cash: Decimal,
170
171    /// Commissions paid
172    #[serde(
173        rename = "@commissions",
174        default,
175        deserialize_with = "deserialize_optional_decimal"
176    )]
177    pub commissions: Option<Decimal>,
178
179    /// Deposits
180    #[serde(
181        rename = "@deposits",
182        default,
183        deserialize_with = "deserialize_optional_decimal"
184    )]
185    pub deposits: Option<Decimal>,
186
187    /// Withdrawals
188    #[serde(
189        rename = "@withdrawals",
190        default,
191        deserialize_with = "deserialize_optional_decimal"
192    )]
193    pub withdrawals: Option<Decimal>,
194
195    /// Dividends
196    #[serde(
197        rename = "@dividends",
198        default,
199        deserialize_with = "deserialize_optional_decimal"
200    )]
201    pub dividends: Option<Decimal>,
202
203    /// Ending cash
204    #[serde(rename = "@endingCash")]
205    pub ending_cash: Decimal,
206}
207
208/// Trade confirmation
209#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
210pub struct TradeConfirm {
211    /// Account ID
212    #[serde(rename = "@accountId")]
213    pub account_id: String,
214
215    /// Execution ID
216    #[serde(rename = "@execID")]
217    pub exec_id: String,
218
219    /// Order ID
220    #[serde(rename = "@orderID", default)]
221    pub order_id: Option<String>,
222
223    /// Trade date
224    #[serde(rename = "@tradeDate", deserialize_with = "deserialize_flex_date")]
225    pub trade_date: NaiveDate,
226
227    /// Trade time
228    #[serde(rename = "@tradeTime", default)]
229    pub trade_time: Option<String>,
230
231    /// Symbol
232    #[serde(rename = "@symbol")]
233    pub symbol: String,
234
235    /// Asset category
236    #[serde(rename = "@assetCategory")]
237    pub asset_category: AssetCategory,
238
239    /// Quantity
240    #[serde(rename = "@quantity")]
241    pub quantity: Decimal,
242
243    /// Price
244    #[serde(rename = "@price")]
245    pub price: Decimal,
246}
247
248/// Option exercise/assignment/expiration
249#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
250pub struct OptionEAE {
251    /// Account ID
252    #[serde(rename = "@accountId")]
253    pub account_id: String,
254
255    /// Transaction ID
256    #[serde(rename = "@transactionID", default)]
257    pub transaction_id: Option<String>,
258
259    /// Action type
260    #[serde(rename = "@type")]
261    pub action_type: OptionAction,
262
263    /// Date
264    #[serde(rename = "@date", deserialize_with = "deserialize_flex_date")]
265    pub date: NaiveDate,
266
267    /// Symbol
268    #[serde(rename = "@symbol")]
269    pub symbol: String,
270
271    /// Quantity
272    #[serde(rename = "@quantity")]
273    pub quantity: Decimal,
274
275    /// Strike
276    #[serde(
277        rename = "@strike",
278        default,
279        deserialize_with = "deserialize_optional_decimal"
280    )]
281    pub strike: Option<Decimal>,
282
283    /// Underlying symbol
284    #[serde(rename = "@underlyingSymbol", default)]
285    pub underlying_symbol: Option<String>,
286}
287
288/// Foreign exchange transaction
289#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
290pub struct FxTransaction {
291    /// Account ID
292    #[serde(rename = "@accountId")]
293    pub account_id: String,
294
295    /// Transaction ID
296    #[serde(rename = "@transactionID", default)]
297    pub transaction_id: Option<String>,
298
299    /// Date/time
300    #[serde(rename = "@dateTime", default)]
301    pub date_time: Option<String>,
302
303    /// From currency
304    #[serde(rename = "@fromCurrency")]
305    pub from_currency: String,
306
307    /// To currency
308    #[serde(rename = "@toCurrency")]
309    pub to_currency: String,
310
311    /// Quantity
312    #[serde(rename = "@quantity")]
313    pub quantity: Decimal,
314
315    /// Proceeds
316    #[serde(rename = "@proceeds")]
317    pub proceeds: Decimal,
318
319    /// FX rate
320    #[serde(
321        rename = "@fxRateToBase",
322        default,
323        deserialize_with = "deserialize_optional_decimal"
324    )]
325    pub fx_rate_to_base: Option<Decimal>,
326}
327
328/// Change in dividend accruals
329#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
330pub struct ChangeInDividendAccrual {
331    /// Account ID
332    #[serde(rename = "@accountId")]
333    pub account_id: String,
334
335    /// Symbol
336    #[serde(rename = "@symbol")]
337    pub symbol: String,
338
339    /// Ex date
340    #[serde(rename = "@exDate", deserialize_with = "deserialize_flex_date")]
341    pub ex_date: NaiveDate,
342
343    /// Pay date
344    #[serde(
345        rename = "@payDate",
346        default,
347        deserialize_with = "deserialize_optional_date"
348    )]
349    pub pay_date: Option<NaiveDate>,
350
351    /// Gross rate
352    #[serde(rename = "@grossRate")]
353    pub gross_rate: Decimal,
354
355    /// Net amount
356    #[serde(rename = "@netAmount")]
357    pub net_amount: Decimal,
358}
359
360/// Open dividend accruals
361#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
362pub struct OpenDividendAccrual {
363    /// Account ID
364    #[serde(rename = "@accountId")]
365    pub account_id: String,
366
367    /// Symbol
368    #[serde(rename = "@symbol")]
369    pub symbol: String,
370
371    /// Ex date
372    #[serde(rename = "@exDate", deserialize_with = "deserialize_flex_date")]
373    pub ex_date: NaiveDate,
374
375    /// Pay date
376    #[serde(
377        rename = "@payDate",
378        default,
379        deserialize_with = "deserialize_optional_date"
380    )]
381    pub pay_date: Option<NaiveDate>,
382
383    /// Quantity
384    #[serde(rename = "@quantity")]
385    pub quantity: Decimal,
386
387    /// Rate
388    #[serde(rename = "@grossRate")]
389    pub gross_rate: Decimal,
390}
391
392/// Interest accruals by currency
393#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
394pub struct InterestAccrualsCurrency {
395    /// Account ID
396    #[serde(rename = "@accountId")]
397    pub account_id: String,
398
399    /// Currency
400    #[serde(rename = "@currency")]
401    pub currency: String,
402
403    /// From date
404    #[serde(rename = "@fromDate", deserialize_with = "deserialize_flex_date")]
405    pub from_date: NaiveDate,
406
407    /// To date
408    #[serde(rename = "@toDate", deserialize_with = "deserialize_flex_date")]
409    pub to_date: NaiveDate,
410
411    /// Starting accrual balance
412    #[serde(rename = "@startingAccrualBalance")]
413    pub starting_balance: Decimal,
414
415    /// Interest accrued
416    #[serde(rename = "@interestAccrued")]
417    pub interest_accrued: Decimal,
418
419    /// Ending accrual balance
420    #[serde(rename = "@endingAccrualBalance")]
421    pub ending_balance: Decimal,
422}
423
424/// Security transfer
425#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
426pub struct Transfer {
427    /// Account ID
428    #[serde(rename = "@accountId")]
429    pub account_id: String,
430
431    /// Transfer type
432    #[serde(rename = "@type")]
433    pub transfer_type: TransferType,
434
435    /// Symbol
436    #[serde(rename = "@symbol")]
437    pub symbol: String,
438
439    /// Quantity
440    #[serde(rename = "@quantity")]
441    pub quantity: Decimal,
442
443    /// Direction
444    #[serde(rename = "@direction", default)]
445    pub direction: Option<String>,
446
447    /// Date
448    #[serde(rename = "@date", deserialize_with = "deserialize_flex_date")]
449    pub date: NaiveDate,
450}