契约驱动
模块之间只通过数据类型通信,不直接引用彼此的实现类。上游只关心输出字段是否符合约定,下游只关心输入字段是否存在。
短路优先
流水线中任一模块返回空值或明确的短路信号,后续模块不执行。避免弱信号进入执行层。
可插拔实现
每个模块位置(M1-M4)对应一个 ABC,注册表将算法名称映射到实现类。SystemConfig 中的 method 字段是路由键,不是代码引用。
参数解耦
算法逻辑不在 __init__ 中接收参数,而是通过 configure(params: dict) 方法初始化。params 来自 SystemConfig,key 由算法自行定义。

M1 TrendModule 的输出,描述当前市场趋势状态。

字段类型是否必填说明
directionstr必填趋势方向:"bullish" / "bearish" / "ranging"。ranging 时触发短路,后续模块不执行。
stagestr必填趋势阶段:"impulse" / "pullback" / "consolidation"
extreme_pricefloat必填本段趋势的极值价格(多头时为最高点,空头时为最低点)
pullback_depthfloat必填当前回调深度(0.0 ~ 1.0,相对于趋势幅度)。仅描述数值,当前版本不用于过滤。
strengthfloat | None可选趋势强度分值(0.0 ~ 1.0)。当前版本保留字段,不使用,后续用于影响仓位大小。
methodstr必填产生此结果的算法名称,如 "ema_group"
params_hashstr必填算法参数的哈希值,用于缓存 key 构建
strength 字段当前版本隐藏,置为 None。后续补回时影响仓位计算,届时由 PlanModule 读取。

M2 KeyLevelModule 输出的单个关键位,实际输出为 List[KeyLevel]。

字段类型是否必填说明
pricefloat必填关键价格中轴
zone_lowfloat必填区间下边界(用于图表填充矩形)
zone_highfloat必填区间上边界
level_typestr必填"support" / "resistance" / "both"
touch_countint必填历史触碰次数,越高越强
last_touch_timeint必填最近一次触碰的 K 线收盘时间戳(ms)
methodstr必填产生此关键位的算法名称
区间展示要求:KeyLevel 必须同时包含 zone_low 和 zone_high,图表层使用填充矩形展示,不画单条价格线。

M3 SignalModule 的输出,描述一个入场信号。

字段类型是否必填说明
signal_typestr必填信号类型,如 "golden_candle"、"pattern_signal"
directionstr必填"long" / "short"
entry_candle_timeint必填触发信号的 K 线收盘时间戳(ms)
entry_price_hintfloat必填建议入场价(参考值,PlanModule 可调整)
key_level_refKeyLevel必填触发此信号所依附的关键位
confidencefloat | None可选信号置信度(0.0~1.0)。当前版本保留字段,不使用

M4 PlanModule 的输出,完整的交易计划。

字段类型是否必填说明
symbolstr必填交易对,如 "BTC/USDT:USDT"
directionstr必填"long" / "short"
entry_pricefloat必填计划入场价
stop_lossfloat必填止损价
take_profitfloat必填止盈价
rr_ratiofloat必填盈亏比((tp-entry)/(entry-sl))。低于 min_rr_ratio 时短路。
position_sizefloat必填仓位大小(USDT 计价)
signal_refSignalResult必填来源信号引用
created_atint必填计划生成时间戳(ms)

M1 插槽的抽象基类,所有趋势算法必须继承此类。

from abc import ABC, abstractmethod
from .types import TrendResult

class TrendModule(ABC):
    
    def configure(self, params: dict) -> None:
        """接收来自 SystemConfig 的参数字典,算法自行解析所需字段。"""
        pass
    
    @abstractmethod
    def analyze(self, klines: list[dict], symbol: str, timeframe: str) -> TrendResult | None:
        """
        分析 K 线序列,返回趋势判断结果。
        返回 None 或 direction=="ranging" 时,流水线短路。
        
        Args:
            klines: K 线列表,每条格式 {time, open, high, low, close, volume}
            symbol: 交易对
            timeframe: 时间周期
        """
        ...
    
    @property
    @abstractmethod
    def name(self) -> str:
        """算法注册名称,与方法注册表中的 key 一致。"""
        ...
klines 列表中时间 t 的 K 线只包含 ≤t 时刻的数据(HistoricalDataFeed 保证此约束),算法实现不应假设能看到未来数据。

M2 插槽的抽象基类,所有关键位算法必须继承此类。

from abc import ABC, abstractmethod
from .types import KeyLevel

class KeyLevelModule(ABC):
    
    def configure(self, params: dict) -> None:
        pass
    
    @abstractmethod
    def identify(self, klines: list[dict], symbol: str, timeframe: str) -> list[KeyLevel]:
        """
        识别关键价位区间列表。
        返回空列表 [] 时,流水线短路。
        
        返回的每个 KeyLevel 必须包含 zone_low 和 zone_high(区间,非单条线)。
        """
        ...
    
    @property
    @abstractmethod
    def name(self) -> str: ...

M3 插槽的抽象基类,所有信号算法必须继承此类。

from abc import ABC, abstractmethod
from .types import TrendResult, KeyLevel, SignalResult

class SignalModule(ABC):
    
    def configure(self, params: dict) -> None:
        pass
    
    @abstractmethod
    def detect(
        self,
        klines: list[dict],
        trend: TrendResult,
        key_levels: list[KeyLevel],
        symbol: str,
    ) -> SignalResult | None:
        """
        在给定趋势和关键位上下文中检测入场信号。
        返回 None 时,流水线短路。
        
        Args:
            klines: K 线序列(最新一根为当前 K 线收盘)
            trend: M1 输出的趋势判断
            key_levels: M2 输出的关键位列表
        """
        ...
    
    @property
    @abstractmethod
    def name(self) -> str: ...

M4 插槽的抽象基类,所有交易计划算法必须继承此类。

from abc import ABC, abstractmethod
from .types import SignalResult, TradePlan

class PlanModule(ABC):
    
    def configure(self, params: dict) -> None:
        pass
    
    @abstractmethod
    def generate(
        self,
        signal: SignalResult,
        account_balance: float,
        min_rr_ratio: float,
    ) -> TradePlan | None:
        """
        根据入场信号生成完整交易计划。
        rr_ratio < min_rr_ratio 时返回 None(短路)。
        
        Args:
            signal: M3 输出的入场信号
            account_balance: 当前账户余额(USDT),用于仓位计算
            min_rr_ratio: 最小盈亏比阈值,来自 SystemConfig
        """
        ...
    
    @property
    @abstractmethod
    def name(self) -> str: ...
注册表结构
每个模块插槽维护独立的注册表字典,key 为算法名称字符串,value 为实现类(类对象,非实例)。系统启动时扫描 alphaquant/modules/ 各子目录,自动注册所有实现类。SystemConfig 中的 trend_method(如 "ema_group")在运行时被用作路由 key,查表实例化对应类后调用 configure(params) 注入参数。
新增算法的步骤
  1. 在对应模块子目录下新建实现文件,继承对应的 ABC
  2. 实现 name 属性,返回唯一的算法注册名称(如 "my_new_trend")
  3. 实现核心抽象方法(analyze / identify / detect / generate)
  4. 在子目录的 __init__.py 中导入该类,使注册扫描能发现它
  5. 在 SystemConfig 的 method 字段填写对应名称,参数写入 params 字典
插槽注册名中文名状态文档
M1 TrendModulenaked_candle裸K趋势stablem1_naked_candle.html
M1 TrendModuleema_group均线组趋势stablem1_ema_group.html
M1 TrendModulevegas_tunnelVegas隧道draftm1_vegas_tunnel.html
M1 TrendModuletrendline趋势线planned—
M1 TrendModulepattern_trend形态趋势planned—
M2 KeyLevelModulehorizontal_swing水平关键位stablem2_horizontal_swing.html
M2 KeyLevelModulepattern_level形态关键位planned—
M2 KeyLevelModulespecific_price特定价格planned—
M3 SignalModulegolden_candle金K入场stablem3_golden_candle.html
M3 SignalModulepattern_signal形态信号draft—
M3 SignalModuleema_signal均线信号planned—

流水线按 M1→M2→M3→M4 顺序执行,任一步短路后后续模块不再调用。短路不是错误,是正常的「无信号」状态。

模块短路条件原因
M1 TrendModuledirection == "ranging" 或返回 None震荡市场下信号质量低,不值得继续分析
M2 KeyLevelModule返回空列表 []无关键位则 M3 无法判断价格是否进入有效区域
M3 SignalModule返回 None当前 K 线无满足条件的入场形态
M4 PlanModulerr_ratio < min_rr_ratio 或返回 None盈亏比不足,不值得开仓;这是最后一道过滤门
短路信息记录在日志中,但不触发 Discord 通知。只有 M4 成功生成 TradePlan 才推送通知。