11from __future__ import annotations
22
3- import os
4-
53from quant_platform_kit .common .strategies import (
4+ PlatformCapabilityMatrix ,
65 PlatformStrategyPolicy ,
76 StrategyDefinition ,
87 StrategyMetadata ,
98 US_EQUITY_DOMAIN ,
109 build_platform_profile_matrix ,
1110 build_platform_profile_status_matrix ,
11+ derive_enabled_profiles_for_platform ,
12+ derive_eligible_profiles_for_platform ,
1213 get_catalog_strategy_metadata ,
14+ get_enabled_profiles_for_platform ,
1315 resolve_platform_strategy_definition ,
1416)
1517from us_equity_strategies import (
18+ get_platform_runtime_adapter ,
1619 get_runtime_enabled_profiles ,
1720 get_strategy_catalog ,
1821)
1922
2023FIRSTRADE_PLATFORM = "firstrade"
2124
22- # Firstrade is not first-class in UsEquityStrategies yet. Until that repo adds
23- # a native adapter key, this platform uses the same value-native strategy input
24- # shape as LongBridge/Schwab while reporting runtime identity as Firstrade.
25- DEFAULT_STRATEGY_ADAPTER_SOURCE_PLATFORM = "longbridge"
26- SUPPORTED_STRATEGY_ADAPTER_SOURCE_PLATFORMS = frozenset ({"longbridge" , "schwab" })
27-
2825PLATFORM_SUPPORTED_DOMAINS : dict [str , frozenset [str ]] = {
2926 FIRSTRADE_PLATFORM : frozenset ({US_EQUITY_DOMAIN }),
3027}
3128
3229STRATEGY_CATALOG = get_strategy_catalog ()
3330FIRSTRADE_ROLLOUT_ALLOWLIST = get_runtime_enabled_profiles ()
34- FIRSTRADE_ENABLED_PROFILES = frozenset (sorted (FIRSTRADE_ROLLOUT_ALLOWLIST ))
31+ PLATFORM_CAPABILITY_MATRIX = PlatformCapabilityMatrix (
32+ platform_id = FIRSTRADE_PLATFORM ,
33+ supported_domains = PLATFORM_SUPPORTED_DOMAINS [FIRSTRADE_PLATFORM ],
34+ supported_target_modes = frozenset ({"weight" , "value" }),
35+ supported_inputs = frozenset (
36+ {
37+ "benchmark_history" ,
38+ "market_history" ,
39+ "portfolio_snapshot" ,
40+ "derived_indicators" ,
41+ "feature_snapshot" ,
42+ "indicators" ,
43+ "account_state" ,
44+ "snapshot" ,
45+ }
46+ ),
47+ supported_capabilities = frozenset (),
48+ )
49+ ELIGIBLE_STRATEGY_PROFILES = derive_eligible_profiles_for_platform (
50+ STRATEGY_CATALOG ,
51+ capability_matrix = PLATFORM_CAPABILITY_MATRIX ,
52+ runtime_adapter_loader = lambda profile : get_platform_runtime_adapter (
53+ profile ,
54+ platform_id = FIRSTRADE_PLATFORM ,
55+ ),
56+ )
57+ FIRSTRADE_ENABLED_PROFILES = derive_enabled_profiles_for_platform (
58+ STRATEGY_CATALOG ,
59+ capability_matrix = PLATFORM_CAPABILITY_MATRIX ,
60+ runtime_adapter_loader = lambda profile : get_platform_runtime_adapter (
61+ profile ,
62+ platform_id = FIRSTRADE_PLATFORM ,
63+ ),
64+ rollout_allowlist = FIRSTRADE_ROLLOUT_ALLOWLIST ,
65+ )
3566PLATFORM_POLICY = PlatformStrategyPolicy (
3667 platform_id = FIRSTRADE_PLATFORM ,
3768 supported_domains = PLATFORM_SUPPORTED_DOMAINS [FIRSTRADE_PLATFORM ],
@@ -49,31 +80,14 @@ def _without_selection_role_fields(row: dict[str, object]) -> dict[str, object]:
4980 return {key : value for key , value in row .items () if key not in _SELECTION_ROLE_FIELDS }
5081
5182
52- def get_strategy_adapter_source_platform () -> str :
53- value = os .getenv (
54- "FIRSTRADE_STRATEGY_ADAPTER_SOURCE_PLATFORM" ,
55- DEFAULT_STRATEGY_ADAPTER_SOURCE_PLATFORM ,
56- )
57- normalized = str (value or "" ).strip ().lower ()
58- if normalized not in SUPPORTED_STRATEGY_ADAPTER_SOURCE_PLATFORMS :
59- supported = ", " .join (sorted (SUPPORTED_STRATEGY_ADAPTER_SOURCE_PLATFORMS ))
60- raise ValueError (
61- "FIRSTRADE_STRATEGY_ADAPTER_SOURCE_PLATFORM must be one of: "
62- f"{ supported } "
63- )
64- return normalized
65-
66-
6783def get_eligible_profiles_for_platform (platform_id : str ) -> frozenset [str ]:
6884 if platform_id != FIRSTRADE_PLATFORM :
6985 return frozenset ()
70- return FIRSTRADE_ENABLED_PROFILES
86+ return ELIGIBLE_STRATEGY_PROFILES
7187
7288
7389def get_supported_profiles_for_platform (platform_id : str ) -> frozenset [str ]:
74- if platform_id != FIRSTRADE_PLATFORM :
75- return frozenset ()
76- return FIRSTRADE_ENABLED_PROFILES
90+ return get_enabled_profiles_for_platform (platform_id , policy = PLATFORM_POLICY )
7791
7892
7993def get_platform_profile_matrix () -> list [dict [str , object ]]:
@@ -84,22 +98,14 @@ def get_platform_profile_matrix() -> list[dict[str, object]]:
8498
8599
86100def get_platform_profile_status_matrix () -> list [dict [str , object ]]:
87- rows = [
101+ return [
88102 _without_selection_role_fields (row )
89103 for row in build_platform_profile_status_matrix (
90104 STRATEGY_CATALOG ,
91105 policy = PLATFORM_POLICY ,
92- eligible_profiles = FIRSTRADE_ENABLED_PROFILES ,
106+ eligible_profiles = ELIGIBLE_STRATEGY_PROFILES ,
93107 )
94108 ]
95- source_platform = get_strategy_adapter_source_platform ()
96- for row in rows :
97- row ["strategy_adapter_source_platform" ] = source_platform
98- row ["runtime_note" ] = (
99- "enabled through value-native adapter shape pending first-class "
100- "firstrade support in UsEquityStrategies"
101- )
102- return rows
103109
104110
105111def resolve_strategy_definition (
@@ -122,4 +128,3 @@ def resolve_strategy_metadata(
122128) -> StrategyMetadata :
123129 definition = resolve_strategy_definition (raw_value , platform_id = platform_id )
124130 return get_catalog_strategy_metadata (STRATEGY_CATALOG , definition .profile )
125-
0 commit comments