ib_flex/types/common.rs
1//! Common enums used across FLEX statements
2
3use chrono::NaiveDate;
4use rust_decimal::Decimal;
5use serde::{Deserialize, Serialize};
6
7/// Asset category (security type)
8///
9/// Maps to IB's AssetCategory field. Represents the type of financial instrument.
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
11#[serde(rename_all = "UPPERCASE")]
12pub enum AssetCategory {
13 /// Stock
14 #[serde(rename = "STK")]
15 Stock,
16
17 /// Option
18 #[serde(rename = "OPT")]
19 Option,
20
21 /// Future
22 #[serde(rename = "FUT")]
23 Future,
24
25 /// Future Option
26 #[serde(rename = "FOP")]
27 FutureOption,
28
29 /// Cash/Forex
30 #[serde(rename = "CASH")]
31 Cash,
32
33 /// Bond
34 #[serde(rename = "BOND")]
35 Bond,
36
37 /// Treasury Bill (maturity < 1 year)
38 #[serde(rename = "BILL")]
39 Bill,
40
41 /// Commodity
42 #[serde(rename = "CMDTY")]
43 Commodity,
44
45 /// Contract for Difference
46 #[serde(rename = "CFD")]
47 Cfd,
48
49 /// Forex CFD
50 #[serde(rename = "FXCFD")]
51 ForexCfd,
52
53 /// Warrant
54 #[serde(rename = "WAR")]
55 Warrant,
56
57 /// Mutual Fund
58 #[serde(rename = "FUND")]
59 Fund,
60
61 /// Structured Product / Dutch Warrant / Indexed Option
62 #[serde(rename = "IOPT")]
63 StructuredProduct,
64
65 /// Combination / Basket order (spread, combo legs)
66 #[serde(rename = "BAG")]
67 Bag,
68
69 /// Cryptocurrency
70 #[serde(rename = "CRYPTO")]
71 Cryptocurrency,
72
73 /// Physical metals (gold, silver, etc.)
74 #[serde(rename = "METAL")]
75 Metal,
76
77 /// Exchange for Physical
78 #[serde(rename = "EFP")]
79 ExchangeForPhysical,
80
81 /// Event Contract
82 #[serde(rename = "EC")]
83 EventContract,
84
85 /// Index
86 #[serde(rename = "IND")]
87 Index,
88
89 /// Options on Futures (futures-style settlement)
90 #[serde(rename = "FSFOP")]
91 OptionsOnFutures,
92
93 /// Futures-style option
94 #[serde(rename = "FSOPT")]
95 OptionsFuturesStyle,
96
97 /// Unknown or unrecognized asset category
98 #[serde(other)]
99 Unknown,
100}
101
102/// Buy or Sell side
103#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
104#[serde(rename_all = "UPPERCASE")]
105pub enum BuySell {
106 /// Buy
107 #[serde(rename = "BUY")]
108 Buy,
109
110 /// Sell
111 #[serde(rename = "SELL")]
112 Sell,
113
114 /// Cancelled buy
115 #[serde(rename = "BUY (Ca.)")]
116 CancelBuy,
117
118 /// Cancelled sell
119 #[serde(rename = "SELL (Ca.)")]
120 CancelSell,
121
122 /// Unknown
123 #[serde(other)]
124 Unknown,
125}
126
127/// Open or Close indicator (for options/futures)
128#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
129pub enum OpenClose {
130 /// Opening trade
131 #[serde(rename = "O")]
132 Open,
133
134 /// Closing trade
135 #[serde(rename = "C")]
136 Close,
137
138 /// Close and open (same-day round trip)
139 #[serde(rename = "C;O")]
140 CloseOpen,
141
142 /// Unknown
143 #[serde(other)]
144 Unknown,
145}
146
147/// Order type
148#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
149#[serde(rename_all = "UPPERCASE")]
150pub enum OrderType {
151 /// Market order
152 #[serde(rename = "MKT")]
153 Market,
154
155 /// Limit order
156 #[serde(rename = "LMT")]
157 Limit,
158
159 /// Stop order
160 #[serde(rename = "STP")]
161 Stop,
162
163 /// Stop limit order. Flex XML emits the no-space form `STPLMT`; the
164 /// spaced TWS/API spelling is accepted as an alias.
165 #[serde(rename = "STPLMT", alias = "STP LMT")]
166 StopLimit,
167
168 /// Market on close
169 #[serde(rename = "MOC")]
170 MarketOnClose,
171
172 /// Limit on close
173 #[serde(rename = "LOC")]
174 LimitOnClose,
175
176 /// Market if touched
177 #[serde(rename = "MIT")]
178 MarketIfTouched,
179
180 /// Limit if touched
181 #[serde(rename = "LIT")]
182 LimitIfTouched,
183
184 /// Trailing stop
185 #[serde(rename = "TRAIL")]
186 TrailingStop,
187
188 /// Trailing limit. Flex XML emits the no-space form `TRAILLMT`; the
189 /// spaced TWS/API spelling is accepted as an alias.
190 #[serde(rename = "TRAILLMT", alias = "TRAIL LMT")]
191 TrailingLimit,
192
193 /// Mid-price order
194 #[serde(rename = "MIDPX")]
195 MidPrice,
196
197 /// Relative order
198 #[serde(rename = "REL")]
199 Relative,
200
201 /// Multiple order types (complex orders)
202 #[serde(rename = "MULTIPLE")]
203 Multiple,
204
205 /// Unknown or unrecognized order type
206 #[serde(other)]
207 Unknown,
208}
209
210/// Put or Call (for options)
211#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
212pub enum PutCall {
213 /// Put option
214 #[serde(rename = "P")]
215 Put,
216
217 /// Call option
218 #[serde(rename = "C")]
219 Call,
220
221 /// Unknown
222 #[serde(other)]
223 Unknown,
224}
225
226/// Long or Short position side
227#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
228pub enum LongShort {
229 /// Long position
230 Long,
231
232 /// Short position
233 Short,
234
235 /// Unknown
236 #[serde(other)]
237 Unknown,
238}
239
240/// Transaction type for trades
241#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
242pub enum TradeType {
243 /// Exchange trade
244 ExchTrade,
245
246 /// Book trade
247 BookTrade,
248
249 /// Delivery vs Payment trade
250 DvpTrade,
251
252 /// Fractional share trade
253 FracShare,
254
255 /// Fractional share cancellation
256 FracShareCancel,
257
258 /// Manual adjustment
259 Adjustment,
260
261 /// Trade correction
262 TradeCorrect,
263
264 /// Trade cancellation
265 TradeCancel,
266
267 /// IBKR trade
268 IBKRTrade,
269
270 /// Unknown
271 #[serde(other)]
272 Unknown,
273}
274
275/// Cash transaction action type
276///
277/// Represents the type of cash transaction (dividend, interest, fee, etc.).
278/// This enum is used by the `CashTransaction` struct to classify cash activity
279/// in the account statement.
280///
281/// **XML Mapping**: Maps to the `type` attribute in `<CashTransaction>` elements.
282#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)]
283pub enum CashTransactionType {
284 /// Deposits and withdrawals
285 #[serde(rename = "Deposits & Withdrawals")]
286 DepositsWithdrawals,
287
288 /// Dividend payments
289 Dividends,
290
291 /// Withholding tax
292 #[serde(rename = "Withholding Tax")]
293 WithholdingTax,
294
295 /// Broker interest paid
296 #[serde(rename = "Broker Interest Paid")]
297 BrokerInterestPaid,
298
299 /// Broker interest received
300 #[serde(rename = "Broker Interest Received")]
301 BrokerInterestReceived,
302
303 /// Bond interest received
304 #[serde(rename = "Bond Interest Received")]
305 BondInterestReceived,
306
307 /// Bond interest paid
308 #[serde(rename = "Bond Interest Paid")]
309 BondInterestPaid,
310
311 /// Bond interest (generic)
312 #[serde(rename = "Bond Interest")]
313 BondInterest,
314
315 /// Payment in lieu of dividends
316 #[serde(rename = "Payment In Lieu Of Dividends")]
317 PaymentInLieuOfDividends,
318
319 /// Other fees
320 #[serde(rename = "Other Fees")]
321 OtherFees,
322
323 /// Commission adjustments
324 #[serde(rename = "Commission Adjustments")]
325 CommissionAdjustments,
326
327 /// Advisor fees
328 #[serde(rename = "Advisor Fees")]
329 AdvisorFees,
330
331 /// Cash receipts
332 #[serde(rename = "Cash Receipts")]
333 CashReceipts,
334
335 /// Fees
336 Fees,
337
338 /// Unknown type
339 #[serde(other)]
340 Unknown,
341}
342
343/// Corporate action reorganization type
344///
345/// Represents the type of corporate action (split, merger, spinoff, etc.).
346/// This enum is used by the `CorporateAction` struct to classify corporate events
347/// that affect security positions and holdings.
348///
349/// **XML Mapping**: Maps to the `type` attribute in `<CorporateAction>` elements.
350#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
351pub enum CorporateActionType {
352 /// Stock split (forward split)
353 #[serde(rename = "Stock Split")]
354 StockSplit,
355
356 /// Forward split (issue)
357 #[serde(rename = "Forward Split (Issue)")]
358 ForwardSplitIssue,
359
360 /// Forward split
361 #[serde(rename = "Forward Split")]
362 ForwardSplit,
363
364 /// Reverse split
365 #[serde(rename = "Reverse Split")]
366 ReverseSplit,
367
368 /// Merger
369 Merger,
370
371 /// Spinoff
372 Spinoff,
373
374 /// Contract spinoff
375 #[serde(rename = "Contract Spinoff")]
376 ContractSpinoff,
377
378 /// Stock dividend
379 #[serde(rename = "Stock Dividend")]
380 StockDividend,
381
382 /// Cash dividend
383 #[serde(rename = "Cash Dividend")]
384 CashDividend,
385
386 /// Choice dividend
387 #[serde(rename = "Choice Dividend")]
388 ChoiceDividend,
389
390 /// Choice dividend (delivery)
391 #[serde(rename = "Choice Dividend (Delivery)")]
392 ChoiceDivDelivery,
393
394 /// Choice dividend (issue)
395 #[serde(rename = "Choice Dividend (Issue)")]
396 ChoiceDivIssue,
397
398 /// Dividend rights issue
399 #[serde(rename = "Dividend Rights Issue")]
400 DivRightsIssue,
401
402 /// Expired dividend right
403 #[serde(rename = "Expired Dividend Right")]
404 ExpiredDivRight,
405
406 /// Delisted
407 Delisted,
408
409 /// Delist (worthless)
410 #[serde(rename = "Delist (Worthless)")]
411 DelistWorthless,
412
413 /// Name change
414 #[serde(rename = "Name Change")]
415 NameChange,
416
417 /// Symbol change
418 #[serde(rename = "Symbol Change")]
419 SymbolChange,
420
421 /// Issue change
422 #[serde(rename = "Issue Change")]
423 IssueChange,
424
425 /// Bond conversion
426 #[serde(rename = "Bond Conversion")]
427 BondConversion,
428
429 /// Bond maturity
430 #[serde(rename = "Bond Maturity")]
431 BondMaturity,
432
433 /// T-Bill maturity
434 #[serde(rename = "T-Bill Maturity")]
435 TBillMaturity,
436
437 /// Convertible issue
438 #[serde(rename = "Convertible Issue")]
439 ConvertibleIssue,
440
441 /// Coupon payment
442 #[serde(rename = "Coupon Payment")]
443 CouponPayment,
444
445 /// Contract consolidation
446 #[serde(rename = "Contract Consolidation")]
447 ContractConsolidation,
448
449 /// Contract split
450 #[serde(rename = "Contract Split")]
451 ContractSplit,
452
453 /// Contract termination
454 #[serde(rename = "CFD Termination")]
455 CfdTermination,
456
457 /// Fee allocation
458 #[serde(rename = "Fee Allocation")]
459 FeeAllocation,
460
461 /// Rights issue
462 #[serde(rename = "Rights Issue")]
463 RightsIssue,
464
465 /// Subscribe rights
466 #[serde(rename = "Subscribe Rights")]
467 SubscribeRights,
468
469 /// Tender
470 Tender,
471
472 /// Tender (issue)
473 #[serde(rename = "Tender (Issue)")]
474 TenderIssue,
475
476 /// Proxy vote
477 #[serde(rename = "Proxy Vote")]
478 ProxyVote,
479
480 /// Generic voluntary
481 #[serde(rename = "Generic Voluntary")]
482 GenericVoluntary,
483
484 /// Asset purchase
485 #[serde(rename = "Asset Purchase")]
486 AssetPurchase,
487
488 /// Purchase (issue)
489 #[serde(rename = "Purchase (Issue)")]
490 PurchaseIssue,
491
492 /// Unknown
493 #[serde(other)]
494 Unknown,
495}
496
497/// Option action type
498#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
499pub enum OptionAction {
500 /// Assignment
501 Assignment,
502
503 /// Exercise
504 Exercise,
505
506 /// Expiration
507 Expiration,
508
509 /// Expire (alternate form)
510 Expire,
511
512 /// Cash settlement
513 #[serde(rename = "Cash Settlement")]
514 CashSettlement,
515
516 /// Buy to open/close
517 Buy,
518
519 /// Sell to open/close
520 Sell,
521
522 /// Unknown
523 #[serde(other)]
524 Unknown,
525}
526
527/// Transfer type
528#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
529pub enum TransferType {
530 /// ACATS transfer (older statements abbreviate this as `ACAT`)
531 #[serde(rename = "ACATS", alias = "ACAT")]
532 ACATS,
533
534 /// ATON transfer
535 ATON,
536
537 /// Free of payment
538 FOP,
539
540 /// Internal transfer
541 INTERNAL,
542
543 /// Intercompany transfer
544 INTERCOMPANY,
545
546 /// Over-the-counter transfer
547 OTC,
548
549 /// Delivery vs payment
550 DVP,
551
552 /// Unknown
553 #[serde(other)]
554 Unknown,
555}
556
557/// Transaction code
558///
559/// Comprehensive list of IB transaction classification codes.
560/// These codes appear in `notes` fields and can be combined (e.g., "C;W" for closing + wash sale).
561/// They provide critical context for tax reporting and trade classification.
562#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)]
563pub enum TransactionCode {
564 /// Assignment - Option assignment triggering stock delivery
565 #[serde(rename = "A")]
566 Assignment,
567
568 /// Adjustment - Manual adjustment affecting cost basis
569 #[serde(rename = "Adj")]
570 Adjustment,
571
572 /// Allocation - Trade allocation to sub-account (master/sub allocation)
573 #[serde(rename = "Al")]
574 Allocation,
575
576 /// Auto Exercise - Automatic exercise (dividend-related, exercise before ex-div)
577 #[serde(rename = "Ae")]
578 AutoExercise,
579
580 /// Auto FX - AutoFX currency conversion for settlement
581 #[serde(rename = "Af")]
582 AutoFx,
583
584 /// Away Trade - Trade executed away from IB (third-party execution)
585 #[serde(rename = "Aw")]
586 AwayTrade,
587
588 /// Buy-In - Forced purchase to cover failed delivery (forced short cover)
589 #[serde(rename = "B")]
590 BuyIn,
591
592 /// Borrow - Securities borrowing fee (lending charge)
593 #[serde(rename = "Bo")]
594 BorrowFee,
595
596 /// Cancellation - Trade cancelled/busted (trade reversed)
597 #[serde(rename = "Ca")]
598 Cancelled,
599
600 /// Closing - Closing trade (reduces position)
601 #[serde(rename = "C")]
602 Closing,
603
604 /// Cash Delivery - Cash delivery for exercise (cash vs physical)
605 #[serde(rename = "Cd")]
606 CashDelivery,
607
608 /// Complex Position - Complex/combo position (multi-leg strategy)
609 #[serde(rename = "Cp")]
610 ComplexPosition,
611
612 /// Correction - Trade correction (amended execution)
613 #[serde(rename = "Cr")]
614 Correction,
615
616 /// Crossing - Internal IB cross (matched internally)
617 #[serde(rename = "Cs")]
618 Crossing,
619
620 /// Dual Agent - IB dual agent capacity (disclosed dual role)
621 #[serde(rename = "D")]
622 DualAgent,
623
624 /// ETF - ETF creation/redemption (in-kind basket)
625 #[serde(rename = "Et")]
626 Etf,
627
628 /// Expired - From expired position (option/warrant expiry)
629 #[serde(rename = "Ex")]
630 Expired,
631
632 /// Exercise - Option exercise (long option exercised)
633 #[serde(rename = "O")]
634 Exercise,
635
636 /// Guaranteed - Guaranteed account segment (special margin)
637 #[serde(rename = "G")]
638 Guaranteed,
639
640 /// Highest Cost - Highest cost tax lot (tax lot selection)
641 #[serde(rename = "Hc")]
642 HighestCost,
643
644 /// HF Investment - Hedge fund investment (fund subscription)
645 #[serde(rename = "Hi")]
646 HfInvestment,
647
648 /// HF Redemption - Hedge fund redemption (fund redemption)
649 #[serde(rename = "Hr")]
650 HfRedemption,
651
652 /// Internal - Internal transfer (between IB accounts)
653 #[serde(rename = "I")]
654 InternalTransfer,
655
656 /// Affiliate - Affiliate execution (related party trade)
657 #[serde(rename = "Ia")]
658 Affiliate,
659
660 /// Investor - Investment from investor (capital contribution)
661 #[serde(rename = "Iv")]
662 Investor,
663
664 /// Margin Violation - Liquidation due to margin (forced liquidation)
665 #[serde(rename = "L")]
666 MarginLiquidation,
667
668 /// LIFO - LIFO tax lot (tax lot selection)
669 #[serde(rename = "Li")]
670 Lifo,
671
672 /// Loan - Securities lending income (lending income)
673 #[serde(rename = "Ln")]
674 Loan,
675
676 /// Long-Term - Long-term gain/loss (holding > 1 year)
677 #[serde(rename = "Lt")]
678 LongTermGain,
679
680 /// Manual - Manual IB entry (manual adjustment)
681 #[serde(rename = "M")]
682 ManualEntry,
683
684 /// Max Loss - Maximize losses (tax optimization)
685 #[serde(rename = "Ml")]
686 MaxLoss,
687
688 /// Min LT Gain - Minimize long-term gain (tax optimization)
689 #[serde(rename = "Mn")]
690 MinLongTermGain,
691
692 /// Max ST Gain - Maximize short-term gain (tax optimization)
693 #[serde(rename = "Ms")]
694 MaxShortTermGain,
695
696 /// Min ST Gain - Minimize short-term gain (tax optimization)
697 #[serde(rename = "Mi")]
698 MinShortTermGain,
699
700 /// Manual Exercise - Manual exercise (discretionary exercise)
701 #[serde(rename = "Mx")]
702 ManualExercise,
703
704 /// Opening - Opening trade (new position)
705 #[serde(rename = "P")]
706 Opening,
707
708 /// Partial - Partial execution (partial fill)
709 #[serde(rename = "Pt")]
710 Partial,
711
712 /// Frac Riskless - Fractional riskless principal (fractional share method)
713 #[serde(rename = "Fr")]
714 FracRiskless,
715
716 /// Frac Principal - Fractional principal (fractional share method)
717 #[serde(rename = "Fp")]
718 FracPrincipal,
719
720 /// Price Improvement - Better than quoted (price improvement)
721 #[serde(rename = "Pi")]
722 PriceImprovement,
723
724 /// Post Accrual - Accrual posting (accrual entry)
725 #[serde(rename = "Pa")]
726 PostAccrual,
727
728 /// Principal - IB principal execution (principal trade)
729 #[serde(rename = "Pr")]
730 Principal,
731
732 /// Reinvestment - Dividend reinvestment (DRIP)
733 #[serde(rename = "Re")]
734 Reinvestment,
735
736 /// Redemption - Capital distribution (fund redemption)
737 #[serde(rename = "Rd")]
738 Redemption,
739
740 /// Reopen - Position reopened (wash sale reopen)
741 #[serde(rename = "R")]
742 Reopen,
743
744 /// Reverse - Accrual reversal (accounting reversal)
745 #[serde(rename = "Rv")]
746 Reverse,
747
748 /// Reimbursement - Fee refund (expense refund)
749 #[serde(rename = "Ri")]
750 Reimbursement,
751
752 /// Solicited IB - IB solicited order (IB-initiated)
753 #[serde(rename = "Si")]
754 SolicitedIb,
755
756 /// Specific Lot - Specific tax lot (tax lot selection)
757 #[serde(rename = "Sp")]
758 SpecificLot,
759
760 /// Solicited Other - Third-party solicited (broker-solicited)
761 #[serde(rename = "So")]
762 SolicitedOther,
763
764 /// Short Settlement - T+0 or T+1 settlement (accelerated settle)
765 #[serde(rename = "Ss")]
766 ShortSettlement,
767
768 /// Short-Term - Short-term gain/loss (holding <= 1 year)
769 #[serde(rename = "St")]
770 ShortTermGain,
771
772 /// Stock Yield - Stock yield eligible (lending eligible)
773 #[serde(rename = "Sy")]
774 StockYield,
775
776 /// Transfer - Position transfer
777 #[serde(rename = "T")]
778 Transfer,
779
780 /// Wash Sale - Wash sale (loss disallowed)
781 #[serde(rename = "W")]
782 WashSale,
783
784 /// Unknown code
785 #[serde(other)]
786 Unknown,
787}
788
789/// Direction (To/From)
790#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
791pub enum ToFrom {
792 /// To
793 To,
794
795 /// From
796 From,
797
798 /// Unknown
799 #[serde(other)]
800 Unknown,
801}
802
803/// Direction (In/Out)
804#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
805pub enum InOut {
806 /// Incoming
807 IN,
808
809 /// Outgoing
810 OUT,
811
812 /// Unknown
813 #[serde(other)]
814 Unknown,
815}
816
817/// Delivered or Received
818#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
819pub enum DeliveredReceived {
820 /// Delivered
821 Delivered,
822
823 /// Received
824 Received,
825
826 /// Unknown
827 #[serde(other)]
828 Unknown,
829}
830
831/// Level of detail for reporting
832///
833/// Specifies the granularity of data in FLEX reports.
834/// Used by `Trade`, `Position`, and `CashTransaction` structs to indicate
835/// the level of detail requested in the FLEX query.
836///
837/// **XML Mapping**: Maps to the `levelOfDetail` attribute in various elements.
838#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
839pub enum LevelOfDetail {
840 /// Summary level - aggregated data with minimal details (`SUMMARY`)
841 #[serde(rename = "SUMMARY", alias = "Summary")]
842 Summary,
843
844 /// Detail level - standard reporting with all key fields (`DETAIL`)
845 #[serde(rename = "DETAIL", alias = "Detail")]
846 Detail,
847
848 /// Execution level - detailed execution information including time and venue (`EXECUTION`)
849 #[serde(rename = "EXECUTION", alias = "Execution")]
850 Execution,
851
852 /// Tax-lot level details for cost-basis tracking (`LOT`)
853 #[serde(rename = "LOT", alias = "Lot")]
854 Lot,
855
856 /// Closed tax lot (`CLOSED_LOT`) - the realized side of a lot
857 #[serde(rename = "CLOSED_LOT")]
858 ClosedLot,
859
860 /// Order roll-up row (`ORDER`)
861 #[serde(rename = "ORDER")]
862 Order,
863
864 /// Wash-sale adjustment row (`WASH_SALE`)
865 #[serde(rename = "WASH_SALE")]
866 WashSale,
867
868 /// Per-symbol roll-up row (`SYMBOL_SUMMARY`)
869 #[serde(rename = "SYMBOL_SUMMARY")]
870 SymbolSummary,
871
872 /// Per-asset-class roll-up row (`ASSET_SUMMARY`)
873 #[serde(rename = "ASSET_SUMMARY")]
874 AssetSummary,
875
876 /// Per-currency row in cash / equity summaries (`Currency`)
877 Currency,
878
879 /// Base-currency summary row (`BaseCurrency`)
880 BaseCurrency,
881
882 /// Unknown or unrecognized level of detail
883 #[serde(other)]
884 Unknown,
885}
886
887/// Security identifier type
888///
889/// Specifies the type of security identifier used in the `securityID` field.
890/// Different identifiers are used in different markets and contexts.
891///
892/// **XML Mapping**: Maps to the `securityIDType` attribute in various elements.
893///
894/// **Used by**: `Trade`, `SecurityInfo`
895#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
896pub enum SecurityIdType {
897 /// CUSIP - Committee on Uniform Securities Identification Procedures
898 /// 9-character alphanumeric identifier for North American securities
899 #[serde(rename = "CUSIP")]
900 Cusip,
901
902 /// ISIN - International Securities Identification Number
903 /// 12-character alphanumeric code (ISO 6166 standard)
904 #[serde(rename = "ISIN")]
905 Isin,
906
907 /// FIGI - Financial Instrument Global Identifier
908 /// 12-character alphanumeric identifier (Bloomberg Open Symbology)
909 #[serde(rename = "FIGI")]
910 Figi,
911
912 /// SEDOL - Stock Exchange Daily Official List
913 /// 7-character alphanumeric identifier for UK and Irish securities
914 #[serde(rename = "SEDOL")]
915 Sedol,
916
917 /// Unknown or unrecognized security ID type
918 #[serde(other)]
919 Unknown,
920}
921
922/// Security sub-category
923///
924/// Provides additional classification for securities beyond the basic asset category.
925/// Most commonly used for stocks to distinguish between common shares, ETFs, ADRs, REITs, etc.
926///
927/// **XML Mapping**: Maps to the `subCategory` attribute in various elements.
928///
929/// **Used by**: `Trade`, `Position`, `SecurityInfo`
930#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
931pub enum SubCategory {
932 /// Exchange-traded fund
933 #[serde(rename = "ETF")]
934 Etf,
935
936 /// American Depositary Receipt - represents foreign company shares traded in US
937 #[serde(rename = "ADR")]
938 Adr,
939
940 /// Real Estate Investment Trust
941 #[serde(rename = "REIT")]
942 Reit,
943
944 /// Preferred stock
945 #[serde(rename = "Preferred", alias = "PREFERRED")]
946 Preferred,
947
948 /// Common stock
949 #[serde(rename = "Common", alias = "COMMON")]
950 Common,
951
952 /// Depositary Receipt (general)
953 #[serde(rename = "DR")]
954 DepositaryReceipt,
955
956 /// Global Depositary Receipt
957 #[serde(rename = "GDR")]
958 Gdr,
959
960 /// Limited Partnership
961 #[serde(rename = "LP")]
962 LimitedPartnership,
963
964 /// Master Limited Partnership
965 #[serde(rename = "MLP")]
966 MasterLimitedPartnership,
967
968 /// Right (subscription right)
969 #[serde(rename = "Right")]
970 Right,
971
972 /// Unit (combination of securities)
973 #[serde(rename = "Unit")]
974 Unit,
975
976 /// When-Issued security
977 #[serde(rename = "WI")]
978 WhenIssued,
979
980 /// Tracking stock
981 #[serde(rename = "Tracking")]
982 Tracking,
983
984 /// Closed-end fund
985 #[serde(rename = "CEF")]
986 ClosedEndFund,
987
988 /// Unknown or unrecognized sub-category
989 #[serde(other)]
990 Unknown,
991}
992
993/// Derivative instrument information
994///
995/// Contains structured information about derivative contracts (options, futures, warrants).
996/// This enum consolidates derivative-specific fields based on the instrument type.
997///
998/// **Used by**: `Trade`, `Position`
999#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
1000#[serde(tag = "type")]
1001pub enum DerivativeInfo {
1002 /// Option contract (equity or index option)
1003 ///
1004 /// Standard option giving the right (but not obligation) to buy or sell
1005 /// an underlying asset at a specified strike price by the expiration date.
1006 Option {
1007 /// Strike price - price at which the option can be exercised
1008 strike: Decimal,
1009
1010 /// Expiration date - last date the option can be exercised
1011 expiry: NaiveDate,
1012
1013 /// Put or Call - right to sell (Put) or buy (Call)
1014 #[serde(rename = "putCall")]
1015 put_call: PutCall,
1016
1017 /// Symbol of the underlying security (e.g., "AAPL" for Apple stock)
1018 #[serde(rename = "underlyingSymbol")]
1019 underlying_symbol: String,
1020
1021 /// IB contract ID of the underlying security
1022 #[serde(rename = "underlyingConid")]
1023 underlying_conid: Option<String>,
1024 },
1025
1026 /// Future contract
1027 ///
1028 /// Agreement to buy or sell an asset at a predetermined price
1029 /// on a specified future date.
1030 Future {
1031 /// Expiration date - settlement date for the futures contract
1032 expiry: NaiveDate,
1033
1034 /// Symbol of the underlying asset
1035 #[serde(rename = "underlyingSymbol")]
1036 underlying_symbol: String,
1037
1038 /// IB contract ID of the underlying asset
1039 #[serde(rename = "underlyingConid")]
1040 underlying_conid: Option<String>,
1041 },
1042
1043 /// Future option (option on a futures contract)
1044 ///
1045 /// Option where the underlying asset is a futures contract rather than a stock.
1046 FutureOption {
1047 /// Strike price for the option
1048 strike: Decimal,
1049
1050 /// Expiration date of the option
1051 expiry: NaiveDate,
1052
1053 /// Put or Call
1054 #[serde(rename = "putCall")]
1055 put_call: PutCall,
1056
1057 /// Symbol of the underlying futures contract
1058 #[serde(rename = "underlyingSymbol")]
1059 underlying_symbol: String,
1060
1061 /// IB contract ID of the underlying futures
1062 #[serde(rename = "underlyingConid")]
1063 underlying_conid: Option<String>,
1064 },
1065
1066 /// Warrant
1067 ///
1068 /// Long-term option-like security issued by a company, typically
1069 /// with longer expiration periods than standard options.
1070 Warrant {
1071 /// Strike price (if applicable)
1072 strike: Option<Decimal>,
1073
1074 /// Expiration date (if applicable)
1075 expiry: Option<NaiveDate>,
1076
1077 /// Symbol of the underlying security (if applicable)
1078 #[serde(rename = "underlyingSymbol")]
1079 underlying_symbol: Option<String>,
1080 },
1081}
1082
1083#[cfg(test)]
1084mod tests {
1085 use super::*;
1086
1087 #[test]
1088 fn test_asset_category_basic() {
1089 // Test enum construction and comparison
1090 let stock = AssetCategory::Stock;
1091 assert_eq!(stock, AssetCategory::Stock);
1092 assert_ne!(stock, AssetCategory::Option);
1093 }
1094
1095 #[test]
1096 fn test_buy_sell_basic() {
1097 // Test enum construction and comparison
1098 let buy = BuySell::Buy;
1099 assert_eq!(buy, BuySell::Buy);
1100 assert_ne!(buy, BuySell::Sell);
1101 }
1102
1103 #[test]
1104 fn test_open_close_basic() {
1105 let open = OpenClose::Open;
1106 assert_eq!(open, OpenClose::Open);
1107 assert_ne!(open, OpenClose::Close);
1108 }
1109
1110 #[test]
1111 fn test_put_call_basic() {
1112 let call = PutCall::Call;
1113 assert_eq!(call, PutCall::Call);
1114 assert_ne!(call, PutCall::Put);
1115 }
1116}