feat(ml): add trading_symbol field to UniverseAsset for micro contract mapping
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -25,9 +25,12 @@ pub enum AssetClass {
|
||||
/// A single asset in the trading universe.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct UniverseAsset {
|
||||
/// Ticker symbol (e.g. "AAPL").
|
||||
/// Ticker symbol (e.g. "ES.FUT") -- used for data/training.
|
||||
pub symbol: String,
|
||||
/// MIC exchange code (e.g. "XNAS").
|
||||
/// Execution symbol (e.g. "MES.FUT") -- used for order routing.
|
||||
/// When `None`, orders are routed to `symbol` directly.
|
||||
pub trading_symbol: Option<String>,
|
||||
/// MIC exchange code (e.g. "GLBX.MDP3").
|
||||
pub exchange: String,
|
||||
/// Asset classification.
|
||||
pub asset_class: AssetClass,
|
||||
@@ -39,6 +42,15 @@ pub struct UniverseAsset {
|
||||
pub enabled: bool,
|
||||
}
|
||||
|
||||
impl UniverseAsset {
|
||||
/// The symbol to use for order execution.
|
||||
/// Returns `trading_symbol` if set, otherwise `symbol`.
|
||||
#[must_use]
|
||||
pub fn execution_symbol(&self) -> &str {
|
||||
self.trading_symbol.as_deref().unwrap_or(&self.symbol)
|
||||
}
|
||||
}
|
||||
|
||||
/// The full set of assets available for trading.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct AssetUniverse {
|
||||
@@ -84,6 +96,7 @@ impl AssetUniverse {
|
||||
assets: vec![
|
||||
UniverseAsset {
|
||||
symbol: "SPY".to_string(),
|
||||
trading_symbol: None,
|
||||
exchange: "XNYS".to_string(),
|
||||
asset_class: AssetClass::ETF,
|
||||
sector: None,
|
||||
@@ -92,6 +105,7 @@ impl AssetUniverse {
|
||||
},
|
||||
UniverseAsset {
|
||||
symbol: "QQQ".to_string(),
|
||||
trading_symbol: None,
|
||||
exchange: "XNAS".to_string(),
|
||||
asset_class: AssetClass::ETF,
|
||||
sector: None,
|
||||
@@ -100,6 +114,7 @@ impl AssetUniverse {
|
||||
},
|
||||
UniverseAsset {
|
||||
symbol: "AAPL".to_string(),
|
||||
trading_symbol: None,
|
||||
exchange: "XNAS".to_string(),
|
||||
asset_class: AssetClass::Equity,
|
||||
sector: Some("Technology".to_string()),
|
||||
@@ -108,6 +123,7 @@ impl AssetUniverse {
|
||||
},
|
||||
UniverseAsset {
|
||||
symbol: "MSFT".to_string(),
|
||||
trading_symbol: None,
|
||||
exchange: "XNAS".to_string(),
|
||||
asset_class: AssetClass::Equity,
|
||||
sector: Some("Technology".to_string()),
|
||||
@@ -116,6 +132,7 @@ impl AssetUniverse {
|
||||
},
|
||||
UniverseAsset {
|
||||
symbol: "NVDA".to_string(),
|
||||
trading_symbol: None,
|
||||
exchange: "XNAS".to_string(),
|
||||
asset_class: AssetClass::Equity,
|
||||
sector: Some("Technology".to_string()),
|
||||
@@ -124,6 +141,7 @@ impl AssetUniverse {
|
||||
},
|
||||
UniverseAsset {
|
||||
symbol: "AMZN".to_string(),
|
||||
trading_symbol: None,
|
||||
exchange: "XNAS".to_string(),
|
||||
asset_class: AssetClass::Equity,
|
||||
sector: Some("Consumer".to_string()),
|
||||
@@ -132,6 +150,7 @@ impl AssetUniverse {
|
||||
},
|
||||
UniverseAsset {
|
||||
symbol: "IWM".to_string(),
|
||||
trading_symbol: None,
|
||||
exchange: "XNYS".to_string(),
|
||||
asset_class: AssetClass::ETF,
|
||||
sector: None,
|
||||
@@ -209,4 +228,32 @@ mod tests {
|
||||
serde_json::from_str(&json).unwrap_or_else(|_| AssetUniverse::new());
|
||||
assert_eq!(restored.assets.len(), 7);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_trading_symbol_mapping() {
|
||||
let asset = UniverseAsset {
|
||||
symbol: "ES.FUT".to_string(),
|
||||
trading_symbol: Some("MES.FUT".to_string()),
|
||||
exchange: "GLBX.MDP3".to_string(),
|
||||
asset_class: AssetClass::Future,
|
||||
sector: None,
|
||||
min_daily_volume: 1_000_000.0,
|
||||
enabled: true,
|
||||
};
|
||||
assert_eq!(asset.execution_symbol(), "MES.FUT");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_trading_symbol_none_falls_back() {
|
||||
let asset = UniverseAsset {
|
||||
symbol: "ZN.FUT".to_string(),
|
||||
trading_symbol: None,
|
||||
exchange: "GLBX.MDP3".to_string(),
|
||||
asset_class: AssetClass::Future,
|
||||
sector: None,
|
||||
min_daily_volume: 500_000.0,
|
||||
enabled: true,
|
||||
};
|
||||
assert_eq!(asset.execution_symbol(), "ZN.FUT");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user