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