Skip to main content

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    /// Customer type
44    #[serde(rename = "@customerType", default)]
45    pub customer_type: Option<String>,
46
47    /// Date account opened
48    #[serde(
49        rename = "@dateOpened",
50        default,
51        deserialize_with = "deserialize_optional_date"
52    )]
53    pub date_opened: Option<NaiveDate>,
54
55    /// Date account funded
56    #[serde(
57        rename = "@dateFunded",
58        default,
59        deserialize_with = "deserialize_optional_date"
60    )]
61    pub date_funded: Option<NaiveDate>,
62
63    /// Date closed
64    #[serde(
65        rename = "@dateClosed",
66        default,
67        deserialize_with = "deserialize_optional_date"
68    )]
69    pub date_closed: Option<NaiveDate>,
70
71    /// Primary email
72    #[serde(rename = "@primaryEmail", default)]
73    pub primary_email: Option<String>,
74
75    /// Street address
76    #[serde(rename = "@streetAddress", default)]
77    pub street_address: Option<String>,
78
79    /// Street address 2
80    #[serde(rename = "@streetAddress2", default)]
81    pub street_address2: Option<String>,
82
83    /// City
84    #[serde(rename = "@city", default)]
85    pub city: Option<String>,
86
87    /// State
88    #[serde(rename = "@state", default)]
89    pub state: Option<String>,
90
91    /// Country
92    #[serde(rename = "@country", default)]
93    pub country: Option<String>,
94
95    /// Postal code
96    #[serde(rename = "@postalCode", default)]
97    pub postal_code: Option<String>,
98
99    /// Account capabilities
100    #[serde(rename = "@accountCapabilities", default)]
101    pub account_capabilities: Option<String>,
102
103    /// Trading permissions
104    #[serde(rename = "@tradingPermissions", default)]
105    pub trading_permissions: Option<String>,
106
107    /// Registered representative name
108    #[serde(rename = "@registeredRepName", default)]
109    pub registered_rep_name: Option<String>,
110
111    /// Registered representative phone
112    #[serde(rename = "@registeredRepPhone", default)]
113    pub registered_rep_phone: Option<String>,
114
115    /// IB entity
116    #[serde(rename = "@ibEntity", default)]
117    pub ib_entity: Option<String>,
118
119    /// Model
120    #[serde(rename = "@model", default)]
121    pub model: Option<String>,
122}
123
124/// Change in portfolio NAV (Net Asset Value)
125#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
126pub struct ChangeInNAV {
127    /// Account ID
128    #[serde(rename = "@accountId")]
129    pub account_id: String,
130
131    /// Account alias
132    #[serde(rename = "@acctAlias", default)]
133    pub acct_alias: Option<String>,
134
135    /// Model
136    #[serde(rename = "@model", default)]
137    pub model: Option<String>,
138
139    /// Currency
140    #[serde(rename = "@currency", default)]
141    pub currency: Option<String>,
142
143    /// From date
144    #[serde(rename = "@fromDate", deserialize_with = "deserialize_flex_date")]
145    pub from_date: NaiveDate,
146
147    /// To date
148    #[serde(rename = "@toDate", deserialize_with = "deserialize_flex_date")]
149    pub to_date: NaiveDate,
150
151    /// Starting NAV value
152    #[serde(rename = "@startingValue")]
153    pub starting_value: Decimal,
154
155    /// Ending NAV value
156    #[serde(rename = "@endingValue")]
157    pub ending_value: Decimal,
158
159    /// Mark-to-market P&L
160    #[serde(
161        rename = "@mtm",
162        default,
163        deserialize_with = "deserialize_optional_decimal"
164    )]
165    pub mtm: Option<Decimal>,
166
167    /// Realized P&L
168    #[serde(
169        rename = "@realized",
170        default,
171        deserialize_with = "deserialize_optional_decimal"
172    )]
173    pub realized: Option<Decimal>,
174
175    /// Change in unrealized P&L
176    #[serde(
177        rename = "@changeInUnrealized",
178        default,
179        deserialize_with = "deserialize_optional_decimal"
180    )]
181    pub change_in_unrealized: Option<Decimal>,
182
183    /// Deposits and withdrawals
184    #[serde(
185        rename = "@depositsWithdrawals",
186        default,
187        deserialize_with = "deserialize_optional_decimal"
188    )]
189    pub deposits_withdrawals: Option<Decimal>,
190
191    /// Dividends received
192    #[serde(
193        rename = "@dividends",
194        default,
195        deserialize_with = "deserialize_optional_decimal"
196    )]
197    pub dividends: Option<Decimal>,
198
199    /// Withholding tax
200    #[serde(
201        rename = "@withholdingTax",
202        default,
203        deserialize_with = "deserialize_optional_decimal"
204    )]
205    pub withholding_tax: Option<Decimal>,
206
207    /// Change in dividend accruals
208    #[serde(
209        rename = "@changeInDividendAccruals",
210        default,
211        deserialize_with = "deserialize_optional_decimal"
212    )]
213    pub change_in_dividend_accruals: Option<Decimal>,
214
215    /// Interest income
216    #[serde(
217        rename = "@interest",
218        default,
219        deserialize_with = "deserialize_optional_decimal"
220    )]
221    pub interest: Option<Decimal>,
222
223    /// Change in interest accruals
224    #[serde(
225        rename = "@changeInInterestAccruals",
226        default,
227        deserialize_with = "deserialize_optional_decimal"
228    )]
229    pub change_in_interest_accruals: Option<Decimal>,
230
231    /// Advisor fees
232    #[serde(
233        rename = "@advisorFees",
234        default,
235        deserialize_with = "deserialize_optional_decimal"
236    )]
237    pub advisor_fees: Option<Decimal>,
238
239    /// Client fees
240    #[serde(
241        rename = "@clientFees",
242        default,
243        deserialize_with = "deserialize_optional_decimal"
244    )]
245    pub client_fees: Option<Decimal>,
246
247    /// Other fees
248    #[serde(
249        rename = "@otherFees",
250        default,
251        deserialize_with = "deserialize_optional_decimal"
252    )]
253    pub other_fees: Option<Decimal>,
254
255    /// Commissions
256    #[serde(
257        rename = "@commissions",
258        default,
259        deserialize_with = "deserialize_optional_decimal"
260    )]
261    pub commissions: Option<Decimal>,
262
263    /// FX translation P&L
264    #[serde(
265        rename = "@fxTranslation",
266        default,
267        deserialize_with = "deserialize_optional_decimal"
268    )]
269    pub fx_translation: Option<Decimal>,
270
271    /// Time-weighted return
272    #[serde(
273        rename = "@twr",
274        default,
275        deserialize_with = "deserialize_optional_decimal"
276    )]
277    pub twr: Option<Decimal>,
278
279    /// Corporate action proceeds
280    #[serde(
281        rename = "@corporateActionProceeds",
282        default,
283        deserialize_with = "deserialize_optional_decimal"
284    )]
285    pub corporate_action_proceeds: Option<Decimal>,
286}
287
288/// Equity summary by report date in base currency
289#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
290pub struct EquitySummaryByReportDateInBase {
291    /// Account ID
292    #[serde(rename = "@accountId")]
293    pub account_id: String,
294
295    /// Account alias
296    #[serde(rename = "@acctAlias", default)]
297    pub acct_alias: Option<String>,
298
299    /// Model
300    #[serde(rename = "@model", default)]
301    pub model: Option<String>,
302
303    /// Report date
304    #[serde(rename = "@reportDate", deserialize_with = "deserialize_flex_date")]
305    pub report_date: NaiveDate,
306
307    /// Cash
308    #[serde(
309        rename = "@cash",
310        default,
311        deserialize_with = "deserialize_optional_decimal"
312    )]
313    pub cash: Option<Decimal>,
314
315    /// Cash long
316    #[serde(
317        rename = "@cashLong",
318        default,
319        deserialize_with = "deserialize_optional_decimal"
320    )]
321    pub cash_long: Option<Decimal>,
322
323    /// Cash short
324    #[serde(
325        rename = "@cashShort",
326        default,
327        deserialize_with = "deserialize_optional_decimal"
328    )]
329    pub cash_short: Option<Decimal>,
330
331    /// Settled cash
332    #[serde(
333        rename = "@settledCash",
334        default,
335        deserialize_with = "deserialize_optional_decimal"
336    )]
337    pub settled_cash: Option<Decimal>,
338
339    /// Slb cash collateral
340    #[serde(
341        rename = "@slbCashCollateral",
342        default,
343        deserialize_with = "deserialize_optional_decimal"
344    )]
345    pub slb_cash_collateral: Option<Decimal>,
346
347    /// Stock value
348    #[serde(
349        rename = "@stock",
350        default,
351        deserialize_with = "deserialize_optional_decimal"
352    )]
353    pub stock: Option<Decimal>,
354
355    /// Stock long
356    #[serde(
357        rename = "@stockLong",
358        default,
359        deserialize_with = "deserialize_optional_decimal"
360    )]
361    pub stock_long: Option<Decimal>,
362
363    /// Stock short
364    #[serde(
365        rename = "@stockShort",
366        default,
367        deserialize_with = "deserialize_optional_decimal"
368    )]
369    pub stock_short: Option<Decimal>,
370
371    /// Slb direct securities borrowed
372    #[serde(
373        rename = "@slbDirectSecuritiesBorrowed",
374        default,
375        deserialize_with = "deserialize_optional_decimal"
376    )]
377    pub slb_direct_securities_borrowed: Option<Decimal>,
378
379    /// Slb direct securities lent
380    #[serde(
381        rename = "@slbDirectSecuritiesLent",
382        default,
383        deserialize_with = "deserialize_optional_decimal"
384    )]
385    pub slb_direct_securities_lent: Option<Decimal>,
386
387    /// Options value
388    #[serde(
389        rename = "@options",
390        default,
391        deserialize_with = "deserialize_optional_decimal"
392    )]
393    pub options: Option<Decimal>,
394
395    /// Options long
396    #[serde(
397        rename = "@optionsLong",
398        default,
399        deserialize_with = "deserialize_optional_decimal"
400    )]
401    pub options_long: Option<Decimal>,
402
403    /// Options short
404    #[serde(
405        rename = "@optionsShort",
406        default,
407        deserialize_with = "deserialize_optional_decimal"
408    )]
409    pub options_short: Option<Decimal>,
410
411    /// Bonds value
412    #[serde(
413        rename = "@bonds",
414        default,
415        deserialize_with = "deserialize_optional_decimal"
416    )]
417    pub bonds: Option<Decimal>,
418
419    /// Bonds long
420    #[serde(
421        rename = "@bondsLong",
422        default,
423        deserialize_with = "deserialize_optional_decimal"
424    )]
425    pub bonds_long: Option<Decimal>,
426
427    /// Bonds short
428    #[serde(
429        rename = "@bondsShort",
430        default,
431        deserialize_with = "deserialize_optional_decimal"
432    )]
433    pub bonds_short: Option<Decimal>,
434
435    /// Notes value
436    #[serde(
437        rename = "@notes",
438        default,
439        deserialize_with = "deserialize_optional_decimal"
440    )]
441    pub notes: Option<Decimal>,
442
443    /// Funds value
444    #[serde(
445        rename = "@funds",
446        default,
447        deserialize_with = "deserialize_optional_decimal"
448    )]
449    pub funds: Option<Decimal>,
450
451    /// Futures value (unrealized P&L)
452    #[serde(
453        rename = "@futures",
454        default,
455        deserialize_with = "deserialize_optional_decimal"
456    )]
457    pub futures: Option<Decimal>,
458
459    /// Futures long
460    #[serde(
461        rename = "@futuresLong",
462        default,
463        deserialize_with = "deserialize_optional_decimal"
464    )]
465    pub futures_long: Option<Decimal>,
466
467    /// Futures short
468    #[serde(
469        rename = "@futuresShort",
470        default,
471        deserialize_with = "deserialize_optional_decimal"
472    )]
473    pub futures_short: Option<Decimal>,
474
475    /// Commodities value
476    #[serde(
477        rename = "@commodities",
478        default,
479        deserialize_with = "deserialize_optional_decimal"
480    )]
481    pub commodities: Option<Decimal>,
482
483    /// Total
484    #[serde(
485        rename = "@total",
486        default,
487        deserialize_with = "deserialize_optional_decimal"
488    )]
489    pub total: Option<Decimal>,
490
491    /// Total long
492    #[serde(
493        rename = "@totalLong",
494        default,
495        deserialize_with = "deserialize_optional_decimal"
496    )]
497    pub total_long: Option<Decimal>,
498
499    /// Total short
500    #[serde(
501        rename = "@totalShort",
502        default,
503        deserialize_with = "deserialize_optional_decimal"
504    )]
505    pub total_short: Option<Decimal>,
506
507    /// Interest accruals
508    #[serde(
509        rename = "@interestAccruals",
510        default,
511        deserialize_with = "deserialize_optional_decimal"
512    )]
513    pub interest_accruals: Option<Decimal>,
514
515    /// Dividend accruals
516    #[serde(
517        rename = "@dividendAccruals",
518        default,
519        deserialize_with = "deserialize_optional_decimal"
520    )]
521    pub dividend_accruals: Option<Decimal>,
522
523    /// Accrued interest
524    #[serde(
525        rename = "@accruedInterest",
526        default,
527        deserialize_with = "deserialize_optional_decimal"
528    )]
529    pub accrued_interest: Option<Decimal>,
530
531    /// Accrued dividend
532    #[serde(
533        rename = "@accruedDividend",
534        default,
535        deserialize_with = "deserialize_optional_decimal"
536    )]
537    pub accrued_dividend: Option<Decimal>,
538
539    /// Soft dollar value
540    #[serde(
541        rename = "@softDollars",
542        default,
543        deserialize_with = "deserialize_optional_decimal"
544    )]
545    pub soft_dollars: Option<Decimal>,
546
547    /// Forex CFD unrealized P&L
548    #[serde(
549        rename = "@forexCfdUnrealizedPl",
550        default,
551        deserialize_with = "deserialize_optional_decimal"
552    )]
553    pub forex_cfd_unrealized_pl: Option<Decimal>,
554
555    /// CFD unrealized P&L
556    #[serde(
557        rename = "@cfdUnrealizedPl",
558        default,
559        deserialize_with = "deserialize_optional_decimal"
560    )]
561    pub cfd_unrealized_pl: Option<Decimal>,
562
563    /// Broker cash component
564    #[serde(
565        rename = "@brokerCashComponent",
566        default,
567        deserialize_with = "deserialize_optional_decimal"
568    )]
569    pub broker_cash_component: Option<Decimal>,
570
571    /// Broker interest accruals component
572    #[serde(
573        rename = "@brokerInterestAccrualsComponent",
574        default,
575        deserialize_with = "deserialize_optional_decimal"
576    )]
577    pub broker_interest_accruals_component: Option<Decimal>,
578
579    /// Gross position value
580    #[serde(
581        rename = "@grossPositionValue",
582        default,
583        deserialize_with = "deserialize_optional_decimal"
584    )]
585    pub gross_position_value: Option<Decimal>,
586
587    /// Net liquidation value
588    #[serde(
589        rename = "@netLiquidation",
590        default,
591        deserialize_with = "deserialize_optional_decimal"
592    )]
593    pub net_liquidation: Option<Decimal>,
594
595    /// Net liquidation uncertainty
596    #[serde(
597        rename = "@netLiquidationUncertainty",
598        default,
599        deserialize_with = "deserialize_optional_decimal"
600    )]
601    pub net_liquidation_uncertainty: Option<Decimal>,
602}
603
604/// Cash report by currency
605#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
606pub struct CashReportCurrency {
607    /// Account ID
608    #[serde(rename = "@accountId")]
609    pub account_id: String,
610
611    /// Account alias
612    #[serde(rename = "@acctAlias", default)]
613    pub acct_alias: Option<String>,
614
615    /// Model
616    #[serde(rename = "@model", default)]
617    pub model: Option<String>,
618
619    /// Currency
620    #[serde(rename = "@currency")]
621    pub currency: String,
622
623    /// From date
624    #[serde(rename = "@fromDate", deserialize_with = "deserialize_flex_date")]
625    pub from_date: NaiveDate,
626
627    /// To date
628    #[serde(rename = "@toDate", deserialize_with = "deserialize_flex_date")]
629    pub to_date: NaiveDate,
630
631    /// Starting cash
632    #[serde(rename = "@startingCash")]
633    pub starting_cash: Decimal,
634
635    /// Starting cash (securities segment)
636    #[serde(
637        rename = "@startingCashSec",
638        default,
639        deserialize_with = "deserialize_optional_decimal"
640    )]
641    pub starting_cash_sec: Option<Decimal>,
642
643    /// Starting cash (commodities segment)
644    #[serde(
645        rename = "@startingCashCom",
646        default,
647        deserialize_with = "deserialize_optional_decimal"
648    )]
649    pub starting_cash_com: Option<Decimal>,
650
651    /// Commissions paid
652    #[serde(
653        rename = "@commissions",
654        default,
655        deserialize_with = "deserialize_optional_decimal"
656    )]
657    pub commissions: Option<Decimal>,
658
659    /// Commissions (securities segment)
660    #[serde(
661        rename = "@commissionsSec",
662        default,
663        deserialize_with = "deserialize_optional_decimal"
664    )]
665    pub commissions_sec: Option<Decimal>,
666
667    /// Commissions (commodities segment)
668    #[serde(
669        rename = "@commissionsCom",
670        default,
671        deserialize_with = "deserialize_optional_decimal"
672    )]
673    pub commissions_com: Option<Decimal>,
674
675    /// Deposits
676    #[serde(
677        rename = "@deposits",
678        default,
679        deserialize_with = "deserialize_optional_decimal"
680    )]
681    pub deposits: Option<Decimal>,
682
683    /// Withdrawals
684    #[serde(
685        rename = "@withdrawals",
686        default,
687        deserialize_with = "deserialize_optional_decimal"
688    )]
689    pub withdrawals: Option<Decimal>,
690
691    /// Dividends
692    #[serde(
693        rename = "@dividends",
694        default,
695        deserialize_with = "deserialize_optional_decimal"
696    )]
697    pub dividends: Option<Decimal>,
698
699    /// Broker interest received
700    #[serde(
701        rename = "@brokerInterest",
702        default,
703        deserialize_with = "deserialize_optional_decimal"
704    )]
705    pub broker_interest: Option<Decimal>,
706
707    /// Bond interest received
708    #[serde(
709        rename = "@bondInterest",
710        default,
711        deserialize_with = "deserialize_optional_decimal"
712    )]
713    pub bond_interest: Option<Decimal>,
714
715    /// Withholding tax
716    #[serde(
717        rename = "@withholdingTax",
718        default,
719        deserialize_with = "deserialize_optional_decimal"
720    )]
721    pub withholding_tax: Option<Decimal>,
722
723    /// Net trades sales
724    #[serde(
725        rename = "@netTradesSales",
726        default,
727        deserialize_with = "deserialize_optional_decimal"
728    )]
729    pub net_trades_sales: Option<Decimal>,
730
731    /// Net trades purchases
732    #[serde(
733        rename = "@netTradesPurchases",
734        default,
735        deserialize_with = "deserialize_optional_decimal"
736    )]
737    pub net_trades_purchases: Option<Decimal>,
738
739    /// Account transfers
740    #[serde(
741        rename = "@accountTransfers",
742        default,
743        deserialize_with = "deserialize_optional_decimal"
744    )]
745    pub account_transfers: Option<Decimal>,
746
747    /// Internal transfers
748    #[serde(
749        rename = "@internalTransfers",
750        default,
751        deserialize_with = "deserialize_optional_decimal"
752    )]
753    pub internal_transfers: Option<Decimal>,
754
755    /// External transfers
756    #[serde(
757        rename = "@externalTransfers",
758        default,
759        deserialize_with = "deserialize_optional_decimal"
760    )]
761    pub external_transfers: Option<Decimal>,
762
763    /// Link interest
764    #[serde(
765        rename = "@linkingAdjustments",
766        default,
767        deserialize_with = "deserialize_optional_decimal"
768    )]
769    pub linking_adjustments: Option<Decimal>,
770
771    /// Other fees
772    #[serde(
773        rename = "@otherFees",
774        default,
775        deserialize_with = "deserialize_optional_decimal"
776    )]
777    pub other_fees: Option<Decimal>,
778
779    /// FX translation P&L
780    #[serde(
781        rename = "@fxTranslationPnl",
782        default,
783        deserialize_with = "deserialize_optional_decimal"
784    )]
785    pub fx_translation_pnl: Option<Decimal>,
786
787    /// Billable sales tax
788    #[serde(
789        rename = "@billableSalesTax",
790        default,
791        deserialize_with = "deserialize_optional_decimal"
792    )]
793    pub billable_sales_tax: Option<Decimal>,
794
795    /// Realized forex P&L
796    #[serde(
797        rename = "@realizedForexPnl",
798        default,
799        deserialize_with = "deserialize_optional_decimal"
800    )]
801    pub realized_forex_pnl: Option<Decimal>,
802
803    /// Debit card activity
804    #[serde(
805        rename = "@debitCardActivity",
806        default,
807        deserialize_with = "deserialize_optional_decimal"
808    )]
809    pub debit_card_activity: Option<Decimal>,
810
811    /// Client fees
812    #[serde(
813        rename = "@clientFees",
814        default,
815        deserialize_with = "deserialize_optional_decimal"
816    )]
817    pub client_fees: Option<Decimal>,
818
819    /// Cash settling MTM
820    #[serde(
821        rename = "@cashSettlingMtm",
822        default,
823        deserialize_with = "deserialize_optional_decimal"
824    )]
825    pub cash_settling_mtm: Option<Decimal>,
826
827    /// Soft dollar fees
828    #[serde(
829        rename = "@softDollars",
830        default,
831        deserialize_with = "deserialize_optional_decimal"
832    )]
833    pub soft_dollars: Option<Decimal>,
834
835    /// Ending cash
836    #[serde(rename = "@endingCash")]
837    pub ending_cash: Decimal,
838
839    /// Ending cash (securities segment)
840    #[serde(
841        rename = "@endingCashSec",
842        default,
843        deserialize_with = "deserialize_optional_decimal"
844    )]
845    pub ending_cash_sec: Option<Decimal>,
846
847    /// Ending cash (commodities segment)
848    #[serde(
849        rename = "@endingCashCom",
850        default,
851        deserialize_with = "deserialize_optional_decimal"
852    )]
853    pub ending_cash_com: Option<Decimal>,
854
855    /// Ending settled cash
856    #[serde(
857        rename = "@endingSettledCash",
858        default,
859        deserialize_with = "deserialize_optional_decimal"
860    )]
861    pub ending_settled_cash: Option<Decimal>,
862
863    /// Ending settled cash (securities segment)
864    #[serde(
865        rename = "@endingSettledCashSec",
866        default,
867        deserialize_with = "deserialize_optional_decimal"
868    )]
869    pub ending_settled_cash_sec: Option<Decimal>,
870
871    /// Ending settled cash (commodities segment)
872    #[serde(
873        rename = "@endingSettledCashCom",
874        default,
875        deserialize_with = "deserialize_optional_decimal"
876    )]
877    pub ending_settled_cash_com: Option<Decimal>,
878}
879
880/// Trade confirmation
881#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
882pub struct TradeConfirm {
883    /// Account ID
884    #[serde(rename = "@accountId")]
885    pub account_id: String,
886
887    /// Account alias
888    #[serde(rename = "@acctAlias", default)]
889    pub acct_alias: Option<String>,
890
891    /// Model
892    #[serde(rename = "@model", default)]
893    pub model: Option<String>,
894
895    /// Execution ID
896    #[serde(rename = "@execID")]
897    pub exec_id: String,
898
899    /// Transaction ID
900    #[serde(rename = "@transactionID", default)]
901    pub transaction_id: Option<String>,
902
903    /// Trade ID
904    #[serde(rename = "@tradeID", default)]
905    pub trade_id: Option<String>,
906
907    /// Order ID
908    #[serde(rename = "@orderID", default)]
909    pub order_id: Option<String>,
910
911    /// Trade date
912    #[serde(rename = "@tradeDate", deserialize_with = "deserialize_flex_date")]
913    pub trade_date: NaiveDate,
914
915    /// Trade time
916    #[serde(rename = "@tradeTime", default)]
917    pub trade_time: Option<String>,
918
919    /// Date time
920    #[serde(rename = "@dateTime", default)]
921    pub date_time: Option<String>,
922
923    /// Settlement date
924    #[serde(
925        rename = "@settleDate",
926        default,
927        deserialize_with = "deserialize_optional_date"
928    )]
929    pub settle_date: Option<NaiveDate>,
930
931    /// Symbol
932    #[serde(rename = "@symbol")]
933    pub symbol: String,
934
935    /// Description
936    #[serde(rename = "@description", default)]
937    pub description: Option<String>,
938
939    /// Contract ID
940    #[serde(rename = "@conid", default)]
941    pub conid: Option<String>,
942
943    /// Asset category
944    #[serde(rename = "@assetCategory")]
945    pub asset_category: AssetCategory,
946
947    // Security identifiers
948    /// CUSIP
949    #[serde(rename = "@cusip", default)]
950    pub cusip: Option<String>,
951
952    /// ISIN
953    #[serde(rename = "@isin", default)]
954    pub isin: Option<String>,
955
956    /// FIGI
957    #[serde(rename = "@figi", default)]
958    pub figi: Option<String>,
959
960    /// Listing exchange
961    #[serde(rename = "@listingExchange", default)]
962    pub listing_exchange: Option<String>,
963
964    // Options fields
965    /// Strike
966    #[serde(
967        rename = "@strike",
968        default,
969        deserialize_with = "deserialize_optional_decimal"
970    )]
971    pub strike: Option<Decimal>,
972
973    /// Expiry
974    #[serde(
975        rename = "@expiry",
976        default,
977        deserialize_with = "deserialize_optional_date"
978    )]
979    pub expiry: Option<NaiveDate>,
980
981    /// Put/Call
982    #[serde(rename = "@putCall", default)]
983    pub put_call: Option<String>,
984
985    /// Multiplier
986    #[serde(
987        rename = "@multiplier",
988        default,
989        deserialize_with = "deserialize_optional_decimal"
990    )]
991    pub multiplier: Option<Decimal>,
992
993    // Underlying
994    /// Underlying symbol
995    #[serde(rename = "@underlyingSymbol", default)]
996    pub underlying_symbol: Option<String>,
997
998    /// Underlying contract ID
999    #[serde(rename = "@underlyingConid", default)]
1000    pub underlying_conid: Option<String>,
1001
1002    // Trade details
1003    /// Quantity
1004    #[serde(rename = "@quantity")]
1005    pub quantity: Decimal,
1006
1007    /// Price
1008    #[serde(rename = "@price")]
1009    pub price: Decimal,
1010
1011    /// Proceeds
1012    #[serde(
1013        rename = "@proceeds",
1014        default,
1015        deserialize_with = "deserialize_optional_decimal"
1016    )]
1017    pub proceeds: Option<Decimal>,
1018
1019    /// Commission
1020    #[serde(
1021        rename = "@commission",
1022        default,
1023        deserialize_with = "deserialize_optional_decimal"
1024    )]
1025    pub commission: Option<Decimal>,
1026
1027    /// Taxes
1028    #[serde(
1029        rename = "@tax",
1030        default,
1031        deserialize_with = "deserialize_optional_decimal"
1032    )]
1033    pub tax: Option<Decimal>,
1034
1035    /// Net cash
1036    #[serde(
1037        rename = "@netCash",
1038        default,
1039        deserialize_with = "deserialize_optional_decimal"
1040    )]
1041    pub net_cash: Option<Decimal>,
1042
1043    /// Currency
1044    #[serde(rename = "@currency", default)]
1045    pub currency: Option<String>,
1046
1047    /// FX rate to base
1048    #[serde(
1049        rename = "@fxRateToBase",
1050        default,
1051        deserialize_with = "deserialize_optional_decimal"
1052    )]
1053    pub fx_rate_to_base: Option<Decimal>,
1054
1055    /// Buy/Sell
1056    #[serde(rename = "@buySell", default)]
1057    pub buy_sell: Option<String>,
1058
1059    /// Order type
1060    #[serde(rename = "@orderType", default)]
1061    pub order_type: Option<String>,
1062
1063    /// Exchange
1064    #[serde(rename = "@exchange", default)]
1065    pub exchange: Option<String>,
1066
1067    /// Clearing ID
1068    #[serde(rename = "@clearingID", default)]
1069    pub clearing_id: Option<String>,
1070
1071    /// Away broker commission
1072    #[serde(
1073        rename = "@awayBrokerCommission",
1074        default,
1075        deserialize_with = "deserialize_optional_decimal"
1076    )]
1077    pub away_broker_commission: Option<Decimal>,
1078
1079    /// Regulatory fee
1080    #[serde(
1081        rename = "@regulatoryFee",
1082        default,
1083        deserialize_with = "deserialize_optional_decimal"
1084    )]
1085    pub regulatory_fee: Option<Decimal>,
1086
1087    /// Order reference
1088    #[serde(rename = "@orderReference", default)]
1089    pub order_reference: Option<String>,
1090
1091    /// Level of detail
1092    #[serde(rename = "@levelOfDetail", default)]
1093    pub level_of_detail: Option<String>,
1094}
1095
1096/// Option exercise/assignment/expiration
1097#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
1098pub struct OptionEAE {
1099    /// Account ID
1100    #[serde(rename = "@accountId")]
1101    pub account_id: String,
1102
1103    /// Account alias
1104    #[serde(rename = "@acctAlias", default)]
1105    pub acct_alias: Option<String>,
1106
1107    /// Model
1108    #[serde(rename = "@model", default)]
1109    pub model: Option<String>,
1110
1111    /// Transaction ID
1112    #[serde(rename = "@transactionID", default)]
1113    pub transaction_id: Option<String>,
1114
1115    /// Action ID
1116    #[serde(rename = "@actionID", default)]
1117    pub action_id: Option<String>,
1118
1119    /// Action type
1120    #[serde(rename = "@type", default)]
1121    pub action_type: Option<OptionAction>,
1122
1123    /// Date
1124    #[serde(rename = "@date", deserialize_with = "deserialize_flex_date")]
1125    pub date: NaiveDate,
1126
1127    /// Date time
1128    #[serde(rename = "@dateTime", default)]
1129    pub date_time: Option<String>,
1130
1131    /// Contract ID
1132    #[serde(rename = "@conid", default)]
1133    pub conid: Option<String>,
1134
1135    /// Symbol
1136    #[serde(rename = "@symbol")]
1137    pub symbol: String,
1138
1139    /// Description
1140    #[serde(rename = "@description", default)]
1141    pub description: Option<String>,
1142
1143    /// Asset category
1144    #[serde(rename = "@assetCategory", default)]
1145    pub asset_category: Option<AssetCategory>,
1146
1147    // Security identifiers
1148    /// CUSIP
1149    #[serde(rename = "@cusip", default)]
1150    pub cusip: Option<String>,
1151
1152    /// ISIN
1153    #[serde(rename = "@isin", default)]
1154    pub isin: Option<String>,
1155
1156    /// FIGI
1157    #[serde(rename = "@figi", default)]
1158    pub figi: Option<String>,
1159
1160    /// Listing exchange
1161    #[serde(rename = "@listingExchange", default)]
1162    pub listing_exchange: Option<String>,
1163
1164    /// Quantity
1165    #[serde(rename = "@quantity")]
1166    pub quantity: Decimal,
1167
1168    /// Strike
1169    #[serde(
1170        rename = "@strike",
1171        default,
1172        deserialize_with = "deserialize_optional_decimal"
1173    )]
1174    pub strike: Option<Decimal>,
1175
1176    /// Expiry
1177    #[serde(
1178        rename = "@expiry",
1179        default,
1180        deserialize_with = "deserialize_optional_date"
1181    )]
1182    pub expiry: Option<NaiveDate>,
1183
1184    /// Put/Call
1185    #[serde(rename = "@putCall", default)]
1186    pub put_call: Option<String>,
1187
1188    /// Multiplier
1189    #[serde(
1190        rename = "@multiplier",
1191        default,
1192        deserialize_with = "deserialize_optional_decimal"
1193    )]
1194    pub multiplier: Option<Decimal>,
1195
1196    /// Underlying symbol
1197    #[serde(rename = "@underlyingSymbol", default)]
1198    pub underlying_symbol: Option<String>,
1199
1200    /// Underlying contract ID
1201    #[serde(rename = "@underlyingConid", default)]
1202    pub underlying_conid: Option<String>,
1203
1204    /// Trade price
1205    #[serde(
1206        rename = "@tradePrice",
1207        default,
1208        deserialize_with = "deserialize_optional_decimal"
1209    )]
1210    pub trade_price: Option<Decimal>,
1211
1212    /// Proceeds
1213    #[serde(
1214        rename = "@proceeds",
1215        default,
1216        deserialize_with = "deserialize_optional_decimal"
1217    )]
1218    pub proceeds: Option<Decimal>,
1219
1220    /// Commission
1221    #[serde(
1222        rename = "@commission",
1223        default,
1224        deserialize_with = "deserialize_optional_decimal"
1225    )]
1226    pub commission: Option<Decimal>,
1227
1228    /// Currency
1229    #[serde(rename = "@currency", default)]
1230    pub currency: Option<String>,
1231
1232    /// FX rate to base
1233    #[serde(
1234        rename = "@fxRateToBase",
1235        default,
1236        deserialize_with = "deserialize_optional_decimal"
1237    )]
1238    pub fx_rate_to_base: Option<Decimal>,
1239
1240    /// FIFO P&L realized
1241    #[serde(
1242        rename = "@fifoPnlRealized",
1243        default,
1244        deserialize_with = "deserialize_optional_decimal"
1245    )]
1246    pub fifo_pnl_realized: Option<Decimal>,
1247
1248    /// Notes/codes
1249    #[serde(rename = "@notes", default)]
1250    pub notes: Option<String>,
1251
1252    /// Level of detail
1253    #[serde(rename = "@levelOfDetail", default)]
1254    pub level_of_detail: Option<String>,
1255}
1256
1257/// Foreign exchange transaction
1258#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
1259pub struct FxTransaction {
1260    /// Account ID
1261    #[serde(rename = "@accountId")]
1262    pub account_id: String,
1263
1264    /// Account alias
1265    #[serde(rename = "@acctAlias", default)]
1266    pub acct_alias: Option<String>,
1267
1268    /// Model
1269    #[serde(rename = "@model", default)]
1270    pub model: Option<String>,
1271
1272    /// Transaction ID
1273    #[serde(rename = "@transactionID", default)]
1274    pub transaction_id: Option<String>,
1275
1276    /// Action ID
1277    #[serde(rename = "@actionID", default)]
1278    pub action_id: Option<String>,
1279
1280    /// Report date
1281    #[serde(
1282        rename = "@reportDate",
1283        default,
1284        deserialize_with = "deserialize_optional_date"
1285    )]
1286    pub report_date: Option<NaiveDate>,
1287
1288    /// Date/time
1289    #[serde(rename = "@dateTime", default)]
1290    pub date_time: Option<String>,
1291
1292    /// Description
1293    #[serde(rename = "@description", default)]
1294    pub description: Option<String>,
1295
1296    /// Functional currency
1297    #[serde(rename = "@functionalCurrency", default)]
1298    pub functional_currency: Option<String>,
1299
1300    /// From currency
1301    #[serde(rename = "@fromCurrency")]
1302    pub from_currency: String,
1303
1304    /// To currency
1305    #[serde(rename = "@toCurrency")]
1306    pub to_currency: String,
1307
1308    /// Quantity
1309    #[serde(rename = "@quantity")]
1310    pub quantity: Decimal,
1311
1312    /// Proceeds
1313    #[serde(rename = "@proceeds")]
1314    pub proceeds: Decimal,
1315
1316    /// Cost
1317    #[serde(
1318        rename = "@cost",
1319        default,
1320        deserialize_with = "deserialize_optional_decimal"
1321    )]
1322    pub cost: Option<Decimal>,
1323
1324    /// Realized P&L
1325    #[serde(
1326        rename = "@realizedPL",
1327        default,
1328        deserialize_with = "deserialize_optional_decimal"
1329    )]
1330    pub realized_pl: Option<Decimal>,
1331
1332    /// FX rate
1333    #[serde(
1334        rename = "@fxRateToBase",
1335        default,
1336        deserialize_with = "deserialize_optional_decimal"
1337    )]
1338    pub fx_rate_to_base: Option<Decimal>,
1339
1340    /// Level of detail
1341    #[serde(rename = "@levelOfDetail", default)]
1342    pub level_of_detail: Option<String>,
1343
1344    /// Asset category
1345    #[serde(rename = "@assetCategory", default)]
1346    pub asset_category: Option<String>,
1347}
1348
1349/// Change in dividend accruals
1350#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
1351pub struct ChangeInDividendAccrual {
1352    /// Account ID
1353    #[serde(rename = "@accountId")]
1354    pub account_id: String,
1355
1356    /// Account alias
1357    #[serde(rename = "@acctAlias", default)]
1358    pub acct_alias: Option<String>,
1359
1360    /// Model
1361    #[serde(rename = "@model", default)]
1362    pub model: Option<String>,
1363
1364    /// Currency
1365    #[serde(rename = "@currency", default)]
1366    pub currency: Option<String>,
1367
1368    /// FX rate to base
1369    #[serde(
1370        rename = "@fxRateToBase",
1371        default,
1372        deserialize_with = "deserialize_optional_decimal"
1373    )]
1374    pub fx_rate_to_base: Option<Decimal>,
1375
1376    /// Asset category
1377    #[serde(rename = "@assetCategory", default)]
1378    pub asset_category: Option<AssetCategory>,
1379
1380    /// Symbol
1381    #[serde(rename = "@symbol")]
1382    pub symbol: String,
1383
1384    /// Description
1385    #[serde(rename = "@description", default)]
1386    pub description: Option<String>,
1387
1388    /// Contract ID
1389    #[serde(rename = "@conid", default)]
1390    pub conid: Option<String>,
1391
1392    /// Security ID
1393    #[serde(rename = "@securityID", default)]
1394    pub security_id: Option<String>,
1395
1396    /// Security ID type
1397    #[serde(rename = "@securityIDType", default)]
1398    pub security_id_type: Option<String>,
1399
1400    /// CUSIP
1401    #[serde(rename = "@cusip", default)]
1402    pub cusip: Option<String>,
1403
1404    /// ISIN
1405    #[serde(rename = "@isin", default)]
1406    pub isin: Option<String>,
1407
1408    /// FIGI
1409    #[serde(rename = "@figi", default)]
1410    pub figi: Option<String>,
1411
1412    /// Listing exchange
1413    #[serde(rename = "@listingExchange", default)]
1414    pub listing_exchange: Option<String>,
1415
1416    /// Ex date
1417    #[serde(rename = "@exDate", deserialize_with = "deserialize_flex_date")]
1418    pub ex_date: NaiveDate,
1419
1420    /// Pay date
1421    #[serde(
1422        rename = "@payDate",
1423        default,
1424        deserialize_with = "deserialize_optional_date"
1425    )]
1426    pub pay_date: Option<NaiveDate>,
1427
1428    /// Date
1429    #[serde(
1430        rename = "@date",
1431        default,
1432        deserialize_with = "deserialize_optional_date"
1433    )]
1434    pub date: Option<NaiveDate>,
1435
1436    /// Quantity
1437    #[serde(
1438        rename = "@quantity",
1439        default,
1440        deserialize_with = "deserialize_optional_decimal"
1441    )]
1442    pub quantity: Option<Decimal>,
1443
1444    /// Tax
1445    #[serde(
1446        rename = "@tax",
1447        default,
1448        deserialize_with = "deserialize_optional_decimal"
1449    )]
1450    pub tax: Option<Decimal>,
1451
1452    /// Fee
1453    #[serde(
1454        rename = "@fee",
1455        default,
1456        deserialize_with = "deserialize_optional_decimal"
1457    )]
1458    pub fee: Option<Decimal>,
1459
1460    /// Gross rate
1461    #[serde(rename = "@grossRate")]
1462    pub gross_rate: Decimal,
1463
1464    /// Gross amount
1465    #[serde(
1466        rename = "@grossAmount",
1467        default,
1468        deserialize_with = "deserialize_optional_decimal"
1469    )]
1470    pub gross_amount: Option<Decimal>,
1471
1472    /// Net amount
1473    #[serde(rename = "@netAmount")]
1474    pub net_amount: Decimal,
1475
1476    /// From accrual (prior period)
1477    #[serde(
1478        rename = "@fromAccrual",
1479        default,
1480        deserialize_with = "deserialize_optional_decimal"
1481    )]
1482    pub from_accrual: Option<Decimal>,
1483
1484    /// To accrual (current period)
1485    #[serde(
1486        rename = "@toAccrual",
1487        default,
1488        deserialize_with = "deserialize_optional_decimal"
1489    )]
1490    pub to_accrual: Option<Decimal>,
1491
1492    /// Code
1493    #[serde(rename = "@code", default)]
1494    pub code: Option<String>,
1495}
1496
1497/// Open dividend accruals
1498#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
1499pub struct OpenDividendAccrual {
1500    /// Account ID
1501    #[serde(rename = "@accountId")]
1502    pub account_id: String,
1503
1504    /// Account alias
1505    #[serde(rename = "@acctAlias", default)]
1506    pub acct_alias: Option<String>,
1507
1508    /// Model
1509    #[serde(rename = "@model", default)]
1510    pub model: Option<String>,
1511
1512    /// Currency
1513    #[serde(rename = "@currency", default)]
1514    pub currency: Option<String>,
1515
1516    /// FX rate to base
1517    #[serde(
1518        rename = "@fxRateToBase",
1519        default,
1520        deserialize_with = "deserialize_optional_decimal"
1521    )]
1522    pub fx_rate_to_base: Option<Decimal>,
1523
1524    /// Asset category
1525    #[serde(rename = "@assetCategory", default)]
1526    pub asset_category: Option<AssetCategory>,
1527
1528    /// Symbol
1529    #[serde(rename = "@symbol")]
1530    pub symbol: String,
1531
1532    /// Description
1533    #[serde(rename = "@description", default)]
1534    pub description: Option<String>,
1535
1536    /// Contract ID
1537    #[serde(rename = "@conid", default)]
1538    pub conid: Option<String>,
1539
1540    /// Security ID
1541    #[serde(rename = "@securityID", default)]
1542    pub security_id: Option<String>,
1543
1544    /// Security ID type
1545    #[serde(rename = "@securityIDType", default)]
1546    pub security_id_type: Option<String>,
1547
1548    /// CUSIP
1549    #[serde(rename = "@cusip", default)]
1550    pub cusip: Option<String>,
1551
1552    /// ISIN
1553    #[serde(rename = "@isin", default)]
1554    pub isin: Option<String>,
1555
1556    /// FIGI
1557    #[serde(rename = "@figi", default)]
1558    pub figi: Option<String>,
1559
1560    /// Listing exchange
1561    #[serde(rename = "@listingExchange", default)]
1562    pub listing_exchange: Option<String>,
1563
1564    /// Ex date
1565    #[serde(rename = "@exDate", deserialize_with = "deserialize_flex_date")]
1566    pub ex_date: NaiveDate,
1567
1568    /// Pay date
1569    #[serde(
1570        rename = "@payDate",
1571        default,
1572        deserialize_with = "deserialize_optional_date"
1573    )]
1574    pub pay_date: Option<NaiveDate>,
1575
1576    /// Quantity
1577    #[serde(rename = "@quantity")]
1578    pub quantity: Decimal,
1579
1580    /// Tax
1581    #[serde(
1582        rename = "@tax",
1583        default,
1584        deserialize_with = "deserialize_optional_decimal"
1585    )]
1586    pub tax: Option<Decimal>,
1587
1588    /// Fee
1589    #[serde(
1590        rename = "@fee",
1591        default,
1592        deserialize_with = "deserialize_optional_decimal"
1593    )]
1594    pub fee: Option<Decimal>,
1595
1596    /// Gross rate
1597    #[serde(rename = "@grossRate")]
1598    pub gross_rate: Decimal,
1599
1600    /// Gross amount
1601    #[serde(
1602        rename = "@grossAmount",
1603        default,
1604        deserialize_with = "deserialize_optional_decimal"
1605    )]
1606    pub gross_amount: Option<Decimal>,
1607
1608    /// Net amount
1609    #[serde(
1610        rename = "@netAmount",
1611        default,
1612        deserialize_with = "deserialize_optional_decimal"
1613    )]
1614    pub net_amount: Option<Decimal>,
1615
1616    /// Code
1617    #[serde(rename = "@code", default)]
1618    pub code: Option<String>,
1619}
1620
1621/// Interest accruals by currency
1622#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
1623pub struct InterestAccrualsCurrency {
1624    /// Account ID
1625    #[serde(rename = "@accountId")]
1626    pub account_id: String,
1627
1628    /// Currency
1629    #[serde(rename = "@currency")]
1630    pub currency: String,
1631
1632    /// From date
1633    #[serde(rename = "@fromDate", deserialize_with = "deserialize_flex_date")]
1634    pub from_date: NaiveDate,
1635
1636    /// To date
1637    #[serde(rename = "@toDate", deserialize_with = "deserialize_flex_date")]
1638    pub to_date: NaiveDate,
1639
1640    /// Starting accrual balance
1641    #[serde(rename = "@startingAccrualBalance")]
1642    pub starting_balance: Decimal,
1643
1644    /// Interest accrued
1645    #[serde(rename = "@interestAccrued")]
1646    pub interest_accrued: Decimal,
1647
1648    /// Ending accrual balance
1649    #[serde(rename = "@endingAccrualBalance")]
1650    pub ending_balance: Decimal,
1651}
1652
1653/// Security transfer
1654#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
1655pub struct Transfer {
1656    /// Account ID
1657    #[serde(rename = "@accountId")]
1658    pub account_id: String,
1659
1660    /// Account alias
1661    #[serde(rename = "@acctAlias", default)]
1662    pub acct_alias: Option<String>,
1663
1664    /// Model
1665    #[serde(rename = "@model", default)]
1666    pub model: Option<String>,
1667
1668    /// Transaction ID
1669    #[serde(rename = "@transactionID", default)]
1670    pub transaction_id: Option<String>,
1671
1672    /// Transfer type
1673    #[serde(rename = "@type", default)]
1674    pub transfer_type: Option<TransferType>,
1675
1676    /// Contract ID
1677    #[serde(rename = "@conid", default)]
1678    pub conid: Option<String>,
1679
1680    /// Symbol
1681    #[serde(rename = "@symbol")]
1682    pub symbol: String,
1683
1684    /// Description
1685    #[serde(rename = "@description", default)]
1686    pub description: Option<String>,
1687
1688    /// Asset category
1689    #[serde(rename = "@assetCategory", default)]
1690    pub asset_category: Option<AssetCategory>,
1691
1692    // Security identifiers
1693    /// CUSIP
1694    #[serde(rename = "@cusip", default)]
1695    pub cusip: Option<String>,
1696
1697    /// ISIN
1698    #[serde(rename = "@isin", default)]
1699    pub isin: Option<String>,
1700
1701    /// FIGI
1702    #[serde(rename = "@figi", default)]
1703    pub figi: Option<String>,
1704
1705    /// Listing exchange
1706    #[serde(rename = "@listingExchange", default)]
1707    pub listing_exchange: Option<String>,
1708
1709    /// Quantity
1710    #[serde(rename = "@quantity")]
1711    pub quantity: Decimal,
1712
1713    /// Price
1714    #[serde(
1715        rename = "@transferPrice",
1716        default,
1717        deserialize_with = "deserialize_optional_decimal"
1718    )]
1719    pub transfer_price: Option<Decimal>,
1720
1721    /// Position amount
1722    #[serde(
1723        rename = "@positionAmount",
1724        default,
1725        deserialize_with = "deserialize_optional_decimal"
1726    )]
1727    pub position_amount: Option<Decimal>,
1728
1729    /// Position amount in base
1730    #[serde(
1731        rename = "@positionAmountInBase",
1732        default,
1733        deserialize_with = "deserialize_optional_decimal"
1734    )]
1735    pub position_amount_in_base: Option<Decimal>,
1736
1737    /// Cash transfer
1738    #[serde(
1739        rename = "@cashTransfer",
1740        default,
1741        deserialize_with = "deserialize_optional_decimal"
1742    )]
1743    pub cash_transfer: Option<Decimal>,
1744
1745    /// Currency
1746    #[serde(rename = "@currency", default)]
1747    pub currency: Option<String>,
1748
1749    /// FX rate to base
1750    #[serde(
1751        rename = "@fxRateToBase",
1752        default,
1753        deserialize_with = "deserialize_optional_decimal"
1754    )]
1755    pub fx_rate_to_base: Option<Decimal>,
1756
1757    /// Direction
1758    #[serde(rename = "@direction", default)]
1759    pub direction: Option<String>,
1760
1761    /// Date
1762    #[serde(rename = "@date", deserialize_with = "deserialize_flex_date")]
1763    pub date: NaiveDate,
1764
1765    /// Payer/payee account
1766    #[serde(rename = "@ppiPayerPayeeAccount", default)]
1767    pub ppi_payer_payee_account: Option<String>,
1768
1769    /// Delivering/receiving broker
1770    #[serde(rename = "@deliveringReceivingBroker", default)]
1771    pub delivering_receiving_broker: Option<String>,
1772
1773    // Options fields
1774    /// Strike
1775    #[serde(
1776        rename = "@strike",
1777        default,
1778        deserialize_with = "deserialize_optional_decimal"
1779    )]
1780    pub strike: Option<Decimal>,
1781
1782    /// Expiry
1783    #[serde(
1784        rename = "@expiry",
1785        default,
1786        deserialize_with = "deserialize_optional_date"
1787    )]
1788    pub expiry: Option<NaiveDate>,
1789
1790    /// Put/Call
1791    #[serde(rename = "@putCall", default)]
1792    pub put_call: Option<String>,
1793
1794    /// Multiplier
1795    #[serde(
1796        rename = "@multiplier",
1797        default,
1798        deserialize_with = "deserialize_optional_decimal"
1799    )]
1800    pub multiplier: Option<Decimal>,
1801}
1802
1803// =============================================================================
1804// Performance Summary Types
1805// =============================================================================
1806
1807/// Mark-to-market performance summary by underlying security
1808///
1809/// Provides MTM performance metrics for each security in the portfolio,
1810/// including realized and unrealized P&L, commissions, and transaction MTM.
1811#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
1812pub struct MTMPerformanceSummaryUnderlying {
1813    /// Account ID
1814    #[serde(rename = "@accountId")]
1815    pub account_id: String,
1816
1817    /// Account alias
1818    #[serde(rename = "@acctAlias", default)]
1819    pub acct_alias: Option<String>,
1820
1821    /// Model
1822    #[serde(rename = "@model", default)]
1823    pub model: Option<String>,
1824
1825    /// Report date
1826    #[serde(
1827        rename = "@reportDate",
1828        default,
1829        deserialize_with = "deserialize_optional_date"
1830    )]
1831    pub report_date: Option<NaiveDate>,
1832
1833    /// Symbol
1834    #[serde(rename = "@symbol", default)]
1835    pub symbol: Option<String>,
1836
1837    /// Description
1838    #[serde(rename = "@description", default)]
1839    pub description: Option<String>,
1840
1841    /// Contract ID
1842    #[serde(rename = "@conid", default)]
1843    pub conid: Option<String>,
1844
1845    /// Asset category
1846    #[serde(rename = "@assetCategory", default)]
1847    pub asset_category: Option<AssetCategory>,
1848
1849    // Security identifiers
1850    /// CUSIP
1851    #[serde(rename = "@cusip", default)]
1852    pub cusip: Option<String>,
1853
1854    /// ISIN
1855    #[serde(rename = "@isin", default)]
1856    pub isin: Option<String>,
1857
1858    /// Listing exchange
1859    #[serde(rename = "@listingExchange", default)]
1860    pub listing_exchange: Option<String>,
1861
1862    /// Underlying symbol
1863    #[serde(rename = "@underlyingSymbol", default)]
1864    pub underlying_symbol: Option<String>,
1865
1866    /// Underlying contract ID
1867    #[serde(rename = "@underlyingConid", default)]
1868    pub underlying_conid: Option<String>,
1869
1870    /// Underlying listing exchange
1871    #[serde(rename = "@underlyingListingExchange", default)]
1872    pub underlying_listing_exchange: Option<String>,
1873
1874    // P&L fields
1875    /// Cost adjustment
1876    #[serde(
1877        rename = "@costAdj",
1878        default,
1879        deserialize_with = "deserialize_optional_decimal"
1880    )]
1881    pub cost_adj: Option<Decimal>,
1882
1883    /// Realized short-term profit
1884    #[serde(
1885        rename = "@realizedSTProfit",
1886        default,
1887        deserialize_with = "deserialize_optional_decimal"
1888    )]
1889    pub realized_st_profit: Option<Decimal>,
1890
1891    /// Realized short-term loss
1892    #[serde(
1893        rename = "@realizedSTLoss",
1894        default,
1895        deserialize_with = "deserialize_optional_decimal"
1896    )]
1897    pub realized_st_loss: Option<Decimal>,
1898
1899    /// Realized long-term profit
1900    #[serde(
1901        rename = "@realizedLTProfit",
1902        default,
1903        deserialize_with = "deserialize_optional_decimal"
1904    )]
1905    pub realized_lt_profit: Option<Decimal>,
1906
1907    /// Realized long-term loss
1908    #[serde(
1909        rename = "@realizedLTLoss",
1910        default,
1911        deserialize_with = "deserialize_optional_decimal"
1912    )]
1913    pub realized_lt_loss: Option<Decimal>,
1914
1915    /// Unrealized short-term profit
1916    #[serde(
1917        rename = "@unrealizedSTProfit",
1918        default,
1919        deserialize_with = "deserialize_optional_decimal"
1920    )]
1921    pub unrealized_st_profit: Option<Decimal>,
1922
1923    /// Unrealized short-term loss
1924    #[serde(
1925        rename = "@unrealizedSTLoss",
1926        default,
1927        deserialize_with = "deserialize_optional_decimal"
1928    )]
1929    pub unrealized_st_loss: Option<Decimal>,
1930
1931    /// Unrealized long-term profit
1932    #[serde(
1933        rename = "@unrealizedLTProfit",
1934        default,
1935        deserialize_with = "deserialize_optional_decimal"
1936    )]
1937    pub unrealized_lt_profit: Option<Decimal>,
1938
1939    /// Unrealized long-term loss
1940    #[serde(
1941        rename = "@unrealizedLTLoss",
1942        default,
1943        deserialize_with = "deserialize_optional_decimal"
1944    )]
1945    pub unrealized_lt_loss: Option<Decimal>,
1946
1947    /// Transaction MTM
1948    #[serde(
1949        rename = "@transactionMtm",
1950        default,
1951        deserialize_with = "deserialize_optional_decimal"
1952    )]
1953    pub transaction_mtm: Option<Decimal>,
1954
1955    /// Commissions
1956    #[serde(
1957        rename = "@commissions",
1958        default,
1959        deserialize_with = "deserialize_optional_decimal"
1960    )]
1961    pub commissions: Option<Decimal>,
1962
1963    /// Other fees
1964    #[serde(
1965        rename = "@other",
1966        default,
1967        deserialize_with = "deserialize_optional_decimal"
1968    )]
1969    pub other: Option<Decimal>,
1970
1971    /// Level of detail
1972    #[serde(rename = "@levelOfDetail", default)]
1973    pub level_of_detail: Option<String>,
1974}
1975
1976/// FIFO performance summary by underlying security
1977///
1978/// Provides FIFO-based performance metrics including realized and unrealized
1979/// P&L calculated using FIFO cost basis method.
1980#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
1981pub struct FIFOPerformanceSummaryUnderlying {
1982    /// Account ID
1983    #[serde(rename = "@accountId")]
1984    pub account_id: String,
1985
1986    /// Account alias
1987    #[serde(rename = "@acctAlias", default)]
1988    pub acct_alias: Option<String>,
1989
1990    /// Model
1991    #[serde(rename = "@model", default)]
1992    pub model: Option<String>,
1993
1994    /// Report date
1995    #[serde(
1996        rename = "@reportDate",
1997        default,
1998        deserialize_with = "deserialize_optional_date"
1999    )]
2000    pub report_date: Option<NaiveDate>,
2001
2002    /// Symbol
2003    #[serde(rename = "@symbol", default)]
2004    pub symbol: Option<String>,
2005
2006    /// Description
2007    #[serde(rename = "@description", default)]
2008    pub description: Option<String>,
2009
2010    /// Contract ID
2011    #[serde(rename = "@conid", default)]
2012    pub conid: Option<String>,
2013
2014    /// Asset category
2015    #[serde(rename = "@assetCategory", default)]
2016    pub asset_category: Option<AssetCategory>,
2017
2018    // Security identifiers
2019    /// CUSIP
2020    #[serde(rename = "@cusip", default)]
2021    pub cusip: Option<String>,
2022
2023    /// ISIN
2024    #[serde(rename = "@isin", default)]
2025    pub isin: Option<String>,
2026
2027    /// Listing exchange
2028    #[serde(rename = "@listingExchange", default)]
2029    pub listing_exchange: Option<String>,
2030
2031    /// Underlying symbol
2032    #[serde(rename = "@underlyingSymbol", default)]
2033    pub underlying_symbol: Option<String>,
2034
2035    /// Underlying contract ID
2036    #[serde(rename = "@underlyingConid", default)]
2037    pub underlying_conid: Option<String>,
2038
2039    // P&L fields
2040    /// Realized short-term P&L
2041    #[serde(
2042        rename = "@realizedShortTermPnl",
2043        default,
2044        deserialize_with = "deserialize_optional_decimal"
2045    )]
2046    pub realized_short_term_pnl: Option<Decimal>,
2047
2048    /// Realized long-term P&L
2049    #[serde(
2050        rename = "@realizedLongTermPnl",
2051        default,
2052        deserialize_with = "deserialize_optional_decimal"
2053    )]
2054    pub realized_long_term_pnl: Option<Decimal>,
2055
2056    /// Realized total P&L
2057    #[serde(
2058        rename = "@realizedTotalPnl",
2059        default,
2060        deserialize_with = "deserialize_optional_decimal"
2061    )]
2062    pub realized_total_pnl: Option<Decimal>,
2063
2064    /// Unrealized short-term P&L
2065    #[serde(
2066        rename = "@unrealizedShortTermPnl",
2067        default,
2068        deserialize_with = "deserialize_optional_decimal"
2069    )]
2070    pub unrealized_short_term_pnl: Option<Decimal>,
2071
2072    /// Unrealized long-term P&L
2073    #[serde(
2074        rename = "@unrealizedLongTermPnl",
2075        default,
2076        deserialize_with = "deserialize_optional_decimal"
2077    )]
2078    pub unrealized_long_term_pnl: Option<Decimal>,
2079
2080    /// Unrealized total P&L
2081    #[serde(
2082        rename = "@unrealizedTotalPnl",
2083        default,
2084        deserialize_with = "deserialize_optional_decimal"
2085    )]
2086    pub unrealized_total_pnl: Option<Decimal>,
2087
2088    /// Total income
2089    #[serde(
2090        rename = "@totalIncome",
2091        default,
2092        deserialize_with = "deserialize_optional_decimal"
2093    )]
2094    pub total_income: Option<Decimal>,
2095
2096    /// Level of detail
2097    #[serde(rename = "@levelOfDetail", default)]
2098    pub level_of_detail: Option<String>,
2099}
2100
2101/// Month-to-date/Year-to-date performance summary
2102#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
2103pub struct MTDYTDPerformanceSummary {
2104    /// Account ID
2105    #[serde(rename = "@accountId")]
2106    pub account_id: String,
2107
2108    /// Account alias
2109    #[serde(rename = "@acctAlias", default)]
2110    pub acct_alias: Option<String>,
2111
2112    /// Model
2113    #[serde(rename = "@model", default)]
2114    pub model: Option<String>,
2115
2116    /// Symbol
2117    #[serde(rename = "@symbol", default)]
2118    pub symbol: Option<String>,
2119
2120    /// Contract ID
2121    #[serde(rename = "@conid", default)]
2122    pub conid: Option<String>,
2123
2124    /// Asset category
2125    #[serde(rename = "@assetCategory", default)]
2126    pub asset_category: Option<AssetCategory>,
2127
2128    // MTD fields
2129    /// MTD realized P&L
2130    #[serde(
2131        rename = "@mtdRealizedPnl",
2132        default,
2133        deserialize_with = "deserialize_optional_decimal"
2134    )]
2135    pub mtd_realized_pnl: Option<Decimal>,
2136
2137    /// MTD unrealized P&L
2138    #[serde(
2139        rename = "@mtdUnrealizedPnl",
2140        default,
2141        deserialize_with = "deserialize_optional_decimal"
2142    )]
2143    pub mtd_unrealized_pnl: Option<Decimal>,
2144
2145    /// MTD commissions
2146    #[serde(
2147        rename = "@mtdCommissions",
2148        default,
2149        deserialize_with = "deserialize_optional_decimal"
2150    )]
2151    pub mtd_commissions: Option<Decimal>,
2152
2153    /// MTD fees
2154    #[serde(
2155        rename = "@mtdFees",
2156        default,
2157        deserialize_with = "deserialize_optional_decimal"
2158    )]
2159    pub mtd_fees: Option<Decimal>,
2160
2161    // YTD fields
2162    /// YTD realized P&L
2163    #[serde(
2164        rename = "@ytdRealizedPnl",
2165        default,
2166        deserialize_with = "deserialize_optional_decimal"
2167    )]
2168    pub ytd_realized_pnl: Option<Decimal>,
2169
2170    /// YTD unrealized P&L
2171    #[serde(
2172        rename = "@ytdUnrealizedPnl",
2173        default,
2174        deserialize_with = "deserialize_optional_decimal"
2175    )]
2176    pub ytd_unrealized_pnl: Option<Decimal>,
2177
2178    /// YTD commissions
2179    #[serde(
2180        rename = "@ytdCommissions",
2181        default,
2182        deserialize_with = "deserialize_optional_decimal"
2183    )]
2184    pub ytd_commissions: Option<Decimal>,
2185
2186    /// YTD fees
2187    #[serde(
2188        rename = "@ytdFees",
2189        default,
2190        deserialize_with = "deserialize_optional_decimal"
2191    )]
2192    pub ytd_fees: Option<Decimal>,
2193
2194    /// Level of detail
2195    #[serde(rename = "@levelOfDetail", default)]
2196    pub level_of_detail: Option<String>,
2197}
2198
2199// =============================================================================
2200// Statement of Funds Types
2201// =============================================================================
2202
2203/// Statement of funds line item
2204///
2205/// Represents a single cash flow entry in the statement of funds,
2206/// tracking debits and credits with running balance.
2207#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
2208pub struct StatementOfFundsLine {
2209    /// Account ID
2210    #[serde(rename = "@accountId")]
2211    pub account_id: String,
2212
2213    /// Account alias
2214    #[serde(rename = "@acctAlias", default)]
2215    pub acct_alias: Option<String>,
2216
2217    /// Model
2218    #[serde(rename = "@model", default)]
2219    pub model: Option<String>,
2220
2221    /// Report date
2222    #[serde(
2223        rename = "@reportDate",
2224        default,
2225        deserialize_with = "deserialize_optional_date"
2226    )]
2227    pub report_date: Option<NaiveDate>,
2228
2229    /// Date
2230    #[serde(
2231        rename = "@date",
2232        default,
2233        deserialize_with = "deserialize_optional_date"
2234    )]
2235    pub date: Option<NaiveDate>,
2236
2237    /// Currency
2238    #[serde(rename = "@currency", default)]
2239    pub currency: Option<String>,
2240
2241    /// Activity code
2242    #[serde(rename = "@activityCode", default)]
2243    pub activity_code: Option<String>,
2244
2245    /// Activity description
2246    #[serde(rename = "@activityDescription", default)]
2247    pub activity_description: Option<String>,
2248
2249    /// Trade ID
2250    #[serde(rename = "@tradeID", default)]
2251    pub trade_id: Option<String>,
2252
2253    /// Symbol
2254    #[serde(rename = "@symbol", default)]
2255    pub symbol: Option<String>,
2256
2257    /// Contract ID
2258    #[serde(rename = "@conid", default)]
2259    pub conid: Option<String>,
2260
2261    /// Debit amount
2262    #[serde(
2263        rename = "@debit",
2264        default,
2265        deserialize_with = "deserialize_optional_decimal"
2266    )]
2267    pub debit: Option<Decimal>,
2268
2269    /// Credit amount
2270    #[serde(
2271        rename = "@credit",
2272        default,
2273        deserialize_with = "deserialize_optional_decimal"
2274    )]
2275    pub credit: Option<Decimal>,
2276
2277    /// Amount
2278    #[serde(
2279        rename = "@amount",
2280        default,
2281        deserialize_with = "deserialize_optional_decimal"
2282    )]
2283    pub amount: Option<Decimal>,
2284
2285    /// Balance
2286    #[serde(
2287        rename = "@balance",
2288        default,
2289        deserialize_with = "deserialize_optional_decimal"
2290    )]
2291    pub balance: Option<Decimal>,
2292
2293    /// FX rate to base
2294    #[serde(
2295        rename = "@fxRateToBase",
2296        default,
2297        deserialize_with = "deserialize_optional_decimal"
2298    )]
2299    pub fx_rate_to_base: Option<Decimal>,
2300
2301    /// Level of detail
2302    #[serde(rename = "@levelOfDetail", default)]
2303    pub level_of_detail: Option<String>,
2304}
2305
2306// =============================================================================
2307// Position Value Change Types
2308// =============================================================================
2309
2310/// Change in position value for reconciliation
2311///
2312/// Tracks how position values changed due to various factors like
2313/// transactions, MTM changes, corporate actions, and FX translation.
2314#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
2315pub struct ChangeInPositionValue {
2316    /// Account ID
2317    #[serde(rename = "@accountId")]
2318    pub account_id: String,
2319
2320    /// Account alias
2321    #[serde(rename = "@acctAlias", default)]
2322    pub acct_alias: Option<String>,
2323
2324    /// Model
2325    #[serde(rename = "@model", default)]
2326    pub model: Option<String>,
2327
2328    /// Report date
2329    #[serde(
2330        rename = "@reportDate",
2331        default,
2332        deserialize_with = "deserialize_optional_date"
2333    )]
2334    pub report_date: Option<NaiveDate>,
2335
2336    /// Symbol
2337    #[serde(rename = "@symbol", default)]
2338    pub symbol: Option<String>,
2339
2340    /// Contract ID
2341    #[serde(rename = "@conid", default)]
2342    pub conid: Option<String>,
2343
2344    /// Asset category
2345    #[serde(rename = "@assetCategory", default)]
2346    pub asset_category: Option<AssetCategory>,
2347
2348    /// Currency
2349    #[serde(rename = "@currency", default)]
2350    pub currency: Option<String>,
2351
2352    /// Prior period value
2353    #[serde(
2354        rename = "@priorPeriodValue",
2355        default,
2356        deserialize_with = "deserialize_optional_decimal"
2357    )]
2358    pub prior_period_value: Option<Decimal>,
2359
2360    /// Transactions
2361    #[serde(
2362        rename = "@transactions",
2363        default,
2364        deserialize_with = "deserialize_optional_decimal"
2365    )]
2366    pub transactions: Option<Decimal>,
2367
2368    /// MTM prior period positions
2369    #[serde(
2370        rename = "@mtmPriorPeriodPositions",
2371        default,
2372        deserialize_with = "deserialize_optional_decimal"
2373    )]
2374    pub mtm_prior_period_positions: Option<Decimal>,
2375
2376    /// MTM transactions
2377    #[serde(
2378        rename = "@mtmTransactions",
2379        default,
2380        deserialize_with = "deserialize_optional_decimal"
2381    )]
2382    pub mtm_transactions: Option<Decimal>,
2383
2384    /// Corporate actions
2385    #[serde(
2386        rename = "@corporateActions",
2387        default,
2388        deserialize_with = "deserialize_optional_decimal"
2389    )]
2390    pub corporate_actions: Option<Decimal>,
2391
2392    /// FX translation
2393    #[serde(
2394        rename = "@fxTranslation",
2395        default,
2396        deserialize_with = "deserialize_optional_decimal"
2397    )]
2398    pub fx_translation: Option<Decimal>,
2399
2400    /// Other
2401    #[serde(
2402        rename = "@other",
2403        default,
2404        deserialize_with = "deserialize_optional_decimal"
2405    )]
2406    pub other: Option<Decimal>,
2407
2408    /// Ending value
2409    #[serde(
2410        rename = "@endingValue",
2411        default,
2412        deserialize_with = "deserialize_optional_decimal"
2413    )]
2414    pub ending_value: Option<Decimal>,
2415
2416    /// Level of detail
2417    #[serde(rename = "@levelOfDetail", default)]
2418    pub level_of_detail: Option<String>,
2419}
2420
2421// =============================================================================
2422// Fee Detail Types
2423// =============================================================================
2424
2425/// Unbundled commission detail
2426///
2427/// Breaks down commission charges into components: execution, clearing,
2428/// regulatory, third-party, and exchange fees.
2429#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
2430pub struct UnbundledCommissionDetail {
2431    /// Account ID
2432    #[serde(rename = "@accountId")]
2433    pub account_id: String,
2434
2435    /// Account alias
2436    #[serde(rename = "@acctAlias", default)]
2437    pub acct_alias: Option<String>,
2438
2439    /// Model
2440    #[serde(rename = "@model", default)]
2441    pub model: Option<String>,
2442
2443    /// Symbol
2444    #[serde(rename = "@symbol", default)]
2445    pub symbol: Option<String>,
2446
2447    /// Description
2448    #[serde(rename = "@description", default)]
2449    pub description: Option<String>,
2450
2451    /// Contract ID
2452    #[serde(rename = "@conid", default)]
2453    pub conid: Option<String>,
2454
2455    /// Asset category
2456    #[serde(rename = "@assetCategory", default)]
2457    pub asset_category: Option<AssetCategory>,
2458
2459    /// Execution ID
2460    #[serde(rename = "@execID", default)]
2461    pub exec_id: Option<String>,
2462
2463    /// Order ID
2464    #[serde(rename = "@orderID", default)]
2465    pub order_id: Option<String>,
2466
2467    /// Trade ID
2468    #[serde(rename = "@tradeID", default)]
2469    pub trade_id: Option<String>,
2470
2471    /// Trade date/time (format: YYYYMMDD;HHMMSS)
2472    #[serde(rename = "@dateTime", default)]
2473    pub date_time: Option<String>,
2474
2475    /// Exchange
2476    #[serde(rename = "@exchange", default)]
2477    pub exchange: Option<String>,
2478
2479    /// Quantity
2480    #[serde(
2481        rename = "@quantity",
2482        default,
2483        deserialize_with = "deserialize_optional_decimal"
2484    )]
2485    pub quantity: Option<Decimal>,
2486
2487    /// Price
2488    #[serde(
2489        rename = "@price",
2490        default,
2491        deserialize_with = "deserialize_optional_decimal"
2492    )]
2493    pub price: Option<Decimal>,
2494
2495    /// Execution commission
2496    #[serde(
2497        rename = "@executionCommission",
2498        default,
2499        deserialize_with = "deserialize_optional_decimal"
2500    )]
2501    pub execution_commission: Option<Decimal>,
2502
2503    /// Clearing commission
2504    #[serde(
2505        rename = "@clearingCommission",
2506        default,
2507        deserialize_with = "deserialize_optional_decimal"
2508    )]
2509    pub clearing_commission: Option<Decimal>,
2510
2511    /// Regulatory commission
2512    #[serde(
2513        rename = "@regulatoryCommission",
2514        default,
2515        deserialize_with = "deserialize_optional_decimal"
2516    )]
2517    pub regulatory_commission: Option<Decimal>,
2518
2519    /// Third party commission
2520    #[serde(
2521        rename = "@thirdPartyCommission",
2522        default,
2523        deserialize_with = "deserialize_optional_decimal"
2524    )]
2525    pub third_party_commission: Option<Decimal>,
2526
2527    /// Third party regulatory commission
2528    #[serde(
2529        rename = "@thirdPartyRegulatoryCommission",
2530        default,
2531        deserialize_with = "deserialize_optional_decimal"
2532    )]
2533    pub third_party_regulatory_commission: Option<Decimal>,
2534
2535    /// Total commission
2536    #[serde(
2537        rename = "@totalCommission",
2538        default,
2539        deserialize_with = "deserialize_optional_decimal"
2540    )]
2541    pub total_commission: Option<Decimal>,
2542
2543    /// Currency
2544    #[serde(rename = "@currency", default)]
2545    pub currency: Option<String>,
2546}
2547
2548/// Client fee (advisory/service fees)
2549#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
2550pub struct ClientFee {
2551    /// Account ID
2552    #[serde(rename = "@accountId")]
2553    pub account_id: String,
2554
2555    /// Account alias
2556    #[serde(rename = "@acctAlias", default)]
2557    pub acct_alias: Option<String>,
2558
2559    /// Model
2560    #[serde(rename = "@model", default)]
2561    pub model: Option<String>,
2562
2563    /// Date
2564    #[serde(
2565        rename = "@date",
2566        default,
2567        deserialize_with = "deserialize_optional_date"
2568    )]
2569    pub date: Option<NaiveDate>,
2570
2571    /// Currency
2572    #[serde(rename = "@currency", default)]
2573    pub currency: Option<String>,
2574
2575    /// Revenue
2576    #[serde(
2577        rename = "@revenue",
2578        default,
2579        deserialize_with = "deserialize_optional_decimal"
2580    )]
2581    pub revenue: Option<Decimal>,
2582
2583    /// Expense
2584    #[serde(
2585        rename = "@expense",
2586        default,
2587        deserialize_with = "deserialize_optional_decimal"
2588    )]
2589    pub expense: Option<Decimal>,
2590
2591    /// Net
2592    #[serde(
2593        rename = "@net",
2594        default,
2595        deserialize_with = "deserialize_optional_decimal"
2596    )]
2597    pub net: Option<Decimal>,
2598
2599    /// Description
2600    #[serde(rename = "@description", default)]
2601    pub description: Option<String>,
2602}
2603
2604/// Client fee detail
2605#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
2606pub struct ClientFeesDetail {
2607    /// Account ID
2608    #[serde(rename = "@accountId")]
2609    pub account_id: String,
2610
2611    /// Account alias
2612    #[serde(rename = "@acctAlias", default)]
2613    pub acct_alias: Option<String>,
2614
2615    /// Model
2616    #[serde(rename = "@model", default)]
2617    pub model: Option<String>,
2618
2619    /// Date
2620    #[serde(
2621        rename = "@date",
2622        default,
2623        deserialize_with = "deserialize_optional_date"
2624    )]
2625    pub date: Option<NaiveDate>,
2626
2627    /// Currency
2628    #[serde(rename = "@currency", default)]
2629    pub currency: Option<String>,
2630
2631    /// Fee type
2632    #[serde(rename = "@feeType", default)]
2633    pub fee_type: Option<String>,
2634
2635    /// Revenue
2636    #[serde(
2637        rename = "@revenue",
2638        default,
2639        deserialize_with = "deserialize_optional_decimal"
2640    )]
2641    pub revenue: Option<Decimal>,
2642
2643    /// Expense
2644    #[serde(
2645        rename = "@expense",
2646        default,
2647        deserialize_with = "deserialize_optional_decimal"
2648    )]
2649    pub expense: Option<Decimal>,
2650
2651    /// Net
2652    #[serde(
2653        rename = "@net",
2654        default,
2655        deserialize_with = "deserialize_optional_decimal"
2656    )]
2657    pub net: Option<Decimal>,
2658
2659    /// Description
2660    #[serde(rename = "@description", default)]
2661    pub description: Option<String>,
2662
2663    /// FX rate to base
2664    #[serde(
2665        rename = "@fxRateToBase",
2666        default,
2667        deserialize_with = "deserialize_optional_decimal"
2668    )]
2669    pub fx_rate_to_base: Option<Decimal>,
2670}
2671
2672// =============================================================================
2673// Securities Lending Types
2674// =============================================================================
2675
2676/// Securities lending/borrowing activity
2677#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
2678pub struct SLBActivity {
2679    /// Account ID
2680    #[serde(rename = "@accountId")]
2681    pub account_id: String,
2682
2683    /// Account alias
2684    #[serde(rename = "@acctAlias", default)]
2685    pub acct_alias: Option<String>,
2686
2687    /// Model
2688    #[serde(rename = "@model", default)]
2689    pub model: Option<String>,
2690
2691    /// Symbol
2692    #[serde(rename = "@symbol", default)]
2693    pub symbol: Option<String>,
2694
2695    /// Description
2696    #[serde(rename = "@description", default)]
2697    pub description: Option<String>,
2698
2699    /// Contract ID
2700    #[serde(rename = "@conid", default)]
2701    pub conid: Option<String>,
2702
2703    /// Asset category
2704    #[serde(rename = "@assetCategory", default)]
2705    pub asset_category: Option<AssetCategory>,
2706
2707    /// Activity date
2708    #[serde(
2709        rename = "@date",
2710        default,
2711        deserialize_with = "deserialize_optional_date"
2712    )]
2713    pub date: Option<NaiveDate>,
2714
2715    /// Activity type
2716    #[serde(rename = "@type", default)]
2717    pub activity_type: Option<String>,
2718
2719    /// Quantity
2720    #[serde(
2721        rename = "@quantity",
2722        default,
2723        deserialize_with = "deserialize_optional_decimal"
2724    )]
2725    pub quantity: Option<Decimal>,
2726
2727    /// Collateral amount
2728    #[serde(
2729        rename = "@collateralAmount",
2730        default,
2731        deserialize_with = "deserialize_optional_decimal"
2732    )]
2733    pub collateral_amount: Option<Decimal>,
2734
2735    /// Fee/rate
2736    #[serde(
2737        rename = "@feeRate",
2738        default,
2739        deserialize_with = "deserialize_optional_decimal"
2740    )]
2741    pub fee_rate: Option<Decimal>,
2742
2743    /// Net lend fee
2744    #[serde(
2745        rename = "@netLendFee",
2746        default,
2747        deserialize_with = "deserialize_optional_decimal"
2748    )]
2749    pub net_lend_fee: Option<Decimal>,
2750
2751    /// Currency
2752    #[serde(rename = "@currency", default)]
2753    pub currency: Option<String>,
2754
2755    /// FX rate to base
2756    #[serde(
2757        rename = "@fxRateToBase",
2758        default,
2759        deserialize_with = "deserialize_optional_decimal"
2760    )]
2761    pub fx_rate_to_base: Option<Decimal>,
2762}
2763
2764/// Securities lending fee
2765#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
2766pub struct SLBFee {
2767    /// Account ID
2768    #[serde(rename = "@accountId")]
2769    pub account_id: String,
2770
2771    /// Account alias
2772    #[serde(rename = "@acctAlias", default)]
2773    pub acct_alias: Option<String>,
2774
2775    /// Model
2776    #[serde(rename = "@model", default)]
2777    pub model: Option<String>,
2778
2779    /// Symbol
2780    #[serde(rename = "@symbol", default)]
2781    pub symbol: Option<String>,
2782
2783    /// Description
2784    #[serde(rename = "@description", default)]
2785    pub description: Option<String>,
2786
2787    /// Contract ID
2788    #[serde(rename = "@conid", default)]
2789    pub conid: Option<String>,
2790
2791    /// Asset category
2792    #[serde(rename = "@assetCategory", default)]
2793    pub asset_category: Option<AssetCategory>,
2794
2795    /// Value date
2796    #[serde(
2797        rename = "@valueDate",
2798        default,
2799        deserialize_with = "deserialize_optional_date"
2800    )]
2801    pub value_date: Option<NaiveDate>,
2802
2803    /// Start date
2804    #[serde(
2805        rename = "@startDate",
2806        default,
2807        deserialize_with = "deserialize_optional_date"
2808    )]
2809    pub start_date: Option<NaiveDate>,
2810
2811    /// Quantity
2812    #[serde(
2813        rename = "@quantity",
2814        default,
2815        deserialize_with = "deserialize_optional_decimal"
2816    )]
2817    pub quantity: Option<Decimal>,
2818
2819    /// Collateral amount
2820    #[serde(
2821        rename = "@collateralAmount",
2822        default,
2823        deserialize_with = "deserialize_optional_decimal"
2824    )]
2825    pub collateral_amount: Option<Decimal>,
2826
2827    /// Fee rate
2828    #[serde(
2829        rename = "@feeRate",
2830        default,
2831        deserialize_with = "deserialize_optional_decimal"
2832    )]
2833    pub fee_rate: Option<Decimal>,
2834
2835    /// Fee
2836    #[serde(
2837        rename = "@fee",
2838        default,
2839        deserialize_with = "deserialize_optional_decimal"
2840    )]
2841    pub fee: Option<Decimal>,
2842
2843    /// Carry charge
2844    #[serde(
2845        rename = "@carryCharge",
2846        default,
2847        deserialize_with = "deserialize_optional_decimal"
2848    )]
2849    pub carry_charge: Option<Decimal>,
2850
2851    /// Currency
2852    #[serde(rename = "@currency", default)]
2853    pub currency: Option<String>,
2854
2855    /// FX rate to base
2856    #[serde(
2857        rename = "@fxRateToBase",
2858        default,
2859        deserialize_with = "deserialize_optional_decimal"
2860    )]
2861    pub fx_rate_to_base: Option<Decimal>,
2862}
2863
2864/// Hard to borrow stock details
2865#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
2866pub struct HardToBorrowDetail {
2867    /// Account ID
2868    #[serde(rename = "@accountId")]
2869    pub account_id: String,
2870
2871    /// Account alias
2872    #[serde(rename = "@acctAlias", default)]
2873    pub acct_alias: Option<String>,
2874
2875    /// Model
2876    #[serde(rename = "@model", default)]
2877    pub model: Option<String>,
2878
2879    /// Symbol
2880    #[serde(rename = "@symbol", default)]
2881    pub symbol: Option<String>,
2882
2883    /// Description
2884    #[serde(rename = "@description", default)]
2885    pub description: Option<String>,
2886
2887    /// Contract ID
2888    #[serde(rename = "@conid", default)]
2889    pub conid: Option<String>,
2890
2891    /// Asset category
2892    #[serde(rename = "@assetCategory", default)]
2893    pub asset_category: Option<AssetCategory>,
2894
2895    /// Value date
2896    #[serde(
2897        rename = "@valueDate",
2898        default,
2899        deserialize_with = "deserialize_optional_date"
2900    )]
2901    pub value_date: Option<NaiveDate>,
2902
2903    /// Quantity
2904    #[serde(
2905        rename = "@quantity",
2906        default,
2907        deserialize_with = "deserialize_optional_decimal"
2908    )]
2909    pub quantity: Option<Decimal>,
2910
2911    /// Price
2912    #[serde(
2913        rename = "@price",
2914        default,
2915        deserialize_with = "deserialize_optional_decimal"
2916    )]
2917    pub price: Option<Decimal>,
2918
2919    /// Value
2920    #[serde(
2921        rename = "@value",
2922        default,
2923        deserialize_with = "deserialize_optional_decimal"
2924    )]
2925    pub value: Option<Decimal>,
2926
2927    /// Borrow fee rate
2928    #[serde(
2929        rename = "@borrowFeeRate",
2930        default,
2931        deserialize_with = "deserialize_optional_decimal"
2932    )]
2933    pub borrow_fee_rate: Option<Decimal>,
2934
2935    /// Borrow fee
2936    #[serde(
2937        rename = "@borrowFee",
2938        default,
2939        deserialize_with = "deserialize_optional_decimal"
2940    )]
2941    pub borrow_fee: Option<Decimal>,
2942
2943    /// Currency
2944    #[serde(rename = "@currency", default)]
2945    pub currency: Option<String>,
2946
2947    /// FX rate to base
2948    #[serde(
2949        rename = "@fxRateToBase",
2950        default,
2951        deserialize_with = "deserialize_optional_decimal"
2952    )]
2953    pub fx_rate_to_base: Option<Decimal>,
2954}
2955
2956// =============================================================================
2957// FX Lot Types
2958// =============================================================================
2959
2960/// FX position lot detail
2961#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
2962pub struct FxLot {
2963    /// Account ID
2964    #[serde(rename = "@accountId")]
2965    pub account_id: String,
2966
2967    /// Account alias
2968    #[serde(rename = "@acctAlias", default)]
2969    pub acct_alias: Option<String>,
2970
2971    /// Model
2972    #[serde(rename = "@model", default)]
2973    pub model: Option<String>,
2974
2975    /// Asset category
2976    #[serde(rename = "@assetCategory", default)]
2977    pub asset_category: Option<String>,
2978
2979    /// Report date
2980    #[serde(
2981        rename = "@reportDate",
2982        default,
2983        deserialize_with = "deserialize_optional_date"
2984    )]
2985    pub report_date: Option<NaiveDate>,
2986
2987    /// Functional currency
2988    #[serde(rename = "@functionalCurrency", default)]
2989    pub functional_currency: Option<String>,
2990
2991    /// FX currency
2992    #[serde(rename = "@fxCurrency", default)]
2993    pub fx_currency: Option<String>,
2994
2995    /// Quantity
2996    #[serde(
2997        rename = "@quantity",
2998        default,
2999        deserialize_with = "deserialize_optional_decimal"
3000    )]
3001    pub quantity: Option<Decimal>,
3002
3003    /// Cost price
3004    #[serde(
3005        rename = "@costPrice",
3006        default,
3007        deserialize_with = "deserialize_optional_decimal"
3008    )]
3009    pub cost_price: Option<Decimal>,
3010
3011    /// Cost basis
3012    #[serde(
3013        rename = "@costBasis",
3014        default,
3015        deserialize_with = "deserialize_optional_decimal"
3016    )]
3017    pub cost_basis: Option<Decimal>,
3018
3019    /// Close price
3020    #[serde(
3021        rename = "@closePrice",
3022        default,
3023        deserialize_with = "deserialize_optional_decimal"
3024    )]
3025    pub close_price: Option<Decimal>,
3026
3027    /// Value
3028    #[serde(
3029        rename = "@value",
3030        default,
3031        deserialize_with = "deserialize_optional_decimal"
3032    )]
3033    pub value: Option<Decimal>,
3034
3035    /// Unrealized P&L
3036    #[serde(
3037        rename = "@unrealizedPL",
3038        default,
3039        deserialize_with = "deserialize_optional_decimal"
3040    )]
3041    pub unrealized_pl: Option<Decimal>,
3042
3043    /// Level of detail
3044    #[serde(rename = "@levelOfDetail", default)]
3045    pub level_of_detail: Option<String>,
3046}
3047
3048// =============================================================================
3049// Transfer Types
3050// =============================================================================
3051
3052/// Unsettled transfer
3053#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
3054pub struct UnsettledTransfer {
3055    /// Account ID
3056    #[serde(rename = "@accountId")]
3057    pub account_id: String,
3058
3059    /// Account alias
3060    #[serde(rename = "@acctAlias", default)]
3061    pub acct_alias: Option<String>,
3062
3063    /// Model
3064    #[serde(rename = "@model", default)]
3065    pub model: Option<String>,
3066
3067    /// Symbol
3068    #[serde(rename = "@symbol", default)]
3069    pub symbol: Option<String>,
3070
3071    /// Description
3072    #[serde(rename = "@description", default)]
3073    pub description: Option<String>,
3074
3075    /// Contract ID
3076    #[serde(rename = "@conid", default)]
3077    pub conid: Option<String>,
3078
3079    /// Asset category
3080    #[serde(rename = "@assetCategory", default)]
3081    pub asset_category: Option<AssetCategory>,
3082
3083    /// Direction
3084    #[serde(rename = "@direction", default)]
3085    pub direction: Option<String>,
3086
3087    /// Date
3088    #[serde(
3089        rename = "@date",
3090        default,
3091        deserialize_with = "deserialize_optional_date"
3092    )]
3093    pub date: Option<NaiveDate>,
3094
3095    /// Expected date
3096    #[serde(
3097        rename = "@expectedDate",
3098        default,
3099        deserialize_with = "deserialize_optional_date"
3100    )]
3101    pub expected_date: Option<NaiveDate>,
3102
3103    /// Quantity
3104    #[serde(
3105        rename = "@quantity",
3106        default,
3107        deserialize_with = "deserialize_optional_decimal"
3108    )]
3109    pub quantity: Option<Decimal>,
3110
3111    /// Currency
3112    #[serde(rename = "@currency", default)]
3113    pub currency: Option<String>,
3114
3115    /// FX rate to base
3116    #[serde(
3117        rename = "@fxRateToBase",
3118        default,
3119        deserialize_with = "deserialize_optional_decimal"
3120    )]
3121    pub fx_rate_to_base: Option<Decimal>,
3122}
3123
3124/// Trade transfer between accounts/brokers
3125#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
3126pub struct TradeTransfer {
3127    /// Account ID
3128    #[serde(rename = "@accountId")]
3129    pub account_id: String,
3130
3131    /// Account alias
3132    #[serde(rename = "@acctAlias", default)]
3133    pub acct_alias: Option<String>,
3134
3135    /// Model
3136    #[serde(rename = "@model", default)]
3137    pub model: Option<String>,
3138
3139    /// Symbol
3140    #[serde(rename = "@symbol", default)]
3141    pub symbol: Option<String>,
3142
3143    /// Description
3144    #[serde(rename = "@description", default)]
3145    pub description: Option<String>,
3146
3147    /// Contract ID
3148    #[serde(rename = "@conid", default)]
3149    pub conid: Option<String>,
3150
3151    /// Asset category
3152    #[serde(rename = "@assetCategory", default)]
3153    pub asset_category: Option<AssetCategory>,
3154
3155    /// Transfer type
3156    #[serde(rename = "@transferType", default)]
3157    pub transfer_type: Option<String>,
3158
3159    /// Direction
3160    #[serde(rename = "@direction", default)]
3161    pub direction: Option<String>,
3162
3163    /// Delivery type
3164    #[serde(rename = "@deliveryType", default)]
3165    pub delivery_type: Option<String>,
3166
3167    /// Quantity
3168    #[serde(
3169        rename = "@quantity",
3170        default,
3171        deserialize_with = "deserialize_optional_decimal"
3172    )]
3173    pub quantity: Option<Decimal>,
3174
3175    /// Transfer price
3176    #[serde(
3177        rename = "@transferPrice",
3178        default,
3179        deserialize_with = "deserialize_optional_decimal"
3180    )]
3181    pub transfer_price: Option<Decimal>,
3182
3183    /// Date
3184    #[serde(
3185        rename = "@date",
3186        default,
3187        deserialize_with = "deserialize_optional_date"
3188    )]
3189    pub date: Option<NaiveDate>,
3190
3191    /// Executing broker
3192    #[serde(rename = "@executingBroker", default)]
3193    pub executing_broker: Option<String>,
3194
3195    /// Currency
3196    #[serde(rename = "@currency", default)]
3197    pub currency: Option<String>,
3198
3199    /// FX rate to base
3200    #[serde(
3201        rename = "@fxRateToBase",
3202        default,
3203        deserialize_with = "deserialize_optional_decimal"
3204    )]
3205    pub fx_rate_to_base: Option<Decimal>,
3206}
3207
3208// =============================================================================
3209// Prior Period Types
3210// =============================================================================
3211
3212/// Prior period position
3213#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
3214pub struct PriorPeriodPosition {
3215    /// Account ID
3216    #[serde(rename = "@accountId")]
3217    pub account_id: String,
3218
3219    /// Account alias
3220    #[serde(rename = "@acctAlias", default)]
3221    pub acct_alias: Option<String>,
3222
3223    /// Model
3224    #[serde(rename = "@model", default)]
3225    pub model: Option<String>,
3226
3227    /// Symbol
3228    #[serde(rename = "@symbol", default)]
3229    pub symbol: Option<String>,
3230
3231    /// Description
3232    #[serde(rename = "@description", default)]
3233    pub description: Option<String>,
3234
3235    /// Contract ID
3236    #[serde(rename = "@conid", default)]
3237    pub conid: Option<String>,
3238
3239    /// Asset category
3240    #[serde(rename = "@assetCategory", default)]
3241    pub asset_category: Option<AssetCategory>,
3242
3243    /// Prior MTM P&L
3244    #[serde(
3245        rename = "@priorMtmPnl",
3246        default,
3247        deserialize_with = "deserialize_optional_decimal"
3248    )]
3249    pub prior_mtm_pnl: Option<Decimal>,
3250
3251    /// Date
3252    #[serde(
3253        rename = "@date",
3254        default,
3255        deserialize_with = "deserialize_optional_date"
3256    )]
3257    pub date: Option<NaiveDate>,
3258
3259    /// Quantity
3260    #[serde(
3261        rename = "@quantity",
3262        default,
3263        deserialize_with = "deserialize_optional_decimal"
3264    )]
3265    pub quantity: Option<Decimal>,
3266
3267    /// Price
3268    #[serde(
3269        rename = "@price",
3270        default,
3271        deserialize_with = "deserialize_optional_decimal"
3272    )]
3273    pub price: Option<Decimal>,
3274
3275    /// Currency
3276    #[serde(rename = "@currency", default)]
3277    pub currency: Option<String>,
3278}
3279
3280// =============================================================================
3281// Interest Detail Types
3282// =============================================================================
3283
3284/// Tier interest detail
3285#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
3286pub struct TierInterestDetail {
3287    /// Account ID
3288    #[serde(rename = "@accountId")]
3289    pub account_id: String,
3290
3291    /// Account alias
3292    #[serde(rename = "@acctAlias", default)]
3293    pub acct_alias: Option<String>,
3294
3295    /// Model
3296    #[serde(rename = "@model", default)]
3297    pub model: Option<String>,
3298
3299    /// Currency
3300    #[serde(rename = "@currency", default)]
3301    pub currency: Option<String>,
3302
3303    /// FX rate to base currency
3304    #[serde(
3305        rename = "@fxRateToBase",
3306        default,
3307        deserialize_with = "deserialize_optional_decimal"
3308    )]
3309    pub fx_rate_to_base: Option<Decimal>,
3310
3311    /// Interest type (e.g., "Debit Interest", "Short Credit Interest")
3312    #[serde(rename = "@interestType", default)]
3313    pub interest_type: Option<String>,
3314
3315    /// Report date
3316    #[serde(
3317        rename = "@reportDate",
3318        default,
3319        deserialize_with = "deserialize_optional_date"
3320    )]
3321    pub report_date: Option<NaiveDate>,
3322
3323    /// Value date
3324    #[serde(
3325        rename = "@valueDate",
3326        default,
3327        deserialize_with = "deserialize_optional_date"
3328    )]
3329    pub value_date: Option<NaiveDate>,
3330
3331    /// Tier break (Roman numerals like "I", "II", etc.)
3332    #[serde(rename = "@tierBreak", default)]
3333    pub tier_break: Option<String>,
3334
3335    /// Balance threshold
3336    #[serde(
3337        rename = "@balanceThreshold",
3338        default,
3339        deserialize_with = "deserialize_optional_decimal"
3340    )]
3341    pub balance_threshold: Option<Decimal>,
3342
3343    /// Securities principal
3344    #[serde(
3345        rename = "@securitiesPrincipal",
3346        default,
3347        deserialize_with = "deserialize_optional_decimal"
3348    )]
3349    pub securities_principal: Option<Decimal>,
3350
3351    /// Commodities principal
3352    #[serde(
3353        rename = "@commoditiesPrincipal",
3354        default,
3355        deserialize_with = "deserialize_optional_decimal"
3356    )]
3357    pub commodities_principal: Option<Decimal>,
3358
3359    /// IBUKL principal
3360    #[serde(
3361        rename = "@ibuklPrincipal",
3362        default,
3363        deserialize_with = "deserialize_optional_decimal"
3364    )]
3365    pub ibukl_principal: Option<Decimal>,
3366
3367    /// Total principal
3368    #[serde(
3369        rename = "@totalPrincipal",
3370        default,
3371        deserialize_with = "deserialize_optional_decimal"
3372    )]
3373    pub total_principal: Option<Decimal>,
3374
3375    /// Interest rate
3376    #[serde(
3377        rename = "@rate",
3378        default,
3379        deserialize_with = "deserialize_optional_decimal"
3380    )]
3381    pub rate: Option<Decimal>,
3382
3383    /// Securities interest
3384    #[serde(
3385        rename = "@securitiesInterest",
3386        default,
3387        deserialize_with = "deserialize_optional_decimal"
3388    )]
3389    pub securities_interest: Option<Decimal>,
3390
3391    /// Commodities interest
3392    #[serde(
3393        rename = "@commoditiesInterest",
3394        default,
3395        deserialize_with = "deserialize_optional_decimal"
3396    )]
3397    pub commodities_interest: Option<Decimal>,
3398
3399    /// IBUKL interest
3400    #[serde(
3401        rename = "@ibuklInterest",
3402        default,
3403        deserialize_with = "deserialize_optional_decimal"
3404    )]
3405    pub ibukl_interest: Option<Decimal>,
3406
3407    /// Total interest
3408    #[serde(
3409        rename = "@totalInterest",
3410        default,
3411        deserialize_with = "deserialize_optional_decimal"
3412    )]
3413    pub total_interest: Option<Decimal>,
3414
3415    /// Code
3416    #[serde(rename = "@code", default)]
3417    pub code: Option<String>,
3418
3419    /// From account
3420    #[serde(rename = "@fromAcct", default)]
3421    pub from_acct: Option<String>,
3422
3423    /// To account
3424    #[serde(rename = "@toAcct", default)]
3425    pub to_acct: Option<String>,
3426
3427    /// Margin balance
3428    #[serde(rename = "@marginBalance", default)]
3429    pub margin_balance: Option<String>,
3430
3431    // Legacy fields (may appear in older reports)
3432    /// Date
3433    #[serde(
3434        rename = "@date",
3435        default,
3436        deserialize_with = "deserialize_optional_date"
3437    )]
3438    pub date: Option<NaiveDate>,
3439
3440    /// From date
3441    #[serde(
3442        rename = "@fromDate",
3443        default,
3444        deserialize_with = "deserialize_optional_date"
3445    )]
3446    pub from_date: Option<NaiveDate>,
3447
3448    /// To date
3449    #[serde(
3450        rename = "@toDate",
3451        default,
3452        deserialize_with = "deserialize_optional_date"
3453    )]
3454    pub to_date: Option<NaiveDate>,
3455
3456    /// Balance (legacy)
3457    #[serde(
3458        rename = "@balance",
3459        default,
3460        deserialize_with = "deserialize_optional_decimal"
3461    )]
3462    pub balance: Option<Decimal>,
3463
3464    /// Interest rate (legacy field name)
3465    #[serde(
3466        rename = "@interestRate",
3467        default,
3468        deserialize_with = "deserialize_optional_decimal"
3469    )]
3470    pub interest_rate: Option<Decimal>,
3471
3472    /// Interest (legacy)
3473    #[serde(
3474        rename = "@interest",
3475        default,
3476        deserialize_with = "deserialize_optional_decimal"
3477    )]
3478    pub interest: Option<Decimal>,
3479}
3480
3481// =============================================================================
3482// Miscellaneous Activity Types
3483// =============================================================================
3484
3485/// Debit card activity
3486#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
3487pub struct DebitCardActivity {
3488    /// Account ID
3489    #[serde(rename = "@accountId")]
3490    pub account_id: String,
3491
3492    /// Account alias
3493    #[serde(rename = "@acctAlias", default)]
3494    pub acct_alias: Option<String>,
3495
3496    /// Model
3497    #[serde(rename = "@model", default)]
3498    pub model: Option<String>,
3499
3500    /// Date
3501    #[serde(
3502        rename = "@date",
3503        default,
3504        deserialize_with = "deserialize_optional_date"
3505    )]
3506    pub date: Option<NaiveDate>,
3507
3508    /// Merchant
3509    #[serde(rename = "@merchant", default)]
3510    pub merchant: Option<String>,
3511
3512    /// Category
3513    #[serde(rename = "@category", default)]
3514    pub category: Option<String>,
3515
3516    /// Status
3517    #[serde(rename = "@status", default)]
3518    pub status: Option<String>,
3519
3520    /// Transaction type
3521    #[serde(rename = "@transactionType", default)]
3522    pub transaction_type: Option<String>,
3523
3524    /// Amount
3525    #[serde(
3526        rename = "@amount",
3527        default,
3528        deserialize_with = "deserialize_optional_decimal"
3529    )]
3530    pub amount: Option<Decimal>,
3531
3532    /// Currency
3533    #[serde(rename = "@currency", default)]
3534    pub currency: Option<String>,
3535
3536    /// FX rate to base
3537    #[serde(
3538        rename = "@fxRateToBase",
3539        default,
3540        deserialize_with = "deserialize_optional_decimal"
3541    )]
3542    pub fx_rate_to_base: Option<Decimal>,
3543}
3544
3545/// Sales tax
3546#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
3547pub struct SalesTax {
3548    /// Account ID
3549    #[serde(rename = "@accountId")]
3550    pub account_id: String,
3551
3552    /// Account alias
3553    #[serde(rename = "@acctAlias", default)]
3554    pub acct_alias: Option<String>,
3555
3556    /// Model
3557    #[serde(rename = "@model", default)]
3558    pub model: Option<String>,
3559
3560    /// Date
3561    #[serde(
3562        rename = "@date",
3563        default,
3564        deserialize_with = "deserialize_optional_date"
3565    )]
3566    pub date: Option<NaiveDate>,
3567
3568    /// Symbol
3569    #[serde(rename = "@symbol", default)]
3570    pub symbol: Option<String>,
3571
3572    /// Description
3573    #[serde(rename = "@description", default)]
3574    pub description: Option<String>,
3575
3576    /// Contract ID
3577    #[serde(rename = "@conid", default)]
3578    pub conid: Option<String>,
3579
3580    /// Tax type
3581    #[serde(rename = "@taxType", default)]
3582    pub tax_type: Option<String>,
3583
3584    /// Tax amount
3585    #[serde(
3586        rename = "@taxAmount",
3587        default,
3588        deserialize_with = "deserialize_optional_decimal"
3589    )]
3590    pub tax_amount: Option<Decimal>,
3591
3592    /// Proceeds
3593    #[serde(
3594        rename = "@proceeds",
3595        default,
3596        deserialize_with = "deserialize_optional_decimal"
3597    )]
3598    pub proceeds: Option<Decimal>,
3599
3600    /// Currency
3601    #[serde(rename = "@currency", default)]
3602    pub currency: Option<String>,
3603
3604    /// FX rate to base
3605    #[serde(
3606        rename = "@fxRateToBase",
3607        default,
3608        deserialize_with = "deserialize_optional_decimal"
3609    )]
3610    pub fx_rate_to_base: Option<Decimal>,
3611}
3612
3613// =============================================================================
3614// Summary Types
3615// =============================================================================
3616
3617/// Symbol summary (aggregated trading data by symbol)
3618#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
3619pub struct SymbolSummary {
3620    /// Account ID
3621    #[serde(rename = "@accountId")]
3622    pub account_id: String,
3623
3624    /// Account alias
3625    #[serde(rename = "@acctAlias", default)]
3626    pub acct_alias: Option<String>,
3627
3628    /// Model
3629    #[serde(rename = "@model", default)]
3630    pub model: Option<String>,
3631
3632    /// Symbol
3633    #[serde(rename = "@symbol", default)]
3634    pub symbol: Option<String>,
3635
3636    /// Description
3637    #[serde(rename = "@description", default)]
3638    pub description: Option<String>,
3639
3640    /// Contract ID
3641    #[serde(rename = "@conid", default)]
3642    pub conid: Option<String>,
3643
3644    /// Asset category
3645    #[serde(rename = "@assetCategory", default)]
3646    pub asset_category: Option<AssetCategory>,
3647
3648    /// Total buy quantity
3649    #[serde(
3650        rename = "@totalBuyQuantity",
3651        default,
3652        deserialize_with = "deserialize_optional_decimal"
3653    )]
3654    pub total_buy_quantity: Option<Decimal>,
3655
3656    /// Total sell quantity
3657    #[serde(
3658        rename = "@totalSellQuantity",
3659        default,
3660        deserialize_with = "deserialize_optional_decimal"
3661    )]
3662    pub total_sell_quantity: Option<Decimal>,
3663
3664    /// Total buy value
3665    #[serde(
3666        rename = "@totalBuyValue",
3667        default,
3668        deserialize_with = "deserialize_optional_decimal"
3669    )]
3670    pub total_buy_value: Option<Decimal>,
3671
3672    /// Total sell value
3673    #[serde(
3674        rename = "@totalSellValue",
3675        default,
3676        deserialize_with = "deserialize_optional_decimal"
3677    )]
3678    pub total_sell_value: Option<Decimal>,
3679
3680    /// Total commission
3681    #[serde(
3682        rename = "@totalCommission",
3683        default,
3684        deserialize_with = "deserialize_optional_decimal"
3685    )]
3686    pub total_commission: Option<Decimal>,
3687
3688    /// Realized P&L
3689    #[serde(
3690        rename = "@realizedPnl",
3691        default,
3692        deserialize_with = "deserialize_optional_decimal"
3693    )]
3694    pub realized_pnl: Option<Decimal>,
3695
3696    /// Currency
3697    #[serde(rename = "@currency", default)]
3698    pub currency: Option<String>,
3699}
3700
3701/// Asset summary (aggregated trading data by asset class)
3702#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
3703pub struct AssetSummary {
3704    /// Account ID
3705    #[serde(rename = "@accountId")]
3706    pub account_id: String,
3707
3708    /// Account alias
3709    #[serde(rename = "@acctAlias", default)]
3710    pub acct_alias: Option<String>,
3711
3712    /// Model
3713    #[serde(rename = "@model", default)]
3714    pub model: Option<String>,
3715
3716    /// Asset category
3717    #[serde(rename = "@assetCategory", default)]
3718    pub asset_category: Option<AssetCategory>,
3719
3720    /// Total buy quantity
3721    #[serde(
3722        rename = "@totalBuyQuantity",
3723        default,
3724        deserialize_with = "deserialize_optional_decimal"
3725    )]
3726    pub total_buy_quantity: Option<Decimal>,
3727
3728    /// Total sell quantity
3729    #[serde(
3730        rename = "@totalSellQuantity",
3731        default,
3732        deserialize_with = "deserialize_optional_decimal"
3733    )]
3734    pub total_sell_quantity: Option<Decimal>,
3735
3736    /// Total buy value
3737    #[serde(
3738        rename = "@totalBuyValue",
3739        default,
3740        deserialize_with = "deserialize_optional_decimal"
3741    )]
3742    pub total_buy_value: Option<Decimal>,
3743
3744    /// Total sell value
3745    #[serde(
3746        rename = "@totalSellValue",
3747        default,
3748        deserialize_with = "deserialize_optional_decimal"
3749    )]
3750    pub total_sell_value: Option<Decimal>,
3751
3752    /// Total commission
3753    #[serde(
3754        rename = "@totalCommission",
3755        default,
3756        deserialize_with = "deserialize_optional_decimal"
3757    )]
3758    pub total_commission: Option<Decimal>,
3759
3760    /// Realized P&L
3761    #[serde(
3762        rename = "@realizedPnl",
3763        default,
3764        deserialize_with = "deserialize_optional_decimal"
3765    )]
3766    pub realized_pnl: Option<Decimal>,
3767
3768    /// Currency
3769    #[serde(rename = "@currency", default)]
3770    pub currency: Option<String>,
3771}
3772
3773/// Order record
3774#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
3775pub struct Order {
3776    /// Account ID
3777    #[serde(rename = "@accountId")]
3778    pub account_id: String,
3779
3780    /// Account alias
3781    #[serde(rename = "@acctAlias", default)]
3782    pub acct_alias: Option<String>,
3783
3784    /// Model
3785    #[serde(rename = "@model", default)]
3786    pub model: Option<String>,
3787
3788    /// Order ID
3789    #[serde(rename = "@orderID", default)]
3790    pub order_id: Option<String>,
3791
3792    /// Symbol
3793    #[serde(rename = "@symbol", default)]
3794    pub symbol: Option<String>,
3795
3796    /// Description
3797    #[serde(rename = "@description", default)]
3798    pub description: Option<String>,
3799
3800    /// Contract ID
3801    #[serde(rename = "@conid", default)]
3802    pub conid: Option<String>,
3803
3804    /// Asset category
3805    #[serde(rename = "@assetCategory", default)]
3806    pub asset_category: Option<AssetCategory>,
3807
3808    /// Order time
3809    #[serde(rename = "@orderTime", default)]
3810    pub order_time: Option<String>,
3811
3812    /// Order type
3813    #[serde(rename = "@orderType", default)]
3814    pub order_type: Option<String>,
3815
3816    /// Side (buy/sell)
3817    #[serde(rename = "@side", default)]
3818    pub side: Option<String>,
3819
3820    /// Time in force
3821    #[serde(rename = "@tif", default)]
3822    pub tif: Option<String>,
3823
3824    /// Order quantity
3825    #[serde(
3826        rename = "@orderQty",
3827        default,
3828        deserialize_with = "deserialize_optional_decimal"
3829    )]
3830    pub order_qty: Option<Decimal>,
3831
3832    /// Limit price
3833    #[serde(
3834        rename = "@limitPrice",
3835        default,
3836        deserialize_with = "deserialize_optional_decimal"
3837    )]
3838    pub limit_price: Option<Decimal>,
3839
3840    /// Stop price
3841    #[serde(
3842        rename = "@stopPrice",
3843        default,
3844        deserialize_with = "deserialize_optional_decimal"
3845    )]
3846    pub stop_price: Option<Decimal>,
3847
3848    /// Filled quantity
3849    #[serde(
3850        rename = "@filledQty",
3851        default,
3852        deserialize_with = "deserialize_optional_decimal"
3853    )]
3854    pub filled_qty: Option<Decimal>,
3855
3856    /// Average fill price
3857    #[serde(
3858        rename = "@avgPrice",
3859        default,
3860        deserialize_with = "deserialize_optional_decimal"
3861    )]
3862    pub avg_price: Option<Decimal>,
3863
3864    /// Remaining quantity
3865    #[serde(
3866        rename = "@remainingQty",
3867        default,
3868        deserialize_with = "deserialize_optional_decimal"
3869    )]
3870    pub remaining_qty: Option<Decimal>,
3871
3872    /// Order status
3873    #[serde(rename = "@status", default)]
3874    pub status: Option<String>,
3875
3876    /// Currency
3877    #[serde(rename = "@currency", default)]
3878    pub currency: Option<String>,
3879}