diff --git a/.github/workflows/manual-strategy-switch.yml b/.github/workflows/manual-strategy-switch.yml index 7dbfef0..b00f030 100644 --- a/.github/workflows/manual-strategy-switch.yml +++ b/.github/workflows/manual-strategy-switch.yml @@ -407,6 +407,31 @@ jobs: print(f"- `{assignment['name']}` = `{assignment['value']}`") PY + - name: Preflight IBKR deployment plan + if: env.PLATFORM == 'ibkr' && env.SERVICE_TARGETS_MODE != 'off' + env: + TARGET_REPOSITORY: ${{ steps.platform.outputs.repository }} + run: | + set -euo pipefail + platform_root="${RUNNER_TEMP}/interactive-brokers-platform" + repository_variables_file="${RUNNER_TEMP}/ibkr-repository-variables.json" + trap 'rm -f "${repository_variables_file}"' EXIT + + gh auth setup-git + git clone --quiet --depth 1 --branch main \ + "https://github.com/${TARGET_REPOSITORY}.git" \ + "${platform_root}" + python3 -m pip install --quiet uv + uv sync --frozen --no-dev --quiet --project "${platform_root}" + gh variable list \ + --repo "${TARGET_REPOSITORY}" \ + --json name,value \ + > "${repository_variables_file}" + python3 python/scripts/preflight_ibkr_switch.py \ + --target-file "${TARGET_FILE}" \ + --platform-root "${platform_root}" \ + --repository-variables-file "${repository_variables_file}" + - name: Apply GitHub variable updates if: env.APPLY_SWITCH == 'true' run: python3 python/scripts/runtime_settings.py apply "${TARGET_FILE}" --yes diff --git a/internal_dependency_matrix.json b/internal_dependency_matrix.json index 77976bb..a722361 100644 --- a/internal_dependency_matrix.json +++ b/internal_dependency_matrix.json @@ -62,28 +62,42 @@ "path": "pyproject.toml", "package": "cn-equity-strategies", "source_repo": "CnEquityStrategies", - "ref": "73844e92a8570a61e5a9dc6c245809d0b27b89bc" + "ref": "00fa762466617d0961bb8b03821f56b1b9c2b866" + }, + { + "consumer_repo": "CnEquitySnapshotPipelines", + "path": "pyproject.toml", + "package": "quant-platform-kit", + "source_repo": "QuantPlatformKit", + "ref": "8ba8276948ff71a8cc0a810f98b7437a1311c671" }, { "consumer_repo": "CnEquitySnapshotPipelines", "path": "uv.lock", "package": "cn-equity-strategies", "source_repo": "CnEquityStrategies", - "ref": "73844e92a8570a61e5a9dc6c245809d0b27b89bc" + "ref": "00fa762466617d0961bb8b03821f56b1b9c2b866" + }, + { + "consumer_repo": "CnEquitySnapshotPipelines", + "path": "uv.lock", + "package": "quant-platform-kit", + "source_repo": "QuantPlatformKit", + "ref": "8ba8276948ff71a8cc0a810f98b7437a1311c671" }, { "consumer_repo": "CnEquityStrategies", "path": "pyproject.toml", "package": "quant-platform-kit", "source_repo": "QuantPlatformKit", - "ref": "92458590a463e7219f0369a3505031ee74414135" + "ref": "776fe71e57e2924fcd1c73126f41d244242240bb" }, { "consumer_repo": "CnEquityStrategies", "path": "uv.lock", "package": "quant-platform-kit", "source_repo": "QuantPlatformKit", - "ref": "92458590a463e7219f0369a3505031ee74414135" + "ref": "776fe71e57e2924fcd1c73126f41d244242240bb" }, { "consumer_repo": "CryptoLivePoolPipelines", @@ -118,14 +132,14 @@ "path": "pyproject.toml", "package": "quant-platform-kit", "source_repo": "QuantPlatformKit", - "ref": "92458590a463e7219f0369a3505031ee74414135" + "ref": "776fe71e57e2924fcd1c73126f41d244242240bb" }, { "consumer_repo": "CryptoStrategies", "path": "uv.lock", "package": "quant-platform-kit", "source_repo": "QuantPlatformKit", - "ref": "92458590a463e7219f0369a3505031ee74414135" + "ref": "776fe71e57e2924fcd1c73126f41d244242240bb" }, { "consumer_repo": "FirstradePlatform", @@ -174,14 +188,14 @@ "path": "pyproject.toml", "package": "quant-platform-kit", "source_repo": "QuantPlatformKit", - "ref": "92458590a463e7219f0369a3505031ee74414135" + "ref": "776fe71e57e2924fcd1c73126f41d244242240bb" }, { "consumer_repo": "HkEquityStrategies", "path": "uv.lock", "package": "quant-platform-kit", "source_repo": "QuantPlatformKit", - "ref": "92458590a463e7219f0369a3505031ee74414135" + "ref": "776fe71e57e2924fcd1c73126f41d244242240bb" }, { "consumer_repo": "InteractiveBrokersPlatform", @@ -195,7 +209,7 @@ "path": "pyproject.toml", "package": "quant-platform-kit", "source_repo": "QuantPlatformKit", - "ref": "92458590a463e7219f0369a3505031ee74414135" + "ref": "776fe71e57e2924fcd1c73126f41d244242240bb" }, { "consumer_repo": "InteractiveBrokersPlatform", @@ -216,7 +230,7 @@ "path": "uv.lock", "package": "quant-platform-kit", "source_repo": "QuantPlatformKit", - "ref": "92458590a463e7219f0369a3505031ee74414135" + "ref": "776fe71e57e2924fcd1c73126f41d244242240bb" }, { "consumer_repo": "InteractiveBrokersPlatform", @@ -342,14 +356,14 @@ "path": "pyproject.toml", "package": "quant-platform-kit", "source_repo": "QuantPlatformKit", - "ref": "8ba8276948ff71a8cc0a810f98b7437a1311c671" + "ref": "776fe71e57e2924fcd1c73126f41d244242240bb" }, { "consumer_repo": "UsEquityStrategies", "path": "uv.lock", "package": "quant-platform-kit", "source_repo": "QuantPlatformKit", - "ref": "8ba8276948ff71a8cc0a810f98b7437a1311c671" + "ref": "776fe71e57e2924fcd1c73126f41d244242240bb" } ] } diff --git a/platform-config.json b/platform-config.json index d0f532a..6798f04 100644 --- a/platform-config.json +++ b/platform-config.json @@ -62,27 +62,27 @@ "profiles": { "us_daily": { "timezone": "America/New_York", - "main_time": "45 15 * * *", - "probe_time": "35 9,15 * * *", - "precheck_time": "45 9 * * *" + "main_time": "45 15 * * 1-5", + "probe_time": "35 9,15 * * 1-5", + "precheck_time": "45 9 * * 1-5" }, "us_dca_month_end": { "timezone": "America/New_York", - "main_time": "45 15 25-29 * *", - "probe_time": "35 9,15 25-29 * *", - "precheck_time": "45 9 25-29 * *" + "main_time": "45 15 * * 1-5", + "probe_time": "35 9,15 * * 1-5", + "precheck_time": "45 9 * * 1-5" }, "us_snapshot_month_start": { "timezone": "America/New_York", - "main_time": "45 15 1-7 * *", - "probe_time": "35 9,15 1-7 * *", - "precheck_time": "45 9 1-7 * *" + "main_time": "45 15 * * 1-5", + "probe_time": "35 9,15 * * 1-5", + "precheck_time": "45 9 * * 1-5" }, "hk_daily": { "timezone": "Asia/Hong_Kong", - "main_time": "45 15 * * *", - "probe_time": "35 9,15 * * *", - "precheck_time": "45 9 * * *" + "main_time": "45 15 * * 1-5", + "probe_time": "35 9,15 * * 1-5", + "precheck_time": "45 9 * * 1-5" }, "hk_snapshot_month_start": { "timezone": "Asia/Hong_Kong", @@ -501,6 +501,13 @@ "dry_run" ], "blocked_live_reason": "", + "runtime_artifacts": { + "feature_snapshot": { + "required": true, + "path": "gs://qsl-runtime-logs-shared/strategy-artifacts/us_equity/global_etf_rotation/global_etf_rotation_feature_snapshot_latest.csv", + "manifest_path": "gs://qsl-runtime-logs-shared/strategy-artifacts/us_equity/global_etf_rotation/global_etf_rotation_feature_snapshot_latest.csv.manifest.json" + } + }, "features": { "income_layer": true, "option_overlay": true, @@ -541,6 +548,13 @@ "dry_run" ], "blocked_live_reason": "", + "runtime_artifacts": { + "feature_snapshot": { + "required": true, + "path": "gs://qsl-runtime-logs-shared/strategy-artifacts/us_equity/russell_top50_leader_rotation_staging/russell_top50_leader_rotation_feature_snapshot_latest.csv", + "manifest_path": "gs://qsl-runtime-logs-shared/strategy-artifacts/us_equity/russell_top50_leader_rotation_staging/russell_top50_leader_rotation_feature_snapshot_latest.csv.manifest.json" + } + }, "features": { "income_layer": true, "option_overlay": true, @@ -691,13 +705,17 @@ "scheduler_profile": "hk_snapshot_month_start", "runtime_enabled": true, "lifecycle_stage": "runtime_enabled", - "can_switch_live": true, + "can_switch_live": false, "allowed_execution_modes": [ - "live", "paper", "dry_run" ], - "blocked_live_reason": "", + "blocked_live_reason": "production_snapshot_artifact_route_not_configured", + "runtime_artifacts": { + "feature_snapshot": { + "required": true + } + }, "features": { "income_layer": false, "option_overlay": false, diff --git a/python/scripts/build_config.py b/python/scripts/build_config.py index da237f4..7955b58 100644 --- a/python/scripts/build_config.py +++ b/python/scripts/build_config.py @@ -39,6 +39,7 @@ } SCHEDULER_FIELDS = {"timezone", "main_time", "probe_time", "precheck_time"} MARKET_FIELDS = {"market", "market_calendar", "market_timezone"} +FEATURE_SNAPSHOT_FIELDS = {"required", "path", "manifest_path"} RUNTIME_MODELS = {"cloud_run", "oracle_vps_self_hosted", "not_configured"} SETTINGS_ACTIVATION_MODES = { "cloud_run_sync_workflow", @@ -79,6 +80,13 @@ def validate(config: dict) -> list[str]: errors.append( f"scheduler profile {profile}: {field} must have 2 time fields or 5 cron fields" ) + continue + if profile.startswith("us_"): + cron = value.split() + if len(cron) != 5 or cron[2] != "*" or cron[4] != "1-5": + errors.append( + f"scheduler profile {profile}: {field} must be Mon-Fri cron with day-of-month '*'" + ) for pid, pdata in config.get("platforms", {}).items(): if "capabilities" not in pdata: errors.append(f"platform {pid}: missing capabilities") @@ -220,6 +228,56 @@ def validate(config: dict) -> list[str]: f"{scheduler_timezone!r} must match market_timezone " f"{market_timezone!r}" ) + runtime_artifacts = sdata.get("runtime_artifacts") + if runtime_artifacts is None: + continue + if not isinstance(runtime_artifacts, dict): + errors.append(f"strategy {sid}: runtime_artifacts must be an object") + continue + unsupported_artifacts = sorted(set(runtime_artifacts) - {"feature_snapshot"}) + if unsupported_artifacts: + errors.append( + f"strategy {sid}: unsupported runtime_artifacts {unsupported_artifacts}" + ) + feature_snapshot = runtime_artifacts.get("feature_snapshot") + if feature_snapshot is None: + continue + if not isinstance(feature_snapshot, dict): + errors.append( + f"strategy {sid}: runtime_artifacts.feature_snapshot must be an object" + ) + continue + unsupported_fields = sorted(set(feature_snapshot) - FEATURE_SNAPSHOT_FIELDS) + if unsupported_fields: + errors.append( + f"strategy {sid}: unsupported feature snapshot fields {unsupported_fields}" + ) + required = feature_snapshot.get("required") + if not isinstance(required, bool): + errors.append( + f"strategy {sid}: runtime_artifacts.feature_snapshot.required must be boolean" + ) + snapshot_path = feature_snapshot.get("path") + manifest_path = feature_snapshot.get("manifest_path") + for field, value in (("path", snapshot_path), ("manifest_path", manifest_path)): + if value is not None and ( + not isinstance(value, str) or not value.startswith("gs://") + ): + errors.append( + f"strategy {sid}: runtime_artifacts.feature_snapshot.{field} must be a gs:// URI" + ) + has_snapshot_path = isinstance(snapshot_path, str) and bool(snapshot_path.strip()) + has_manifest_path = isinstance(manifest_path, str) and bool(manifest_path.strip()) + if has_snapshot_path != has_manifest_path: + errors.append( + f"strategy {sid}: feature snapshot path and manifest_path must be configured together" + ) + if required is True and sdata.get("can_switch_live") is True and not ( + has_snapshot_path and has_manifest_path + ): + errors.append( + f"strategy {sid}: live feature snapshot requires path and manifest_path" + ) return errors diff --git a/python/scripts/build_runtime_switch.py b/python/scripts/build_runtime_switch.py index 6ba7eeb..54c5a60 100644 --- a/python/scripts/build_runtime_switch.py +++ b/python/scripts/build_runtime_switch.py @@ -64,6 +64,18 @@ "ibkr": "IBKR_CASH_ONLY_EXECUTION", "firstrade": "FIRSTRADE_CASH_ONLY_EXECUTION", } +PLATFORM_FEATURE_SNAPSHOT_VARIABLES = { + "schwab": ("SCHWAB_FEATURE_SNAPSHOT_PATH", "SCHWAB_FEATURE_SNAPSHOT_MANIFEST_PATH"), + "longbridge": ( + "LONGBRIDGE_FEATURE_SNAPSHOT_PATH", + "LONGBRIDGE_FEATURE_SNAPSHOT_MANIFEST_PATH", + ), + "ibkr": ("IBKR_FEATURE_SNAPSHOT_PATH", "IBKR_FEATURE_SNAPSHOT_MANIFEST_PATH"), + "firstrade": ( + "FIRSTRADE_FEATURE_SNAPSHOT_PATH", + "FIRSTRADE_FEATURE_SNAPSHOT_MANIFEST_PATH", + ), +} INCOME_LAYER_VARIABLES = ( "INCOME_LAYER_ENABLED", "INCOME_LAYER_START_USD", @@ -747,6 +759,57 @@ def _market_plan_for_strategy(strategy_profile: str) -> dict[str, str]: return market +def _feature_snapshot_extra_variables( + platform: str, + strategy_profile: str, + extra_variables: dict[str, Any], +) -> dict[str, str]: + variable_names = PLATFORM_FEATURE_SNAPSHOT_VARIABLES.get(platform) + if not variable_names: + return {} + snapshot_variable, manifest_variable = variable_names + + config = _load_platform_config() + strategies = config.get("strategies") + strategy = strategies.get(strategy_profile) if isinstance(strategies, dict) else None + if not isinstance(strategy, dict): + raise ValueError(f"strategy {strategy_profile!r} is missing from the runtime artifact catalog") + runtime_artifacts = strategy.get("runtime_artifacts") or {} + if not isinstance(runtime_artifacts, dict): + raise ValueError(f"strategy {strategy_profile!r} runtime_artifacts must be an object") + feature_snapshot = runtime_artifacts.get("feature_snapshot") or {} + if not isinstance(feature_snapshot, dict): + raise ValueError( + f"strategy {strategy_profile!r} runtime_artifacts.feature_snapshot must be an object" + ) + + explicit = snapshot_variable in extra_variables or manifest_variable in extra_variables + if explicit: + snapshot_path = extra_variables.get(snapshot_variable) + manifest_path = extra_variables.get(manifest_variable) + else: + snapshot_path = feature_snapshot.get("path") + manifest_path = feature_snapshot.get("manifest_path") + snapshot_path = snapshot_path.strip() if isinstance(snapshot_path, str) else "" + manifest_path = manifest_path.strip() if isinstance(manifest_path, str) else "" + if explicit and not feature_snapshot and (snapshot_path or manifest_path): + raise ValueError( + f"strategy {strategy_profile!r} does not accept feature snapshot artifacts" + ) + if bool(snapshot_path) != bool(manifest_path): + raise ValueError( + f"strategy {strategy_profile!r} feature snapshot path and manifest path must be configured together" + ) + if feature_snapshot.get("required") is True and not (snapshot_path and manifest_path): + raise ValueError( + f"strategy {strategy_profile!r} requires feature snapshot path and manifest path" + ) + return { + snapshot_variable: snapshot_path, + manifest_variable: manifest_path, + } + + def _build_runtime_target(args: argparse.Namespace) -> dict[str, Any]: platform = _normalize_platform(args.platform) target_name = _normalize_target_name(args.target_name) @@ -903,6 +966,13 @@ def build_switch_target(args: argparse.Namespace) -> dict[str, Any]: _reject_direct_dca_extra_variables(extra_variables) _reject_direct_ibit_zscore_exit_extra_variables(extra_variables) _reject_research_only_extra_variables(extra_variables) + extra_variables.update( + _feature_snapshot_extra_variables( + platform, + runtime_target["strategy_profile"], + extra_variables, + ) + ) if args.set_platform_dry_run_variable: extra_variables[PLATFORM_DRY_RUN_VARIABLES[platform]] = env_string(runtime_target["dry_run_only"]) diff --git a/python/scripts/preflight_ibkr_switch.py b/python/scripts/preflight_ibkr_switch.py new file mode 100644 index 0000000..a13478e --- /dev/null +++ b/python/scripts/preflight_ibkr_switch.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python3 +"""Validate an IBKR switch with the target platform's deployment planner.""" + +from __future__ import annotations + +import argparse +import json +import os +import re +import subprocess +import sys +from pathlib import Path +from typing import Any + +SCRIPT_DIR = Path(__file__).resolve().parent +if str(SCRIPT_DIR) not in sys.path: + sys.path.insert(0, str(SCRIPT_DIR)) + +from runtime_settings import build_assignments, load_target # noqa: E402 + + +PROTECTED_ENV_NAMES = { + "GH_TOKEN", + "HOME", + "PATH", + "PYTHONHOME", + "PYTHONPATH", + "VIRTUAL_ENV", +} + + +def _load_repository_variables(path: Path) -> dict[str, str]: + payload = json.loads(path.read_text(encoding="utf-8")) + if not isinstance(payload, list): + raise ValueError("repository variables file must contain a list") + variables: dict[str, str] = {} + for item in payload: + if not isinstance(item, dict): + raise ValueError("repository variable entries must be objects") + name = str(item.get("name") or "").strip() + if not re.fullmatch(r"[A-Z][A-Z0-9_]*", name): + raise ValueError("repository variable names must use uppercase environment syntax") + if name in PROTECTED_ENV_NAMES or name.startswith(("LD_", "DYLD_")): + continue + value = item.get("value") + variables[name] = value if isinstance(value, str) else str(value or "") + return variables + + +def _candidate_environment(target: dict[str, Any], variables: dict[str, str]) -> dict[str, str]: + environment = os.environ.copy() + environment.update(variables) + candidate_inventory = False + for assignment in build_assignments(target): + if assignment.name == "CLOUD_RUN_SERVICE_TARGETS_JSON": + candidate_inventory = True + if assignment.deletes_variable: + environment.pop(assignment.name, None) + else: + environment[assignment.name] = assignment.value + if not candidate_inventory: + raise ValueError("candidate CLOUD_RUN_SERVICE_TARGETS_JSON assignment is required") + return environment + + +def preflight(target_file: Path, platform_root: Path, repository_variables_file: Path) -> None: + target = load_target(target_file) + runtime_target = target.get("runtime_target") + if not isinstance(runtime_target, dict) or runtime_target.get("platform_id") != "ibkr": + raise ValueError("preflight_ibkr_switch.py only accepts IBKR targets") + + variables = _load_repository_variables(repository_variables_file) + environment = _candidate_environment(target, variables) + python_path = platform_root / ".venv" / "bin" / "python" + planner_path = platform_root / "scripts" / "build_cloud_run_env_sync_plan.py" + if not python_path.is_file() or not planner_path.is_file(): + raise ValueError("IBKR planner runtime is incomplete") + + result = subprocess.run( + [str(python_path), str(planner_path), "--json"], + cwd=platform_root, + env=environment, + capture_output=True, + text=True, + timeout=90, + check=False, + ) + if result.returncode != 0: + raise ValueError("IBKR deployment planner rejected the candidate runtime settings") + + +def build_parser() -> argparse.ArgumentParser: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--target-file", required=True, type=Path) + parser.add_argument("--platform-root", required=True, type=Path) + parser.add_argument("--repository-variables-file", required=True, type=Path) + return parser + + +def main(argv: list[str] | None = None) -> int: + args = build_parser().parse_args(argv) + try: + preflight(args.target_file, args.platform_root, args.repository_variables_file) + except (OSError, ValueError, json.JSONDecodeError, subprocess.SubprocessError) as exc: + print(f"error: {exc}", file=sys.stderr) + return 2 + print("IBKR deployment plan preflight passed.") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/python/scripts/runtime_settings.py b/python/scripts/runtime_settings.py index 53d213f..63115aa 100644 --- a/python/scripts/runtime_settings.py +++ b/python/scripts/runtime_settings.py @@ -405,6 +405,7 @@ def validate_runtime_target(target: dict[str, Any], errors: list[str]) -> None: value = scheduler.get(field) if not isinstance(value, str) or len(value.split()) not in {2, 5}: errors.append(f"runtime_target.scheduler.{field} must have 2 time fields or 5 cron fields") + validate_live_ibkr_us_scheduler(runtime_target, scheduler, errors) configured_market_fields = [] for field in MARKET_FIELDS: @@ -426,6 +427,49 @@ def validate_runtime_target(target: dict[str, Any], errors: list[str]) -> None: errors.append(f"runtime_target.market_timezone is invalid: {market_timezone!r}") +def validate_live_ibkr_us_scheduler( + runtime_target: dict[str, Any], + scheduler: dict[str, Any], + errors: list[str], +) -> None: + if ( + runtime_target.get("platform_id") != "ibkr" + or runtime_target.get("execution_mode") != "live" + or runtime_target.get("dry_run_only") is not False + ): + return + + market = str(runtime_target.get("market") or "").strip().upper() + if not market: + config = load_platform_config() + strategies = config.get("strategies", {}) + domains = config.get("domains", {}) + profile = str(runtime_target.get("strategy_profile") or "").strip() + strategy = strategies.get(profile) if isinstance(strategies, dict) else None + domain = ( + domains.get(strategy.get("domain")) + if isinstance(strategy, dict) and isinstance(domains, dict) + else None + ) + market = str(domain.get("market") or "").strip().upper() if isinstance(domain, dict) else "" + if market != "US": + return + + for field in ("main_time", "probe_time", "precheck_time"): + value = scheduler.get(field) + if not isinstance(value, str): + continue + cron = value.split() + if len(cron) == 2: + continue + if len(cron) == 5 and cron[2] == "*" and cron[4] == "1-5": + continue + errors.append( + f"runtime_target.scheduler.{field} must be a two-field time or Mon-Fri cron " + "for live IBKR US targets" + ) + + def validate_runtime_target_strategy_policy(runtime_target: dict[str, Any], errors: list[str]) -> None: config = load_platform_config() strategies = config.get("strategies", {}) diff --git a/python/tests/test_internal_dependency_matrix.py b/python/tests/test_internal_dependency_matrix.py index a5e39b3..cbc58bf 100644 --- a/python/tests/test_internal_dependency_matrix.py +++ b/python/tests/test_internal_dependency_matrix.py @@ -103,13 +103,13 @@ def test_qpk_migrated_consumers_use_current_baseline_pins(self): expected_pins_by_consumer = { "BinancePlatform": "92458590a463e7219f0369a3505031ee74414135", "CharlesSchwabPlatform": "92458590a463e7219f0369a3505031ee74414135", - "CnEquityStrategies": "92458590a463e7219f0369a3505031ee74414135", - "CryptoStrategies": "92458590a463e7219f0369a3505031ee74414135", + "CnEquityStrategies": "776fe71e57e2924fcd1c73126f41d244242240bb", + "CryptoStrategies": "776fe71e57e2924fcd1c73126f41d244242240bb", "FirstradePlatform": "92458590a463e7219f0369a3505031ee74414135", - "HkEquityStrategies": "92458590a463e7219f0369a3505031ee74414135", - "InteractiveBrokersPlatform": "92458590a463e7219f0369a3505031ee74414135", + "HkEquityStrategies": "776fe71e57e2924fcd1c73126f41d244242240bb", + "InteractiveBrokersPlatform": "776fe71e57e2924fcd1c73126f41d244242240bb", "LongBridgePlatform": "92458590a463e7219f0369a3505031ee74414135", - "UsEquityStrategies": "8ba8276948ff71a8cc0a810f98b7437a1311c671", + "UsEquityStrategies": "776fe71e57e2924fcd1c73126f41d244242240bb", } matrix_pins = check_internal_dependency_matrix.load_matrix(ROOT / "internal_dependency_matrix.json") refs = { diff --git a/python/tests/test_runtime_settings.py b/python/tests/test_runtime_settings.py index a933b91..a359df2 100644 --- a/python/tests/test_runtime_settings.py +++ b/python/tests/test_runtime_settings.py @@ -4,7 +4,9 @@ import json import os import re +import subprocess import sys +import tempfile import unittest from pathlib import Path from unittest.mock import patch @@ -140,6 +142,130 @@ def test_manual_switch_rejects_inventory_bypass_before_variable_write(self): workflow.index("Apply GitHub variable updates"), ) + def test_manual_switch_preflights_ibkr_plan_before_variable_write(self): + workflow = (ROOT / ".github" / "workflows" / "manual-strategy-switch.yml").read_text(encoding="utf-8") + + self.assertIn("Preflight IBKR deployment plan", workflow) + self.assertIn("python/scripts/preflight_ibkr_switch.py", workflow) + self.assertIn("uv sync --frozen --no-dev", workflow) + self.assertLess( + workflow.index("Preflight IBKR deployment plan"), + workflow.index("Apply GitHub variable updates"), + ) + + def test_preflight_ibkr_switch_uses_candidate_inventory_without_printing_plan(self): + with tempfile.TemporaryDirectory(dir=ROOT) as temp_dir: + temp = Path(temp_dir) + existing_path = temp / "existing.json" + existing_path.write_text( + runtime_settings.compact_json( + { + "targets": [ + { + "service": "interactive-brokers-live-service", + "ACCOUNT_GROUP": "live", + "runtime_target": { + "platform_id": "ibkr", + "strategy_profile": "soxl_soxx_trend_income", + "dry_run_only": False, + "deployment_selector": "live", + "account_selector": ["LIVE"], + "account_scope": "live", + "service_name": "interactive-brokers-live-service", + "execution_mode": "live", + }, + } + ] + } + ), + encoding="utf-8", + ) + args = build_runtime_switch.build_parser().parse_args( + [ + "--platform", + "ibkr", + "--target-name", + "live", + "--strategy-profile", + "tqqq_growth_income", + "--account-selector", + "LIVE", + "--service-name", + "interactive-brokers-live-service", + "--plugin-mode", + "none", + "--existing-service-targets-json-file", + str(existing_path), + ] + ) + target_path = temp / "target.json" + target_path.write_text( + runtime_settings.compact_json(build_runtime_switch.build_switch_target(args)), + encoding="utf-8", + ) + variables_path = temp / "variables.json" + variables_path.write_text( + json.dumps( + [ + {"name": "CLOUD_RUN_SERVICE_TARGETS_JSON", "value": '{"targets":[]}'}, + {"name": "UNCHANGED_SETTING", "value": "preserved"}, + ] + ), + encoding="utf-8", + ) + platform_root = temp / "platform" + planner_path = platform_root / "scripts" / "build_cloud_run_env_sync_plan.py" + planner_path.parent.mkdir(parents=True) + capture_path = temp / "capture.json" + planner_path.write_text( + """ +import json +import os +from pathlib import Path + +inventory = json.loads(os.environ["CLOUD_RUN_SERVICE_TARGETS_JSON"]) +Path(os.environ["CAPTURE_PATH"]).write_text( + json.dumps( + { + "profile": inventory["targets"][0]["runtime_target"]["strategy_profile"], + "unchanged": os.environ.get("UNCHANGED_SETTING"), + } + ), + encoding="utf-8", +) +print('{"candidate_inventory":"must-not-be-forwarded"}') +""".strip(), + encoding="utf-8", + ) + python_path = platform_root / ".venv" / "bin" / "python" + python_path.parent.mkdir(parents=True) + python_path.symlink_to(sys.executable) + + result = subprocess.run( + [ + sys.executable, + str(ROOT / "python" / "scripts" / "preflight_ibkr_switch.py"), + "--target-file", + str(target_path), + "--platform-root", + str(platform_root), + "--repository-variables-file", + str(variables_path), + ], + capture_output=True, + text=True, + env={**os.environ, "CAPTURE_PATH": str(capture_path)}, + check=False, + ) + + self.assertEqual(result.returncode, 0, result.stderr) + self.assertEqual(result.stdout, "IBKR deployment plan preflight passed.\n") + self.assertNotIn("candidate_inventory", result.stdout + result.stderr) + self.assertEqual( + json.loads(capture_path.read_text(encoding="utf-8")), + {"profile": "tqqq_growth_income", "unchanged": "preserved"}, + ) + def test_settings_activation_comes_from_platform_config(self): self.assertEqual( runtime_settings.platform_settings_activation("binance"), @@ -706,9 +832,9 @@ def test_build_switch_target_defaults_longbridge_sg_tqqq(self): target["runtime_target"]["scheduler"], { "timezone": "America/New_York", - "main_time": "45 15 * * *", - "probe_time": "35 9,15 * * *", - "precheck_time": "45 9 * * *", + "main_time": "45 15 * * 1-5", + "probe_time": "35 9,15 * * 1-5", + "precheck_time": "45 9 * * 1-5", }, ) self.assertEqual(assignments["STRATEGY_PROFILE"], "tqqq_growth_income") @@ -737,6 +863,18 @@ def test_market_plan_covers_every_catalog_strategy(self): }, ) + def test_live_us_scheduler_profiles_are_weekday_only(self): + config = build_runtime_switch._load_platform_config() + + for profile, scheduler in config["scheduling"]["profiles"].items(): + if not profile.startswith("us_"): + continue + for field in ("main_time", "probe_time", "precheck_time"): + cron = scheduler[field].split() + self.assertEqual(len(cron), 5, (profile, field)) + self.assertEqual(cron[2], "*", (profile, field)) + self.assertEqual(cron[4], "1-5", (profile, field)) + def test_build_switch_target_uses_fork_repository_overrides(self): parser = build_runtime_switch.build_parser() args = parser.parse_args( @@ -936,7 +1074,7 @@ def test_build_switch_target_defaults_binance_repository_scope(self): }, ) - def test_build_switch_target_uses_dca_monthly_scheduler_window(self): + def test_build_switch_target_uses_weekday_trigger_for_monthly_dca(self): parser = build_runtime_switch.build_parser() args = parser.parse_args( [ @@ -957,9 +1095,9 @@ def test_build_switch_target_uses_dca_monthly_scheduler_window(self): target["runtime_target"]["scheduler"], { "timezone": "America/New_York", - "main_time": "45 15 25-29 * *", - "probe_time": "35 9,15 25-29 * *", - "precheck_time": "45 9 25-29 * *", + "main_time": "45 15 * * 1-5", + "probe_time": "35 9,15 * * 1-5", + "precheck_time": "45 9 * * 1-5", }, ) @@ -986,9 +1124,9 @@ def test_build_switch_target_uses_daily_scheduler_when_ibit_smart_dca_is_smart(s target["runtime_target"]["scheduler"], { "timezone": "America/New_York", - "main_time": "45 15 * * *", - "probe_time": "35 9,15 * * *", - "precheck_time": "45 9 * * *", + "main_time": "45 15 * * 1-5", + "probe_time": "35 9,15 * * 1-5", + "precheck_time": "45 9 * * 1-5", }, ) self.assertEqual(plugin_payload["strategy_plugins"][0]["plugin"], "ibit_zscore_exit") @@ -1442,8 +1580,19 @@ def test_build_switch_target_uses_snapshot_scheduler_window(self): "hk", "--strategy-profile", "hk_low_vol_dividend_quality_snapshot", + "--execution-mode", + "paper", "--plugin-mode", "none", + "--extra-variables-json", + json.dumps( + { + "LONGBRIDGE_FEATURE_SNAPSHOT_PATH": "gs://manual/snapshot.csv", + "LONGBRIDGE_FEATURE_SNAPSHOT_MANIFEST_PATH": ( + "gs://manual/snapshot.csv.manifest.json" + ), + } + ), ] ) @@ -1459,6 +1608,169 @@ def test_build_switch_target_uses_snapshot_scheduler_window(self): }, ) + def test_build_switch_target_auto_configures_ibkr_snapshot_artifacts(self): + cases = { + "global_etf_rotation": ( + "gs://qsl-runtime-logs-shared/strategy-artifacts/us_equity/global_etf_rotation/" + "global_etf_rotation_feature_snapshot_latest.csv" + ), + "russell_top50_leader_rotation": ( + "gs://qsl-runtime-logs-shared/strategy-artifacts/us_equity/" + "russell_top50_leader_rotation_staging/" + "russell_top50_leader_rotation_feature_snapshot_latest.csv" + ), + } + for profile, snapshot_path in cases.items(): + with self.subTest(profile=profile): + args = build_runtime_switch.build_parser().parse_args( + [ + "--platform", + "ibkr", + "--target-name", + "live", + "--strategy-profile", + profile, + "--plugin-mode", + "none", + ] + ) + + target = build_runtime_switch.build_switch_target(args) + assignments = { + item.name: item.value for item in runtime_settings.build_assignments(target) + } + + self.assertEqual(assignments["IBKR_FEATURE_SNAPSHOT_PATH"], snapshot_path) + self.assertEqual( + assignments["IBKR_FEATURE_SNAPSHOT_MANIFEST_PATH"], + f"{snapshot_path}.manifest.json", + ) + + def test_build_switch_target_clears_stale_ibkr_snapshot_artifacts(self): + existing = { + "targets": [ + { + "service": "interactive-brokers-live-service", + "ACCOUNT_GROUP": "live", + "IBKR_FEATURE_SNAPSHOT_PATH": "gs://stale/snapshot.csv", + "IBKR_FEATURE_SNAPSHOT_MANIFEST_PATH": "gs://stale/snapshot.csv.manifest.json", + "runtime_target": { + "platform_id": "ibkr", + "strategy_profile": "global_etf_rotation", + "dry_run_only": False, + "deployment_selector": "live", + "account_selector": ["LIVE"], + "account_scope": "live", + "service_name": "interactive-brokers-live-service", + "execution_mode": "live", + }, + } + ] + } + path = ROOT / ".pytest_runtime_service_targets_snapshot.json" + path.write_text(runtime_settings.compact_json(existing), encoding="utf-8") + self.addCleanup(lambda: path.unlink(missing_ok=True)) + args = build_runtime_switch.build_parser().parse_args( + [ + "--platform", + "ibkr", + "--target-name", + "live", + "--strategy-profile", + "tqqq_growth_income", + "--account-selector", + "LIVE", + "--service-name", + "interactive-brokers-live-service", + "--plugin-mode", + "none", + "--existing-service-targets-json-file", + str(path), + ] + ) + + target = build_runtime_switch.build_switch_target(args) + assignments = {item.name: item.value for item in runtime_settings.build_assignments(target)} + selected = json.loads(assignments["CLOUD_RUN_SERVICE_TARGETS_JSON"])["targets"][0] + + self.assertEqual(selected["IBKR_FEATURE_SNAPSHOT_PATH"], "") + self.assertEqual(selected["IBKR_FEATURE_SNAPSHOT_MANIFEST_PATH"], "") + + def test_snapshot_strategy_without_catalog_artifacts_requires_explicit_pair(self): + args = build_runtime_switch.build_parser().parse_args( + [ + "--platform", + "longbridge", + "--target-name", + "hk", + "--strategy-profile", + "hk_low_vol_dividend_quality_snapshot", + "--execution-mode", + "paper", + "--plugin-mode", + "none", + ] + ) + + with self.assertRaisesRegex(ValueError, "requires feature snapshot path and manifest path"): + build_runtime_switch.build_switch_target(args) + + def test_snapshot_strategy_accepts_explicit_platform_artifact_pair(self): + args = build_runtime_switch.build_parser().parse_args( + [ + "--platform", + "longbridge", + "--target-name", + "hk", + "--strategy-profile", + "hk_low_vol_dividend_quality_snapshot", + "--execution-mode", + "paper", + "--plugin-mode", + "none", + "--extra-variables-json", + json.dumps( + { + "LONGBRIDGE_FEATURE_SNAPSHOT_PATH": "gs://manual/snapshot.csv", + "LONGBRIDGE_FEATURE_SNAPSHOT_MANIFEST_PATH": ( + "gs://manual/snapshot.csv.manifest.json" + ), + } + ), + ] + ) + + target = build_runtime_switch.build_switch_target(args) + + self.assertEqual( + target["extra_variables"]["LONGBRIDGE_FEATURE_SNAPSHOT_PATH"], + "gs://manual/snapshot.csv", + ) + + def test_non_snapshot_strategy_rejects_snapshot_artifact_override(self): + args = build_runtime_switch.build_parser().parse_args( + [ + "--platform", + "ibkr", + "--target-name", + "live", + "--strategy-profile", + "tqqq_growth_income", + "--extra-variables-json", + json.dumps( + { + "IBKR_FEATURE_SNAPSHOT_PATH": "gs://unexpected/snapshot.csv", + "IBKR_FEATURE_SNAPSHOT_MANIFEST_PATH": ( + "gs://unexpected/snapshot.csv.manifest.json" + ), + } + ), + ] + ) + + with self.assertRaisesRegex(ValueError, "does not accept feature snapshot artifacts"): + build_runtime_switch.build_switch_target(args) + def test_scheduler_plan_uses_catalog_strategy_override_without_code_mapping(self): scheduler = { "timezone": "Europe/London", @@ -1509,6 +1821,28 @@ def test_build_config_rejects_unknown_strategy_scheduler_profile(self): build_config.validate(config), ) + def test_build_config_requires_live_snapshot_artifact_pair(self): + config = build_config.load_config() + config["strategies"]["global_etf_rotation"]["runtime_artifacts"][ + "feature_snapshot" + ].pop("manifest_path") + + self.assertIn( + "strategy global_etf_rotation: live feature snapshot requires path and manifest_path", + build_config.validate(config), + ) + + def test_build_config_rejects_non_boolean_snapshot_requirement(self): + config = build_config.load_config() + config["strategies"]["global_etf_rotation"]["runtime_artifacts"][ + "feature_snapshot" + ]["required"] = "true" + + self.assertIn( + "strategy global_etf_rotation: runtime_artifacts.feature_snapshot.required must be boolean", + build_config.validate(config), + ) + def test_build_config_reports_malformed_scheduler_timezone(self): config = build_config.load_config() config["scheduling"]["profiles"]["us_daily"]["timezone"] = "../UTC" @@ -1601,6 +1935,25 @@ def test_runtime_target_scheduler_rejects_invalid_cron_shape(self): runtime_settings.validate_target(target), ) + def test_live_ibkr_us_scheduler_rejects_weekend_cron(self): + args = build_runtime_switch.build_parser().parse_args( + [ + "--platform", + "ibkr", + "--target-name", + "live", + "--strategy-profile", + "tqqq_growth_income", + ] + ) + target = build_runtime_switch.build_switch_target(args) + target["runtime_target"]["scheduler"]["main_time"] = "45 15 * * *" + + self.assertIn( + "runtime_target.scheduler.main_time must be a two-field time or Mon-Fri cron for live IBKR US targets", + runtime_settings.validate_target(target), + ) + def test_runtime_target_scheduler_rejects_extra_fields(self): _, target = self.load_target("examples/targets/longbridge/hk_combo.example.json") target["runtime_target"]["scheduler"]["offset_minutes"] = 10 diff --git a/web/strategy-switch-console/index.html b/web/strategy-switch-console/index.html index fbd1c89..5c15242 100644 --- a/web/strategy-switch-console/index.html +++ b/web/strategy-switch-console/index.html @@ -13,7 +13,7 @@ window.__PLATFORM_CONFIG__ = {"longbridge": {"dry_run_only": false, "margin_policy": true, "reserved_cash": true, "income_layer": true, "option_overlay": true, "dca": true, "execution_mode": "live", "service_name": "", "default_execution_mode": "live"}, "ibkr": {"dry_run_only": false, "margin_policy": true, "reserved_cash": true, "income_layer": true, "option_overlay": true, "dca": true, "execution_mode": "live", "service_name": "", "default_execution_mode": "live"}, "schwab": {"dry_run_only": false, "margin_policy": true, "reserved_cash": true, "income_layer": true, "option_overlay": true, "dca": true, "execution_mode": "live", "service_name": "charles-schwab-quant-service", "default_execution_mode": "live"}, "firstrade": {"dry_run_only": false, "margin_policy": true, "reserved_cash": true, "income_layer": true, "option_overlay": true, "dca": true, "execution_mode": "live", "service_name": "firstrade-quant-service", "default_execution_mode": "live"}, "qmt": {"dry_run_only": true, "margin_policy": false, "reserved_cash": false, "income_layer": false, "option_overlay": false, "dca": false, "execution_mode": "paper", "service_name": "qmt-quant-service", "default_execution_mode": "paper"}, "binance": {"dry_run_only": false, "margin_policy": false, "reserved_cash": false, "income_layer": false, "option_overlay": false, "dca": false, "execution_mode": "live", "service_name": "binance-platform", "default_execution_mode": "live"}}; window.__DEFAULT_ACCOUNT_OPTIONS__ = {"longbridge": [{"key": "preview", "label": "LongBridge", "target_name": "preview", "supported_domains": ["us_equity", "hk_equity"], "cash_currency": "USD", "default_execution_mode": "live", "service_name": ""}], "ibkr": [{"key": "preview", "label": "IBKR", "target_name": "preview", "supported_domains": ["us_equity", "hk_equity"], "cash_currency": "USD", "default_execution_mode": "live", "service_name": ""}], "schwab": [{"key": "preview", "label": "Schwab", "target_name": "preview", "supported_domains": ["us_equity"], "cash_currency": "USD", "default_execution_mode": "live", "service_name": "charles-schwab-quant-service"}], "firstrade": [{"key": "preview", "label": "Firstrade", "target_name": "preview", "supported_domains": ["us_equity"], "cash_currency": "USD", "default_execution_mode": "live", "service_name": "firstrade-quant-service"}], "qmt": [{"key": "default", "label": "QMT", "target_name": "default", "supported_domains": ["cn_equity"], "cash_currency": "CNY", "service_name": "qmt-quant-service", "default_execution_mode": "paper"}], "binance": [{"key": "default", "label": "Binance", "target_name": "default", "supported_domains": ["crypto"], "cash_currency": "USD", "service_name": "binance-platform", "default_execution_mode": "live"}]}; window.__DOMAIN_LABELS__ = {"us_equity": {"zh": "美股", "en": "US Equity"}, "hk_equity": {"zh": "港股", "en": "HK Equity"}, "cn_equity": {"zh": "A股", "en": "CN A-share"}, "crypto": {"zh": "加密", "en": "Crypto"}}; -window.__DEFAULT_STRATEGY_PROFILES__ = [{"profile": "tqqq_growth_income", "label": "纳斯达克增长收益", "label_en": "NASDAQ Growth Income", "label_zh": "纳斯达克增长收益", "domain": "us_equity", "runtime_enabled": true, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": "", "income_layer_enabled": true, "option_overlay_enabled": true, "combo_enabled": false}, {"profile": "soxl_soxx_trend_income", "label": "半导体趋势收益", "label_en": "Semiconductor Trend Income", "label_zh": "半导体趋势收益", "domain": "us_equity", "runtime_enabled": true, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": "", "income_layer_enabled": true, "option_overlay_enabled": true, "combo_enabled": false}, {"profile": "nasdaq_sp500_smart_dca", "label": "纳指标普定投", "label_en": "NASDAQ/S&P 500 DCA", "label_zh": "纳指标普定投", "domain": "us_equity", "runtime_enabled": true, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": "", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "ibit_smart_dca", "label": "IBIT比特币定投", "label_en": "IBIT Bitcoin DCA", "label_zh": "IBIT比特币定投", "domain": "us_equity", "runtime_enabled": true, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": "", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "global_etf_rotation", "label": "全球ETF轮动", "label_en": "Global ETF Rotation", "label_zh": "全球ETF轮动", "domain": "us_equity", "runtime_enabled": true, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": "", "income_layer_enabled": true, "option_overlay_enabled": true, "combo_enabled": false}, {"profile": "russell_top50_leader_rotation", "label": "罗素Top50领涨", "label_en": "Russell Top50 Leaders", "label_zh": "罗素Top50领涨", "domain": "us_equity", "runtime_enabled": true, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": "", "income_layer_enabled": true, "option_overlay_enabled": true, "combo_enabled": false}, {"profile": "tecl_xlk_trend_income", "label": "TECL/XLK趋势收益", "label_en": "TECL/XLK Trend Income", "label_zh": "TECL/XLK趋势收益", "domain": "us_equity", "runtime_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "failed_promotion_vs_live_profiles", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "us_equity_combo", "label": "美股核心组合", "label_en": "US Core Combo", "label_zh": "美股核心组合", "domain": "us_equity", "runtime_enabled": false, "lifecycle_stage": "shadow_candidate", "can_switch_live": false, "allowed_execution_modes": ["paper", "dry_run"], "blocked_live_reason": "shadow_candidate_requires_evidence_package", "income_layer_enabled": true, "option_overlay_enabled": true, "combo_enabled": true, "combo_mode": "dynamic"}, {"profile": "us_equity_combo_core", "label": "美股核心组合影子", "label_en": "US Core Combo Shadow", "label_zh": "美股核心组合影子", "domain": "us_equity", "runtime_enabled": false, "lifecycle_stage": "shadow_candidate", "can_switch_live": false, "allowed_execution_modes": ["paper", "dry_run"], "blocked_live_reason": "shadow_candidate_requires_evidence_package", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": true, "combo_mode": "dynamic"}, {"profile": "us_equity_combo_leveraged", "label": "美股加速组合", "label_en": "US Alpha Combo", "label_zh": "美股加速组合", "domain": "us_equity", "runtime_enabled": false, "lifecycle_stage": "shadow_candidate", "can_switch_live": false, "allowed_execution_modes": ["paper", "dry_run"], "blocked_live_reason": "shadow_candidate_requires_evidence_package", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": true, "combo_mode": "dynamic"}, {"profile": "hk_global_etf_tactical_rotation", "label": "港股ETF战术轮动", "label_en": "HK ETF Tactical Rotation", "label_zh": "港股ETF战术轮动", "domain": "hk_equity", "runtime_enabled": true, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": "", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "hk_low_vol_dividend_quality_snapshot", "label": "港股红利质量", "label_en": "HK Dividend Quality", "label_zh": "港股红利质量", "domain": "hk_equity", "runtime_enabled": true, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": "", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "hk_equity_combo", "label": "港股恒生组合", "label_en": "HK Core Combo", "label_zh": "港股恒生组合", "domain": "hk_equity", "runtime_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": true, "combo_mode": "dynamic"}, {"profile": "cn_industry_etf_rotation", "label": "A股行业ETF轮动", "label_en": "CN Industry ETF Rotation", "label_zh": "A股行业ETF轮动", "domain": "cn_equity", "runtime_enabled": true, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": "", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "cn_industry_etf_rotation_aggressive", "label": "A股ETF轮动", "label_en": "CN ETF Rotation", "label_zh": "A股ETF轮动", "domain": "cn_equity", "runtime_enabled": false, "lifecycle_stage": "live_candidate", "can_switch_live": false, "allowed_execution_modes": ["paper", "dry_run"], "blocked_live_reason": "live_candidate_requires_evidence_package", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "cn_index_etf_tactical_rotation", "label": "A股宽基ETF战术轮动", "label_en": "CN Index ETF Tactical Rotation", "label_zh": "A股宽基ETF战术轮动", "domain": "cn_equity", "runtime_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "cn_chinext_tactical_rotation", "label": "创业板战术轮动", "label_en": "CN ChiNext Tactical Rotation", "label_zh": "创业板战术轮动", "domain": "cn_equity", "runtime_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "cn_chinext_growth_momentum_quality", "label": "创业板成长动量质量", "label_en": "CN ChiNext Growth Momentum Quality", "label_zh": "创业板成长动量质量", "domain": "cn_equity", "runtime_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "cn_dividend_quality_snapshot", "label": "A股红利质量", "label_en": "CN Dividend Quality", "label_zh": "A股红利质量", "domain": "cn_equity", "runtime_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "cn_chinext_growth_momentum_quality_snapshot", "label": "创业板成长质量快照", "label_en": "CN ChiNext Growth Quality Snapshot", "label_zh": "创业板成长质量快照", "domain": "cn_equity", "runtime_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "cn_star_growth_momentum_quality", "label": "科创板成长动量质量", "label_en": "CN STAR Growth Momentum Quality", "label_zh": "科创板成长动量质量", "domain": "cn_equity", "runtime_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "cn_equity_combo", "label": "A股进取组合", "label_en": "CN Alpha Combo", "label_zh": "A股进取组合", "domain": "cn_equity", "runtime_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": true, "combo_mode": "dynamic"}, {"profile": "crypto_live_pool_rotation", "label": "加密实时池轮动", "label_en": "Crypto Live Pool Rotation", "label_zh": "加密实时池轮动", "domain": "crypto", "runtime_enabled": true, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": "", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "crypto_btc_dca", "label": "BTC定投", "label_en": "BTC DCA", "label_zh": "BTC定投", "domain": "crypto", "runtime_enabled": false, "lifecycle_stage": "shadow_candidate", "can_switch_live": false, "allowed_execution_modes": ["paper", "dry_run"], "blocked_live_reason": "shadow_candidate_requires_evidence_package", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "crypto_trend_rotation", "label": "山寨趋势轮动", "label_en": "Altcoin Trend", "label_zh": "山寨趋势轮动", "domain": "crypto", "runtime_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "crypto_equity_combo", "label": "加密动量组合", "label_en": "Crypto Core Combo", "label_zh": "加密动量组合", "domain": "crypto", "runtime_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": true, "combo_mode": "dynamic"}]; +window.__DEFAULT_STRATEGY_PROFILES__ = [{"profile": "tqqq_growth_income", "label": "纳斯达克增长收益", "label_en": "NASDAQ Growth Income", "label_zh": "纳斯达克增长收益", "domain": "us_equity", "runtime_enabled": true, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": "", "income_layer_enabled": true, "option_overlay_enabled": true, "combo_enabled": false}, {"profile": "soxl_soxx_trend_income", "label": "半导体趋势收益", "label_en": "Semiconductor Trend Income", "label_zh": "半导体趋势收益", "domain": "us_equity", "runtime_enabled": true, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": "", "income_layer_enabled": true, "option_overlay_enabled": true, "combo_enabled": false}, {"profile": "nasdaq_sp500_smart_dca", "label": "纳指标普定投", "label_en": "NASDAQ/S&P 500 DCA", "label_zh": "纳指标普定投", "domain": "us_equity", "runtime_enabled": true, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": "", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "ibit_smart_dca", "label": "IBIT比特币定投", "label_en": "IBIT Bitcoin DCA", "label_zh": "IBIT比特币定投", "domain": "us_equity", "runtime_enabled": true, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": "", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "global_etf_rotation", "label": "全球ETF轮动", "label_en": "Global ETF Rotation", "label_zh": "全球ETF轮动", "domain": "us_equity", "runtime_enabled": true, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": "", "income_layer_enabled": true, "option_overlay_enabled": true, "combo_enabled": false}, {"profile": "russell_top50_leader_rotation", "label": "罗素Top50领涨", "label_en": "Russell Top50 Leaders", "label_zh": "罗素Top50领涨", "domain": "us_equity", "runtime_enabled": true, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": "", "income_layer_enabled": true, "option_overlay_enabled": true, "combo_enabled": false}, {"profile": "tecl_xlk_trend_income", "label": "TECL/XLK趋势收益", "label_en": "TECL/XLK Trend Income", "label_zh": "TECL/XLK趋势收益", "domain": "us_equity", "runtime_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "failed_promotion_vs_live_profiles", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "us_equity_combo", "label": "美股核心组合", "label_en": "US Core Combo", "label_zh": "美股核心组合", "domain": "us_equity", "runtime_enabled": false, "lifecycle_stage": "shadow_candidate", "can_switch_live": false, "allowed_execution_modes": ["paper", "dry_run"], "blocked_live_reason": "shadow_candidate_requires_evidence_package", "income_layer_enabled": true, "option_overlay_enabled": true, "combo_enabled": true, "combo_mode": "dynamic"}, {"profile": "us_equity_combo_core", "label": "美股核心组合影子", "label_en": "US Core Combo Shadow", "label_zh": "美股核心组合影子", "domain": "us_equity", "runtime_enabled": false, "lifecycle_stage": "shadow_candidate", "can_switch_live": false, "allowed_execution_modes": ["paper", "dry_run"], "blocked_live_reason": "shadow_candidate_requires_evidence_package", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": true, "combo_mode": "dynamic"}, {"profile": "us_equity_combo_leveraged", "label": "美股加速组合", "label_en": "US Alpha Combo", "label_zh": "美股加速组合", "domain": "us_equity", "runtime_enabled": false, "lifecycle_stage": "shadow_candidate", "can_switch_live": false, "allowed_execution_modes": ["paper", "dry_run"], "blocked_live_reason": "shadow_candidate_requires_evidence_package", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": true, "combo_mode": "dynamic"}, {"profile": "hk_global_etf_tactical_rotation", "label": "港股ETF战术轮动", "label_en": "HK ETF Tactical Rotation", "label_zh": "港股ETF战术轮动", "domain": "hk_equity", "runtime_enabled": true, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": "", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "hk_low_vol_dividend_quality_snapshot", "label": "港股红利质量", "label_en": "HK Dividend Quality", "label_zh": "港股红利质量", "domain": "hk_equity", "runtime_enabled": true, "lifecycle_stage": "runtime_enabled", "can_switch_live": false, "allowed_execution_modes": ["paper", "dry_run"], "blocked_live_reason": "production_snapshot_artifact_route_not_configured", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "hk_equity_combo", "label": "港股恒生组合", "label_en": "HK Core Combo", "label_zh": "港股恒生组合", "domain": "hk_equity", "runtime_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": true, "combo_mode": "dynamic"}, {"profile": "cn_industry_etf_rotation", "label": "A股行业ETF轮动", "label_en": "CN Industry ETF Rotation", "label_zh": "A股行业ETF轮动", "domain": "cn_equity", "runtime_enabled": true, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": "", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "cn_industry_etf_rotation_aggressive", "label": "A股ETF轮动", "label_en": "CN ETF Rotation", "label_zh": "A股ETF轮动", "domain": "cn_equity", "runtime_enabled": false, "lifecycle_stage": "live_candidate", "can_switch_live": false, "allowed_execution_modes": ["paper", "dry_run"], "blocked_live_reason": "live_candidate_requires_evidence_package", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "cn_index_etf_tactical_rotation", "label": "A股宽基ETF战术轮动", "label_en": "CN Index ETF Tactical Rotation", "label_zh": "A股宽基ETF战术轮动", "domain": "cn_equity", "runtime_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "cn_chinext_tactical_rotation", "label": "创业板战术轮动", "label_en": "CN ChiNext Tactical Rotation", "label_zh": "创业板战术轮动", "domain": "cn_equity", "runtime_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "cn_chinext_growth_momentum_quality", "label": "创业板成长动量质量", "label_en": "CN ChiNext Growth Momentum Quality", "label_zh": "创业板成长动量质量", "domain": "cn_equity", "runtime_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "cn_dividend_quality_snapshot", "label": "A股红利质量", "label_en": "CN Dividend Quality", "label_zh": "A股红利质量", "domain": "cn_equity", "runtime_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "cn_chinext_growth_momentum_quality_snapshot", "label": "创业板成长质量快照", "label_en": "CN ChiNext Growth Quality Snapshot", "label_zh": "创业板成长质量快照", "domain": "cn_equity", "runtime_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "cn_star_growth_momentum_quality", "label": "科创板成长动量质量", "label_en": "CN STAR Growth Momentum Quality", "label_zh": "科创板成长动量质量", "domain": "cn_equity", "runtime_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "cn_equity_combo", "label": "A股进取组合", "label_en": "CN Alpha Combo", "label_zh": "A股进取组合", "domain": "cn_equity", "runtime_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": true, "combo_mode": "dynamic"}, {"profile": "crypto_live_pool_rotation", "label": "加密实时池轮动", "label_en": "Crypto Live Pool Rotation", "label_zh": "加密实时池轮动", "domain": "crypto", "runtime_enabled": true, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": "", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "crypto_btc_dca", "label": "BTC定投", "label_en": "BTC DCA", "label_zh": "BTC定投", "domain": "crypto", "runtime_enabled": false, "lifecycle_stage": "shadow_candidate", "can_switch_live": false, "allowed_execution_modes": ["paper", "dry_run"], "blocked_live_reason": "shadow_candidate_requires_evidence_package", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "crypto_trend_rotation", "label": "山寨趋势轮动", "label_en": "Altcoin Trend", "label_zh": "山寨趋势轮动", "domain": "crypto", "runtime_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false}, {"profile": "crypto_equity_combo", "label": "加密动量组合", "label_en": "Crypto Core Combo", "label_zh": "加密动量组合", "domain": "crypto", "runtime_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package", "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": true, "combo_mode": "dynamic"}]; window.__DCA_PROFILE_DEFAULTS__ = {"nasdaq_sp500_smart_dca": {"defaultMode": "fixed", "defaultBaseInvestmentUsd": "1000"}, "ibit_smart_dca": {"defaultMode": "fixed", "defaultBaseInvestmentUsd": "1000"}}; window.__INCOME_LAYER_DEFAULTS__ = {"tqqq_growth_income": {"startUsd": 250000, "maxRatio": "0.55", "allocations": {"SCHD": 0.3, "DGRO": 0.2, "SGOV": 0.4, "SPYI": 0.08, "QQQI": 0.02}}, "soxl_soxx_trend_income": {"startUsd": 150000, "maxRatio": "0.95", "allocations": {"SCHD": 0.15, "DGRO": 0.1, "SGOV": 0.7, "SPYI": 0.04, "QQQI": 0.01}}, "global_etf_rotation": {"startUsd": 500000, "maxRatio": "0.15", "allocations": {"SCHD": 0.4, "DGRO": 0.25, "SGOV": 0.3, "SPYI": 0.05}}, "russell_top50_leader_rotation": {"startUsd": 300000, "maxRatio": "0.25", "allocations": {"SCHD": 0.45, "DGRO": 0.3, "SGOV": 0.25}}, "us_equity_combo": {"startUsd": 300000, "maxRatio": "0.25", "allocations": {"SCHD": 0.25, "DGRO": 0.25, "SGOV": 0.2, "SPYI": 0.15, "QQQI": 0.15}}}; window.__OPTION_OVERLAY_DEFAULTS__ = {"tqqq_growth_income": {"liveGate": "promotion_required", "liveStatus": "research_only", "families": [{"family": "growth", "recipe": "tqqq_leaps_growth_v1", "startUsd": "250000", "ratio": "0.03", "ratioKind": "budget"}]}, "soxl_soxx_trend_income": {"liveGate": "promotion_required", "liveStatus": "research_only", "families": [{"family": "income", "recipe": "soxx_put_credit_spread_income_v1", "startUsd": "150000", "ratio": "0.01", "ratioKind": "risk"}]}, "global_etf_rotation": {"liveGate": "promotion_required", "liveStatus": "research_only", "families": [{"family": "growth", "recipe": "spy_leaps_growth_v1", "startUsd": "500000", "ratio": "0.015", "ratioKind": "budget"}]}, "russell_top50_leader_rotation": {"liveGate": "promotion_required", "liveStatus": "research_only", "families": [{"family": "growth", "recipe": "spy_leaps_growth_v1", "startUsd": "300000", "ratio": "0.015", "ratioKind": "budget"}]}, "us_equity_combo": {"liveGate": "promotion_required", "liveStatus": "research_only", "families": [{"family": "growth", "recipe": "spy_leaps_growth_v1", "startUsd": "300000", "ratio": "0.015", "ratioKind": "budget"}]}}; diff --git a/web/strategy-switch-console/page_asset.js b/web/strategy-switch-console/page_asset.js index 3a2732c..f5a7ac4 100644 --- a/web/strategy-switch-console/page_asset.js +++ b/web/strategy-switch-console/page_asset.js @@ -1,2 +1,2 @@ // Generated by scripts/sync_strategy_switch_page_asset.py; do not edit by hand. -export const PAGE_HTML = "\n\n\n \n \n \n QuantRuntimeSettings Strategy Switch\n \n \n\n\n\n\n\n
\n
\n

策略切换

\n

选平台、目标账号和策略,一次执行完成切换。

\n
\n
\n \n \n \n \n
\n
\n\n
\n
\n 初始化控制台\n

读取策略配置

\n

正在读取登录状态、账号配置和当前状态。

\n
\n
\n
\n\n
\n \n\n
\n
\n
\n 策略健康 / 只读\n

先看机器结论,再决定动作。

\n

健康不等于已批准 live;正常实盘、资金和杠杆变更仍需人工确认。

\n
\n
\n 等待登录\n 最近计算:—\n
\n
\n
登录后读取私有策略健康快照;没有快照时不会展示虚构指标。
\n
\n
策略总数0
\n
健康0
\n
观察0
\n
需要复核0
\n
严重0
\n
\n
\n

策略状态

\n
\n \n \n \n \n \n
\n
\n
\n
\n\n \n
\n\n \n\n\n"; +export const PAGE_HTML = "\n\n\n \n \n \n QuantRuntimeSettings Strategy Switch\n \n \n\n\n\n\n\n
\n
\n

策略切换

\n

选平台、目标账号和策略,一次执行完成切换。

\n
\n
\n \n \n \n \n
\n
\n\n
\n
\n 初始化控制台\n

读取策略配置

\n

正在读取登录状态、账号配置和当前状态。

\n
\n
\n
\n\n
\n \n\n
\n
\n
\n 策略健康 / 只读\n

先看机器结论,再决定动作。

\n

健康不等于已批准 live;正常实盘、资金和杠杆变更仍需人工确认。

\n
\n
\n 等待登录\n 最近计算:—\n
\n
\n
登录后读取私有策略健康快照;没有快照时不会展示虚构指标。
\n
\n
策略总数0
\n
健康0
\n
观察0
\n
需要复核0
\n
严重0
\n
\n
\n

策略状态

\n
\n \n \n \n \n \n
\n
\n
\n
\n\n \n
\n\n \n\n\n"; diff --git a/web/strategy-switch-console/strategy-profiles.example.json b/web/strategy-switch-console/strategy-profiles.example.json index 72b3621..c0fa729 100644 --- a/web/strategy-switch-console/strategy-profiles.example.json +++ b/web/strategy-switch-console/strategy-profiles.example.json @@ -1 +1 @@ -[{"profile":"tqqq_growth_income","label":"纳斯达克增长收益","label_en":"NASDAQ Growth Income","label_zh":"纳斯达克增长收益","domain":"us_equity","runtime_enabled":true,"income_layer_enabled":true,"option_overlay_enabled":true,"combo_enabled":false,"lifecycle_stage":"runtime_enabled","can_switch_live":true,"allowed_execution_modes":["live","paper","dry_run"],"blocked_live_reason":"","income_layer_start_usd":"250000","income_layer_max_ratio":"0.55","income_layer_allocations":{"SCHD":0.3,"DGRO":0.2,"SGOV":0.4,"SPYI":0.08,"QQQI":0.02},"option_overlay_live_gate":"promotion_required","option_overlay_live_status":"research_only","option_growth_overlay_enabled":true,"option_growth_overlay_recipe":"tqqq_leaps_growth_v1","option_growth_overlay_start_usd":"250000","option_growth_overlay_nav_budget_ratio":"0.03"},{"profile":"soxl_soxx_trend_income","label":"半导体趋势收益","label_en":"Semiconductor Trend Income","label_zh":"半导体趋势收益","domain":"us_equity","runtime_enabled":true,"income_layer_enabled":true,"option_overlay_enabled":true,"combo_enabled":false,"lifecycle_stage":"runtime_enabled","can_switch_live":true,"allowed_execution_modes":["live","paper","dry_run"],"blocked_live_reason":"","income_layer_start_usd":"150000","income_layer_max_ratio":"0.95","income_layer_allocations":{"SCHD":0.15,"DGRO":0.1,"SGOV":0.7,"SPYI":0.04,"QQQI":0.01},"option_overlay_live_gate":"promotion_required","option_overlay_live_status":"research_only","option_income_overlay_enabled":true,"option_income_overlay_recipe":"soxx_put_credit_spread_income_v1","option_income_overlay_start_usd":"150000","option_income_overlay_nav_risk_ratio":"0.01"},{"profile":"nasdaq_sp500_smart_dca","label":"纳指标普定投","label_en":"NASDAQ/S&P 500 DCA","label_zh":"纳指标普定投","domain":"us_equity","runtime_enabled":true,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"runtime_enabled","can_switch_live":true,"allowed_execution_modes":["live","paper","dry_run"],"blocked_live_reason":"","dca_enabled":true,"dca_default_mode":"fixed","dca_default_base_investment_usd":"1000"},{"profile":"ibit_smart_dca","label":"IBIT比特币定投","label_en":"IBIT Bitcoin DCA","label_zh":"IBIT比特币定投","domain":"us_equity","runtime_enabled":true,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"runtime_enabled","can_switch_live":true,"allowed_execution_modes":["live","paper","dry_run"],"blocked_live_reason":"","dca_enabled":true,"dca_default_mode":"fixed","dca_default_base_investment_usd":"1000"},{"profile":"global_etf_rotation","label":"全球ETF轮动","label_en":"Global ETF Rotation","label_zh":"全球ETF轮动","domain":"us_equity","runtime_enabled":true,"income_layer_enabled":true,"option_overlay_enabled":true,"combo_enabled":false,"lifecycle_stage":"runtime_enabled","can_switch_live":true,"allowed_execution_modes":["live","paper","dry_run"],"blocked_live_reason":"","income_layer_start_usd":"500000","income_layer_max_ratio":"0.15","income_layer_allocations":{"SCHD":0.4,"DGRO":0.25,"SGOV":0.3,"SPYI":0.05},"option_overlay_live_gate":"promotion_required","option_overlay_live_status":"research_only","option_growth_overlay_enabled":true,"option_growth_overlay_recipe":"spy_leaps_growth_v1","option_growth_overlay_start_usd":"500000","option_growth_overlay_nav_budget_ratio":"0.015"},{"profile":"russell_top50_leader_rotation","label":"罗素Top50领涨","label_en":"Russell Top50 Leaders","label_zh":"罗素Top50领涨","domain":"us_equity","runtime_enabled":true,"income_layer_enabled":true,"option_overlay_enabled":true,"combo_enabled":false,"lifecycle_stage":"runtime_enabled","can_switch_live":true,"allowed_execution_modes":["live","paper","dry_run"],"blocked_live_reason":"","income_layer_start_usd":"300000","income_layer_max_ratio":"0.25","income_layer_allocations":{"SCHD":0.45,"DGRO":0.3,"SGOV":0.25},"option_overlay_live_gate":"promotion_required","option_overlay_live_status":"research_only","option_growth_overlay_enabled":true,"option_growth_overlay_recipe":"spy_leaps_growth_v1","option_growth_overlay_start_usd":"300000","option_growth_overlay_nav_budget_ratio":"0.015"},{"profile":"tecl_xlk_trend_income","label":"TECL/XLK趋势收益","label_en":"TECL/XLK Trend Income","label_zh":"TECL/XLK趋势收益","domain":"us_equity","runtime_enabled":false,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"research_backtest_only","can_switch_live":false,"allowed_execution_modes":["dry_run"],"blocked_live_reason":"failed_promotion_vs_live_profiles"},{"profile":"us_equity_combo","label":"美股核心组合","label_en":"US Core Combo","label_zh":"美股核心组合","domain":"us_equity","runtime_enabled":false,"income_layer_enabled":true,"option_overlay_enabled":true,"combo_enabled":true,"lifecycle_stage":"shadow_candidate","can_switch_live":false,"allowed_execution_modes":["paper","dry_run"],"blocked_live_reason":"shadow_candidate_requires_evidence_package","combo_mode":"dynamic","income_layer_start_usd":"300000","income_layer_max_ratio":"0.25","income_layer_allocations":{"SCHD":0.25,"DGRO":0.25,"SGOV":0.2,"SPYI":0.15,"QQQI":0.15},"option_overlay_live_gate":"promotion_required","option_overlay_live_status":"research_only","option_growth_overlay_enabled":true,"option_growth_overlay_recipe":"spy_leaps_growth_v1","option_growth_overlay_start_usd":"300000","option_growth_overlay_nav_budget_ratio":"0.015"},{"profile":"us_equity_combo_core","label":"美股核心组合影子","label_en":"US Core Combo Shadow","label_zh":"美股核心组合影子","domain":"us_equity","runtime_enabled":false,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":true,"lifecycle_stage":"shadow_candidate","can_switch_live":false,"allowed_execution_modes":["paper","dry_run"],"blocked_live_reason":"shadow_candidate_requires_evidence_package","combo_mode":"dynamic"},{"profile":"us_equity_combo_leveraged","label":"美股加速组合","label_en":"US Alpha Combo","label_zh":"美股加速组合","domain":"us_equity","runtime_enabled":false,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":true,"lifecycle_stage":"shadow_candidate","can_switch_live":false,"allowed_execution_modes":["paper","dry_run"],"blocked_live_reason":"shadow_candidate_requires_evidence_package","combo_mode":"dynamic"},{"profile":"hk_global_etf_tactical_rotation","label":"港股ETF战术轮动","label_en":"HK ETF Tactical Rotation","label_zh":"港股ETF战术轮动","domain":"hk_equity","runtime_enabled":true,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"runtime_enabled","can_switch_live":true,"allowed_execution_modes":["live","paper","dry_run"],"blocked_live_reason":""},{"profile":"hk_low_vol_dividend_quality_snapshot","label":"港股红利质量","label_en":"HK Dividend Quality","label_zh":"港股红利质量","domain":"hk_equity","runtime_enabled":true,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"runtime_enabled","can_switch_live":true,"allowed_execution_modes":["live","paper","dry_run"],"blocked_live_reason":""},{"profile":"hk_equity_combo","label":"港股恒生组合","label_en":"HK Core Combo","label_zh":"港股恒生组合","domain":"hk_equity","runtime_enabled":false,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":true,"lifecycle_stage":"research_backtest_only","can_switch_live":false,"allowed_execution_modes":["dry_run"],"blocked_live_reason":"research_backtest_only_requires_evidence_package","combo_mode":"dynamic"},{"profile":"cn_industry_etf_rotation","label":"A股行业ETF轮动","label_en":"CN Industry ETF Rotation","label_zh":"A股行业ETF轮动","domain":"cn_equity","runtime_enabled":true,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"runtime_enabled","can_switch_live":true,"allowed_execution_modes":["live","paper","dry_run"],"blocked_live_reason":""},{"profile":"cn_industry_etf_rotation_aggressive","label":"A股ETF轮动","label_en":"CN ETF Rotation","label_zh":"A股ETF轮动","domain":"cn_equity","runtime_enabled":false,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"live_candidate","can_switch_live":false,"allowed_execution_modes":["paper","dry_run"],"blocked_live_reason":"live_candidate_requires_evidence_package"},{"profile":"cn_index_etf_tactical_rotation","label":"A股宽基ETF战术轮动","label_en":"CN Index ETF Tactical Rotation","label_zh":"A股宽基ETF战术轮动","domain":"cn_equity","runtime_enabled":false,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"research_backtest_only","can_switch_live":false,"allowed_execution_modes":["dry_run"],"blocked_live_reason":"research_backtest_only_requires_evidence_package"},{"profile":"cn_chinext_tactical_rotation","label":"创业板战术轮动","label_en":"CN ChiNext Tactical Rotation","label_zh":"创业板战术轮动","domain":"cn_equity","runtime_enabled":false,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"research_backtest_only","can_switch_live":false,"allowed_execution_modes":["dry_run"],"blocked_live_reason":"research_backtest_only_requires_evidence_package"},{"profile":"cn_chinext_growth_momentum_quality","label":"创业板成长动量质量","label_en":"CN ChiNext Growth Momentum Quality","label_zh":"创业板成长动量质量","domain":"cn_equity","runtime_enabled":false,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"research_backtest_only","can_switch_live":false,"allowed_execution_modes":["dry_run"],"blocked_live_reason":"research_backtest_only_requires_evidence_package"},{"profile":"cn_dividend_quality_snapshot","label":"A股红利质量","label_en":"CN Dividend Quality","label_zh":"A股红利质量","domain":"cn_equity","runtime_enabled":false,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"research_backtest_only","can_switch_live":false,"allowed_execution_modes":["dry_run"],"blocked_live_reason":"research_backtest_only_requires_evidence_package"},{"profile":"cn_chinext_growth_momentum_quality_snapshot","label":"创业板成长质量快照","label_en":"CN ChiNext Growth Quality Snapshot","label_zh":"创业板成长质量快照","domain":"cn_equity","runtime_enabled":false,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"research_backtest_only","can_switch_live":false,"allowed_execution_modes":["dry_run"],"blocked_live_reason":"research_backtest_only_requires_evidence_package"},{"profile":"cn_star_growth_momentum_quality","label":"科创板成长动量质量","label_en":"CN STAR Growth Momentum Quality","label_zh":"科创板成长动量质量","domain":"cn_equity","runtime_enabled":false,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"research_backtest_only","can_switch_live":false,"allowed_execution_modes":["dry_run"],"blocked_live_reason":"research_backtest_only_requires_evidence_package"},{"profile":"cn_equity_combo","label":"A股进取组合","label_en":"CN Alpha Combo","label_zh":"A股进取组合","domain":"cn_equity","runtime_enabled":false,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":true,"lifecycle_stage":"research_backtest_only","can_switch_live":false,"allowed_execution_modes":["dry_run"],"blocked_live_reason":"research_backtest_only_requires_evidence_package","combo_mode":"dynamic"},{"profile":"crypto_live_pool_rotation","label":"加密实时池轮动","label_en":"Crypto Live Pool Rotation","label_zh":"加密实时池轮动","domain":"crypto","runtime_enabled":true,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"runtime_enabled","can_switch_live":true,"allowed_execution_modes":["live","paper","dry_run"],"blocked_live_reason":""},{"profile":"crypto_btc_dca","label":"BTC定投","label_en":"BTC DCA","label_zh":"BTC定投","domain":"crypto","runtime_enabled":false,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"shadow_candidate","can_switch_live":false,"allowed_execution_modes":["paper","dry_run"],"blocked_live_reason":"shadow_candidate_requires_evidence_package"},{"profile":"crypto_trend_rotation","label":"山寨趋势轮动","label_en":"Altcoin Trend","label_zh":"山寨趋势轮动","domain":"crypto","runtime_enabled":false,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"research_backtest_only","can_switch_live":false,"allowed_execution_modes":["dry_run"],"blocked_live_reason":"research_backtest_only_requires_evidence_package"},{"profile":"crypto_equity_combo","label":"加密动量组合","label_en":"Crypto Core Combo","label_zh":"加密动量组合","domain":"crypto","runtime_enabled":false,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":true,"lifecycle_stage":"research_backtest_only","can_switch_live":false,"allowed_execution_modes":["dry_run"],"blocked_live_reason":"research_backtest_only_requires_evidence_package","combo_mode":"dynamic"}] +[{"profile":"tqqq_growth_income","label":"纳斯达克增长收益","label_en":"NASDAQ Growth Income","label_zh":"纳斯达克增长收益","domain":"us_equity","runtime_enabled":true,"income_layer_enabled":true,"option_overlay_enabled":true,"combo_enabled":false,"lifecycle_stage":"runtime_enabled","can_switch_live":true,"allowed_execution_modes":["live","paper","dry_run"],"blocked_live_reason":"","income_layer_start_usd":"250000","income_layer_max_ratio":"0.55","income_layer_allocations":{"SCHD":0.3,"DGRO":0.2,"SGOV":0.4,"SPYI":0.08,"QQQI":0.02},"option_overlay_live_gate":"promotion_required","option_overlay_live_status":"research_only","option_growth_overlay_enabled":true,"option_growth_overlay_recipe":"tqqq_leaps_growth_v1","option_growth_overlay_start_usd":"250000","option_growth_overlay_nav_budget_ratio":"0.03"},{"profile":"soxl_soxx_trend_income","label":"半导体趋势收益","label_en":"Semiconductor Trend Income","label_zh":"半导体趋势收益","domain":"us_equity","runtime_enabled":true,"income_layer_enabled":true,"option_overlay_enabled":true,"combo_enabled":false,"lifecycle_stage":"runtime_enabled","can_switch_live":true,"allowed_execution_modes":["live","paper","dry_run"],"blocked_live_reason":"","income_layer_start_usd":"150000","income_layer_max_ratio":"0.95","income_layer_allocations":{"SCHD":0.15,"DGRO":0.1,"SGOV":0.7,"SPYI":0.04,"QQQI":0.01},"option_overlay_live_gate":"promotion_required","option_overlay_live_status":"research_only","option_income_overlay_enabled":true,"option_income_overlay_recipe":"soxx_put_credit_spread_income_v1","option_income_overlay_start_usd":"150000","option_income_overlay_nav_risk_ratio":"0.01"},{"profile":"nasdaq_sp500_smart_dca","label":"纳指标普定投","label_en":"NASDAQ/S&P 500 DCA","label_zh":"纳指标普定投","domain":"us_equity","runtime_enabled":true,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"runtime_enabled","can_switch_live":true,"allowed_execution_modes":["live","paper","dry_run"],"blocked_live_reason":"","dca_enabled":true,"dca_default_mode":"fixed","dca_default_base_investment_usd":"1000"},{"profile":"ibit_smart_dca","label":"IBIT比特币定投","label_en":"IBIT Bitcoin DCA","label_zh":"IBIT比特币定投","domain":"us_equity","runtime_enabled":true,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"runtime_enabled","can_switch_live":true,"allowed_execution_modes":["live","paper","dry_run"],"blocked_live_reason":"","dca_enabled":true,"dca_default_mode":"fixed","dca_default_base_investment_usd":"1000"},{"profile":"global_etf_rotation","label":"全球ETF轮动","label_en":"Global ETF Rotation","label_zh":"全球ETF轮动","domain":"us_equity","runtime_enabled":true,"income_layer_enabled":true,"option_overlay_enabled":true,"combo_enabled":false,"lifecycle_stage":"runtime_enabled","can_switch_live":true,"allowed_execution_modes":["live","paper","dry_run"],"blocked_live_reason":"","income_layer_start_usd":"500000","income_layer_max_ratio":"0.15","income_layer_allocations":{"SCHD":0.4,"DGRO":0.25,"SGOV":0.3,"SPYI":0.05},"option_overlay_live_gate":"promotion_required","option_overlay_live_status":"research_only","option_growth_overlay_enabled":true,"option_growth_overlay_recipe":"spy_leaps_growth_v1","option_growth_overlay_start_usd":"500000","option_growth_overlay_nav_budget_ratio":"0.015"},{"profile":"russell_top50_leader_rotation","label":"罗素Top50领涨","label_en":"Russell Top50 Leaders","label_zh":"罗素Top50领涨","domain":"us_equity","runtime_enabled":true,"income_layer_enabled":true,"option_overlay_enabled":true,"combo_enabled":false,"lifecycle_stage":"runtime_enabled","can_switch_live":true,"allowed_execution_modes":["live","paper","dry_run"],"blocked_live_reason":"","income_layer_start_usd":"300000","income_layer_max_ratio":"0.25","income_layer_allocations":{"SCHD":0.45,"DGRO":0.3,"SGOV":0.25},"option_overlay_live_gate":"promotion_required","option_overlay_live_status":"research_only","option_growth_overlay_enabled":true,"option_growth_overlay_recipe":"spy_leaps_growth_v1","option_growth_overlay_start_usd":"300000","option_growth_overlay_nav_budget_ratio":"0.015"},{"profile":"tecl_xlk_trend_income","label":"TECL/XLK趋势收益","label_en":"TECL/XLK Trend Income","label_zh":"TECL/XLK趋势收益","domain":"us_equity","runtime_enabled":false,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"research_backtest_only","can_switch_live":false,"allowed_execution_modes":["dry_run"],"blocked_live_reason":"failed_promotion_vs_live_profiles"},{"profile":"us_equity_combo","label":"美股核心组合","label_en":"US Core Combo","label_zh":"美股核心组合","domain":"us_equity","runtime_enabled":false,"income_layer_enabled":true,"option_overlay_enabled":true,"combo_enabled":true,"lifecycle_stage":"shadow_candidate","can_switch_live":false,"allowed_execution_modes":["paper","dry_run"],"blocked_live_reason":"shadow_candidate_requires_evidence_package","combo_mode":"dynamic","income_layer_start_usd":"300000","income_layer_max_ratio":"0.25","income_layer_allocations":{"SCHD":0.25,"DGRO":0.25,"SGOV":0.2,"SPYI":0.15,"QQQI":0.15},"option_overlay_live_gate":"promotion_required","option_overlay_live_status":"research_only","option_growth_overlay_enabled":true,"option_growth_overlay_recipe":"spy_leaps_growth_v1","option_growth_overlay_start_usd":"300000","option_growth_overlay_nav_budget_ratio":"0.015"},{"profile":"us_equity_combo_core","label":"美股核心组合影子","label_en":"US Core Combo Shadow","label_zh":"美股核心组合影子","domain":"us_equity","runtime_enabled":false,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":true,"lifecycle_stage":"shadow_candidate","can_switch_live":false,"allowed_execution_modes":["paper","dry_run"],"blocked_live_reason":"shadow_candidate_requires_evidence_package","combo_mode":"dynamic"},{"profile":"us_equity_combo_leveraged","label":"美股加速组合","label_en":"US Alpha Combo","label_zh":"美股加速组合","domain":"us_equity","runtime_enabled":false,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":true,"lifecycle_stage":"shadow_candidate","can_switch_live":false,"allowed_execution_modes":["paper","dry_run"],"blocked_live_reason":"shadow_candidate_requires_evidence_package","combo_mode":"dynamic"},{"profile":"hk_global_etf_tactical_rotation","label":"港股ETF战术轮动","label_en":"HK ETF Tactical Rotation","label_zh":"港股ETF战术轮动","domain":"hk_equity","runtime_enabled":true,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"runtime_enabled","can_switch_live":true,"allowed_execution_modes":["live","paper","dry_run"],"blocked_live_reason":""},{"profile":"hk_low_vol_dividend_quality_snapshot","label":"港股红利质量","label_en":"HK Dividend Quality","label_zh":"港股红利质量","domain":"hk_equity","runtime_enabled":true,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"runtime_enabled","can_switch_live":false,"allowed_execution_modes":["paper","dry_run"],"blocked_live_reason":"production_snapshot_artifact_route_not_configured"},{"profile":"hk_equity_combo","label":"港股恒生组合","label_en":"HK Core Combo","label_zh":"港股恒生组合","domain":"hk_equity","runtime_enabled":false,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":true,"lifecycle_stage":"research_backtest_only","can_switch_live":false,"allowed_execution_modes":["dry_run"],"blocked_live_reason":"research_backtest_only_requires_evidence_package","combo_mode":"dynamic"},{"profile":"cn_industry_etf_rotation","label":"A股行业ETF轮动","label_en":"CN Industry ETF Rotation","label_zh":"A股行业ETF轮动","domain":"cn_equity","runtime_enabled":true,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"runtime_enabled","can_switch_live":true,"allowed_execution_modes":["live","paper","dry_run"],"blocked_live_reason":""},{"profile":"cn_industry_etf_rotation_aggressive","label":"A股ETF轮动","label_en":"CN ETF Rotation","label_zh":"A股ETF轮动","domain":"cn_equity","runtime_enabled":false,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"live_candidate","can_switch_live":false,"allowed_execution_modes":["paper","dry_run"],"blocked_live_reason":"live_candidate_requires_evidence_package"},{"profile":"cn_index_etf_tactical_rotation","label":"A股宽基ETF战术轮动","label_en":"CN Index ETF Tactical Rotation","label_zh":"A股宽基ETF战术轮动","domain":"cn_equity","runtime_enabled":false,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"research_backtest_only","can_switch_live":false,"allowed_execution_modes":["dry_run"],"blocked_live_reason":"research_backtest_only_requires_evidence_package"},{"profile":"cn_chinext_tactical_rotation","label":"创业板战术轮动","label_en":"CN ChiNext Tactical Rotation","label_zh":"创业板战术轮动","domain":"cn_equity","runtime_enabled":false,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"research_backtest_only","can_switch_live":false,"allowed_execution_modes":["dry_run"],"blocked_live_reason":"research_backtest_only_requires_evidence_package"},{"profile":"cn_chinext_growth_momentum_quality","label":"创业板成长动量质量","label_en":"CN ChiNext Growth Momentum Quality","label_zh":"创业板成长动量质量","domain":"cn_equity","runtime_enabled":false,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"research_backtest_only","can_switch_live":false,"allowed_execution_modes":["dry_run"],"blocked_live_reason":"research_backtest_only_requires_evidence_package"},{"profile":"cn_dividend_quality_snapshot","label":"A股红利质量","label_en":"CN Dividend Quality","label_zh":"A股红利质量","domain":"cn_equity","runtime_enabled":false,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"research_backtest_only","can_switch_live":false,"allowed_execution_modes":["dry_run"],"blocked_live_reason":"research_backtest_only_requires_evidence_package"},{"profile":"cn_chinext_growth_momentum_quality_snapshot","label":"创业板成长质量快照","label_en":"CN ChiNext Growth Quality Snapshot","label_zh":"创业板成长质量快照","domain":"cn_equity","runtime_enabled":false,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"research_backtest_only","can_switch_live":false,"allowed_execution_modes":["dry_run"],"blocked_live_reason":"research_backtest_only_requires_evidence_package"},{"profile":"cn_star_growth_momentum_quality","label":"科创板成长动量质量","label_en":"CN STAR Growth Momentum Quality","label_zh":"科创板成长动量质量","domain":"cn_equity","runtime_enabled":false,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"research_backtest_only","can_switch_live":false,"allowed_execution_modes":["dry_run"],"blocked_live_reason":"research_backtest_only_requires_evidence_package"},{"profile":"cn_equity_combo","label":"A股进取组合","label_en":"CN Alpha Combo","label_zh":"A股进取组合","domain":"cn_equity","runtime_enabled":false,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":true,"lifecycle_stage":"research_backtest_only","can_switch_live":false,"allowed_execution_modes":["dry_run"],"blocked_live_reason":"research_backtest_only_requires_evidence_package","combo_mode":"dynamic"},{"profile":"crypto_live_pool_rotation","label":"加密实时池轮动","label_en":"Crypto Live Pool Rotation","label_zh":"加密实时池轮动","domain":"crypto","runtime_enabled":true,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"runtime_enabled","can_switch_live":true,"allowed_execution_modes":["live","paper","dry_run"],"blocked_live_reason":""},{"profile":"crypto_btc_dca","label":"BTC定投","label_en":"BTC DCA","label_zh":"BTC定投","domain":"crypto","runtime_enabled":false,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"shadow_candidate","can_switch_live":false,"allowed_execution_modes":["paper","dry_run"],"blocked_live_reason":"shadow_candidate_requires_evidence_package"},{"profile":"crypto_trend_rotation","label":"山寨趋势轮动","label_en":"Altcoin Trend","label_zh":"山寨趋势轮动","domain":"crypto","runtime_enabled":false,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":false,"lifecycle_stage":"research_backtest_only","can_switch_live":false,"allowed_execution_modes":["dry_run"],"blocked_live_reason":"research_backtest_only_requires_evidence_package"},{"profile":"crypto_equity_combo","label":"加密动量组合","label_en":"Crypto Core Combo","label_zh":"加密动量组合","domain":"crypto","runtime_enabled":false,"income_layer_enabled":false,"option_overlay_enabled":false,"combo_enabled":true,"lifecycle_stage":"research_backtest_only","can_switch_live":false,"allowed_execution_modes":["dry_run"],"blocked_live_reason":"research_backtest_only_requires_evidence_package","combo_mode":"dynamic"}] diff --git a/web/strategy-switch-console/strategy_profiles_asset.js b/web/strategy-switch-console/strategy_profiles_asset.js index d28418f..7f26d64 100644 --- a/web/strategy-switch-console/strategy_profiles_asset.js +++ b/web/strategy-switch-console/strategy_profiles_asset.js @@ -1,2 +1,2 @@ // Generated by scripts/sync_strategy_switch_page_asset.py; do not edit by hand. -export const DEFAULT_STRATEGY_PROFILES = [{"profile": "tqqq_growth_income", "label": "纳斯达克增长收益", "label_en": "NASDAQ Growth Income", "label_zh": "纳斯达克增长收益", "domain": "us_equity", "runtime_enabled": true, "income_layer_enabled": true, "option_overlay_enabled": true, "combo_enabled": false, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": "", "income_layer_start_usd": "250000", "income_layer_max_ratio": "0.55", "income_layer_allocations": {"SCHD": 0.3, "DGRO": 0.2, "SGOV": 0.4, "SPYI": 0.08, "QQQI": 0.02}, "option_overlay_live_gate": "promotion_required", "option_overlay_live_status": "research_only", "option_growth_overlay_enabled": true, "option_growth_overlay_recipe": "tqqq_leaps_growth_v1", "option_growth_overlay_start_usd": "250000", "option_growth_overlay_nav_budget_ratio": "0.03"}, {"profile": "soxl_soxx_trend_income", "label": "半导体趋势收益", "label_en": "Semiconductor Trend Income", "label_zh": "半导体趋势收益", "domain": "us_equity", "runtime_enabled": true, "income_layer_enabled": true, "option_overlay_enabled": true, "combo_enabled": false, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": "", "income_layer_start_usd": "150000", "income_layer_max_ratio": "0.95", "income_layer_allocations": {"SCHD": 0.15, "DGRO": 0.1, "SGOV": 0.7, "SPYI": 0.04, "QQQI": 0.01}, "option_overlay_live_gate": "promotion_required", "option_overlay_live_status": "research_only", "option_income_overlay_enabled": true, "option_income_overlay_recipe": "soxx_put_credit_spread_income_v1", "option_income_overlay_start_usd": "150000", "option_income_overlay_nav_risk_ratio": "0.01"}, {"profile": "nasdaq_sp500_smart_dca", "label": "纳指标普定投", "label_en": "NASDAQ/S&P 500 DCA", "label_zh": "纳指标普定投", "domain": "us_equity", "runtime_enabled": true, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": "", "dca_enabled": true, "dca_default_mode": "fixed", "dca_default_base_investment_usd": "1000"}, {"profile": "ibit_smart_dca", "label": "IBIT比特币定投", "label_en": "IBIT Bitcoin DCA", "label_zh": "IBIT比特币定投", "domain": "us_equity", "runtime_enabled": true, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": "", "dca_enabled": true, "dca_default_mode": "fixed", "dca_default_base_investment_usd": "1000"}, {"profile": "global_etf_rotation", "label": "全球ETF轮动", "label_en": "Global ETF Rotation", "label_zh": "全球ETF轮动", "domain": "us_equity", "runtime_enabled": true, "income_layer_enabled": true, "option_overlay_enabled": true, "combo_enabled": false, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": "", "income_layer_start_usd": "500000", "income_layer_max_ratio": "0.15", "income_layer_allocations": {"SCHD": 0.4, "DGRO": 0.25, "SGOV": 0.3, "SPYI": 0.05}, "option_overlay_live_gate": "promotion_required", "option_overlay_live_status": "research_only", "option_growth_overlay_enabled": true, "option_growth_overlay_recipe": "spy_leaps_growth_v1", "option_growth_overlay_start_usd": "500000", "option_growth_overlay_nav_budget_ratio": "0.015"}, {"profile": "russell_top50_leader_rotation", "label": "罗素Top50领涨", "label_en": "Russell Top50 Leaders", "label_zh": "罗素Top50领涨", "domain": "us_equity", "runtime_enabled": true, "income_layer_enabled": true, "option_overlay_enabled": true, "combo_enabled": false, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": "", "income_layer_start_usd": "300000", "income_layer_max_ratio": "0.25", "income_layer_allocations": {"SCHD": 0.45, "DGRO": 0.3, "SGOV": 0.25}, "option_overlay_live_gate": "promotion_required", "option_overlay_live_status": "research_only", "option_growth_overlay_enabled": true, "option_growth_overlay_recipe": "spy_leaps_growth_v1", "option_growth_overlay_start_usd": "300000", "option_growth_overlay_nav_budget_ratio": "0.015"}, {"profile": "tecl_xlk_trend_income", "label": "TECL/XLK趋势收益", "label_en": "TECL/XLK Trend Income", "label_zh": "TECL/XLK趋势收益", "domain": "us_equity", "runtime_enabled": false, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "failed_promotion_vs_live_profiles"}, {"profile": "us_equity_combo", "label": "美股核心组合", "label_en": "US Core Combo", "label_zh": "美股核心组合", "domain": "us_equity", "runtime_enabled": false, "income_layer_enabled": true, "option_overlay_enabled": true, "combo_enabled": true, "lifecycle_stage": "shadow_candidate", "can_switch_live": false, "allowed_execution_modes": ["paper", "dry_run"], "blocked_live_reason": "shadow_candidate_requires_evidence_package", "combo_mode": "dynamic", "income_layer_start_usd": "300000", "income_layer_max_ratio": "0.25", "income_layer_allocations": {"SCHD": 0.25, "DGRO": 0.25, "SGOV": 0.2, "SPYI": 0.15, "QQQI": 0.15}, "option_overlay_live_gate": "promotion_required", "option_overlay_live_status": "research_only", "option_growth_overlay_enabled": true, "option_growth_overlay_recipe": "spy_leaps_growth_v1", "option_growth_overlay_start_usd": "300000", "option_growth_overlay_nav_budget_ratio": "0.015"}, {"profile": "us_equity_combo_core", "label": "美股核心组合影子", "label_en": "US Core Combo Shadow", "label_zh": "美股核心组合影子", "domain": "us_equity", "runtime_enabled": false, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": true, "lifecycle_stage": "shadow_candidate", "can_switch_live": false, "allowed_execution_modes": ["paper", "dry_run"], "blocked_live_reason": "shadow_candidate_requires_evidence_package", "combo_mode": "dynamic"}, {"profile": "us_equity_combo_leveraged", "label": "美股加速组合", "label_en": "US Alpha Combo", "label_zh": "美股加速组合", "domain": "us_equity", "runtime_enabled": false, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": true, "lifecycle_stage": "shadow_candidate", "can_switch_live": false, "allowed_execution_modes": ["paper", "dry_run"], "blocked_live_reason": "shadow_candidate_requires_evidence_package", "combo_mode": "dynamic"}, {"profile": "hk_global_etf_tactical_rotation", "label": "港股ETF战术轮动", "label_en": "HK ETF Tactical Rotation", "label_zh": "港股ETF战术轮动", "domain": "hk_equity", "runtime_enabled": true, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": ""}, {"profile": "hk_low_vol_dividend_quality_snapshot", "label": "港股红利质量", "label_en": "HK Dividend Quality", "label_zh": "港股红利质量", "domain": "hk_equity", "runtime_enabled": true, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": ""}, {"profile": "hk_equity_combo", "label": "港股恒生组合", "label_en": "HK Core Combo", "label_zh": "港股恒生组合", "domain": "hk_equity", "runtime_enabled": false, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": true, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package", "combo_mode": "dynamic"}, {"profile": "cn_industry_etf_rotation", "label": "A股行业ETF轮动", "label_en": "CN Industry ETF Rotation", "label_zh": "A股行业ETF轮动", "domain": "cn_equity", "runtime_enabled": true, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": ""}, {"profile": "cn_industry_etf_rotation_aggressive", "label": "A股ETF轮动", "label_en": "CN ETF Rotation", "label_zh": "A股ETF轮动", "domain": "cn_equity", "runtime_enabled": false, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "live_candidate", "can_switch_live": false, "allowed_execution_modes": ["paper", "dry_run"], "blocked_live_reason": "live_candidate_requires_evidence_package"}, {"profile": "cn_index_etf_tactical_rotation", "label": "A股宽基ETF战术轮动", "label_en": "CN Index ETF Tactical Rotation", "label_zh": "A股宽基ETF战术轮动", "domain": "cn_equity", "runtime_enabled": false, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package"}, {"profile": "cn_chinext_tactical_rotation", "label": "创业板战术轮动", "label_en": "CN ChiNext Tactical Rotation", "label_zh": "创业板战术轮动", "domain": "cn_equity", "runtime_enabled": false, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package"}, {"profile": "cn_chinext_growth_momentum_quality", "label": "创业板成长动量质量", "label_en": "CN ChiNext Growth Momentum Quality", "label_zh": "创业板成长动量质量", "domain": "cn_equity", "runtime_enabled": false, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package"}, {"profile": "cn_dividend_quality_snapshot", "label": "A股红利质量", "label_en": "CN Dividend Quality", "label_zh": "A股红利质量", "domain": "cn_equity", "runtime_enabled": false, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package"}, {"profile": "cn_chinext_growth_momentum_quality_snapshot", "label": "创业板成长质量快照", "label_en": "CN ChiNext Growth Quality Snapshot", "label_zh": "创业板成长质量快照", "domain": "cn_equity", "runtime_enabled": false, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package"}, {"profile": "cn_star_growth_momentum_quality", "label": "科创板成长动量质量", "label_en": "CN STAR Growth Momentum Quality", "label_zh": "科创板成长动量质量", "domain": "cn_equity", "runtime_enabled": false, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package"}, {"profile": "cn_equity_combo", "label": "A股进取组合", "label_en": "CN Alpha Combo", "label_zh": "A股进取组合", "domain": "cn_equity", "runtime_enabled": false, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": true, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package", "combo_mode": "dynamic"}, {"profile": "crypto_live_pool_rotation", "label": "加密实时池轮动", "label_en": "Crypto Live Pool Rotation", "label_zh": "加密实时池轮动", "domain": "crypto", "runtime_enabled": true, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": ""}, {"profile": "crypto_btc_dca", "label": "BTC定投", "label_en": "BTC DCA", "label_zh": "BTC定投", "domain": "crypto", "runtime_enabled": false, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "shadow_candidate", "can_switch_live": false, "allowed_execution_modes": ["paper", "dry_run"], "blocked_live_reason": "shadow_candidate_requires_evidence_package"}, {"profile": "crypto_trend_rotation", "label": "山寨趋势轮动", "label_en": "Altcoin Trend", "label_zh": "山寨趋势轮动", "domain": "crypto", "runtime_enabled": false, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package"}, {"profile": "crypto_equity_combo", "label": "加密动量组合", "label_en": "Crypto Core Combo", "label_zh": "加密动量组合", "domain": "crypto", "runtime_enabled": false, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": true, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package", "combo_mode": "dynamic"}]; +export const DEFAULT_STRATEGY_PROFILES = [{"profile": "tqqq_growth_income", "label": "纳斯达克增长收益", "label_en": "NASDAQ Growth Income", "label_zh": "纳斯达克增长收益", "domain": "us_equity", "runtime_enabled": true, "income_layer_enabled": true, "option_overlay_enabled": true, "combo_enabled": false, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": "", "income_layer_start_usd": "250000", "income_layer_max_ratio": "0.55", "income_layer_allocations": {"SCHD": 0.3, "DGRO": 0.2, "SGOV": 0.4, "SPYI": 0.08, "QQQI": 0.02}, "option_overlay_live_gate": "promotion_required", "option_overlay_live_status": "research_only", "option_growth_overlay_enabled": true, "option_growth_overlay_recipe": "tqqq_leaps_growth_v1", "option_growth_overlay_start_usd": "250000", "option_growth_overlay_nav_budget_ratio": "0.03"}, {"profile": "soxl_soxx_trend_income", "label": "半导体趋势收益", "label_en": "Semiconductor Trend Income", "label_zh": "半导体趋势收益", "domain": "us_equity", "runtime_enabled": true, "income_layer_enabled": true, "option_overlay_enabled": true, "combo_enabled": false, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": "", "income_layer_start_usd": "150000", "income_layer_max_ratio": "0.95", "income_layer_allocations": {"SCHD": 0.15, "DGRO": 0.1, "SGOV": 0.7, "SPYI": 0.04, "QQQI": 0.01}, "option_overlay_live_gate": "promotion_required", "option_overlay_live_status": "research_only", "option_income_overlay_enabled": true, "option_income_overlay_recipe": "soxx_put_credit_spread_income_v1", "option_income_overlay_start_usd": "150000", "option_income_overlay_nav_risk_ratio": "0.01"}, {"profile": "nasdaq_sp500_smart_dca", "label": "纳指标普定投", "label_en": "NASDAQ/S&P 500 DCA", "label_zh": "纳指标普定投", "domain": "us_equity", "runtime_enabled": true, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": "", "dca_enabled": true, "dca_default_mode": "fixed", "dca_default_base_investment_usd": "1000"}, {"profile": "ibit_smart_dca", "label": "IBIT比特币定投", "label_en": "IBIT Bitcoin DCA", "label_zh": "IBIT比特币定投", "domain": "us_equity", "runtime_enabled": true, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": "", "dca_enabled": true, "dca_default_mode": "fixed", "dca_default_base_investment_usd": "1000"}, {"profile": "global_etf_rotation", "label": "全球ETF轮动", "label_en": "Global ETF Rotation", "label_zh": "全球ETF轮动", "domain": "us_equity", "runtime_enabled": true, "income_layer_enabled": true, "option_overlay_enabled": true, "combo_enabled": false, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": "", "income_layer_start_usd": "500000", "income_layer_max_ratio": "0.15", "income_layer_allocations": {"SCHD": 0.4, "DGRO": 0.25, "SGOV": 0.3, "SPYI": 0.05}, "option_overlay_live_gate": "promotion_required", "option_overlay_live_status": "research_only", "option_growth_overlay_enabled": true, "option_growth_overlay_recipe": "spy_leaps_growth_v1", "option_growth_overlay_start_usd": "500000", "option_growth_overlay_nav_budget_ratio": "0.015"}, {"profile": "russell_top50_leader_rotation", "label": "罗素Top50领涨", "label_en": "Russell Top50 Leaders", "label_zh": "罗素Top50领涨", "domain": "us_equity", "runtime_enabled": true, "income_layer_enabled": true, "option_overlay_enabled": true, "combo_enabled": false, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": "", "income_layer_start_usd": "300000", "income_layer_max_ratio": "0.25", "income_layer_allocations": {"SCHD": 0.45, "DGRO": 0.3, "SGOV": 0.25}, "option_overlay_live_gate": "promotion_required", "option_overlay_live_status": "research_only", "option_growth_overlay_enabled": true, "option_growth_overlay_recipe": "spy_leaps_growth_v1", "option_growth_overlay_start_usd": "300000", "option_growth_overlay_nav_budget_ratio": "0.015"}, {"profile": "tecl_xlk_trend_income", "label": "TECL/XLK趋势收益", "label_en": "TECL/XLK Trend Income", "label_zh": "TECL/XLK趋势收益", "domain": "us_equity", "runtime_enabled": false, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "failed_promotion_vs_live_profiles"}, {"profile": "us_equity_combo", "label": "美股核心组合", "label_en": "US Core Combo", "label_zh": "美股核心组合", "domain": "us_equity", "runtime_enabled": false, "income_layer_enabled": true, "option_overlay_enabled": true, "combo_enabled": true, "lifecycle_stage": "shadow_candidate", "can_switch_live": false, "allowed_execution_modes": ["paper", "dry_run"], "blocked_live_reason": "shadow_candidate_requires_evidence_package", "combo_mode": "dynamic", "income_layer_start_usd": "300000", "income_layer_max_ratio": "0.25", "income_layer_allocations": {"SCHD": 0.25, "DGRO": 0.25, "SGOV": 0.2, "SPYI": 0.15, "QQQI": 0.15}, "option_overlay_live_gate": "promotion_required", "option_overlay_live_status": "research_only", "option_growth_overlay_enabled": true, "option_growth_overlay_recipe": "spy_leaps_growth_v1", "option_growth_overlay_start_usd": "300000", "option_growth_overlay_nav_budget_ratio": "0.015"}, {"profile": "us_equity_combo_core", "label": "美股核心组合影子", "label_en": "US Core Combo Shadow", "label_zh": "美股核心组合影子", "domain": "us_equity", "runtime_enabled": false, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": true, "lifecycle_stage": "shadow_candidate", "can_switch_live": false, "allowed_execution_modes": ["paper", "dry_run"], "blocked_live_reason": "shadow_candidate_requires_evidence_package", "combo_mode": "dynamic"}, {"profile": "us_equity_combo_leveraged", "label": "美股加速组合", "label_en": "US Alpha Combo", "label_zh": "美股加速组合", "domain": "us_equity", "runtime_enabled": false, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": true, "lifecycle_stage": "shadow_candidate", "can_switch_live": false, "allowed_execution_modes": ["paper", "dry_run"], "blocked_live_reason": "shadow_candidate_requires_evidence_package", "combo_mode": "dynamic"}, {"profile": "hk_global_etf_tactical_rotation", "label": "港股ETF战术轮动", "label_en": "HK ETF Tactical Rotation", "label_zh": "港股ETF战术轮动", "domain": "hk_equity", "runtime_enabled": true, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": ""}, {"profile": "hk_low_vol_dividend_quality_snapshot", "label": "港股红利质量", "label_en": "HK Dividend Quality", "label_zh": "港股红利质量", "domain": "hk_equity", "runtime_enabled": true, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "runtime_enabled", "can_switch_live": false, "allowed_execution_modes": ["paper", "dry_run"], "blocked_live_reason": "production_snapshot_artifact_route_not_configured"}, {"profile": "hk_equity_combo", "label": "港股恒生组合", "label_en": "HK Core Combo", "label_zh": "港股恒生组合", "domain": "hk_equity", "runtime_enabled": false, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": true, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package", "combo_mode": "dynamic"}, {"profile": "cn_industry_etf_rotation", "label": "A股行业ETF轮动", "label_en": "CN Industry ETF Rotation", "label_zh": "A股行业ETF轮动", "domain": "cn_equity", "runtime_enabled": true, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": ""}, {"profile": "cn_industry_etf_rotation_aggressive", "label": "A股ETF轮动", "label_en": "CN ETF Rotation", "label_zh": "A股ETF轮动", "domain": "cn_equity", "runtime_enabled": false, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "live_candidate", "can_switch_live": false, "allowed_execution_modes": ["paper", "dry_run"], "blocked_live_reason": "live_candidate_requires_evidence_package"}, {"profile": "cn_index_etf_tactical_rotation", "label": "A股宽基ETF战术轮动", "label_en": "CN Index ETF Tactical Rotation", "label_zh": "A股宽基ETF战术轮动", "domain": "cn_equity", "runtime_enabled": false, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package"}, {"profile": "cn_chinext_tactical_rotation", "label": "创业板战术轮动", "label_en": "CN ChiNext Tactical Rotation", "label_zh": "创业板战术轮动", "domain": "cn_equity", "runtime_enabled": false, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package"}, {"profile": "cn_chinext_growth_momentum_quality", "label": "创业板成长动量质量", "label_en": "CN ChiNext Growth Momentum Quality", "label_zh": "创业板成长动量质量", "domain": "cn_equity", "runtime_enabled": false, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package"}, {"profile": "cn_dividend_quality_snapshot", "label": "A股红利质量", "label_en": "CN Dividend Quality", "label_zh": "A股红利质量", "domain": "cn_equity", "runtime_enabled": false, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package"}, {"profile": "cn_chinext_growth_momentum_quality_snapshot", "label": "创业板成长质量快照", "label_en": "CN ChiNext Growth Quality Snapshot", "label_zh": "创业板成长质量快照", "domain": "cn_equity", "runtime_enabled": false, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package"}, {"profile": "cn_star_growth_momentum_quality", "label": "科创板成长动量质量", "label_en": "CN STAR Growth Momentum Quality", "label_zh": "科创板成长动量质量", "domain": "cn_equity", "runtime_enabled": false, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package"}, {"profile": "cn_equity_combo", "label": "A股进取组合", "label_en": "CN Alpha Combo", "label_zh": "A股进取组合", "domain": "cn_equity", "runtime_enabled": false, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": true, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package", "combo_mode": "dynamic"}, {"profile": "crypto_live_pool_rotation", "label": "加密实时池轮动", "label_en": "Crypto Live Pool Rotation", "label_zh": "加密实时池轮动", "domain": "crypto", "runtime_enabled": true, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "runtime_enabled", "can_switch_live": true, "allowed_execution_modes": ["live", "paper", "dry_run"], "blocked_live_reason": ""}, {"profile": "crypto_btc_dca", "label": "BTC定投", "label_en": "BTC DCA", "label_zh": "BTC定投", "domain": "crypto", "runtime_enabled": false, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "shadow_candidate", "can_switch_live": false, "allowed_execution_modes": ["paper", "dry_run"], "blocked_live_reason": "shadow_candidate_requires_evidence_package"}, {"profile": "crypto_trend_rotation", "label": "山寨趋势轮动", "label_en": "Altcoin Trend", "label_zh": "山寨趋势轮动", "domain": "crypto", "runtime_enabled": false, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": false, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package"}, {"profile": "crypto_equity_combo", "label": "加密动量组合", "label_en": "Crypto Core Combo", "label_zh": "加密动量组合", "domain": "crypto", "runtime_enabled": false, "income_layer_enabled": false, "option_overlay_enabled": false, "combo_enabled": true, "lifecycle_stage": "research_backtest_only", "can_switch_live": false, "allowed_execution_modes": ["dry_run"], "blocked_live_reason": "research_backtest_only_requires_evidence_package", "combo_mode": "dynamic"}];