Step 2: Risk and Stops - Generating reports with pdf. It is missing to reorder the PDF.

This commit is contained in:
DaM
2026-02-13 07:01:44 +01:00
parent 4d769af8bf
commit 44667df3dd
27 changed files with 4318 additions and 103 deletions

View File

@@ -0,0 +1,84 @@
# src/web/api/v2/schemas/calibration_risk.py
from typing import Literal, Optional, Dict, Any
from pydantic import BaseModel, Field, model_validator
class StopConfigSchema(BaseModel):
type: Literal["fixed", "trailing", "atr"]
stop_fraction: Optional[float] = Field(None, gt=0)
atr_period: Optional[int] = Field(None, gt=1)
atr_multiplier: Optional[float] = Field(None, gt=0)
@model_validator(mode="after")
def validate_by_type(self):
if self.type in ("fixed", "trailing"):
if self.stop_fraction is None:
raise ValueError(
"stop_fraction required for fixed/trailing stop"
)
if self.type == "atr":
if self.atr_period is None:
raise ValueError(
"atr_period required for ATR stop"
)
if self.atr_multiplier is None:
raise ValueError(
"atr_multiplier required for ATR stop"
)
return self
# class StopConfigSchema(BaseModel):
# type: Literal["fixed", "trailing", "atr"]
# stop_fraction: Optional[float] = Field(None, gt=0)
# atr_period: Optional[int] = Field(None, gt=1)
# atr_multiplier: Optional[float] = Field(None, gt=0)
class RiskConfigSchema(BaseModel):
risk_fraction: float = Field(..., gt=0, lt=1)
max_position_fraction: float = Field(..., gt=0, lt=1)
class GlobalRiskRulesSchema(BaseModel):
max_drawdown_pct: float = Field(..., gt=0, lt=1)
daily_loss_limit_pct: Optional[float] = Field(None, gt=0, lt=1)
max_consecutive_losses: Optional[int] = Field(None, gt=0)
cooldown_bars: Optional[int] = Field(None, ge=0)
class CalibrationRiskInspectRequest(BaseModel):
symbol: str
timeframe: str
stop: StopConfigSchema
risk: RiskConfigSchema
global_rules: GlobalRiskRulesSchema
account_equity: float = Field(..., gt=0)
class CalibrationRiskInspectResponse(BaseModel):
valid: bool
status: Literal["ok", "warning", "fail"]
checks: Dict[str, Any]
message: str
class CalibrationRiskValidateResponse(BaseModel):
valid: bool
status: Literal["ok", "warning", "fail"]
checks: Dict[str, Any]
message: str
# ⬇️ NUEVO
series: Dict[str, Any]