nautilus_trading/python/
algorithm.rs1use std::collections::HashMap;
19
20use nautilus_core::python::to_pyvalue_err;
21use nautilus_model::identifiers::ExecAlgorithmId;
22use pyo3::{prelude::*, types::PyDict};
23
24use crate::algorithm::{ExecutionAlgorithmConfig, ImportableExecAlgorithmConfig};
25
26#[pyo3::pymethods]
27#[pyo3_stub_gen::derive::gen_stub_pymethods]
28impl ExecutionAlgorithmConfig {
29 #[new]
31 #[pyo3(signature = (exec_algorithm_id=None, log_events=true, log_commands=true))]
32 fn py_new(
33 exec_algorithm_id: Option<ExecAlgorithmId>,
34 log_events: bool,
35 log_commands: bool,
36 ) -> Self {
37 Self {
38 exec_algorithm_id,
39 log_events,
40 log_commands,
41 }
42 }
43
44 #[getter]
45 fn exec_algorithm_id(&self) -> Option<ExecAlgorithmId> {
46 self.exec_algorithm_id
47 }
48
49 #[getter]
50 fn log_events(&self) -> bool {
51 self.log_events
52 }
53
54 #[getter]
55 fn log_commands(&self) -> bool {
56 self.log_commands
57 }
58}
59
60#[pyo3::pymethods]
61#[pyo3_stub_gen::derive::gen_stub_pymethods]
62impl ImportableExecAlgorithmConfig {
63 #[new]
65 #[expect(clippy::needless_pass_by_value)]
66 fn py_new(
67 exec_algorithm_path: String,
68 config_path: String,
69 config: Py<PyDict>,
70 ) -> PyResult<Self> {
71 let json_config = Python::attach(|py| -> PyResult<HashMap<String, serde_json::Value>> {
72 let kwargs = PyDict::new(py);
73 kwargs.set_item("default", py.eval(pyo3::ffi::c_str!("str"), None, None)?)?;
74 let json_str: String = PyModule::import(py, "json")?
75 .call_method("dumps", (config.bind(py),), Some(&kwargs))?
76 .extract()?;
77
78 let json_value: serde_json::Value =
79 serde_json::from_str(&json_str).map_err(to_pyvalue_err)?;
80
81 if let serde_json::Value::Object(map) = json_value {
82 Ok(map.into_iter().collect())
83 } else {
84 Err(to_pyvalue_err("Config must be a dictionary"))
85 }
86 })?;
87
88 Ok(Self {
89 exec_algorithm_path,
90 config_path,
91 config: json_config,
92 })
93 }
94
95 #[getter]
96 fn exec_algorithm_path(&self) -> &String {
97 &self.exec_algorithm_path
98 }
99
100 #[getter]
101 fn config_path(&self) -> &String {
102 &self.config_path
103 }
104
105 #[getter]
106 fn config(&self, py: Python<'_>) -> PyResult<Py<PyDict>> {
107 let py_dict = PyDict::new(py);
108
109 for (key, value) in &self.config {
110 let json_str = serde_json::to_string(value).map_err(to_pyvalue_err)?;
111 let py_value = PyModule::import(py, "json")?.call_method("loads", (json_str,), None)?;
112 py_dict.set_item(key, py_value)?;
113 }
114 Ok(py_dict.unbind())
115 }
116}