Files
qlib/backend/app/domain/entities/signal.py
T
Simon 995ed08548 feat(chart): M9-1 Chart DTO + Chart Service + Chart API(v3 §20)
- domain/entities/chart.py:ChartResult/OHLC/Volume/Series/EventMarker/ChartMetadata
  (adjust_mode + execution_price_basis 口径元数据)+ SelectionHit
- application/services/chart_service.py:个股 K线/量/MA 指标;显示层 qfq/hfq 折算
  (基于主口径 none 行情 × adjust_factor,绝回写研究数据);回测个股视图把实际成交
  转 fills 标记并在显示口径不同时做坐标换算(v3 §20.3/§20.5)
- by-symbol 历史查询:SignalRepository/SelectionRepository.list_by_symbol(含溯源 id)
- api/charts.py:/stocks/{symbol}/chart|signals|selections、/backtests/{id}/stocks/{symbol}/chart
  |trades|positions
- tests/test_charts.py(指标/qfq-hfq 折算断言/回测 fills/API 集成+404);全量 pytest 通过
2026-09-09 07:09:52 +08:00

69 lines
2.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""交易信号领域实体(M8.1,v2 §15 Signal Engine)。
Signal 输入 = Selection 排序(score)+ 价格/技术条件 + 规则;输出事件可解释:
BUY / WATCH / SELL(破位警示),每条带 trigger_reason —— 回答
「某日为什么对该股票给 BUY/SELL」(v2 §8)。
"""
from __future__ import annotations
from datetime import date, datetime
from pydantic import BaseModel, Field
class SignalRules(BaseModel):
"""规则(结构化,MVP):买入区间 + 趋势/动量条件 + 卖出/警示区间。"""
buy_rank_threshold: int = Field(default=20, ge=1, le=500, description="rank<=此值进入买入候选")
buy_require_trend: bool = Field(default=True, description="买入需 close > MA(trend_ma)")
buy_require_momentum: bool = Field(default=False, description="买入需 close > 20 日前 close")
trend_ma: int = Field(default=60, ge=10, le=250)
sell_rank_threshold: int = Field(default=50, ge=1, le=1000, description="rank>此值或破位 → SELL 警示")
sell_on_trend_break: bool = Field(default=True, description="买入区间内 close < MA(trend_ma) → SELL")
max_output_rank: int = Field(default=80, ge=1, le=2000, description="仅输出排名前 N 的信号")
class SignalEvent(BaseModel):
symbol: str
signal_date: date
signal_type: str = Field(pattern="^(BUY|WATCH|SELL)$")
score: float | None = None
price: float | None = None
trigger_reason: list[str] = Field(default_factory=list)
class SignalStatistics(BaseModel):
universe_size: int = 0
buy: int = 0
watch: int = 0
sell: int = 0
class SignalResult(BaseModel):
as_of_date: date
rules: SignalRules
statistics: SignalStatistics
events: list[SignalEvent] = Field(default_factory=list)
config_snapshot: dict = Field(default_factory=dict)
class SignalMeta(BaseModel):
id: str
as_of: date
buy: int = 0
watch: int = 0
sell: int = 0
created_at: datetime | None = None
class SignalHit(BaseModel):
"""个股在信号历史中的命中(by-symbol 查询,供 Chart 标记)。"""
signal_id: str
signal_date: date
signal_type: str
score: float | None = None
price: float | None = None
trigger_reason: list[str] = Field(default_factory=list)