52 lines
1.8 KiB
Python
52 lines
1.8 KiB
Python
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
|
|
from app.services.boundary_values import boundary_decimal
|
|
|
|
|
|
@dataclass(frozen=True, slots=True)
|
|
class NormalizedHistoricalScenarioInputs:
|
|
underlying_units: float
|
|
loan_amount: float
|
|
margin_call_ltv: float
|
|
currency: str = "USD"
|
|
cash_balance: float = 0.0
|
|
financing_rate: float = 0.0
|
|
|
|
|
|
def normalize_historical_scenario_inputs(
|
|
*,
|
|
underlying_units: object,
|
|
loan_amount: object,
|
|
margin_call_ltv: object,
|
|
currency: object = "USD",
|
|
cash_balance: object = 0.0,
|
|
financing_rate: object = 0.0,
|
|
) -> NormalizedHistoricalScenarioInputs:
|
|
normalized_currency = str(currency).strip().upper()
|
|
if not normalized_currency:
|
|
raise ValueError("Currency is required")
|
|
|
|
units = float(boundary_decimal(underlying_units, field_name="underlying_units"))
|
|
normalized_loan_amount = float(boundary_decimal(loan_amount, field_name="loan_amount"))
|
|
ltv = float(boundary_decimal(margin_call_ltv, field_name="margin_call_ltv"))
|
|
normalized_cash_balance = float(boundary_decimal(cash_balance, field_name="cash_balance"))
|
|
normalized_financing_rate = float(boundary_decimal(financing_rate, field_name="financing_rate"))
|
|
|
|
if units <= 0:
|
|
raise ValueError("Underlying units must be positive")
|
|
if normalized_loan_amount < 0:
|
|
raise ValueError("Loan amount must be non-negative")
|
|
if not 0 < ltv < 1:
|
|
raise ValueError("Margin call LTV must be between 0 and 1")
|
|
|
|
return NormalizedHistoricalScenarioInputs(
|
|
underlying_units=units,
|
|
loan_amount=normalized_loan_amount,
|
|
margin_call_ltv=ltv,
|
|
currency=normalized_currency,
|
|
cash_balance=normalized_cash_balance,
|
|
financing_rate=normalized_financing_rate,
|
|
)
|