Spaces:
Configuration error
Configuration error
File size: 7,166 Bytes
0125724 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | """
TradeSense AI — Master Quantitative Research Engine Orchestrator
Executes the end-to-end reproducible research workflow for any ticker and cutoff date.
"""
from datetime import date
from typing import Optional, Dict, Any, Tuple
import pandas as pd
import numpy as np
from backend.app.schemas.contracts import (
StructuredEvidence,
PredictionJournalEntry,
DatasetMetadata,
FeatureMetadata,
SignalType
)
from quant.data.fetcher import CanonicalDataEngine
from quant.features.feature_store import FeatureStoreEngine
from quant.backtesting.engine import WalkForwardEngine
from quant.risk.risk_engine import RiskEngine
from quant.evaluation.evidence_builder import EvidenceBuilder
from quant.journal.journal_engine import PredictionJournalEngine
from quant.copilot.explainer import GroundedCopilotEngine
class TradeSenseMasterEngine:
"""
Main entry point for executing reproducible quantitative research runs.
"""
def __init__(
self,
polygon_api_key: Optional[str] = None,
alpha_vantage_api_key: Optional[str] = None,
fmp_api_key: Optional[str] = None,
twelve_data_api_key: Optional[str] = None
):
self.data_engine = CanonicalDataEngine(
polygon_api_key=polygon_api_key,
alpha_vantage_api_key=alpha_vantage_api_key,
fmp_api_key=fmp_api_key,
twelve_data_api_key=twelve_data_api_key
)
self.journal_engine = PredictionJournalEngine()
self.last_df_clean: Dict[str, pd.DataFrame] = {}
def get_recent_history(self, ticker: str, n_bars: int = 45) -> Dict[str, Any]:
"""Returns recent clean historical OHLCV series for continuous frontend charts."""
ticker = ticker.upper().strip()
df = self.last_df_clean.get(ticker)
if df is None or df.empty:
return {"sessions": [], "closes": [], "opens": [], "highs": [], "lows": [], "volumes": []}
tail_df = df.tail(n_bars)
return {
"sessions": [d.strftime('%Y-%m-%d') for d in tail_df["session"]],
"closes": [round(float(c), 2) for c in tail_df["Close"]],
"opens": [round(float(o), 2) for o in tail_df["Open"]],
"highs": [round(float(h), 2) for h in tail_df["High"]],
"lows": [round(float(l), 2) for l in tail_df["Low"]],
"volumes": [int(v) for v in tail_df["Volume"]]
}
def run_research_pipeline(
self,
ticker: str,
cutoff_session: Optional[date] = None,
horizon_sessions: int = 21
) -> Tuple[StructuredEvidence, PredictionJournalEntry, str, DatasetMetadata]:
"""
Executes the complete end-to-end quantitative pipeline strictly at cutoff session T:
1. Fetch & clean canonical dataset
2. Build supervised feature windows (zero lookahead)
3. Run walk-forward simulation vs. Naive baseline with slippage
4. Generate probabilistic quantile forecast distribution
5. Compute ATR risk and trade target geometry
6. Emit schema-compliant StructuredEvidence JSON object
7. Synthesize grounded AI research note
8. Log immutable PredictionJournal entry
"""
ticker = ticker.upper().strip()
# Step 1: Ingest and clean canonical historical data strictly <= cutoff T
df_clean, dataset_meta = self.data_engine.build_canonical_dataset(
ticker=ticker, years=10, cutoff_session=cutoff_session
)
self.last_df_clean[ticker] = df_clean
# Step 2: Build supervised feature windows
X, Y, sessions, feature_cols, target_scaler = FeatureStoreEngine.build_supervised_windows(
df_clean=df_clean, horizon_sessions=horizon_sessions, lookback_sessions=120
)
# Step 3: Run Walk-Forward evaluation vs Naive baseline with frictions
feat_df = FeatureStoreEngine.calculate_technical_features(df_clean).dropna().reset_index(drop=True)
close_prices = feat_df["Close"].values[120 - 1 : len(feat_df) - horizon_sessions]
wf_engine = WalkForwardEngine(n_splits=4, test_window_size=63, slippage_bps=5.0)
candidate_metrics, naive_metrics, statistical_diagnostics = wf_engine.evaluate_model(
X=X, Y=Y, close_prices=close_prices, sessions=sessions, horizon_sessions=horizon_sessions
)
# Step 4: Extract live inference features at cutoff T
X_live, live_cutoff, current_price, _, feature_meta = FeatureStoreEngine.get_latest_inference_features(
df_clean=df_clean, lookback_sessions=120
)
# Train candidate model with split conformal calibration on historical data <= T
from quant.models.conformal_predictor import SplitConformalReturnPredictor
cal_size = max(10, int(len(X) * 0.20))
X_tr, X_cal = X[:-cal_size], X[-cal_size:]
p_tr, p_cal = close_prices[:-cal_size], close_prices[-cal_size:]
y_tr_rets = (Y[:-cal_size] - p_tr) / np.where(p_tr > 0, p_tr, 1.0)
y_cal_rets = (Y[-cal_size:] - p_cal) / np.where(p_cal > 0, p_cal, 1.0)
active_model = SplitConformalReturnPredictor(n_estimators=120, max_depth=4, random_state=42)
active_model.fit_and_calibrate(X_tr, y_tr_rets, X_cal, y_cal_rets)
conf_res = active_model.predict_distribution(X_live, current_prices=np.array([current_price]))
expected_price = float(conf_res.point_forecast_price[0])
interval_80 = (float(conf_res.interval_80_price[0][0]), float(conf_res.interval_80_price[1][0]))
interval_95 = (float(conf_res.interval_95_price[0][0]), float(conf_res.interval_95_price[1][0]))
# Step 5: Compute Risk Profile & Volatility Sizing
risk_profile = RiskEngine.compute_risk_profile(
df_clean=df_clean, expected_price=expected_price
)
# Step 6: Determine Active Regime & Build Structured Evidence
market_regime = EvidenceBuilder.determine_regime(df_clean)
evidence = EvidenceBuilder.evaluate_signal_and_evidence(
ticker=ticker,
cutoff_session=live_cutoff,
current_price=current_price,
expected_price=expected_price,
interval_80=interval_80,
interval_95=interval_95,
backtest=candidate_metrics,
risk=risk_profile,
market_regime=market_regime,
dataset_version=dataset_meta.dataset_version,
feature_version=feature_meta.feature_version,
dataset_lineage_hash=dataset_meta.sha256_hash,
horizon_sessions=horizon_sessions,
data_quality_report=dataset_meta.quality_report,
statistical_diagnostics=statistical_diagnostics,
)
# Step 7: Synthesize Grounded AI Research Note
research_note = GroundedCopilotEngine.generate_research_note(evidence)
# Step 8: Log to Prediction Journal
journal_entry = self.journal_engine.log_issued_forecast(evidence, current_price=current_price)
return evidence, journal_entry, research_note, dataset_meta
|