Files
MoFin/venv/lib/python3.12/site-packages/alphasift/models.py
T
知微 fa45d8aa5f fix: 小果地址统一node122(兼容LAN+EasyTier)
- health_checklist.json: 192.168.1.122→node122
- ocr_client.py: docstring IP→node122
- docs/market-data-requirements.md: IP→node122
- 所有API调用通过ProxyHandler({})绕过系统代理
  Privoxy对node122:18003返回500,直连正常
2026-06-30 02:56:35 +08:00

250 lines
8.7 KiB
Python

# -*- coding: utf-8 -*-
"""Data models."""
from typing import Any
from dataclasses import dataclass, field
from datetime import datetime
@dataclass
class HardFilterConfig:
exclude_st: bool = True
price_min: float | None = None
price_max: float | None = None
amount_min: float | None = None
market_cap_min: float | None = None
market_cap_max: float | None = None
pe_ttm_min: float | None = None
pe_ttm_max: float | None = None
pb_min: float | None = None
pb_max: float | None = None
volume_ratio_min: float | None = None
turnover_rate_min: float | None = None
change_pct_min: float | None = None
change_pct_max: float | None = None
change_60d_min: float | None = None
change_60d_max: float | None = None
require_ma_bullish: bool = False
require_price_above_ma20: bool = False
signal_score_min: int | None = None
macd_status_whitelist: list[str] | None = None
rsi_status_whitelist: list[str] | None = None
breakout_20d_pct_min: float | None = None
breakout_20d_pct_max: float | None = None
range_20d_pct_max: float | None = None
volume_ratio_20d_min: float | None = None
volume_ratio_20d_max: float | None = None
body_pct_min: float | None = None
body_pct_max: float | None = None
pullback_to_ma20_pct_min: float | None = None
pullback_to_ma20_pct_max: float | None = None
consolidation_days_20d_min: int | None = None
consolidation_days_20d_max: int | None = None
volatility_20d_pct_min: float | None = None
volatility_20d_pct_max: float | None = None
max_drawdown_20d_pct_min: float | None = None
max_drawdown_20d_pct_max: float | None = None
atr_20_pct_min: float | None = None
atr_20_pct_max: float | None = None
@dataclass
class ScreeningConfig:
enabled: bool = False
market_scope: list[str] = field(default_factory=lambda: ["cn"])
hard_filters: HardFilterConfig = field(default_factory=HardFilterConfig)
tech_weight: float = 0.35
factor_weights: dict[str, float] = field(default_factory=dict)
scoring_profile: dict[str, Any] = field(default_factory=dict)
risk_profile: dict[str, Any] = field(default_factory=dict)
portfolio_profile: dict[str, Any] = field(default_factory=dict)
scorecard_profile: dict[str, Any] = field(default_factory=dict)
event_profile: dict[str, Any] = field(default_factory=dict)
ranking_hints: str = ""
max_output: int = 5
@dataclass
class Strategy:
name: str
display_name: str
description: str
version: str = "1"
category: str = "trend"
tags: list[str] = field(default_factory=list)
screening: ScreeningConfig = field(default_factory=ScreeningConfig)
@dataclass
class StrategyInfo:
"""Strategy metadata for list_strategies()."""
name: str
display_name: str
description: str
version: str
category: str
tags: list[str]
market_scope: list[str]
@dataclass
class Pick:
rank: int
code: str
name: str
final_score: float
screen_score: float
llm_score: float | None = None
ranking_reason: str = ""
risk_summary: str = ""
price: float = 0.0
change_pct: float = 0.0
amount: float = 0.0
total_mv: float | None = None
turnover_rate: float | None = None
volume_ratio: float | None = None
pe_ratio: float | None = None
pb_ratio: float | None = None
industry: str = ""
concepts: str = ""
industry_rank: int | None = None
industry_change_pct: float | None = None
industry_heat_score: float | None = None
concept_heat_score: float | None = None
board_heat_score: float | None = None
board_heat_latest_score: float | None = None
board_heat_trend_score: float | None = None
board_heat_persistence_score: float | None = None
board_heat_cooling_score: float | None = None
board_heat_observations: int | None = None
board_heat_state: str = ""
board_heat_summary: str = ""
change_60d: float | None = None
signal_score: float | None = None
ma_bullish: bool | None = None
price_above_ma20: bool | None = None
macd_status: str = ""
rsi_status: str = ""
breakout_20d_pct: float | None = None
range_20d_pct: float | None = None
volume_ratio_20d: float | None = None
body_pct: float | None = None
pullback_to_ma20_pct: float | None = None
consolidation_days_20d: int | None = None
volatility_20d_pct: float | None = None
max_drawdown_20d_pct: float | None = None
atr_20_pct: float | None = None
daily_quality_score: float | None = None
daily_quality_flags: str = ""
daily_source: str = ""
factor_scores: dict[str, float] = field(default_factory=dict)
llm_confidence: float | None = None
llm_sector: str = ""
llm_theme: str = ""
llm_tags: list[str] = field(default_factory=list)
llm_catalysts: list[str] = field(default_factory=list)
llm_risks: list[str] = field(default_factory=list)
llm_thesis: str = ""
llm_style_fit: str = ""
llm_watch_items: list[str] = field(default_factory=list)
llm_invalidators: list[str] = field(default_factory=list)
risk_score: float | None = None
risk_level: str = ""
risk_penalty: float = 0.0
risk_flags: list[str] = field(default_factory=list)
excluded_by_risk: bool = False
portfolio_penalty: float = 0.0
portfolio_flags: list[str] = field(default_factory=list)
post_analysis_status: dict[str, str] = field(default_factory=dict)
post_analysis_summaries: dict[str, str] = field(default_factory=dict)
post_analysis_score_deltas: dict[str, float] = field(default_factory=dict)
post_analysis_results: dict[str, Any] = field(default_factory=dict)
post_analysis_tags: list[str] = field(default_factory=list)
dsa_context: dict[str, Any] = field(default_factory=dict)
dsa_news: list[dict[str, Any]] = field(default_factory=list)
dsa_analysis_summary: str = ""
deep_analysis_status: str = "not_requested"
deep_analysis_query_id: str = ""
deep_analysis_summary: str = ""
deep_analysis_error: str = ""
deep_analysis_result: dict[str, Any] | None = None
deep_analysis_signal_score: int | None = None
deep_analysis_sentiment_score: int | None = None
deep_analysis_operation_advice: str = ""
deep_analysis_trend_prediction: str = ""
deep_analysis_risk_flags: list[str] = field(default_factory=list)
@dataclass
class ScreenResult:
strategy: str
market: str
strategy_version: str = ""
strategy_category: str = ""
snapshot_count: int = 0
after_filter_count: int = 0
picks: list[Pick] = field(default_factory=list)
run_id: str = ""
llm_ranked: bool = False
llm_market_view: str = ""
llm_selection_logic: str = ""
llm_portfolio_risk: str = ""
llm_coverage: float | None = None
llm_parse_errors: list[str] = field(default_factory=list)
degradation: list[str] = field(default_factory=list)
snapshot_source: str = ""
source_errors: list[str] = field(default_factory=list)
deep_analysis_requested: bool = False
post_analyzers: list[str] = field(default_factory=list)
daily_enriched: bool = False
daily_enrich_count: int = 0
risk_enabled: bool = True
portfolio_diversity_enabled: bool = True
portfolio_concentration_notes: list[str] = field(default_factory=list)
saved_path: str = ""
created_at: str = field(default_factory=lambda: datetime.now().isoformat())
@dataclass
class PickEvaluation:
code: str
name: str
rank: int
entry_price: float
current_price: float | None = None
return_pct: float | None = None
final_score: float = 0.0
status: str = "missing"
llm_sector: str = ""
llm_theme: str = ""
llm_tags: list[str] = field(default_factory=list)
risk_level: str = ""
risk_flags: list[str] = field(default_factory=list)
portfolio_flags: list[str] = field(default_factory=list)
shape_status: str = ""
shape_tags: list[str] = field(default_factory=list)
path_status: str = ""
path_days: int | None = None
path_end_return_pct: float | None = None
max_drawdown_pct: float | None = None
max_runup_pct: float | None = None
@dataclass
class EvaluationResult:
run_id: str
strategy: str
market: str
created_at: str
evaluated_at: str = field(default_factory=lambda: datetime.now().isoformat())
elapsed_days: int | None = None
snapshot_source: str = ""
source_errors: list[str] = field(default_factory=list)
picks: list[PickEvaluation] = field(default_factory=list)
average_return_pct: float | None = None
median_return_pct: float | None = None
win_rate: float | None = None
missing_codes: list[str] = field(default_factory=list)
degradation: list[str] = field(default_factory=list)
saved_path: str = ""