@@ -86,6 +86,7 @@ class PlatformRuntimeSettings:
8686 tg_token : str | None
8787 tg_chat_id : str | None
8888 dry_run_only : bool
89+ runtime_target_enabled : bool = True
8990 market : str = DEFAULT_MARKET
9091 market_calendar : str = DEFAULT_MARKET_CALENDAR
9192 market_timezone : str = DEFAULT_MARKET_TIMEZONE
@@ -98,6 +99,8 @@ class PlatformRuntimeSettings:
9899 debug_position_snapshot : bool = False
99100 income_threshold_usd : float | None = None
100101 qqqi_income_ratio : float | None = None
102+ income_layer_enabled : bool | None = None
103+ income_layer_max_ratio : float | None = None
101104 runtime_execution_window_trading_days : int | None = None
102105 feature_snapshot_path : str | None = None
103106 feature_snapshot_manifest_path : str | None = None
@@ -263,6 +266,7 @@ def load_platform_runtime_settings(
263266 tg_token = os .getenv ("TELEGRAM_TOKEN" ),
264267 tg_chat_id = os .getenv ("GLOBAL_TELEGRAM_CHAT_ID" ),
265268 dry_run_only = resolve_bool_value (os .getenv ("LONGBRIDGE_DRY_RUN_ONLY" )),
269+ runtime_target_enabled = _runtime_target_enabled_env (),
266270 reserved_cash_floor_usd = _resolve_non_negative_float_env (
267271 "LONGBRIDGE_MIN_RESERVED_CASH_USD" ,
268272 default = DEFAULT_RESERVED_CASH_FLOOR_USD ,
@@ -283,6 +287,8 @@ def load_platform_runtime_settings(
283287 debug_position_snapshot = resolve_bool_value (os .getenv ("LONGBRIDGE_DEBUG_POSITION_SNAPSHOT" )),
284288 income_threshold_usd = resolve_optional_float_env (os .environ , "INCOME_THRESHOLD_USD" ),
285289 qqqi_income_ratio = _qqqi_income_ratio_env (),
290+ income_layer_enabled = _optional_bool_env ("INCOME_LAYER_ENABLED" ),
291+ income_layer_max_ratio = _optional_ratio_env ("INCOME_LAYER_MAX_RATIO" ),
286292 runtime_execution_window_trading_days = _runtime_execution_window_trading_days_env (
287293 strategy_definition .profile
288294 ),
@@ -366,6 +372,34 @@ def _qqqi_income_ratio_env() -> float | None:
366372 return value
367373
368374
375+ def _optional_bool_env (name : str ) -> bool | None :
376+ raw_value = os .getenv (name )
377+ if raw_value is None or str (raw_value ).strip () == "" :
378+ return None
379+ value = str (raw_value ).strip ().lower ()
380+ if value in {"1" , "true" , "yes" , "y" , "on" }:
381+ return True
382+ if value in {"0" , "false" , "no" , "n" , "off" }:
383+ return False
384+ raise ValueError (f"{ name } must be boolean, got { raw_value !r} " )
385+
386+
387+ def _runtime_target_enabled_env () -> bool :
388+ value = _optional_bool_env ("RUNTIME_TARGET_ENABLED" )
389+ return True if value is None else value
390+
391+
392+ def _optional_ratio_env (name : str ) -> float | None :
393+ value = resolve_optional_float_env (os .environ , name )
394+ if value is None :
395+ return None
396+ if not math .isfinite (value ):
397+ raise ValueError (f"{ name } must be finite, got { value } " )
398+ if not (0.0 <= value <= 1.0 ):
399+ raise ValueError (f"{ name } must be in [0,1], got { value } " )
400+ return value
401+
402+
369403def _resolve_non_negative_float_env (name : str , * , default : float ) -> float :
370404 value = resolve_optional_float_env (os .environ , name )
371405 if value is None :
0 commit comments