use chrono::{DateTime, Utc}; use serde::{Serialize, Deserialize}; use crate::MarketData; #[derive(Debug, Clone, Serialize, Deserialize)] pub enum SignalType { Buy, Sell, Close, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Signal { pub symbol: String, pub signal_type: SignalType, pub strength: f64, // -1.0 to 1.0 pub quantity: Option, pub reason: Option, pub metadata: Option, } // This trait will be implemented by Rust strategies // TypeScript strategies will communicate through FFI pub trait Strategy: Send + Sync { fn on_market_data(&mut self, data: &MarketData) -> Vec; fn on_fill(&mut self, symbol: &str, quantity: f64, price: f64, side: &str); fn get_name(&self) -> &str; fn get_parameters(&self) -> serde_json::Value; } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct StrategyCall { pub method: String, pub data: serde_json::Value, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct StrategyResponse { pub signals: Vec, } // Bridge for TypeScript strategies // This will be used to wrap TypeScript strategies pub struct TypeScriptStrategy { pub name: String, pub id: String, pub parameters: serde_json::Value, // Callback function will be injected from TypeScript pub callback: Option StrategyResponse + Send + Sync>>, } impl TypeScriptStrategy { pub fn new(name: String, id: String, parameters: serde_json::Value) -> Self { Self { name, id, parameters, callback: None, } } } impl Strategy for TypeScriptStrategy { fn on_market_data(&mut self, data: &MarketData) -> Vec { if let Some(callback) = &self.callback { let call = StrategyCall { method: "on_market_data".to_string(), data: serde_json::to_value(data).unwrap_or_default(), }; let response = callback(call); response.signals } else { Vec::new() } } fn on_fill(&mut self, symbol: &str, quantity: f64, price: f64, side: &str) { if let Some(callback) = &self.callback { let call = StrategyCall { method: "on_fill".to_string(), data: serde_json::json!({ "symbol": symbol, "quantity": quantity, "price": price, "side": side }), }; callback(call); } } fn get_name(&self) -> &str { &self.name } fn get_parameters(&self) -> serde_json::Value { self.parameters.clone() } }