use serde::Deserialize;
use serde::Serialize;
use serde_with::{TimestampMilliSeconds, serde_as};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct OptionResponse {
pub ssid: i64,
pub symbol: String,
pub realtime: bool,
pub quote: QuoteOption,
pub reference: ReferenceOption,
}
#[serde_as]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct QuoteOption {
#[serde(rename = "52WeekHigh")]
pub n52week_high: Option<f64>,
#[serde(rename = "52WeekLow")]
pub n52week_low: Option<f64>,
pub ask_price: f64,
pub ask_size: i64,
pub bid_price: f64,
pub bid_size: i64,
pub close_price: f64,
pub delta: f64,
pub gamma: f64,
pub high_price: f64,
pub ind_ask_price: f64,
pub ind_bid_price: f64,
#[serde_as(as = "TimestampMilliSeconds<i64>")]
pub ind_quote_time: chrono::DateTime<chrono::Utc>,
pub implied_yield: f64,
pub last_price: f64,
pub last_size: i64,
pub low_price: f64,
pub mark: f64,
pub mark_change: f64,
pub mark_percent_change: f64,
pub money_intrinsic_value: f64,
pub net_change: f64,
pub net_percent_change: f64,
pub open_interest: f64,
pub open_price: f64,
#[serde_as(as = "TimestampMilliSeconds<i64>")]
pub quote_time: chrono::DateTime<chrono::Utc>,
pub rho: f64,
pub security_status: String,
pub theoretical_option_value: f64,
pub theta: f64,
pub time_value: f64,
pub total_volume: u64,
#[serde_as(as = "TimestampMilliSeconds<i64>")]
pub trade_time: chrono::DateTime<chrono::Utc>,
pub underlying_price: f64,
pub vega: f64,
pub volatility: f64,
}
#[serde_as]
#[serde_with::apply(
Option => #[serde(skip_serializing_if = "Option::is_none")],
)]
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ReferenceOption {
pub contract_type: ContractType,
pub cusip: Option<String>,
pub days_to_expiration: i64,
pub deliverables: Option<String>,
pub description: String,
pub exchange: String,
pub exchange_name: String,
pub exercise_type: Option<ExerciseType>,
pub expiration_day: u8,
pub expiration_month: u8,
pub expiration_type: Option<ExpirationType>,
pub expiration_year: i64,
pub is_penny_pilot: bool,
#[serde_as(as = "TimestampMilliSeconds<i64>")]
pub last_trading_day: chrono::DateTime<chrono::Utc>,
pub multiplier: f64,
pub settlement_type: SettlementType,
pub strike_price: f64,
pub underlying: String,
pub uv_expiration_type: Option<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum ContractType {
#[serde(rename = "P")]
Put,
#[serde(rename = "C")]
Call,
}
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum ExerciseType {
#[serde(rename = "A")]
America,
#[serde(rename = "E")]
European,
}
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum ExpirationType {
#[serde(rename = "M")]
Month,
#[serde(rename = "Q")]
Quarterly,
#[serde(rename = "W")]
Weekly,
#[serde(rename = "S")]
ThirdFriday,
}
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum SettlementType {
#[serde(rename = "A")]
AM,
#[serde(rename = "P")]
PM,
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashMap;
#[test]
fn test_de() {
let json = include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/model/MarketData/QuoteResponse/OptionResponse.json"
));
let val = serde_json::from_str::<HashMap<String, OptionResponse>>(json);
println!("{val:?}");
assert!(val.is_ok());
}
}