Files
qlib/backend/app/domain/entities/strategy.py
T
Simon 9d25d466e5 feat(strategy): M8.3 策略模型 + /api/strategies(命名配置资产,可展开为 ResearchSpec)
- StrategyDefinition:universe/factors/selection/rebalance/costs/portfolio +
  price_adjustment(除 period 外完整策略定义);to_research_spec(period) 展开为标准 Spec
- strategy 表(migration e1f2a3b4c5d6,MySQL 已应用;name 唯一)+ StrategyRepository
- /api/strategies:POST/GET/DELETE + POST /{id}/expand(period+initial_capital → ResearchSpec)
- tests/test_strategies.py(repo CRUD/同名/expand、API CRUD/400/404);全量 pytest 通过
2026-09-09 00:38:09 +08:00

54 lines
1.9 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.3,v2 §17/§5.3)。
Strategy = 完整策略定义(universe + factors + selection + rebalance + costs +
portfolio,除回测区间 period 外),保存为命名资产;回测时补 period 展开为
ResearchSpec(v2 §18 Research Specification 为统一契约,策略是其持久化形态)。
"""
from __future__ import annotations
from datetime import date, datetime
from pydantic import BaseModel, Field
from app.domain.entities.research import (
CostSpec,
FactorSpec,
PortfolioSpec,
SelectionSpec,
UniverseSpec,
)
class StrategyDefinition(BaseModel):
id: str = ""
name: str = Field(min_length=1, max_length=64)
description: str = ""
spec_type: str = Field(default="backtest", pattern="^(backtest|factor_test)$")
universe: UniverseSpec = UniverseSpec()
price_adjustment: str = Field(default="none", pattern="^(none|qfq)$")
factors: list[FactorSpec] = Field(min_length=1)
selection: SelectionSpec = SelectionSpec()
rebalance: str = Field(default="monthly", pattern="^(weekly|monthly)$")
costs: CostSpec = CostSpec()
portfolio: PortfolioSpec = PortfolioSpec()
version: str = "1"
created_at: datetime | None = None
def to_research_spec(self, period: tuple[date, date], initial_capital: float | None = None):
"""补全回测区间/资金后展开为标准 ResearchSpec(可在 Job/回测执行)。"""
from app.domain.entities.research import ResearchSpec
return ResearchSpec(
type=self.spec_type,
universe=self.universe,
price_adjustment=self.price_adjustment,
factors=self.factors,
selection=self.selection,
rebalance=self.rebalance,
period=period,
costs=self.costs,
portfolio=self.portfolio,
initial_capital=initial_capital if initial_capital else 1_000_000.0,
)