1// -------------------------------------------------------------------------------------------------
2// Copyright (C) 2015-2025 Nautech Systems Pty Ltd. All rights reserved.
3// https://nautechsystems.io
4//
5// Licensed under the GNU Lesser General Public License Version 3.0 (the "License");
6// You may not use this file except in compliance with the License.
7// You may obtain a copy of the License at https://www.gnu.org/licenses/lgpl-3.0.en.html
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14// -------------------------------------------------------------------------------------------------
1516use nautilus_core::python::to_pyvalue_err;
17use pyo3::{prelude::*, types::PyDict};
1819use crate::{
20 accounts::{Account, CashAccount, MarginAccount},
21 events::AccountState,
22};
2324#[pyfunction]
25pub fn cash_account_from_account_events(
26 events: Vec<Bound<'_, PyDict>>,
27 calculate_account_state: bool,
28) -> PyResult<CashAccount> {
29let account_events = events
30 .into_iter()
31 .map(|obj| AccountState::py_from_dict(&obj))
32 .collect::<PyResult<Vec<AccountState>>>()
33 .unwrap();
34if account_events.is_empty() {
35return Err(to_pyvalue_err("No account events"));
36 }
37let init_event = account_events[0].clone();
38let mut cash_account = CashAccount::new(init_event, calculate_account_state);
39for event in account_events.iter().skip(1) {
40 cash_account.apply(event.clone());
41 }
42Ok(cash_account)
43}
4445#[pyfunction]
46pub fn margin_account_from_account_events(
47 events: Vec<Bound<'_, PyDict>>,
48 calculate_account_state: bool,
49) -> PyResult<MarginAccount> {
50let account_events = events
51 .into_iter()
52 .map(|obj| AccountState::py_from_dict(&obj))
53 .collect::<PyResult<Vec<AccountState>>>()
54 .unwrap();
55if account_events.is_empty() {
56return Err(to_pyvalue_err("No account events"));
57 }
58let init_event = account_events[0].clone();
59let mut margin_account = MarginAccount::new(init_event, calculate_account_state);
60for event in account_events.iter().skip(1) {
61 margin_account.apply(event.clone());
62 }
63Ok(margin_account)
64}