sandbox_quant/
strategy_session.rs1use 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}