Coverage for src/tinycta/config.py: 100%
15 statements
« prev ^ index » next coverage.py v7.14.1, created at 2026-09-15 05:23 +0000
« prev ^ index » next coverage.py v7.14.1, created at 2026-09-15 05:23 +0000
1"""Configuration model for the Basanos engine."""
3from pydantic import BaseModel, Field, ValidationInfo, field_validator
6class Config(BaseModel):
7 """Configuration for correlation-aware position optimization (Basanos engine).
9 Example:
10 >>> from pydantic import ValidationError
11 >>> from tinycta.config import Config
12 >>> cfg = Config(vola=32, corr=64, clip=4.2, shrink=0.5)
13 >>> cfg.vola, cfg.corr, cfg.clip, cfg.shrink
14 (32, 64, 4.2, 0.5)
16 The model is frozen, so a validated config cannot drift after construction:
18 >>> try:
19 ... cfg.vola = 16
20 ... except ValidationError:
21 ... print("frozen")
22 frozen
24 ``corr`` must not be shorter than ``vola`` — a correlation window below the
25 volatility window is numerically unstable:
27 >>> try:
28 ... Config(vola=64, corr=32, clip=4.2, shrink=0.5)
29 ... except ValidationError:
30 ... print("corr must be >= vola")
31 corr must be >= vola
33 Windows are strictly positive, ``shrink`` lies in ``[0, 1]``, and unknown
34 keys are rejected rather than silently ignored:
36 >>> for bad in ({"vola": 0}, {"shrink": 1.5}, {"typo": 1}):
37 ... kwargs = {"vola": 32, "corr": 64, "clip": 4.2, "shrink": 0.5} | bad
38 ... try:
39 ... Config(**kwargs)
40 ... except ValidationError:
41 ... print("rejected", sorted(bad))
42 rejected ['vola']
43 rejected ['shrink']
44 rejected ['typo']
45 """
47 vola: int = Field(..., gt=0)
48 corr: int = Field(..., gt=0)
49 clip: float = Field(..., gt=0.0)
50 shrink: float = Field(..., ge=0.0, le=1.0)
52 model_config = {"frozen": True, "extra": "forbid"}
54 @field_validator("corr")
55 @classmethod # pragma: no mutate - pydantic field_validator behaves identically without classmethod
56 def corr_greater_than_vola(cls, v: int, info: ValidationInfo) -> int:
57 """Enforce corr >= vola for numerical stability."""
58 vola = info.data.get("vola") if hasattr(info, "data") else None
59 if vola is not None and v < vola:
60 msg = f"corr ({v}) must be >= vola ({vola}) for numerical stability"
61 raise ValueError(msg)
62 return v