feat(factor): M7.1 因子定义入库 + /api/factors 读库(目录契约源)
- factor_definition 表(migration b7f2a5e81c33,MySQL 已应用):name 主键 + 元数据 (formula/brief/frequency/lookback/direction/requires JSON/version)+ FactorDefinition entity(from_registry_def 由代码注册表构造) - FactorRepository Protocol + SQLAlchemy 实现(幂等 upsert/list/get) - /api/factors 改读 DB;目录为空自动 seed 注册表(幂等)—— 保留自定义因子登记能力 (计算仍须代码注册,引用未注册因子照常 FactorError,防伪因子) - tests/test_factor_catalog.py(repo 幂等/roundtrip/registry seed、API seed+字段齐全); test_api 的 client fixture 补 tmp sqlite session(factors 读库);全量 pytest 通过
This commit is contained in:
@@ -11,6 +11,7 @@ from datetime import date
|
||||
import pytest
|
||||
from app.api import deps
|
||||
from app.domain.entities.market import Stock
|
||||
from app.infrastructure.persistence.sqlalchemy.base import Base
|
||||
from app.main import app
|
||||
from app.quant.engine import LocalEngine
|
||||
from app.quant.service import ResearchService
|
||||
@@ -41,7 +42,7 @@ def _mem_stocks() -> list[Stock]:
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def client() -> TestClient:
|
||||
def client(tmp_path) -> TestClient:
|
||||
drifts = {sym: 0.003 - 0.0015 * i for i, sym in enumerate(_SYMS)}
|
||||
daily_df = synthetic_daily(drifts, n=300)
|
||||
bars = bars_dataframe_to_daily_bars(daily_df)
|
||||
@@ -60,6 +61,20 @@ def client() -> TestClient:
|
||||
service = ResearchService(_MemStockRepo(_mem_stocks()), _MemDailyRepo(), LocalEngine())
|
||||
app.dependency_overrides[deps._stock_repo_factory] = lambda: _MemStockRepo(_mem_stocks()) # noqa: SLF001
|
||||
app.dependency_overrides[deps._service_factory] = lambda: service # noqa: SLF001
|
||||
|
||||
# /api/factors 自 M7.1 读 DB(factor_definition)→ 提供 tmp sqlite session
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
engine = create_engine(f"sqlite:///{tmp_path / 'api.db'}", future=True)
|
||||
Base.metadata.create_all(engine)
|
||||
SessionLocal = sessionmaker(bind=engine, expire_on_commit=False)
|
||||
|
||||
def _session_override():
|
||||
with SessionLocal() as s:
|
||||
yield s
|
||||
|
||||
app.dependency_overrides[deps.get_session] = _session_override
|
||||
with TestClient(app) as c:
|
||||
yield c
|
||||
app.dependency_overrides.clear()
|
||||
|
||||
Reference in New Issue
Block a user