neural_trader/
strategy.rs1use napi::bindgen_prelude::*;
4use napi::threadsafe_function::{ErrorStrategy, ThreadsafeFunction};
5use napi_derive::napi;
6use std::sync::Arc;
7use tokio::sync::Mutex;
8
9#[napi(object)]
11pub struct Signal {
12 pub id: String,
13 pub strategy_id: String,
14 pub symbol: String,
15 pub direction: String, pub confidence: f64, pub entry_price: Option<f64>,
18 pub stop_loss: Option<f64>,
19 pub take_profit: Option<f64>,
20 pub reasoning: String,
21 pub timestamp_ns: i64,
22}
23
24#[napi(object)]
26pub struct StrategyConfig {
27 pub name: String,
28 pub symbols: Vec<String>,
29 pub parameters: String, }
31
32#[napi]
34pub struct StrategyRunner {
35 strategies: Arc<Mutex<Vec<String>>>,
38}
39
40#[napi]
41impl StrategyRunner {
42 #[napi(constructor)]
44 pub fn new() -> Self {
45 Self {
46 strategies: Arc::new(Mutex::new(Vec::new())),
47 }
48 }
49
50 #[napi]
52 pub async fn add_momentum_strategy(&self, config: StrategyConfig) -> Result<String> {
53 let strategy_id = format!("momentum-{}", generate_uuid());
54
55 let mut strategies = self.strategies.lock().await;
56 strategies.push(strategy_id.clone());
57
58 tracing::info!("Added momentum strategy: {} with config: {:?}", strategy_id, config.name);
59
60 Ok(strategy_id)
61 }
62
63 #[napi]
65 pub async fn add_mean_reversion_strategy(&self, _config: StrategyConfig) -> Result<String> {
66 let strategy_id = format!("mean-reversion-{}", generate_uuid());
67
68 let mut strategies = self.strategies.lock().await;
69 strategies.push(strategy_id.clone());
70
71 tracing::info!("Added mean reversion strategy: {}", strategy_id);
72
73 Ok(strategy_id)
74 }
75
76 #[napi]
78 pub async fn add_arbitrage_strategy(&self, _config: StrategyConfig) -> Result<String> {
79 let strategy_id = format!("arbitrage-{}", generate_uuid());
80
81 let mut strategies = self.strategies.lock().await;
82 strategies.push(strategy_id.clone());
83
84 tracing::info!("Added arbitrage strategy: {}", strategy_id);
85
86 Ok(strategy_id)
87 }
88
89 #[napi]
91 pub async fn generate_signals(&self) -> Result<Vec<Signal>> {
92 let strategies = self.strategies.lock().await;
93 let mut all_signals = Vec::new();
94
95 for strategy_id in strategies.iter() {
98 tracing::debug!("Generating signals for strategy: {}", strategy_id);
99 }
100
101 Ok(all_signals)
102 }
103
104 #[napi]
106 pub fn subscribe_signals(&self, callback: JsFunction) -> Result<SubscriptionHandle> {
107 let _tsfn: ThreadsafeFunction<Signal, ErrorStrategy::CalleeHandled> =
108 callback.create_threadsafe_function(0, |ctx| Ok(vec![ctx.value]))?;
109
110 let strategies = self.strategies.clone();
112 let handle = tokio::spawn(async move {
113 loop {
114 tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
115
116 let _strategies = strategies.lock().await;
118
119 }
121 });
122
123 Ok(SubscriptionHandle {
124 handle: Arc::new(Mutex::new(Some(handle))),
125 })
126 }
127
128 #[napi]
130 pub async fn list_strategies(&self) -> Result<Vec<String>> {
131 let strategies = self.strategies.lock().await;
132 Ok(strategies.clone())
133 }
134
135 #[napi]
137 pub async fn remove_strategy(&self, strategy_id: String) -> Result<bool> {
138 let mut strategies = self.strategies.lock().await;
139 if let Some(pos) = strategies.iter().position(|id| id == &strategy_id) {
140 strategies.remove(pos);
141 tracing::info!("Removed strategy: {}", strategy_id);
142 Ok(true)
143 } else {
144 Ok(false)
145 }
146 }
147}
148
149#[napi]
151pub struct SubscriptionHandle {
152 handle: Arc<Mutex<Option<tokio::task::JoinHandle<()>>>>,
153}
154
155#[napi]
156impl SubscriptionHandle {
157 #[napi]
159 pub async fn unsubscribe(&self) -> Result<()> {
160 let mut guard = self.handle.lock().await;
161 if let Some(handle) = guard.take() {
162 handle.abort();
163 tracing::info!("Unsubscribed from signals");
164 }
165 Ok(())
166 }
167}
168
169fn generate_uuid() -> String {
171 use std::time::{SystemTime, UNIX_EPOCH};
172 let nanos = SystemTime::now()
173 .duration_since(UNIX_EPOCH)
174 .unwrap()
175 .as_nanos();
176 format!("{:x}", nanos)
177}