portfolio-engine / tests /test_data.py
engineportf's picture
Initial Deployment from Local Engine
208fbf8 verified
Raw
History Blame Contribute Delete
2.7 kB
import sys
import os
from sqlalchemy import create_engine
_this_dir = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, _this_dir)
sys.path.insert(0, os.path.dirname(_this_dir))
import data
def test_fetch_risk_free_rate_falls_back_when_cache_missing(monkeypatch):
"""Missing SQLite tables should not crash engine startup."""
mem_engine = create_engine("sqlite:///:memory:")
monkeypatch.setattr(data, "_get_db_engine", lambda: mem_engine)
assert data.fetch_risk_free_rate(default_rate=0.0375) == 0.0375
def test_fetch_risk_free_rate_reads_latest_cached_value(monkeypatch):
"""Risk-free rate should come from the latest cached benchmark quote when available."""
mem_engine = create_engine("sqlite:///:memory:")
with mem_engine.begin() as conn:
conn.exec_driver_sql(
"CREATE TABLE daily_prices (ticker TEXT, date TEXT, close_price REAL, UNIQUE(ticker, date))"
)
conn.exec_driver_sql(
"INSERT INTO daily_prices VALUES (?, ?, ?)",
("^TNX", "2024-01-01", 3.50)
)
conn.exec_driver_sql(
"INSERT INTO daily_prices VALUES (?, ?, ?)",
("^TNX", "2024-01-02", 4.25)
)
monkeypatch.setattr(data, "_get_db_engine", lambda: mem_engine)
assert data.fetch_risk_free_rate("^TNX", default_rate=0.01) == 0.0425
def test_clean_price_series_stale_and_weekend_data():
import pandas as pd
import numpy as np
# Create dates spanning a weekend (Fri, Sat, Sun, Mon, Tue, Wed, Thu, Fri)
dates = pd.date_range("2024-01-05", periods=8, freq="D") # 2024-01-05 is a Friday
# Friday: 100
# Sat/Sun: 100 (weekend data)
# Mon: 100
# Tue: 100
# Wed: 100 (stale data -> flat for >3 days)
# Thu: 110
# Fri: 110
prices = pd.Series([100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 110.0, 110.0], index=dates, name="TEST")
cleaned = data.clean_price_series(prices)
# Weekends (Sat/Sun) should be dropped
assert len(cleaned) == 6
# Flat prices should be interpolated
assert not cleaned.isna().any()
def test_ewm_incremental_initialization():
import pandas as pd
import numpy as np
np.random.seed(42)
rets = np.random.normal(0, 0.01, 100)
# pandas ewm adjust=False logic
pandas_ewm = pd.Series(rets).ewm(halflife=21, adjust=False).mean()
# Incremental logic used in backtest.py
alpha = 1 - np.exp(-np.log(2)/21)
ewm_mean = np.zeros(100)
ewm_mean[0] = rets[0]
for i in range(1, 100):
ewm_mean[i] = alpha * rets[i] + (1 - alpha) * ewm_mean[i-1]
np.testing.assert_allclose(pandas_ewm.values, ewm_mean, atol=1e-8)