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 WithholdingTax,
293
294 /// Broker interest paid
295 #[serde(rename = "Broker Interest Paid")]
296 BrokerInterestPaid,
297
298 /// Broker interest received
299 #[serde(rename = "Broker Interest Received")]
300 BrokerInterestReceived,
301
302 /// Bond interest received
303 #[serde(rename = "Bond Interest Received")]
304 BondInterestReceived,
305
306 /// Bond interest paid
307 #[serde(rename = "Bond Interest Paid")]
308 BondInterestPaid,
309
310 /// Bond interest (generic)
311 #[serde(rename = "Bond Interest")]
312 BondInterest,
313
314 /// Payment in lieu of dividends
315 #[serde(rename = "Payment In Lieu Of Dividends")]
316 PaymentInLieuOfDividends,
317
318 /// Other fees
319 #[serde(rename = "Other Fees")]
320 OtherFees,
321
322 /// Commission adjustments
323 #[serde(rename = "Commission Adjustments")]
324 CommissionAdjustments,
325
326 /// Advisor fees
327 #[serde(rename = "Advisor Fees")]
328 AdvisorFees,
329
330 /// Cash receipts
331 #[serde(rename = "Cash Receipts")]
332 CashReceipts,
333
334 /// Fees
335 Fees,
336
337 /// Unknown type
338 #[serde(other)]
339 Unknown,
340}
341
342/// Corporate action reorganization type
343///
344/// Represents the type of corporate action (split, merger, spinoff, etc.).
345/// This enum is used by the `CorporateAction` struct to classify corporate events
346/// that affect security positions and holdings.
347///
348/// **XML Mapping**: Maps to the `type` attribute in `<CorporateAction>` elements.
349#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
350pub enum CorporateActionType {
351 /// Stock split (forward split)
352 #[serde(rename = "Stock Split")]
353 StockSplit,
354
355 /// Forward split (issue)
356 #[serde(rename = "Forward Split (Issue)")]
357 ForwardSplitIssue,
358
359 /// Forward split
360 #[serde(rename = "Forward Split")]
361 ForwardSplit,
362
363 /// Reverse split
364 #[serde(rename = "Reverse Split")]
365 ReverseSplit,
366
367 /// Merger
368 Merger,
369
370 /// Spinoff
371 Spinoff,
372
373 /// Contract spinoff
374 #[serde(rename = "Contract Spinoff")]
375 ContractSpinoff,
376
377 /// Stock dividend
378 #[serde(rename = "Stock Dividend")]
379 StockDividend,
380
381 /// Cash dividend
382 #[serde(rename = "Cash Dividend")]
383 CashDividend,
384
385 /// Choice dividend
386 #[serde(rename = "Choice Dividend")]
387 ChoiceDividend,
388
389 /// Choice dividend (delivery)
390 #[serde(rename = "Choice Dividend (Delivery)")]
391 ChoiceDivDelivery,
392
393 /// Choice dividend (issue)
394 #[serde(rename = "Choice Dividend (Issue)")]
395 ChoiceDivIssue,
396
397 /// Dividend rights issue
398 #[serde(rename = "Dividend Rights Issue")]
399 DivRightsIssue,
400
401 /// Expired dividend right
402 #[serde(rename = "Expired Dividend Right")]
403 ExpiredDivRight,
404
405 /// Delisted
406 Delisted,
407
408 /// Delist (worthless)
409 #[serde(rename = "Delist (Worthless)")]
410 DelistWorthless,
411
412 /// Name change
413 #[serde(rename = "Name Change")]
414 NameChange,
415
416 /// Symbol change
417 #[serde(rename = "Symbol Change")]
418 SymbolChange,
419
420 /// Issue change
421 #[serde(rename = "Issue Change")]
422 IssueChange,
423
424 /// Bond conversion
425 #[serde(rename = "Bond Conversion")]
426 BondConversion,
427
428 /// Bond maturity
429 #[serde(rename = "Bond Maturity")]
430 BondMaturity,
431
432 /// T-Bill maturity
433 #[serde(rename = "T-Bill Maturity")]
434 TBillMaturity,
435
436 /// Convertible issue
437 #[serde(rename = "Convertible Issue")]
438 ConvertibleIssue,
439
440 /// Coupon payment
441 #[serde(rename = "Coupon Payment")]
442 CouponPayment,
443
444 /// Contract consolidation
445 #[serde(rename = "Contract Consolidation")]
446 ContractConsolidation,
447
448 /// Contract split
449 #[serde(rename = "Contract Split")]
450 ContractSplit,
451
452 /// Contract termination
453 #[serde(rename = "CFD Termination")]
454 CfdTermination,
455
456 /// Fee allocation
457 #[serde(rename = "Fee Allocation")]
458 FeeAllocation,
459
460 /// Rights issue
461 #[serde(rename = "Rights Issue")]
462 RightsIssue,
463
464 /// Subscribe rights
465 #[serde(rename = "Subscribe Rights")]
466 SubscribeRights,
467
468 /// Tender
469 Tender,
470
471 /// Tender (issue)
472 #[serde(rename = "Tender (Issue)")]
473 TenderIssue,
474
475 /// Proxy vote
476 #[serde(rename = "Proxy Vote")]
477 ProxyVote,
478
479 /// Generic voluntary
480 #[serde(rename = "Generic Voluntary")]
481 GenericVoluntary,
482
483 /// Asset purchase
484 #[serde(rename = "Asset Purchase")]
485 AssetPurchase,
486
487 /// Purchase (issue)
488 #[serde(rename = "Purchase (Issue)")]
489 PurchaseIssue,
490
491 /// Unknown
492 #[serde(other)]
493 Unknown,
494}
495
496/// Option action type
497#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
498pub enum OptionAction {
499 /// Assignment
500 Assignment,
501
502 /// Exercise
503 Exercise,
504
505 /// Expiration
506 Expiration,
507
508 /// Expire (alternate form)
509 Expire,
510
511 /// Cash settlement
512 #[serde(rename = "Cash Settlement")]
513 CashSettlement,
514
515 /// Buy to open/close
516 Buy,
517
518 /// Sell to open/close
519 Sell,
520
521 /// Unknown
522 #[serde(other)]
523 Unknown,
524}
525
526/// Transfer type
527#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
528pub enum TransferType {
529 /// ACATS transfer (older statements abbreviate this as `ACAT`)
530 #[serde(rename = "ACATS", alias = "ACAT")]
531 ACATS,
532
533 /// ATON transfer
534 ATON,
535
536 /// Free of payment
537 FOP,
538
539 /// Internal transfer
540 INTERNAL,
541
542 /// Intercompany transfer
543 INTERCOMPANY,
544
545 /// Over-the-counter transfer
546 OTC,
547
548 /// Delivery vs payment
549 DVP,
550
551 /// Unknown
552 #[serde(other)]
553 Unknown,
554}
555
556/// Transaction code
557///
558/// Comprehensive list of IB transaction classification codes.
559/// These codes appear in `notes` fields and can be combined (e.g., "C;W" for closing + wash sale).
560/// They provide critical context for tax reporting and trade classification.
561#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)]
562pub enum TransactionCode {
563 /// Assignment - Option assignment triggering stock delivery
564 #[serde(rename = "A")]
565 Assignment,
566
567 /// Adjustment - Manual adjustment affecting cost basis
568 #[serde(rename = "Adj")]
569 Adjustment,
570
571 /// Allocation - Trade allocation to sub-account (master/sub allocation)
572 #[serde(rename = "Al")]
573 Allocation,
574
575 /// Auto Exercise - Automatic exercise (dividend-related, exercise before ex-div)
576 #[serde(rename = "Ae")]
577 AutoExercise,
578
579 /// Auto FX - AutoFX currency conversion for settlement
580 #[serde(rename = "Af")]
581 AutoFx,
582
583 /// Away Trade - Trade executed away from IB (third-party execution)
584 #[serde(rename = "Aw")]
585 AwayTrade,
586
587 /// Buy-In - Forced purchase to cover failed delivery (forced short cover)
588 #[serde(rename = "B")]
589 BuyIn,
590
591 /// Borrow - Securities borrowing fee (lending charge)
592 #[serde(rename = "Bo")]
593 BorrowFee,
594
595 /// Cancellation - Trade cancelled/busted (trade reversed)
596 #[serde(rename = "Ca")]
597 Cancelled,
598
599 /// Closing - Closing trade (reduces position)
600 #[serde(rename = "C")]
601 Closing,
602
603 /// Cash Delivery - Cash delivery for exercise (cash vs physical)
604 #[serde(rename = "Cd")]
605 CashDelivery,
606
607 /// Complex Position - Complex/combo position (multi-leg strategy)
608 #[serde(rename = "Cp")]
609 ComplexPosition,
610
611 /// Correction - Trade correction (amended execution)
612 #[serde(rename = "Cr")]
613 Correction,
614
615 /// Crossing - Internal IB cross (matched internally)
616 #[serde(rename = "Cs")]
617 Crossing,
618
619 /// Dual Agent - IB dual agent capacity (disclosed dual role)
620 #[serde(rename = "D")]
621 DualAgent,
622
623 /// ETF - ETF creation/redemption (in-kind basket)
624 #[serde(rename = "Et")]
625 Etf,
626
627 /// Expired - From expired position (option/warrant expiry)
628 #[serde(rename = "Ex")]
629 Expired,
630
631 /// Exercise - Option exercise (long option exercised)
632 #[serde(rename = "O")]
633 Exercise,
634
635 /// Guaranteed - Guaranteed account segment (special margin)
636 #[serde(rename = "G")]
637 Guaranteed,
638
639 /// Highest Cost - Highest cost tax lot (tax lot selection)
640 #[serde(rename = "Hc")]
641 HighestCost,
642
643 /// HF Investment - Hedge fund investment (fund subscription)
644 #[serde(rename = "Hi")]
645 HfInvestment,
646
647 /// HF Redemption - Hedge fund redemption (fund redemption)
648 #[serde(rename = "Hr")]
649 HfRedemption,
650
651 /// Internal - Internal transfer (between IB accounts)
652 #[serde(rename = "I")]
653 InternalTransfer,
654
655 /// Affiliate - Affiliate execution (related party trade)
656 #[serde(rename = "Ia")]
657 Affiliate,
658
659 /// Investor - Investment from investor (capital contribution)
660 #[serde(rename = "Iv")]
661 Investor,
662
663 /// Margin Violation - Liquidation due to margin (forced liquidation)
664 #[serde(rename = "L")]
665 MarginLiquidation,
666
667 /// LIFO - LIFO tax lot (tax lot selection)
668 #[serde(rename = "Li")]
669 Lifo,
670
671 /// Loan - Securities lending income (lending income)
672 #[serde(rename = "Ln")]
673 Loan,
674
675 /// Long-Term - Long-term gain/loss (holding > 1 year)
676 #[serde(rename = "Lt")]
677 LongTermGain,
678
679 /// Manual - Manual IB entry (manual adjustment)
680 #[serde(rename = "M")]
681 ManualEntry,
682
683 /// Max Loss - Maximize losses (tax optimization)
684 #[serde(rename = "Ml")]
685 MaxLoss,
686
687 /// Min LT Gain - Minimize long-term gain (tax optimization)
688 #[serde(rename = "Mn")]
689 MinLongTermGain,
690
691 /// Max ST Gain - Maximize short-term gain (tax optimization)
692 #[serde(rename = "Ms")]
693 MaxShortTermGain,
694
695 /// Min ST Gain - Minimize short-term gain (tax optimization)
696 #[serde(rename = "Mi")]
697 MinShortTermGain,
698
699 /// Manual Exercise - Manual exercise (discretionary exercise)
700 #[serde(rename = "Mx")]
701 ManualExercise,
702
703 /// Opening - Opening trade (new position)
704 #[serde(rename = "P")]
705 Opening,
706
707 /// Partial - Partial execution (partial fill)
708 #[serde(rename = "Pt")]
709 Partial,
710
711 /// Frac Riskless - Fractional riskless principal (fractional share method)
712 #[serde(rename = "Fr")]
713 FracRiskless,
714
715 /// Frac Principal - Fractional principal (fractional share method)
716 #[serde(rename = "Fp")]
717 FracPrincipal,
718
719 /// Price Improvement - Better than quoted (price improvement)
720 #[serde(rename = "Pi")]
721 PriceImprovement,
722
723 /// Post Accrual - Accrual posting (accrual entry)
724 #[serde(rename = "Pa")]
725 PostAccrual,
726
727 /// Principal - IB principal execution (principal trade)
728 #[serde(rename = "Pr")]
729 Principal,
730
731 /// Reinvestment - Dividend reinvestment (DRIP)
732 #[serde(rename = "Re")]
733 Reinvestment,
734
735 /// Redemption - Capital distribution (fund redemption)
736 #[serde(rename = "Rd")]
737 Redemption,
738
739 /// Reopen - Position reopened (wash sale reopen)
740 #[serde(rename = "R")]
741 Reopen,
742
743 /// Reverse - Accrual reversal (accounting reversal)
744 #[serde(rename = "Rv")]
745 Reverse,
746
747 /// Reimbursement - Fee refund (expense refund)
748 #[serde(rename = "Ri")]
749 Reimbursement,
750
751 /// Solicited IB - IB solicited order (IB-initiated)
752 #[serde(rename = "Si")]
753 SolicitedIb,
754
755 /// Specific Lot - Specific tax lot (tax lot selection)
756 #[serde(rename = "Sp")]
757 SpecificLot,
758
759 /// Solicited Other - Third-party solicited (broker-solicited)
760 #[serde(rename = "So")]
761 SolicitedOther,
762
763 /// Short Settlement - T+0 or T+1 settlement (accelerated settle)
764 #[serde(rename = "Ss")]
765 ShortSettlement,
766
767 /// Short-Term - Short-term gain/loss (holding <= 1 year)
768 #[serde(rename = "St")]
769 ShortTermGain,
770
771 /// Stock Yield - Stock yield eligible (lending eligible)
772 #[serde(rename = "Sy")]
773 StockYield,
774
775 /// Transfer - Position transfer
776 #[serde(rename = "T")]
777 Transfer,
778
779 /// Wash Sale - Wash sale (loss disallowed)
780 #[serde(rename = "W")]
781 WashSale,
782
783 /// Unknown code
784 #[serde(other)]
785 Unknown,
786}
787
788/// Direction (To/From)
789#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
790pub enum ToFrom {
791 /// To
792 To,
793
794 /// From
795 From,
796
797 /// Unknown
798 #[serde(other)]
799 Unknown,
800}
801
802/// Direction (In/Out)
803#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
804pub enum InOut {
805 /// Incoming
806 IN,
807
808 /// Outgoing
809 OUT,
810
811 /// Unknown
812 #[serde(other)]
813 Unknown,
814}
815
816/// Delivered or Received
817#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
818pub enum DeliveredReceived {
819 /// Delivered
820 Delivered,
821
822 /// Received
823 Received,
824
825 /// Unknown
826 #[serde(other)]
827 Unknown,
828}
829
830/// Level of detail for reporting
831///
832/// Specifies the granularity of data in FLEX reports.
833/// Used by `Trade`, `Position`, and `CashTransaction` structs to indicate
834/// the level of detail requested in the FLEX query.
835///
836/// **XML Mapping**: Maps to the `levelOfDetail` attribute in various elements.
837#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
838pub enum LevelOfDetail {
839 /// Summary level - aggregated data with minimal details
840 Summary,
841
842 /// Detail level - standard reporting with all key fields
843 Detail,
844
845 /// Execution level - detailed execution information including time and venue
846 Execution,
847
848 /// Lot level - tax lot level details for cost basis tracking
849 Lot,
850
851 /// Unknown or unrecognized level of detail
852 #[serde(other)]
853 Unknown,
854}
855
856/// Security identifier type
857///
858/// Specifies the type of security identifier used in the `securityID` field.
859/// Different identifiers are used in different markets and contexts.
860///
861/// **XML Mapping**: Maps to the `securityIDType` attribute in various elements.
862///
863/// **Used by**: `Trade`, `SecurityInfo`
864#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
865pub enum SecurityIdType {
866 /// CUSIP - Committee on Uniform Securities Identification Procedures
867 /// 9-character alphanumeric identifier for North American securities
868 #[serde(rename = "CUSIP")]
869 Cusip,
870
871 /// ISIN - International Securities Identification Number
872 /// 12-character alphanumeric code (ISO 6166 standard)
873 #[serde(rename = "ISIN")]
874 Isin,
875
876 /// FIGI - Financial Instrument Global Identifier
877 /// 12-character alphanumeric identifier (Bloomberg Open Symbology)
878 #[serde(rename = "FIGI")]
879 Figi,
880
881 /// SEDOL - Stock Exchange Daily Official List
882 /// 7-character alphanumeric identifier for UK and Irish securities
883 #[serde(rename = "SEDOL")]
884 Sedol,
885
886 /// Unknown or unrecognized security ID type
887 #[serde(other)]
888 Unknown,
889}
890
891/// Security sub-category
892///
893/// Provides additional classification for securities beyond the basic asset category.
894/// Most commonly used for stocks to distinguish between common shares, ETFs, ADRs, REITs, etc.
895///
896/// **XML Mapping**: Maps to the `subCategory` attribute in various elements.
897///
898/// **Used by**: `Trade`, `Position`, `SecurityInfo`
899#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize)]
900pub enum SubCategory {
901 /// Exchange-traded fund
902 #[serde(rename = "ETF")]
903 Etf,
904
905 /// American Depositary Receipt - represents foreign company shares traded in US
906 #[serde(rename = "ADR")]
907 Adr,
908
909 /// Real Estate Investment Trust
910 #[serde(rename = "REIT")]
911 Reit,
912
913 /// Preferred stock
914 #[serde(rename = "Preferred", alias = "PREFERRED")]
915 Preferred,
916
917 /// Common stock
918 #[serde(rename = "Common", alias = "COMMON")]
919 Common,
920
921 /// Depositary Receipt (general)
922 #[serde(rename = "DR")]
923 DepositaryReceipt,
924
925 /// Global Depositary Receipt
926 #[serde(rename = "GDR")]
927 Gdr,
928
929 /// Limited Partnership
930 #[serde(rename = "LP")]
931 LimitedPartnership,
932
933 /// Master Limited Partnership
934 #[serde(rename = "MLP")]
935 MasterLimitedPartnership,
936
937 /// Right (subscription right)
938 #[serde(rename = "Right")]
939 Right,
940
941 /// Unit (combination of securities)
942 #[serde(rename = "Unit")]
943 Unit,
944
945 /// When-Issued security
946 #[serde(rename = "WI")]
947 WhenIssued,
948
949 /// Tracking stock
950 #[serde(rename = "Tracking")]
951 Tracking,
952
953 /// Closed-end fund
954 #[serde(rename = "CEF")]
955 ClosedEndFund,
956
957 /// Unknown or unrecognized sub-category
958 #[serde(other)]
959 Unknown,
960}
961
962/// Derivative instrument information
963///
964/// Contains structured information about derivative contracts (options, futures, warrants).
965/// This enum consolidates derivative-specific fields based on the instrument type.
966///
967/// **Used by**: `Trade`, `Position`
968#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
969#[serde(tag = "type")]
970pub enum DerivativeInfo {
971 /// Option contract (equity or index option)
972 ///
973 /// Standard option giving the right (but not obligation) to buy or sell
974 /// an underlying asset at a specified strike price by the expiration date.
975 Option {
976 /// Strike price - price at which the option can be exercised
977 strike: Decimal,
978
979 /// Expiration date - last date the option can be exercised
980 expiry: NaiveDate,
981
982 /// Put or Call - right to sell (Put) or buy (Call)
983 #[serde(rename = "putCall")]
984 put_call: PutCall,
985
986 /// Symbol of the underlying security (e.g., "AAPL" for Apple stock)
987 #[serde(rename = "underlyingSymbol")]
988 underlying_symbol: String,
989
990 /// IB contract ID of the underlying security
991 #[serde(rename = "underlyingConid")]
992 underlying_conid: Option<String>,
993 },
994
995 /// Future contract
996 ///
997 /// Agreement to buy or sell an asset at a predetermined price
998 /// on a specified future date.
999 Future {
1000 /// Expiration date - settlement date for the futures contract
1001 expiry: NaiveDate,
1002
1003 /// Symbol of the underlying asset
1004 #[serde(rename = "underlyingSymbol")]
1005 underlying_symbol: String,
1006
1007 /// IB contract ID of the underlying asset
1008 #[serde(rename = "underlyingConid")]
1009 underlying_conid: Option<String>,
1010 },
1011
1012 /// Future option (option on a futures contract)
1013 ///
1014 /// Option where the underlying asset is a futures contract rather than a stock.
1015 FutureOption {
1016 /// Strike price for the option
1017 strike: Decimal,
1018
1019 /// Expiration date of the option
1020 expiry: NaiveDate,
1021
1022 /// Put or Call
1023 #[serde(rename = "putCall")]
1024 put_call: PutCall,
1025
1026 /// Symbol of the underlying futures contract
1027 #[serde(rename = "underlyingSymbol")]
1028 underlying_symbol: String,
1029
1030 /// IB contract ID of the underlying futures
1031 #[serde(rename = "underlyingConid")]
1032 underlying_conid: Option<String>,
1033 },
1034
1035 /// Warrant
1036 ///
1037 /// Long-term option-like security issued by a company, typically
1038 /// with longer expiration periods than standard options.
1039 Warrant {
1040 /// Strike price (if applicable)
1041 strike: Option<Decimal>,
1042
1043 /// Expiration date (if applicable)
1044 expiry: Option<NaiveDate>,
1045
1046 /// Symbol of the underlying security (if applicable)
1047 #[serde(rename = "underlyingSymbol")]
1048 underlying_symbol: Option<String>,
1049 },
1050}
1051
1052#[cfg(test)]
1053mod tests {
1054 use super::*;
1055
1056 #[test]
1057 fn test_asset_category_basic() {
1058 // Test enum construction and comparison
1059 let stock = AssetCategory::Stock;
1060 assert_eq!(stock, AssetCategory::Stock);
1061 assert_ne!(stock, AssetCategory::Option);
1062 }
1063
1064 #[test]
1065 fn test_buy_sell_basic() {
1066 // Test enum construction and comparison
1067 let buy = BuySell::Buy;
1068 assert_eq!(buy, BuySell::Buy);
1069 assert_ne!(buy, BuySell::Sell);
1070 }
1071
1072 #[test]
1073 fn test_open_close_basic() {
1074 let open = OpenClose::Open;
1075 assert_eq!(open, OpenClose::Open);
1076 assert_ne!(open, OpenClose::Close);
1077 }
1078
1079 #[test]
1080 fn test_put_call_basic() {
1081 let call = PutCall::Call;
1082 assert_eq!(call, PutCall::Call);
1083 assert_ne!(call, PutCall::Put);
1084 }
1085}