Skip to main content

sandbox_quant/
strategy_session.rs

1use std::path::{Path, PathBuf};
2
3use anyhow::{Context, Result};
4use serde::{Deserialize, Serialize};
5
6use crate::strategy_catalog::StrategyCatalog;
7
8#[derive(Debug, Clone)]
9pub struct LoadedStrategySession {
10    pub catalog: StrategyCatalog,
11    pub selected_source_tag: Option<String>,
12}
13
14#[derive(Debug, Serialize, Deserialize)]
15struct PersistedStrategySession {
16    selected_source_tag: String,
17    profiles: Vec<crate::strategy_catalog::StrategyProfile>,
18}
19
20fn strategy_session_path() -> PathBuf {
21    std::env::var("SQ_STRATEGY_SESSION_PATH")
22        .map(PathBuf::from)
23        .unwrap_or_else(|_| PathBuf::from("data/strategy_session.json"))
24}
25
26pub fn load_strategy_session(
27    default_symbol: &str,
28    config_fast: usize,
29    config_slow: usize,
30    min_ticks_between_signals: u64,
31) -> Result<Option<LoadedStrategySession>> {
32    let path = strategy_session_path();
33    load_strategy_session_from_path(
34        &path,
35        default_symbol,
36        config_fast,
37        config_slow,
38        min_ticks_between_signals,
39    )
40}
41
42pub fn load_strategy_session_from_path(
43    path: &Path,
44    default_symbol: &str,
45    config_fast: usize,
46    config_slow: usize,
47    min_ticks_between_signals: u64,
48) -> Result<Option<LoadedStrategySession>> {
49    if !path.exists() {
50        return Ok(None);
51    }
52
53    let payload = std::fs::read_to_string(&path)
54        .with_context(|| format!("failed to read {}", path.display()))?;
55    let persisted: PersistedStrategySession =
56        serde_json::from_str(&payload).context("failed to parse persisted strategy session json")?;
57
58    Ok(Some(LoadedStrategySession {
59        catalog: StrategyCatalog::from_profiles(
60            persisted.profiles,
61            default_symbol,
62            config_fast,
63            config_slow,
64            min_ticks_between_signals,
65        ),
66        selected_source_tag: Some(persisted.selected_source_tag),
67    }))
68}
69
70pub fn persist_strategy_session(
71    catalog: &StrategyCatalog,
72    selected_source_tag: &str,
73) -> Result<()> {
74    let path = strategy_session_path();
75    persist_strategy_session_to_path(&path, catalog, selected_source_tag)
76}
77
78pub fn persist_strategy_session_to_path(
79    path: &Path,
80    catalog: &StrategyCatalog,
81    selected_source_tag: &str,
82) -> Result<()> {
83    if let Some(parent) = path.parent() {
84        std::fs::create_dir_all(parent)
85            .with_context(|| format!("failed to create {}", parent.display()))?;
86    }
87
88    let payload = PersistedStrategySession {
89        selected_source_tag: selected_source_tag.to_string(),
90        profiles: catalog.profiles().to_vec(),
91    };
92    let json = serde_json::to_string_pretty(&payload)
93        .context("failed to serialize persisted strategy session json")?;
94    std::fs::write(&path, json).with_context(|| format!("failed to write {}", path.display()))?;
95    Ok(())
96}