| from __future__ import annotations |
|
|
| import yaml |
| import numpy as np |
| from typing import Dict |
| from pydantic import BaseModel, Field, field_validator |
|
|
|
|
| class UserParams(BaseModel): |
| lambda_mean: float = Field(gt=0) |
| lambda_std: float = Field(gt=0) |
| mu_mean: float |
| mu_std: float = Field(gt=0) |
| sigma_mean: float = Field(gt=0) |
| sigma_std: float = Field(gt=0) |
|
|
|
|
| class UPILimits(BaseModel): |
| max_txn_amount: float = Field(gt=0) |
| daily_limit: float = Field(gt=0) |
|
|
|
|
| class RiskModel(BaseModel): |
| weights: Dict[str, float] |
|
|
| @field_validator("weights") |
| @classmethod |
| def check_weights(cls, v): |
| if not v: |
| raise ValueError("weights cannot be empty") |
| return v |
|
|
|
|
| class Config(BaseModel): |
| num_users: int = Field(gt=0) |
| simulation_days: int = Field(gt=0) |
| fraud_ratio: float = Field(ge=0, le=1) |
| benchmark_mode: str = "standard" |
|
|
| user_params: UserParams |
| upi_limits: UPILimits |
| risk_model: RiskModel |
|
|
| random_seed: int |
|
|
| @property |
| def simulation_seconds(self) -> int: |
| return self.simulation_days * 24 * 60 * 60 |
|
|
|
|
| def load_config(path: str) -> Config: |
| with open(path, "r") as f: |
| raw = yaml.safe_load(f) |
|
|
| config = Config(**raw) |
|
|
| np.random.seed(config.random_seed) |
|
|
| return config |
|
|