""" tests/conftest.py — Shared fixtures for ChanMacro tests. """ import os import sys import pytest import sqlite3 import numpy as np import pandas as pd from datetime import date, timedelta from pathlib import Path # Ensure package root on path sys.path.insert(0, str(Path(__file__).parent.parent)) @pytest.fixture def db_path(tmp_path): """Create a temporary SQLite database with full mock data.""" db = str(tmp_path / "test_macro.db") from database import init_db conn = init_db(db) np.random.seed(42) base = date(2025, 9, 1) n_days = 300 # Generate realistic price series with 3 regime periods prices = [90000] regimes = [] for i in range(n_days): if i < 100: ret = np.random.normal(0.003, 0.015) regime = "TREND" elif i < 200: ret = np.random.normal(0.000, 0.012) regime = "RANGE" else: ret = np.random.normal(-0.003, 0.025) regime = "PANIC" prices.append(prices[-1] * (1 + ret)) regimes.append(regime) for i in range(n_days): d = base + timedelta(days=i) c = prices[i] r = regimes[i] # OHLCV conn.execute(""" INSERT OR REPLACE INTO ohlcv_daily (date,symbol,open,high,low,close,volume,ema20,ema60,ema120,atr_14,bb_width,adx_14) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?) """, ( d.strftime("%Y-%m-%d"), "BTC/USDT:USDT", c * 0.99, c * 1.03, c * 0.97, c, 1000, c * (0.98 if r == "TREND" else 1.02 if r == "PANIC" else 1.0), c * (0.95 if r == "TREND" else 1.05 if r == "PANIC" else 1.0), c * (0.90 if r == "TREND" else 1.10 if r == "PANIC" else 1.0), c * (0.02 if r == "PANIC" else 0.015), 4.5, 28.0 if r == "TREND" else 18.0, )) # Breadth adv = 42 if r == "TREND" else 25 if r == "RANGE" else 8 conn.execute(""" INSERT OR REPLACE INTO breadth_daily (date,total_tracked,advance_top50,decline_top50,above_ema20_top50, new_highs_20d_top50,advance_top30,advance_top20, above_ema20_top30,above_ema20_top20,new_highs_20d_top30,new_highs_20d_top20) VALUES (?,50,?,?,?,?,?,?,?,?,?,?) """, ( d.strftime("%Y-%m-%d"), adv, 50 - adv, adv, min(adv, 15), int(adv * 0.7), int(adv * 0.5), int(adv * 0.7), int(adv * 0.5), min(int(adv * 0.7), 12), min(int(adv * 0.5), 8), )) # Derivatives oi_chg = 3.5 if r == "TREND" else 0.5 if r == "RANGE" else -2.0 conn.execute(""" INSERT OR REPLACE INTO derivatives (date,symbol,funding_rate,open_interest,oi_24h_change_pct, long_liquidations,short_liquidations,basis_annualised_pct) VALUES (?,?,?,?,?,?,?,?) """, ( d.strftime("%Y-%m-%d"), "BTC/USDT:USDT", 0.0001 + np.random.normal(0, 0.0002), 35e9, oi_chg + np.random.normal(0, 1.0), 50e6 * np.random.random(), 30e6 * np.random.random(), 8.5 if r == "TREND" else 3.0, )) # Regime history conn.execute(""" INSERT OR REPLACE INTO regime_history (date,regime,confidence,regime_version,maturity_score,all_scores_json,confirmation_days) VALUES (?,?,?,?,?,?,?) """, (d.strftime("%Y-%m-%d"), r, 0.75, "v1_price_breadth_vol", 50, "{}", 1)) conn.commit() conn.close() # Override config to use test DB from config import config old_db = config.db_path config.db_path = db yield db config.db_path = old_db @pytest.fixture def sample_state(db_path): """Build a MarketStateVector for a known test date.""" from models import ( MarketStateVector, MarketRegime, BreadthBucket, OIState, VolRegime, ) state = MarketStateVector( date=date(2026, 3, 15), regime=MarketRegime.TREND, regime_confidence=0.82, regime_version="v1_price_breadth_vol", regime_maturity_score=55.0, breadth_top20=82.0, breadth_top30=78.0, breadth_top50=74.0, breadth_bucket=BreadthBucket.STRONG, breadth_divergence=8.0, oi_state=OIState.NEW_LONGS, volatility_regime=VolRegime.NORMAL_VOL, ) state.market_state_hash = state.compute_hash() return state