feat(v0.2): 市场阶段与主线识别 + 因子挖掘全链路 + 数据层完善

- 市场环境: 新增情绪周期6阶段(冰点/启动/主升/高潮/退潮/修复, 连板梯队驱动,
  EMA平滑+2日确认+弱档否决, 平均段长9.7天)与概念/行业主线排名(涨停梯队聚合,
  可配置宽基/风格标签过滤); 市场环境页重构, regime 透明加列, 与5档state并存
- 挖掘: 因子与策略挖掘全链路(API/worker/进程锁/候选库/前端工作台/文档),
  周度调度默认关闭且永不自动发布
- 回测: 财务快照因子(点时口径), 批量回测预计算共享下期收益,
  信号路径矩阵列依赖展开修复(consecutive_limit_ups 缺列报错)
- 数据/性能: enriched 生成与预热治理, 重任务限流, 行情/K线缓存复用, 时区修复
- 测试: 后端全量 914 通过; GUI 黑盒验证截图存证 gui-test-screenshots/
This commit is contained in:
shy3130
2026-08-16 23:39:07 +08:00
parent eb869c7ad2
commit 697c27bb02
129 changed files with 20324 additions and 602 deletions
+40 -1
View File
@@ -6,9 +6,10 @@ from __future__ import annotations
import logging
import time
from typing import Literal
from fastapi import APIRouter, HTTPException, Request
from pydantic import BaseModel, Field
from pydantic import BaseModel, ConfigDict, Field
from app import secrets_store
from app.data_providers.custom.config import MAX_TIMEOUT
@@ -427,6 +428,14 @@ class CustomSourceTestIn(BaseModel):
config: CustomSourceIn | None = None
class MiningSchedulePrefs(BaseModel):
model_config = ConfigDict(extra="forbid", strict=True)
mining_schedule_enabled: bool
mining_schedule_weekday: int = Field(ge=0, le=4)
mining_budget_profile: Literal["balanced", "strict"]
@router.get("/preferences")
def get_preferences() -> dict:
"""返回用户偏好设置。"""
@@ -485,6 +494,7 @@ def get_preferences() -> dict:
"depth_finalize_time": preferences.get_depth_finalize_time(),
"review_schedule": preferences.get_review_schedule(),
"review_push_channels": preferences.get_review_push_channels(),
**preferences.get_mining_schedule(),
}
@@ -657,6 +667,18 @@ def update_data_source_job_timeouts(req: DataSourceJobTimeoutPrefs) -> dict:
return req.model_dump()
@router.put("/preferences/mining-schedule")
def update_mining_schedule(req: MiningSchedulePrefs) -> dict:
"""一次更新周度自动 mining 配置。"""
from app.services import preferences
return preferences.set_mining_schedule(
req.mining_schedule_enabled,
req.mining_schedule_weekday,
req.mining_budget_profile,
)
@router.get("/preferences/watchlist-columns")
def get_watchlist_columns() -> dict:
"""返回自选列表列配置。"""
@@ -927,6 +949,23 @@ class PipelineIndexSymbolsIn(BaseModel):
symbols: str = ""
class MainlineFilterIn(BaseModel):
"""市场主线过滤配置(宽基/风格标签按成员数过滤 + 名称黑名单)。"""
min_members: int | None = None
max_members: int | None = None
blacklist: list[str] | str | None = None
@router.put("/preferences/mainline-filter")
def update_mainline_filter(req: MainlineFilterIn) -> dict:
"""更新市场主线过滤配置。部分更新; 修改后需重算主线(POST /api/regime/mainline/recompute)生效。"""
from app.services import preferences
payload = req.model_dump()
return preferences.set_mainline_filter_config(payload)
@router.put("/preferences/pipeline-index-symbols")
def update_pipeline_index_symbols(req: PipelineIndexSymbolsIn) -> dict:
"""保存指数自定义拉取代码。"""