Initial commit: Vault Dashboard for options hedging
- FastAPI + NiceGUI web application - QuantLib-based Black-Scholes pricing with Greeks - Protective put, laddered, and LEAPS strategies - Real-time WebSocket updates - TradingView-style charts via Lightweight-Charts - Docker containerization - GitLab CI/CD pipeline for VPS deployment - VPN-only access configuration
This commit is contained in:
85
tests/conftest.py
Normal file
85
tests/conftest.py
Normal file
@@ -0,0 +1,85 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
import pandas as pd
|
||||
import pytest
|
||||
|
||||
from app.models.portfolio import LombardPortfolio
|
||||
from app.strategies.base import StrategyConfig
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_portfolio() -> LombardPortfolio:
|
||||
"""Research-paper baseline portfolio: 1M collateral, 600k loan, 460 spot, 75% LTV trigger."""
|
||||
gold_ounces = 1_000_000.0 / 460.0
|
||||
return LombardPortfolio(
|
||||
gold_ounces=gold_ounces,
|
||||
gold_price_per_ounce=460.0,
|
||||
loan_amount=600_000.0,
|
||||
initial_ltv=0.60,
|
||||
margin_call_ltv=0.75,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_strategy_config(sample_portfolio: LombardPortfolio) -> StrategyConfig:
|
||||
return StrategyConfig(
|
||||
portfolio=sample_portfolio,
|
||||
spot_price=sample_portfolio.gold_price_per_ounce,
|
||||
volatility=0.16,
|
||||
risk_free_rate=0.045,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def sample_option_chain(sample_portfolio: LombardPortfolio) -> dict[str, object]:
|
||||
"""Deterministic mock option chain around a 460 GLD reference price."""
|
||||
spot = sample_portfolio.gold_price_per_ounce
|
||||
return {
|
||||
"symbol": "GLD",
|
||||
"updated_at": datetime(2026, 3, 21, 0, 0).isoformat(),
|
||||
"source": "mock",
|
||||
"calls": [
|
||||
{"strike": round(spot * 1.05, 2), "premium": round(spot * 0.03, 2), "expiry": "2026-06-19"},
|
||||
{"strike": round(spot * 1.10, 2), "premium": round(spot * 0.02, 2), "expiry": "2026-09-18"},
|
||||
],
|
||||
"puts": [
|
||||
{"strike": round(spot * 0.95, 2), "premium": round(spot * 0.028, 2), "expiry": "2026-06-19"},
|
||||
{"strike": round(spot * 0.90, 2), "premium": round(spot * 0.018, 2), "expiry": "2026-09-18"},
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_yfinance_data(monkeypatch):
|
||||
"""Patch yfinance in the data layer with deterministic historical close data."""
|
||||
# Lazy import here to avoid side effects when the environment lacks Python 3.11's
|
||||
# datetime.UTC symbol used in the data_service module.
|
||||
from app.services import data_service as data_service_module
|
||||
|
||||
history = pd.DataFrame({"Close": [458.0, 460.0]}, index=pd.date_range("2026-03-20", periods=2, freq="D"))
|
||||
|
||||
class FakeTicker:
|
||||
def __init__(self, symbol: str) -> None:
|
||||
self.symbol = symbol
|
||||
|
||||
def history(self, period: str, interval: str):
|
||||
return history.copy()
|
||||
|
||||
class FakeYFinance:
|
||||
Ticker = FakeTicker
|
||||
|
||||
monkeypatch.setattr(data_service_module, "yf", FakeYFinance())
|
||||
return {
|
||||
"symbol": "GLD",
|
||||
"history": history,
|
||||
"last_price": 460.0,
|
||||
"previous_price": 458.0,
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_yfinance(mock_yfinance_data):
|
||||
"""Compatibility alias for tests that request a yfinance fixture name."""
|
||||
return mock_yfinance_data
|
||||
Reference in New Issue
Block a user