use indexmap::IndexMap;
use nautilus_common::{
actor::{DataActor, DataActorCore, data_actor::DataActorConfig},
nautilus_actor,
};
use nautilus_model::identifiers::{ActorId, StrategyId};
use nautilus_trading::{
nautilus_strategy,
strategy::{config::StrategyConfig, core::StrategyCore},
};
use crate::cache::TestCacheDatabaseControl;
#[derive(Debug)]
pub struct StateActor {
core: DataActorCore,
control: TestCacheDatabaseControl,
state_load: Option<IndexMap<String, Vec<u8>>>,
state_save: IndexMap<String, Vec<u8>>,
fail_load: bool,
fail_save: bool,
fail_start: bool,
}
impl StateActor {
#[must_use]
pub fn new(
actor_id: ActorId,
control: TestCacheDatabaseControl,
state_save: IndexMap<String, Vec<u8>>,
) -> Self {
Self {
core: DataActorCore::new(DataActorConfig {
actor_id: Some(actor_id),
..Default::default()
}),
control,
state_load: None,
state_save,
fail_load: false,
fail_save: false,
fail_start: false,
}
}
#[must_use]
pub const fn with_fail_load(mut self) -> Self {
self.fail_load = true;
self
}
#[must_use]
pub const fn with_fail_save(mut self) -> Self {
self.fail_save = true;
self
}
#[must_use]
pub const fn with_fail_start(mut self) -> Self {
self.fail_start = true;
self
}
#[must_use]
pub const fn state_load(&self) -> Option<&IndexMap<String, Vec<u8>>> {
self.state_load.as_ref()
}
}
impl DataActor for StateActor {
fn on_load(&mut self, state: IndexMap<String, Vec<u8>>) -> anyhow::Result<()> {
self.control.record("actor.on_load");
if self.fail_load {
anyhow::bail!("test actor on_load failure");
}
self.state_load = Some(state);
Ok(())
}
fn on_start(&mut self) -> anyhow::Result<()> {
self.control.record("actor.on_start");
if self.fail_start {
anyhow::bail!("test actor on_start failure");
}
Ok(())
}
fn on_stop(&mut self) -> anyhow::Result<()> {
self.control.record("actor.on_stop");
Ok(())
}
fn on_save(&self) -> anyhow::Result<IndexMap<String, Vec<u8>>> {
self.control.record("actor.on_save");
if self.fail_save {
anyhow::bail!("test actor on_save failure");
}
Ok(self.state_save.clone())
}
}
nautilus_actor!(StateActor);
#[derive(Debug)]
pub struct StateStrategy {
core: StrategyCore,
control: TestCacheDatabaseControl,
state_load: Option<IndexMap<String, Vec<u8>>>,
state_save: IndexMap<String, Vec<u8>>,
fail_load: bool,
fail_save: bool,
fail_start: bool,
}
impl StateStrategy {
#[must_use]
pub fn new(
strategy_id: StrategyId,
control: TestCacheDatabaseControl,
state_save: IndexMap<String, Vec<u8>>,
) -> Self {
Self {
core: StrategyCore::new(StrategyConfig {
strategy_id: Some(strategy_id),
..Default::default()
}),
control,
state_load: None,
state_save,
fail_load: false,
fail_save: false,
fail_start: false,
}
}
#[must_use]
pub const fn with_fail_load(mut self) -> Self {
self.fail_load = true;
self
}
#[must_use]
pub const fn with_fail_save(mut self) -> Self {
self.fail_save = true;
self
}
#[must_use]
pub const fn with_fail_start(mut self) -> Self {
self.fail_start = true;
self
}
#[must_use]
pub const fn state_load(&self) -> Option<&IndexMap<String, Vec<u8>>> {
self.state_load.as_ref()
}
}
impl DataActor for StateStrategy {
fn on_load(&mut self, state: IndexMap<String, Vec<u8>>) -> anyhow::Result<()> {
self.control.record("strategy.on_load");
if self.fail_load {
anyhow::bail!("test strategy on_load failure");
}
self.state_load = Some(state);
Ok(())
}
fn on_start(&mut self) -> anyhow::Result<()> {
self.control.record("strategy.on_start");
if self.fail_start {
anyhow::bail!("test strategy on_start failure");
}
Ok(())
}
fn on_stop(&mut self) -> anyhow::Result<()> {
self.control.record("strategy.on_stop");
Ok(())
}
fn on_save(&self) -> anyhow::Result<IndexMap<String, Vec<u8>>> {
self.control.record("strategy.on_save");
if self.fail_save {
anyhow::bail!("test strategy on_save failure");
}
Ok(self.state_save.clone())
}
}
nautilus_strategy!(StateStrategy);