""" Tests for P2/P3 features: - Noise-Filtered Transformer (deep learning sequence model) - Options Flow Sentiment (alternative data ingestion) - Exact True Risk Parity (ERC allocation engine) """ import pytest import numpy as np import pandas as pd from unittest.mock import patch, MagicMock # ───────────────────────────────────────────── # TRANSFORMER (Deep Learning Sequence Model) # ───────────────────────────────────────────── import dl_models def test_transformer_train_and_predict(): """Train the NoiseFilteredTransformer on synthetic cross-asset data and verify predictions.""" features_dict = {} for t in ['AAPL', 'MSFT', 'GOOGL']: df = pd.DataFrame(np.random.randn(100, 10), columns=[f'feat_{i}' for i in range(10)]) df['target'] = df['feat_0'] * 0.5 + df['feat_1'] * 0.2 + np.random.randn(100) * 0.1 df['ret'] = np.random.randn(100) * 0.01 features_dict[t] = df model, scaler = dl_models.train_cross_asset_transformer( features_dict, seq_len=60, epochs=2, batch_size=16, silent=True ) assert model is not None assert scaler is not None preds = dl_models.predict_transformer(model, scaler, features_dict, seq_len=60) assert len(preds) == 3 assert 'AAPL' in preds assert 'MSFT' in preds assert 'GOOGL' in preds assert isinstance(preds['AAPL'], float) # ───────────────────────────────────────────── # OPTIONS FLOW SENTIMENT (Alternative Data) # ───────────────────────────────────────────── import alternative_data @patch('alternative_data.yf.Ticker') def test_options_sentiment_success(mock_ticker): """Verify put/call ratio and IV skew extraction from a mocked options chain.""" mock_tk = MagicMock() mock_ticker.return_value = mock_tk mock_tk.options = ('2026-07-01',) mock_chain = MagicMock() mock_chain.calls = pd.DataFrame({ 'volume': [100, 200, 300], 'impliedVolatility': [0.1, 0.15, 0.2] }) mock_chain.puts = pd.DataFrame({ 'volume': [50, 150], 'impliedVolatility': [0.2, 0.3] }) mock_tk.option_chain.return_value = mock_chain results = alternative_data.fetch_options_sentiment(['AAPL'], silent=True) assert 'AAPL' in results assert 'put_call_ratio' in results['AAPL'] assert 'iv_skew' in results['AAPL'] # calls volume sum = 600, puts volume sum = 200 → ratio = 0.333 assert pytest.approx(results['AAPL']['put_call_ratio'], 0.01) == 0.333 # calls mean IV = 0.15, puts mean IV = 0.25 → skew = 0.10 assert pytest.approx(results['AAPL']['iv_skew'], 0.01) == 0.10 @patch('alternative_data.yf.Ticker') def test_options_sentiment_no_options_available(mock_ticker): """Verify safe defaults when a ticker has no listed options chains.""" mock_tk = MagicMock() mock_ticker.return_value = mock_tk mock_tk.options = () results = alternative_data.fetch_options_sentiment(['TSLA'], silent=True) assert 'TSLA' in results assert results['TSLA']['put_call_ratio'] == 1.0 assert results['TSLA']['iv_skew'] == 0.0 # ───────────────────────────────────────────── # EXACT TRUE RISK PARITY (ERC Engine) # ───────────────────────────────────────────── from erc_engine import exact_risk_parity_allocation def test_exact_risk_parity_equal_contributions(): """Mathematically verify that ERC produces equal marginal risk contributions.""" # 3 assets with widely different volatilities vols = np.array([0.1, 0.2, 0.4]) corr = np.array([ [1.0, 0.3, 0.2], [0.3, 1.0, 0.4], [0.2, 0.4, 1.0] ]) cov = np.outer(vols, vols) * corr cov_df = pd.DataFrame(cov, columns=['A', 'B', 'C'], index=['A', 'B', 'C']) weights = exact_risk_parity_allocation(cov_df, silent=True) assert len(weights) == 3 assert np.isclose(weights.sum(), 1.0) # Compute marginal risk contributions: w_i * (Σw)_i w_arr = weights.values marginal_risk = cov.dot(w_arr) risk_contributions = w_arr * marginal_risk # All risk contributions must be equal within tight tolerance mean_rc = np.mean(risk_contributions) np.testing.assert_allclose(risk_contributions, mean_rc, rtol=1e-3, atol=1e-5) # Lower-vol asset A should have the highest weight assert weights['A'] > weights['C'] assert weights['A'] > weights['B']