barter/engine/state/
builder.rs1use crate::engine::state::{
2 EngineState, asset::generate_empty_indexed_asset_states,
3 connectivity::generate_empty_indexed_connectivity_states,
4 instrument::generate_indexed_instrument_states, order::Orders, position::PositionManager,
5 trading::TradingState,
6};
7use barter_execution::balance::{AssetBalance, Balance};
8use barter_instrument::{
9 Keyed,
10 asset::{AssetIndex, ExchangeAsset, name::AssetNameInternal},
11 exchange::{ExchangeId, ExchangeIndex},
12 index::IndexedInstruments,
13 instrument::{Instrument, InstrumentIndex},
14};
15use barter_integration::collection::snapshot::Snapshot;
16use chrono::{DateTime, Utc};
17use fnv::FnvHashMap;
18use tracing::debug;
19
20#[derive(Debug, Clone)]
22pub struct EngineStateBuilder<'a, GlobalData, FnInstrumentData> {
23 instruments: &'a IndexedInstruments,
24 trading_state: Option<TradingState>,
25 time_engine_start: Option<DateTime<Utc>>,
26 global: GlobalData,
27 balances: FnvHashMap<ExchangeAsset<AssetNameInternal>, Balance>,
28 instrument_data_init: FnInstrumentData,
29}
30
31impl<'a, GlobalData, FnInstrumentData> EngineStateBuilder<'a, GlobalData, FnInstrumentData> {
32 pub fn new(
40 instruments: &'a IndexedInstruments,
41 global: GlobalData,
42 instrument_data_init: FnInstrumentData,
43 ) -> Self {
44 Self {
45 instruments,
46 time_engine_start: None,
47 trading_state: None,
48 global,
49 balances: FnvHashMap::default(),
50 instrument_data_init,
51 }
52 }
53
54 pub fn trading_state(self, value: TradingState) -> Self {
58 Self {
59 trading_state: Some(value),
60 ..self
61 }
62 }
63
64 pub fn time_engine_start(self, value: DateTime<Utc>) -> Self {
71 Self {
72 time_engine_start: Some(value),
73 ..self
74 }
75 }
76
77 pub fn balances<BalanceIter, KeyedBalance>(mut self, balances: BalanceIter) -> Self
85 where
86 BalanceIter: IntoIterator<Item = KeyedBalance>,
87 KeyedBalance: Into<Keyed<ExchangeAsset<AssetNameInternal>, Balance>>,
88 {
89 self.balances.extend(balances.into_iter().map(|keyed| {
90 let Keyed { key, value } = keyed.into();
91
92 (key, value)
93 }));
94 self
95 }
96
97 pub fn build<InstrumentData>(self) -> EngineState<GlobalData, InstrumentData>
101 where
102 FnInstrumentData: Fn(
103 &'a Keyed<InstrumentIndex, Instrument<Keyed<ExchangeIndex, ExchangeId>, AssetIndex>>,
104 ) -> InstrumentData,
105 {
106 let Self {
107 instruments,
108 time_engine_start,
109 trading_state,
110 global,
111 balances,
112 instrument_data_init,
113 } = self;
114
115 let time_engine_start = time_engine_start.unwrap_or_else(|| {
117 debug!("EngineStateBuilder using Utc::now as time_engine_start default");
118 Utc::now()
119 });
120 let trading = trading_state.unwrap_or_default();
121
122 let connectivity = generate_empty_indexed_connectivity_states(instruments);
124
125 let mut assets = generate_empty_indexed_asset_states(instruments);
127 for (key, balance) in balances {
128 assets
129 .asset_mut(&key)
130 .update_from_balance(Snapshot(&AssetBalance {
131 asset: key.asset,
132 balance,
133 time_exchange: time_engine_start,
134 }))
135 }
136
137 let instruments = generate_indexed_instrument_states(
139 instruments,
140 time_engine_start,
141 PositionManager::default,
142 Orders::default,
143 instrument_data_init,
144 );
145
146 EngineState {
147 trading,
148 global,
149 connectivity,
150 assets,
151 instruments,
152 }
153 }
154}