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 通过
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
"""策略领域实体(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,
|
||||
)
|
||||
Reference in New Issue
Block a user