Skip to main content

nautilus_model/accounts/
stubs.rs

1// -------------------------------------------------------------------------------------------------
2//  Copyright (C) 2015-2026 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// -------------------------------------------------------------------------------------------------
15
16//! Lightweight stub implementations useful in unit tests where a full account object is
17//! unnecessary.
18
19use rstest::fixture;
20use rust_decimal::Decimal;
21
22use crate::{
23    accounts::{Account, AccountAny, BettingAccount, CashAccount, MarginAccount, WalletAccount},
24    enums::{AccountType, LiquiditySide},
25    events::account::{
26        state::AccountState,
27        stubs::{
28            betting_account_state, cash_account_state, cash_account_state_million_usd,
29            cash_account_state_million_usdt, cash_account_state_multi, margin_account_state,
30            wallet_account_state,
31        },
32    },
33    fees::MakerTakerFeeRates,
34    identifiers::stubs::{account_id, uuid4},
35    instruments::InstrumentAny,
36    types::{AccountBalance, Currency, Money, Price, Quantity},
37};
38
39impl Default for CashAccount {
40    /// Creates a new default [`CashAccount`] instance.
41    fn default() -> Self {
42        // million dollar account
43        let init_event = AccountState::new(
44            account_id(),
45            AccountType::Cash,
46            vec![AccountBalance::new(
47                Money::from("1000000 USD"),
48                Money::from("0 USD"),
49                Money::from("1000000 USD"),
50            )],
51            vec![],
52            true,
53            uuid4(),
54            0.into(),
55            0.into(),
56            Some(Currency::USD()),
57        );
58        Self::new(init_event, false, false)
59    }
60}
61
62impl Default for AccountAny {
63    /// Creates a new default [`AccountAny`] instance.
64    fn default() -> Self {
65        Self::Cash(CashAccount::default())
66    }
67}
68
69#[fixture]
70pub fn margin_account(margin_account_state: AccountState) -> MarginAccount {
71    MarginAccount::new(margin_account_state, true)
72}
73
74#[fixture]
75pub fn cash_account(cash_account_state: AccountState) -> CashAccount {
76    CashAccount::new(cash_account_state, true, false)
77}
78
79#[fixture]
80pub fn betting_account(betting_account_state: AccountState) -> BettingAccount {
81    BettingAccount::new(betting_account_state, true)
82}
83
84#[fixture]
85pub fn wallet_account(wallet_account_state: AccountState) -> WalletAccount {
86    WalletAccount::new(wallet_account_state, true)
87}
88
89#[fixture]
90pub fn cash_account_million_usd(cash_account_state_million_usd: AccountState) -> CashAccount {
91    CashAccount::new(cash_account_state_million_usd, true, false)
92}
93
94#[fixture]
95pub fn cash_account_multi(cash_account_state_multi: AccountState) -> CashAccount {
96    CashAccount::new(cash_account_state_multi, true, false)
97}
98
99#[fixture]
100pub fn cash_account_borrowing(cash_account_state: AccountState) -> CashAccount {
101    CashAccount::new(cash_account_state, true, true)
102}
103
104#[fixture]
105pub fn cash_account_borrowing_million_usd(
106    cash_account_state_million_usd: AccountState,
107) -> CashAccount {
108    CashAccount::new(cash_account_state_million_usd, true, true)
109}
110
111/// Calculates commission in test fixtures.
112///
113/// # Panics
114///
115/// Panics if the underlying `calculate_commission` returns an error.
116#[must_use]
117pub fn calculate_commission(
118    instrument: &InstrumentAny,
119    quantity: Quantity,
120    price: Price,
121    currency: Option<Currency>,
122) -> Money {
123    let account_state = if Some(Currency::USDT()) == currency {
124        cash_account_state_million_usdt()
125    } else {
126        cash_account_state_million_usd("1000000 USD", "0 USD", "1000000 USD")
127    };
128    let account = cash_account_million_usd(account_state);
129    let fee_rates = MakerTakerFeeRates::new(Decimal::ZERO, Decimal::ZERO);
130    account
131        .calculate_commission(
132            instrument,
133            quantity,
134            price,
135            LiquiditySide::Taker,
136            fee_rates,
137            None,
138        )
139        .unwrap()
140}