rustrade_execution/client/ibkr/
contract.rs1use ibapi::contracts::{Contract, Currency, Exchange, OptionRight, SecurityType, Symbol};
4use thiserror::Error;
5
6#[derive(Debug, Clone, PartialEq, Eq, Error)]
18#[non_exhaustive]
19pub enum ContractConfigError {
20 #[error("OPT contract requires a `right` field (expected one of C/CALL/P/PUT)")]
22 MissingOptionRight,
23
24 #[error("unrecognized option right {right:?} (expected one of C/CALL/P/PUT)")]
26 UnrecognizedOptionRight { right: String },
27
28 #[error("OPT contract requires a `strike` field")]
30 MissingStrike,
31
32 #[error("FUT/OPT contract requires a `last_trade_date` field")]
34 MissingLastTradeDate,
35
36 #[error("unrecognized security_type {security_type:?} (expected one of STK/FUT/OPT/CASH)")]
38 UnrecognizedSecurityType { security_type: String },
39}
40
41fn parse_option_right(right: &str) -> Option<OptionRight> {
46 let right = right.trim();
47 if right.eq_ignore_ascii_case("C") || right.eq_ignore_ascii_case("CALL") {
48 Some(OptionRight::Call)
49 } else if right.eq_ignore_ascii_case("P") || right.eq_ignore_ascii_case("PUT") {
50 Some(OptionRight::Put)
51 } else {
52 None
53 }
54}
55
56pub fn stock_contract(symbol: &str, exchange: &str, currency: &str) -> Contract {
58 Contract::stock(symbol)
59 .on_exchange(exchange)
60 .in_currency(currency)
61 .build()
62}
63
64pub fn futures_contract(
66 symbol: &str,
67 last_trade_date: &str,
68 exchange: &str,
69 currency: &str,
70) -> Contract {
71 Contract {
72 symbol: Symbol::new(symbol),
73 security_type: SecurityType::Future,
74 last_trade_date_or_contract_month: last_trade_date.to_string(),
75 exchange: Exchange::new(exchange),
76 currency: Currency::new(currency),
77 ..Default::default()
78 }
79}
80
81pub fn option_contract(
97 symbol: &str,
98 last_trade_date: &str,
99 strike: f64,
100 right: &str,
101 exchange: &str,
102 currency: &str,
103) -> Result<Contract, ContractConfigError> {
104 let right =
105 parse_option_right(right).ok_or_else(|| ContractConfigError::UnrecognizedOptionRight {
106 right: right.to_string(),
107 })?;
108 Ok(Contract {
109 symbol: Symbol::new(symbol),
110 security_type: SecurityType::Option,
111 last_trade_date_or_contract_month: last_trade_date.to_string(),
112 strike,
113 right: Some(right),
114 exchange: Exchange::new(exchange),
115 currency: Currency::new(currency),
116 ..Default::default()
117 })
118}
119
120pub fn forex_contract(symbol: &str, currency: &str) -> Contract {
122 Contract {
123 symbol: Symbol::new(symbol),
124 security_type: SecurityType::ForexPair,
125 exchange: Exchange::new("IDEALPRO"),
126 currency: Currency::new(currency),
127 ..Default::default()
128 }
129}