From 67ffcc7496f9a89c5cd3aa8fe71afc529d4fa838 Mon Sep 17 00:00:00 2001 From: Pigbibi <20649888+Pigbibi@users.noreply.github.com> Date: Fri, 19 Jun 2026 04:55:35 +0800 Subject: [PATCH] Pass reserved cash policy to strategy runtime --- requirements.txt | 2 +- strategy_runtime.py | 6 ++++++ tests/test_strategy_runtime.py | 27 +++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index c874c27..3549fae 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ flask gunicorn quant-platform-kit @ git+https://github.com/QuantStrategyLab/QuantPlatformKit.git@b846c9d777a450e95d23c264853997d671f47dd9 -us-equity-strategies @ git+https://github.com/QuantStrategyLab/UsEquityStrategies.git@361338f60900182e3be535cd5fd2be2b9a07b422 +us-equity-strategies @ git+https://github.com/QuantStrategyLab/UsEquityStrategies.git@0cd90a37f3ea5e4b6fe27c9a435834df7df3a25f hk-equity-strategies @ git+https://github.com/QuantStrategyLab/HkEquityStrategies.git@4007746ac21379f7ce7cf8e999d2bb37123f6767 pandas requests diff --git a/strategy_runtime.py b/strategy_runtime.py index be056bf..ba9dd96 100644 --- a/strategy_runtime.py +++ b/strategy_runtime.py @@ -167,6 +167,12 @@ def _default_runtime_settings(profile: str, display_name: str) -> PlatformRuntim def _build_runtime_overrides(profile: str, runtime_settings: PlatformRuntimeSettings) -> dict[str, Any]: overrides: dict[str, Any] = {} + reserved_cash_floor_usd = getattr(runtime_settings, "reserved_cash_floor_usd", 0.0) + reserved_cash_ratio = getattr(runtime_settings, "reserved_cash_ratio", None) + if float(reserved_cash_floor_usd or 0.0) > 0.0: + overrides["reserved_cash_floor_usd"] = float(reserved_cash_floor_usd) + if reserved_cash_ratio is not None and float(reserved_cash_ratio or 0.0) > 0.0: + overrides["reserved_cash_ratio"] = float(reserved_cash_ratio) income_layer_enabled = getattr(runtime_settings, "income_layer_enabled", None) income_layer_start_usd = getattr(runtime_settings, "income_layer_start_usd", None) income_layer_max_ratio = getattr(runtime_settings, "income_layer_max_ratio", None) diff --git a/tests/test_strategy_runtime.py b/tests/test_strategy_runtime.py index a13a2a9..5725e65 100644 --- a/tests/test_strategy_runtime.py +++ b/tests/test_strategy_runtime.py @@ -126,6 +126,8 @@ def _build_runtime_settings( dca_mode: str | None = None, dca_base_investment_usd: float | None = None, runtime_execution_window_trading_days: int | None = None, + reserved_cash_floor_usd: float = 0.0, + reserved_cash_ratio: float = 0.0, ) -> PlatformRuntimeSettings: return PlatformRuntimeSettings( project_id=None, @@ -141,6 +143,8 @@ def _build_runtime_settings( tg_token=None, tg_chat_id=None, dry_run_only=False, + reserved_cash_floor_usd=reserved_cash_floor_usd, + reserved_cash_ratio=reserved_cash_ratio, income_threshold_usd=income_threshold_usd, qqqi_income_ratio=qqqi_income_ratio, income_layer_enabled=income_layer_enabled, @@ -329,6 +333,29 @@ def test_load_strategy_runtime_applies_dca_overrides_from_settings(self): self.assertTrue(runtime.merged_runtime_config["smart_multiplier_enabled"]) self.assertEqual(runtime.merged_runtime_config["base_investment_usd"], 500.0) + def test_load_strategy_runtime_applies_reserved_cash_policy_overrides_from_settings(self): + entrypoint = _SemiconductorEntrypoint() + + with patch.object(strategy_runtime_module, "load_strategy_entrypoint_for_profile", return_value=entrypoint): + with patch.object( + strategy_runtime_module, + "load_strategy_runtime_adapter_for_profile", + return_value=StrategyRuntimeAdapter(portfolio_input_name="portfolio_snapshot"), + ): + runtime = strategy_runtime_module.load_strategy_runtime( + "soxl_soxx_trend_income", + runtime_settings=_build_runtime_settings( + "soxl_soxx_trend_income", + reserved_cash_floor_usd=150.0, + reserved_cash_ratio=0.03, + ), + ) + + self.assertEqual(runtime.runtime_overrides["reserved_cash_floor_usd"], 150.0) + self.assertEqual(runtime.runtime_overrides["reserved_cash_ratio"], 0.03) + self.assertEqual(runtime.merged_runtime_config["reserved_cash_floor_usd"], 150.0) + self.assertEqual(runtime.merged_runtime_config["reserved_cash_ratio"], 0.03) + def test_load_strategy_runtime_applies_tech_execution_window_overrides_from_settings(self): entrypoint = _TechEntrypoint()