1#![warn(rustc::all)]
50#![deny(unsafe_code)]
51#![deny(unsafe_op_in_unsafe_fn)]
52#![deny(nonstandard_style)]
53#![deny(missing_debug_implementations)]
54#![deny(clippy::missing_errors_doc)]
55#![deny(clippy::missing_panics_doc)]
56#![deny(rustdoc::broken_intra_doc_links)]
57
58use std::{path::Path, time::Duration};
59
60#[cfg(feature = "mimalloc")]
61use mimalloc::MiMalloc;
62use nautilus_common::live::runtime::shutdown_runtime;
63use nautilus_system::python::controller::PyController;
64use pyo3::{prelude::*, pyfunction};
65
66#[cfg(feature = "mimalloc")]
67#[global_allocator]
68static GLOBAL: MiMalloc = MiMalloc;
69
70const RUNTIME_SHUTDOWN_TIMEOUT_SECS: u64 = 10;
71
72#[pyfunction]
73fn _shutdown_nautilus_runtime() {
74 shutdown_runtime(Duration::from_secs(RUNTIME_SHUTDOWN_TIMEOUT_SECS));
75}
76
77#[pymodule] fn _libnautilus(py: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> {
82 #[cfg(feature = "mimalloc")]
83 nautilus_common::logging::headers::register_allocator_mimalloc();
84
85 let sys = PyModule::import(py, "sys")?;
86 let modules = sys.getattr("modules")?;
87 let sys_modules: &Bound<'_, PyAny> = modules.cast()?;
88
89 let module_name = "nautilus_trader._libnautilus";
90
91 sys_modules.set_item(module_name, m)?;
93
94 let n = "analysis";
96 let submodule = pyo3::wrap_pymodule!(nautilus_analysis::python::analysis);
97 m.add_wrapped(submodule)?;
98 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
99
100 let n = "core";
101 let submodule = pyo3::wrap_pymodule!(nautilus_core::python::core);
102 m.add_wrapped(submodule)?;
103 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
104
105 let n = "common";
106 let submodule = pyo3::wrap_pymodule!(nautilus_common::python::common);
107 m.add_wrapped(submodule)?;
108 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
109
110 let n = "cryptography";
111 let submodule = pyo3::wrap_pymodule!(nautilus_cryptography::python::cryptography);
112 m.add_wrapped(submodule)?;
113 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
114
115 let n = "data";
116 let submodule = pyo3::wrap_pymodule!(nautilus_data::python::data);
117 m.add_wrapped(submodule)?;
118 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
119
120 let n = "execution";
121 let submodule = pyo3::wrap_pymodule!(nautilus_execution::python::execution);
122 m.add_wrapped(submodule)?;
123 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
124
125 let n = "indicators";
126 let submodule = pyo3::wrap_pymodule!(nautilus_indicators::python::indicators);
127 m.add_wrapped(submodule)?;
128 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
129
130 let n = "infrastructure";
131 let submodule = pyo3::wrap_pymodule!(nautilus_infrastructure::python::infrastructure);
132 m.add_wrapped(submodule)?;
133 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
134
135 let n = "live";
136 let submodule = pyo3::wrap_pymodule!(nautilus_live::python::live);
137 m.add_wrapped(submodule)?;
138 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
139
140 let n = "model";
141 let submodule = pyo3::wrap_pymodule!(nautilus_model::python::model);
142 m.add_wrapped(submodule)?;
143 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
144
145 let n = "network";
146 let submodule = pyo3::wrap_pymodule!(nautilus_network::python::network);
147 m.add_wrapped(submodule)?;
148 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
149
150 let n = "persistence";
151 let submodule = pyo3::wrap_pymodule!(nautilus_persistence::python::persistence);
152 m.add_wrapped(submodule)?;
153 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
154
155 let n = "portfolio";
156 let submodule = pyo3::wrap_pymodule!(nautilus_portfolio::python::portfolio);
157 m.add_wrapped(submodule)?;
158 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
159
160 let n = "risk";
161 let submodule = pyo3::wrap_pymodule!(nautilus_risk::python::risk);
162 m.add_wrapped(submodule)?;
163 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
164
165 let n = "serialization";
166 let submodule = pyo3::wrap_pymodule!(nautilus_serialization::python::serialization);
167 m.add_wrapped(submodule)?;
168 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
169
170 let n = "testkit";
171 let submodule = pyo3::wrap_pymodule!(nautilus_testkit::python::testkit);
172 m.add_wrapped(submodule)?;
173 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
174
175 let n = "trading";
176 let submodule = pyo3::wrap_pymodule!(nautilus_trading::python::trading);
177 m.add_wrapped(submodule)?;
178
179 m.getattr(n)?
182 .cast::<PyModule>()?
183 .add_class::<PyController>()?;
184 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
185
186 let n = "backtest";
187 let submodule = pyo3::wrap_pymodule!(nautilus_backtest::python::backtest);
188 m.add_wrapped(submodule)?;
189 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
190
191 let n = "architect_ax";
196 let submodule = pyo3::wrap_pymodule!(nautilus_architect_ax::python::architect_ax);
197 m.add_wrapped(submodule)?;
198 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
199
200 #[cfg(feature = "betfair")]
201 {
202 let n = "betfair";
203 let submodule = pyo3::wrap_pymodule!(nautilus_betfair::python::betfair);
204 m.add_wrapped(submodule)?;
205 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
206 }
207
208 let n = "binance";
209 let submodule = pyo3::wrap_pymodule!(nautilus_binance::python::binance);
210 m.add_wrapped(submodule)?;
211 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
212
213 let n = "bybit";
214 let submodule = pyo3::wrap_pymodule!(nautilus_bybit::python::bybit);
215 m.add_wrapped(submodule)?;
216 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
217
218 #[cfg(feature = "coinapi")]
219 {
220 let n = "coinapi";
221 let submodule = pyo3::wrap_pymodule!(nautilus_coinapi::python::coinapi);
222 m.add_wrapped(submodule)?;
223 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
224 }
225
226 let n = "coinbase";
227 let submodule = pyo3::wrap_pymodule!(nautilus_coinbase::python::coinbase);
228 m.add_wrapped(submodule)?;
229 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
230
231 let n = "databento";
232 let submodule = pyo3::wrap_pymodule!(nautilus_databento::python::databento);
233 m.add_wrapped(submodule)?;
234 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
235
236 let n = "deribit";
237 let submodule = pyo3::wrap_pymodule!(nautilus_deribit::python::deribit);
238 m.add_wrapped(submodule)?;
239 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
240
241 let n = "derive";
242 let submodule = pyo3::wrap_pymodule!(nautilus_derive::python::derive);
243 m.add_wrapped(submodule)?;
244 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
245
246 let n = "dydx";
247 let submodule = pyo3::wrap_pymodule!(nautilus_dydx::python::dydx);
248 m.add_wrapped(submodule)?;
249 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
250
251 let n = "hyperliquid";
252 let submodule = pyo3::wrap_pymodule!(nautilus_hyperliquid::python::hyperliquid);
253 m.add_wrapped(submodule)?;
254 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
255
256 let n = "kraken";
257 let submodule = pyo3::wrap_pymodule!(nautilus_kraken::python::kraken);
258 m.add_wrapped(submodule)?;
259 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
260
261 let n = "lighter";
262 let submodule = pyo3::wrap_pymodule!(nautilus_lighter::python::lighter);
263 m.add_wrapped(submodule)?;
264 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
265
266 let n = "interactive_brokers";
267 let submodule = pyo3::wrap_pymodule!(nautilus_interactive_brokers::python::interactive_brokers);
268 m.add_wrapped(submodule)?;
269 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
270
271 let n = "okx";
272 let submodule = pyo3::wrap_pymodule!(nautilus_okx::python::okx);
273 m.add_wrapped(submodule)?;
274 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
275
276 let n = "polymarket";
277 let submodule = pyo3::wrap_pymodule!(nautilus_polymarket::python::polymarket);
278 m.add_wrapped(submodule)?;
279 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
280
281 let n = "sandbox";
282 let submodule = pyo3::wrap_pymodule!(nautilus_sandbox::python::sandbox);
283 m.add_wrapped(submodule)?;
284 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
285
286 let n = "tardis";
287 let submodule = pyo3::wrap_pymodule!(nautilus_tardis::python::tardis);
288 m.add_wrapped(submodule)?;
289 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
290
291 #[cfg(feature = "defi")]
292 {
293 let n = "blockchain";
295 let submodule = pyo3::wrap_pymodule!(nautilus_blockchain::python::blockchain);
296 m.add_wrapped(submodule)?;
297 sys_modules.set_item(format!("{module_name}.{n}"), m.getattr(n)?)?;
298 }
299
300 m.add_function(pyo3::wrap_pyfunction!(_shutdown_nautilus_runtime, m)?)?;
303 let shutdown_callable = m.getattr("_shutdown_nautilus_runtime")?;
304 let atexit = PyModule::import(py, "atexit")?;
305 atexit.call_method1("register", (shutdown_callable,))?;
306
307 Ok(())
308}
309
310pub fn stub_info() -> pyo3_stub_gen::Result<pyo3_stub_gen::StubInfo> {
328 let workspace_root = Path::new(env!("CARGO_MANIFEST_DIR"))
329 .parent()
330 .unwrap()
331 .parent()
332 .unwrap();
333 let pyproject_path = workspace_root.join("python").join("pyproject.toml");
334
335 pyo3_stub_gen::StubInfo::from_pyproject_toml(&pyproject_path)
336}