1use nautilus_common::{cache::CacheConfig, enums::Environment, logging::logger::LoggerConfig};
17use nautilus_core::UUID4;
18use posei_trader::engine::config::DataEngineConfig;
19use nautilus_execution::engine::config::ExecutionEngineConfig;
20use nautilus_model::identifiers::TraderId;
21use nautilus_portfolio::config::PortfolioConfig;
22use nautilus_risk::engine::config::RiskEngineConfig;
23
24use crate::{config::KernelConfig, kernel::PoseiKernel};
25
26#[derive(Debug)]
31pub struct PoseiKernelBuilder {
32 name: String,
33 trader_id: TraderId,
34 environment: Environment,
35 instance_id: Option<UUID4>,
36 load_state: bool,
37 save_state: bool,
38 logging: Option<LoggerConfig>,
39 timeout_connection: u32,
40 timeout_reconciliation: u32,
41 timeout_portfolio: u32,
42 timeout_disconnection: u32,
43 timeout_post_stop: u32,
44 timeout_shutdown: u32,
45 cache: Option<CacheConfig>,
46 data_engine: Option<DataEngineConfig>,
47 risk_engine: Option<RiskEngineConfig>,
48 exec_engine: Option<ExecutionEngineConfig>,
49 portfolio: Option<PortfolioConfig>,
50}
51
52impl PoseiKernelBuilder {
53 #[must_use]
55 pub const fn new(name: String, trader_id: TraderId, environment: Environment) -> Self {
56 Self {
57 name,
58 trader_id,
59 environment,
60 instance_id: None,
61 load_state: true,
62 save_state: true,
63 logging: None,
64 timeout_connection: 60,
65 timeout_reconciliation: 30,
66 timeout_portfolio: 10,
67 timeout_disconnection: 10,
68 timeout_post_stop: 10,
69 timeout_shutdown: 5,
70 cache: None,
71 data_engine: None,
72 risk_engine: None,
73 exec_engine: None,
74 portfolio: None,
75 }
76 }
77
78 #[must_use]
80 pub const fn with_instance_id(mut self, instance_id: UUID4) -> Self {
81 self.instance_id = Some(instance_id);
82 self
83 }
84
85 #[must_use]
87 pub const fn with_load_state(mut self, load_state: bool) -> Self {
88 self.load_state = load_state;
89 self
90 }
91
92 #[must_use]
94 pub const fn with_save_state(mut self, save_state: bool) -> Self {
95 self.save_state = save_state;
96 self
97 }
98
99 #[must_use]
101 pub fn with_logging_config(mut self, config: LoggerConfig) -> Self {
102 self.logging = Some(config);
103 self
104 }
105
106 #[must_use]
108 pub const fn with_timeout_connection(mut self, timeout: u32) -> Self {
109 self.timeout_connection = timeout;
110 self
111 }
112
113 #[must_use]
115 pub const fn with_timeout_reconciliation(mut self, timeout: u32) -> Self {
116 self.timeout_reconciliation = timeout;
117 self
118 }
119
120 #[must_use]
122 pub const fn with_timeout_portfolio(mut self, timeout: u32) -> Self {
123 self.timeout_portfolio = timeout;
124 self
125 }
126
127 #[must_use]
129 pub const fn with_timeout_disconnection(mut self, timeout: u32) -> Self {
130 self.timeout_disconnection = timeout;
131 self
132 }
133
134 #[must_use]
136 pub const fn with_timeout_post_stop(mut self, timeout: u32) -> Self {
137 self.timeout_post_stop = timeout;
138 self
139 }
140
141 #[must_use]
143 pub const fn with_timeout_shutdown(mut self, timeout: u32) -> Self {
144 self.timeout_shutdown = timeout;
145 self
146 }
147
148 #[must_use]
150 pub fn with_cache_config(mut self, config: CacheConfig) -> Self {
151 self.cache = Some(config);
152 self
153 }
154
155 #[must_use]
157 pub fn with_data_engine_config(mut self, config: DataEngineConfig) -> Self {
158 self.data_engine = Some(config);
159 self
160 }
161
162 #[must_use]
164 pub fn with_risk_engine_config(mut self, config: RiskEngineConfig) -> Self {
165 self.risk_engine = Some(config);
166 self
167 }
168
169 #[must_use]
171 pub const fn with_exec_engine_config(mut self, config: ExecutionEngineConfig) -> Self {
172 self.exec_engine = Some(config);
173 self
174 }
175
176 #[must_use]
178 pub const fn with_portfolio_config(mut self, config: PortfolioConfig) -> Self {
179 self.portfolio = Some(config);
180 self
181 }
182
183 pub fn build(self) -> anyhow::Result<PoseiKernel> {
189 let config = KernelConfig {
190 environment: self.environment,
191 trader_id: self.trader_id,
192 load_state: self.load_state,
193 save_state: self.save_state,
194 logging: self.logging.unwrap_or_default(),
195 instance_id: self.instance_id,
196 timeout_connection: self.timeout_connection,
197 timeout_reconciliation: self.timeout_reconciliation,
198 timeout_portfolio: self.timeout_portfolio,
199 timeout_disconnection: self.timeout_disconnection,
200 timeout_post_stop: self.timeout_post_stop,
201 timeout_shutdown: self.timeout_shutdown,
202 cache: self.cache,
203 msgbus: None, data_engine: self.data_engine,
205 risk_engine: self.risk_engine,
206 exec_engine: self.exec_engine,
207 portfolio: self.portfolio,
208 streaming: None, };
210
211 PoseiKernel::new(self.name, config)
212 }
213}
214
215impl Default for PoseiKernelBuilder {
216 fn default() -> Self {
218 Self::new(
219 "PoseiKernel".to_string(),
220 TraderId::default(),
221 Environment::Backtest,
222 )
223 }
224}
225
226#[cfg(test)]
231mod tests {
232 use nautilus_model::identifiers::TraderId;
233 use rstest::*;
234
235 use super::*;
236
237 #[rstest]
238 fn test_builder_default() {
239 let builder = PoseiKernelBuilder::default();
240 assert_eq!(builder.name, "PoseiKernel");
241 assert_eq!(builder.environment, Environment::Backtest);
242 assert!(builder.load_state);
243 assert!(builder.save_state);
244 }
245
246 #[rstest]
247 fn test_builder_fluent_api() {
248 let trader_id = TraderId::from("TRADER-001");
249 let instance_id = UUID4::new();
250
251 let builder =
252 PoseiKernelBuilder::new("TestKernel".to_string(), trader_id, Environment::Live)
253 .with_instance_id(instance_id)
254 .with_load_state(false)
255 .with_save_state(false)
256 .with_timeout_connection(30);
257
258 assert_eq!(builder.name, "TestKernel");
259 assert_eq!(builder.trader_id, trader_id);
260 assert_eq!(builder.environment, Environment::Live);
261 assert_eq!(builder.instance_id, Some(instance_id));
262 assert!(!builder.load_state);
263 assert!(!builder.save_state);
264 assert_eq!(builder.timeout_connection, 30);
265 }
266
267 #[rstest]
268 fn test_builder_build() {
269 #[cfg(feature = "python")]
270 pyo3::prepare_freethreaded_python();
271
272 let result = PoseiKernelBuilder::default().build();
273 assert!(result.is_ok());
274
275 let kernel = result.unwrap();
276 assert_eq!(kernel.name(), "PoseiKernel".to_string());
277 assert_eq!(kernel.environment(), Environment::Backtest);
278 }
279
280 #[rstest]
281 fn test_builder_with_configs() {
282 let cache_config = CacheConfig::default();
283 let data_engine_config = DataEngineConfig::default();
284
285 let builder = PoseiKernelBuilder::default()
286 .with_cache_config(cache_config)
287 .with_data_engine_config(data_engine_config);
288
289 assert!(builder.cache.is_some());
290 assert!(builder.data_engine.is_some());
291 }
292}