refactor(portfolio): TET副本类名对齐策略库扫描约定—*StrategyEx→*ExStrategy(AllWeatherExStrategy等8类):strategy_registry._extract_class_names只认endswith('Strategy')的类名,Ex结尾类被判'无策略类'整文件跳过→策略库/代码编辑器看不到副本;改名后_scan_self_owned自动识别4文件(type=portfolio);CLI/API/前端选项值(all_weather_ex等)不变;328绿 [vps]
This commit is contained in:
@@ -185,28 +185,28 @@ def _build_strategy(args: argparse.Namespace, provider: Any) -> Any:
|
||||
return ChannelTestStrategy(provider=provider, config=ChannelTestConfig())
|
||||
# TET Phase 2 验证副本(issue #19):取数走 _ex strict 接口,逻辑与原策略同源 copy
|
||||
if name == "all_weather_ex":
|
||||
from .strategies import AllWeatherConfigEx, AllWeatherStrategyEx
|
||||
return AllWeatherStrategyEx(
|
||||
from .strategies import AllWeatherExConfig, AllWeatherExStrategy
|
||||
return AllWeatherExStrategy(
|
||||
provider=provider,
|
||||
config=AllWeatherConfigEx(max_pool=args.max_pool),
|
||||
config=AllWeatherExConfig(max_pool=args.max_pool),
|
||||
)
|
||||
if name == "momentum_timing_ex":
|
||||
from .strategies import MomentumTimingConfigEx, MomentumTimingStrategyEx
|
||||
return MomentumTimingStrategyEx(
|
||||
from .strategies import MomentumTimingExConfig, MomentumTimingExStrategy
|
||||
return MomentumTimingExStrategy(
|
||||
provider=provider,
|
||||
config=MomentumTimingConfigEx(max_pool=args.max_pool),
|
||||
config=MomentumTimingExConfig(max_pool=args.max_pool),
|
||||
)
|
||||
if name == "value_selection_ex":
|
||||
from .strategies import ValueSelectionConfigEx, ValueSelectionStrategyEx
|
||||
return ValueSelectionStrategyEx(
|
||||
from .strategies import ValueSelectionExConfig, ValueSelectionExStrategy
|
||||
return ValueSelectionExStrategy(
|
||||
provider=provider,
|
||||
config=ValueSelectionConfigEx(max_pool=args.max_pool),
|
||||
config=ValueSelectionExConfig(max_pool=args.max_pool),
|
||||
)
|
||||
if name == "small_cap_ex":
|
||||
from .strategies import SmallCapConfigEx, SmallCapStrategyEx
|
||||
return SmallCapStrategyEx(
|
||||
from .strategies import SmallCapExConfig, SmallCapExStrategy
|
||||
return SmallCapExStrategy(
|
||||
provider=provider,
|
||||
config=SmallCapConfigEx(max_pool=args.max_pool),
|
||||
config=SmallCapExConfig(max_pool=args.max_pool),
|
||||
)
|
||||
raise ValueError(
|
||||
f"未知 strategy: {name}(支持: all_weather / momentum_timing / value_selection / small_cap"
|
||||
@@ -225,28 +225,28 @@ def _register_schedule(strategy: Any) -> None:
|
||||
try:
|
||||
from .strategies import (
|
||||
AllWeatherStrategy,
|
||||
AllWeatherStrategyEx,
|
||||
AllWeatherExStrategy,
|
||||
MomentumTimingStrategy,
|
||||
MomentumTimingStrategyEx,
|
||||
MomentumTimingExStrategy,
|
||||
SmallCapStrategy,
|
||||
SmallCapStrategyEx,
|
||||
SmallCapExStrategy,
|
||||
ValueSelectionStrategy,
|
||||
ValueSelectionStrategyEx,
|
||||
ValueSelectionExStrategy,
|
||||
)
|
||||
if isinstance(strategy, (AllWeatherStrategy, AllWeatherStrategyEx)):
|
||||
if isinstance(strategy, (AllWeatherStrategy, AllWeatherExStrategy)):
|
||||
run_daily(strategy.prepare_stock_list, "9:05")
|
||||
run_monthly(strategy.monthly_adjustment, 1, "9:30")
|
||||
run_daily(strategy.stop_loss, "14:00")
|
||||
return
|
||||
if isinstance(strategy, (MomentumTimingStrategy, MomentumTimingStrategyEx)):
|
||||
if isinstance(strategy, (MomentumTimingStrategy, MomentumTimingExStrategy)):
|
||||
# 原策略 handle_data 单位时间触发 → 每日 9:30
|
||||
run_daily(strategy.handle_data, "9:30")
|
||||
return
|
||||
if isinstance(strategy, (ValueSelectionStrategy, ValueSelectionStrategyEx)):
|
||||
if isinstance(strategy, (ValueSelectionStrategy, ValueSelectionExStrategy)):
|
||||
# 原策略 run_monthly 第 5 个交易日(月度调仓)
|
||||
run_monthly(strategy.monthly_adjustment, 5, "9:30")
|
||||
return
|
||||
if isinstance(strategy, (SmallCapStrategy, SmallCapStrategyEx)):
|
||||
if isinstance(strategy, (SmallCapStrategy, SmallCapExStrategy)):
|
||||
# 原策略 handle_data 单位时间触发 → 每日 9:30
|
||||
# 5 日调仓周期由 handle_data 内部 day_count % tc == 0 控制(对齐 g.t % g.tc)
|
||||
run_daily(strategy.handle_data, "9:30")
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
"""sanguo_portfolio 策略层。"""
|
||||
from .all_weather import AllWeatherConfig, AllWeatherStrategy, BrokerFacade
|
||||
from .all_weather_ex import AllWeatherConfigEx, AllWeatherStrategyEx
|
||||
from .all_weather_ex import AllWeatherExConfig, AllWeatherExStrategy
|
||||
from .channel_test import ChannelTestConfig, ChannelTestStrategy
|
||||
from .momentum_timing import MomentumTimingConfig, MomentumTimingStrategy
|
||||
from .momentum_timing_ex import MomentumTimingConfigEx, MomentumTimingStrategyEx
|
||||
from .momentum_timing_ex import MomentumTimingExConfig, MomentumTimingExStrategy
|
||||
from .small_cap import SmallCapConfig, SmallCapStrategy
|
||||
from .small_cap_ex import SmallCapConfigEx, SmallCapStrategyEx
|
||||
from .small_cap_ex import SmallCapExConfig, SmallCapExStrategy
|
||||
from .value_selection import ValueSelectionConfig, ValueSelectionStrategy
|
||||
from .value_selection_ex import ValueSelectionConfigEx, ValueSelectionStrategyEx
|
||||
from .value_selection_ex import ValueSelectionExConfig, ValueSelectionExStrategy
|
||||
|
||||
__all__ = [
|
||||
"AllWeatherStrategy",
|
||||
@@ -22,12 +22,12 @@ __all__ = [
|
||||
"ValueSelectionStrategy",
|
||||
"ValueSelectionConfig",
|
||||
# TET Phase 2 验证副本(issue #19,验证后 Phase 3 删)
|
||||
"AllWeatherStrategyEx",
|
||||
"AllWeatherConfigEx",
|
||||
"MomentumTimingStrategyEx",
|
||||
"MomentumTimingConfigEx",
|
||||
"SmallCapStrategyEx",
|
||||
"SmallCapConfigEx",
|
||||
"ValueSelectionStrategyEx",
|
||||
"ValueSelectionConfigEx",
|
||||
"AllWeatherExStrategy",
|
||||
"AllWeatherExConfig",
|
||||
"MomentumTimingExStrategy",
|
||||
"MomentumTimingExConfig",
|
||||
"SmallCapExStrategy",
|
||||
"SmallCapExConfig",
|
||||
"ValueSelectionExStrategy",
|
||||
"ValueSelectionExConfig",
|
||||
]
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
"""聚宽"全天候轮动"策略(post48819)翻译到 BulletTrade 框架。
|
||||
|
||||
聚宽源码完整保留在原仓库 transcript,这里做**结构等价**翻译:
|
||||
- ``initialize`` → ``AllWeatherStrategyEx.initialize``
|
||||
- ``prepare_stock_list`` → ``AllWeatherStrategyEx.prepare_stock_list``
|
||||
- ``stop_loss`` → ``AllWeatherStrategyEx.stop_loss``
|
||||
- ``monthly_adjustment`` → ``AllWeatherStrategyEx.monthly_adjustment``
|
||||
- ``SMALL/BIG/ROIC_BIG/BM`` → ``AllWeatherStrategyEx.small/big/roic_big/bm``
|
||||
- ``initialize`` → ``AllWeatherExStrategy.initialize``
|
||||
- ``prepare_stock_list`` → ``AllWeatherExStrategy.prepare_stock_list``
|
||||
- ``stop_loss`` → ``AllWeatherExStrategy.stop_loss``
|
||||
- ``monthly_adjustment`` → ``AllWeatherExStrategy.monthly_adjustment``
|
||||
- ``SMALL/BIG/ROIC_BIG/BM`` → ``AllWeatherExStrategy.small/big/roic_big/bm``
|
||||
- ``filter_*`` → ``sanguo_portfolio.filters``
|
||||
|
||||
策略层不直接 import bullet-trade 顶层 API(避免 Mac dev 环境装不全崩),通过两个注入点接入:
|
||||
@@ -57,7 +57,7 @@ class BrokerFacade:
|
||||
|
||||
# ------------------------ 策略 ------------------------
|
||||
@dataclass
|
||||
class AllWeatherConfigEx:
|
||||
class AllWeatherExConfig:
|
||||
"""全天候策略参数(聚宽 initialize 的硬编码抽出来便于调参)。"""
|
||||
|
||||
stock_num: int = 3 # g.stock_num
|
||||
@@ -79,7 +79,7 @@ class AllWeatherConfigEx:
|
||||
max_pool: int = 0 # 0=不限;MVP/验证用,限制 _stock_pool 返回前 N 只(避免全成分基本面下载过慢)
|
||||
|
||||
|
||||
class AllWeatherStrategyEx:
|
||||
class AllWeatherExStrategy:
|
||||
"""聚宽"全天候轮动"策略(动态选股 + 大小盘轮动 + 海外 ETF 兜底 + 涨停盯盘)。
|
||||
|
||||
实例化时不连数据/不下单,所有 IO 走注入的 ``provider`` 和 ``broker``。
|
||||
@@ -90,11 +90,11 @@ class AllWeatherStrategyEx:
|
||||
self,
|
||||
provider: Any,
|
||||
broker: Optional[BrokerFacade] = None,
|
||||
config: Optional[AllWeatherConfigEx] = None,
|
||||
config: Optional[AllWeatherExConfig] = None,
|
||||
) -> None:
|
||||
self.provider = provider
|
||||
self.broker = broker or BrokerFacade()
|
||||
self.config = config or AllWeatherConfigEx()
|
||||
self.config = config or AllWeatherExConfig()
|
||||
|
||||
# 聚宽 g.* 全局变量映射到实例属性
|
||||
self.hold_list: List[str] = []
|
||||
@@ -603,4 +603,4 @@ def _shift_date(date_str: str, days: int) -> str:
|
||||
return (dt + datetime.timedelta(days=days)).strftime("%Y-%m-%d")
|
||||
|
||||
|
||||
__all__ = ["AllWeatherStrategyEx", "AllWeatherConfigEx", "BrokerFacade"]
|
||||
__all__ = ["AllWeatherExStrategy", "AllWeatherExConfig", "BrokerFacade"]
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
聚宽源码完整保留在 ``docs/research/joinquant_strategies/03_momentum_timing/source.py``,
|
||||
这里做**结构等价 + bug 修复**翻译:
|
||||
- ``initialize`` → ``MomentumTimingStrategyEx.initialize``
|
||||
- ``calRPS`` → ``MomentumTimingStrategyEx._cal_rps`` (**修复取数区间**)
|
||||
- ``findStockPool`` → ``MomentumTimingStrategyEx._find_stock_pool``
|
||||
- ``selectStocks`` → ``MomentumTimingStrategyEx._select_stocks``
|
||||
- ``calBuySign`` → ``MomentumTimingStrategyEx._cal_buy_sign``
|
||||
- ``handle_data`` → ``MomentumTimingStrategyEx.handle_data`` (**修复 date.today()**)
|
||||
- ``initialize`` → ``MomentumTimingExStrategy.initialize``
|
||||
- ``calRPS`` → ``MomentumTimingExStrategy._cal_rps`` (**修复取数区间**)
|
||||
- ``findStockPool`` → ``MomentumTimingExStrategy._find_stock_pool``
|
||||
- ``selectStocks`` → ``MomentumTimingExStrategy._select_stocks``
|
||||
- ``calBuySign`` → ``MomentumTimingExStrategy._cal_buy_sign``
|
||||
- ``handle_data`` → ``MomentumTimingExStrategy.handle_data`` (**修复 date.today()**)
|
||||
|
||||
策略层不直接 import bullet-trade 顶层 API(避免 Mac dev 环境装不全崩),
|
||||
通过两个注入点接入(照 all_weather 模式):
|
||||
@@ -66,7 +66,7 @@ _DEFAULT_INDEX_LIST: List[str] = [
|
||||
|
||||
|
||||
@dataclass
|
||||
class MomentumTimingConfigEx:
|
||||
class MomentumTimingExConfig:
|
||||
"""牛熊分界+取强舍弱+均线动量 策略参数(聚宽 g.* 全局变量抽出便于调参)。"""
|
||||
|
||||
# 板块列表(默认 10 个中证行业指数 000928-000937,G1 补全后切回原版,见模块顶部说明)
|
||||
@@ -82,7 +82,7 @@ class MomentumTimingConfigEx:
|
||||
|
||||
|
||||
# ------------------------ 策略 ------------------------
|
||||
class MomentumTimingStrategyEx:
|
||||
class MomentumTimingExStrategy:
|
||||
"""牛熊分界+取强舍弱+均线动量策略(纯量价,无基本面)。
|
||||
|
||||
实例化时不连数据/不下单,所有 IO 走注入的 ``provider`` 和 ``broker``。
|
||||
@@ -93,11 +93,11 @@ class MomentumTimingStrategyEx:
|
||||
self,
|
||||
provider: Any,
|
||||
broker: Optional[BrokerFacade] = None,
|
||||
config: Optional[MomentumTimingConfigEx] = None,
|
||||
config: Optional[MomentumTimingExConfig] = None,
|
||||
) -> None:
|
||||
self.provider = provider
|
||||
self.broker = broker or BrokerFacade()
|
||||
self.config = config or MomentumTimingConfigEx()
|
||||
self.config = config or MomentumTimingExConfig()
|
||||
|
||||
# =================== initialize ===================
|
||||
def initialize(self, context: Any) -> None:
|
||||
@@ -440,4 +440,4 @@ def _shift_date(date_str: str, days: int) -> str:
|
||||
return (dt + datetime.timedelta(days=days)).strftime("%Y-%m-%d")
|
||||
|
||||
|
||||
__all__ = ["MomentumTimingStrategyEx", "MomentumTimingConfigEx"]
|
||||
__all__ = ["MomentumTimingExStrategy", "MomentumTimingExConfig"]
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
- statsmodels 回归 import(原代码 import 但未实际用)
|
||||
|
||||
翻译对照:
|
||||
- ``initialize`` → ``SmallCapStrategyEx.initialize``
|
||||
- ``pick_stocks`` → ``SmallCapStrategyEx._pick_stocks`` (**py2→py3**: df.sort→sort_values)
|
||||
- ``compute_signals``→ ``SmallCapStrategyEx.handle_data`` (**5 日计数器**替代 g.t)
|
||||
- ``rebalance`` → ``SmallCapStrategyEx._rebalance`` (**仅保留股票部分**,
|
||||
- ``initialize`` → ``SmallCapExStrategy.initialize``
|
||||
- ``pick_stocks`` → ``SmallCapExStrategy._pick_stocks`` (**py2→py3**: df.sort→sort_values)
|
||||
- ``compute_signals``→ ``SmallCapExStrategy.handle_data`` (**5 日计数器**替代 g.t)
|
||||
- ``rebalance`` → ``SmallCapExStrategy._rebalance`` (**仅保留股票部分**,
|
||||
去掉期货/账户调配/保证金,等权调仓)
|
||||
- ``compute_hedge_ratio`` / ``get_next_month_future`` / SubPortfolio → **删除**
|
||||
|
||||
@@ -54,7 +54,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
# ------------------------ Config ------------------------
|
||||
@dataclass
|
||||
class SmallCapConfigEx:
|
||||
class SmallCapExConfig:
|
||||
"""小市值 20 只轮动策略参数(聚宽 g.* 全局变量抽出便于调参)。
|
||||
|
||||
默认值严格对齐原策略 ``set_params`` (source.py 第 38-48 行):
|
||||
@@ -87,7 +87,7 @@ class SmallCapConfigEx:
|
||||
|
||||
|
||||
# ------------------------ 策略 ------------------------
|
||||
class SmallCapStrategyEx:
|
||||
class SmallCapExStrategy:
|
||||
"""小市值 20 只轮动策略(纯选股,无对冲)。
|
||||
|
||||
实例化时不连数据/不下单,所有 IO 走注入的 ``provider`` 和 ``broker``。
|
||||
@@ -103,11 +103,11 @@ class SmallCapStrategyEx:
|
||||
self,
|
||||
provider: Any,
|
||||
broker: Optional[BrokerFacade] = None,
|
||||
config: Optional[SmallCapConfigEx] = None,
|
||||
config: Optional[SmallCapExConfig] = None,
|
||||
) -> None:
|
||||
self.provider = provider
|
||||
self.broker = broker or BrokerFacade()
|
||||
self.config = config or SmallCapConfigEx()
|
||||
self.config = config or SmallCapExConfig()
|
||||
|
||||
# 聚宽 g.* 全局变量映射到实例属性
|
||||
self.day_count: int = 0 # g.t:运行天数
|
||||
@@ -446,4 +446,4 @@ def _shift_date(date_str: str, days: int) -> str:
|
||||
return (dt + datetime.timedelta(days=days)).strftime("%Y-%m-%d")
|
||||
|
||||
|
||||
__all__ = ["SmallCapStrategyEx", "SmallCapConfigEx"]
|
||||
__all__ = ["SmallCapExStrategy", "SmallCapExConfig"]
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
聚宽源码完整保留在 ``docs/research/joinquant_strategies/01_value_selection/source.py``,
|
||||
这里做**结构等价 + bug 修复 + py2→py3** 翻译:
|
||||
- ``initialize`` → ``ValueSelectionStrategyEx.initialize``
|
||||
- ``get_stock_list`` → ``ValueSelectionStrategyEx._get_stock_list``
|
||||
- ``initialize`` → ``ValueSelectionExStrategy.initialize``
|
||||
- ``get_stock_list`` → ``ValueSelectionExStrategy._get_stock_list``
|
||||
- ``get_check_stocks_sort`` → **删除**(排序后不截断+全买的死代码,KISS)
|
||||
- ``buy`` / ``sell`` → 调仓逻辑合入 ``monthly_adjustment``
|
||||
- ``get_data`` (pd.Panel) → ``provider.get_value_metrics`` 接口替代
|
||||
@@ -56,7 +56,7 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
# ------------------------ Config ------------------------
|
||||
@dataclass
|
||||
class ValueSelectionConfigEx:
|
||||
class ValueSelectionExConfig:
|
||||
"""价值精选 6 条策略参数(聚宽 g.* 全局变量抽出便于调参)。
|
||||
|
||||
6 条过滤阈值严格对齐原策略 source.py 第 91-97 行注释 + 第 105-171 行代码。
|
||||
@@ -97,7 +97,7 @@ class ValueSelectionConfigEx:
|
||||
|
||||
|
||||
# ------------------------ 策略 ------------------------
|
||||
class ValueSelectionStrategyEx:
|
||||
class ValueSelectionExStrategy:
|
||||
"""价值精选 6 条策略(全市场横向比较 + 月度调仓)。
|
||||
|
||||
实例化时不连数据/不下单,所有 IO 走注入的 ``provider`` 和 ``broker``。
|
||||
@@ -115,11 +115,11 @@ class ValueSelectionStrategyEx:
|
||||
self,
|
||||
provider: Any,
|
||||
broker: Optional[BrokerFacade] = None,
|
||||
config: Optional[ValueSelectionConfigEx] = None,
|
||||
config: Optional[ValueSelectionExConfig] = None,
|
||||
) -> None:
|
||||
self.provider = provider
|
||||
self.broker = broker or BrokerFacade()
|
||||
self.config = config or ValueSelectionConfigEx()
|
||||
self.config = config or ValueSelectionExConfig()
|
||||
|
||||
# =================== initialize ===================
|
||||
def initialize(self, context: Any) -> None:
|
||||
@@ -455,4 +455,4 @@ def _is_valid_number(v: Any) -> bool:
|
||||
return not math.isnan(fv) and not math.isinf(fv)
|
||||
|
||||
|
||||
__all__ = ["ValueSelectionStrategyEx", "ValueSelectionConfigEx"]
|
||||
__all__ = ["ValueSelectionExStrategy", "ValueSelectionExConfig"]
|
||||
|
||||
Reference in New Issue
Block a user