--- library_name: transformers tags: - finance - sentiment-analysis - text-classification - market-impact - gated-fusion - multitask-learning - event-study datasets: - NickyNicky/finance-financialmodelingprep-stock-news-sentiments-rss-feed - siddharthmb/stocks-ohlcv license: mit --- # FinImpact Direction1D V4 This repository contains a custom Hugging Face/PyTorch model for financial text impact modeling. It combines a financial language encoder with market context features through a gated fusion head. This v4 checkpoint is trained primarily as a 1-day market-impact signal model and adds return-aware auxiliary losses for directional-score alignment and confidence calibration. ## Task Input: - Financial news title/body - Symbol-level market context available before the event date Outputs: - `direction_1d`: bearish / neutral / bullish future 1-day abnormal market reaction - auxiliary diagnostics: `sentiment`, `direction_5d`, and `volatility` heads are still exported, but their default loss weights are zero in this v4 run. ## Architecture - Encoder: `microsoft/deberta-v3-large` - Pooling: attention-mask-aware mean pooling over `last_hidden_state` - Text branch: LayerNorm -> Linear -> GELU -> Dropout - Numeric branch: LayerNorm -> Linear -> GELU -> Dropout - Fusion: learned sigmoid gate between text and numeric branches - Heads: 1D direction classification head plus auxiliary diagnostic heads - Return-aware training: `P(bullish) - P(bearish)` is softly aligned to realized 1-day abnormal return sign/magnitude This is intentionally not an embedding-only classifier. The model fine-tunes a contextual encoder and learns a supervised 1-day market-impact boundary. ## Training Data News source: - `NickyNicky/finance-financialmodelingprep-stock-news-sentiments-rss-feed` - Fields used: `symbol`, `publishedDate`, `title`, `text`, `sentiment`, `sentimentScore` Price source: - `siddharthmb/stocks-ohlcv` - Daily close data used to build lagged market features and future-return labels. Training rows after join: `13930` Time split: - train: `10865` - validation: `1532` - test: `1533` Symbols: `AAPL, ABNB, ADBE, ADI, ADP, AMAT, AMD, AMZN, ARKK, ASML, AVGO, BA, BABA, BAC, BIDU, BMY, CAT, CMCSA, COIN, COST, CRM, CSCO, CVX, DHR, DIS, ELF, GE, GM, GOOGL, HD, IBM, INTC, IOVA, JNJ, JPM, KO, LULU, MA, MCD, MDB, META, MRNA, MSFT, MU, NFLX, NKE, NVDA, ORCL, PEP, PFE, PLTR, PYPL, QCOM, RCL, SHOP, SNOW, SPOT, TGT, TSLA, TSM, TXN, UAL, UBER, UNH, UPS, WMT, XOM, ZM` ## Numeric Features - `source_sentiment_score` - `sentiment_abs_score` - `site_benzinga` - `site_globenewswire` - `site_yahoo_finance` - `site_marketwatch` - `text_char_len` - `title_char_len` - `is_after_close` - `is_premarket` - `is_market_hours` - `published_hour_sin` - `published_hour_cos` - `ret_1d_lag` - `ret_5d_lag` - `ret_20d_lag` - `vol_5d` - `vol_20d` - `vol_60d` - `vol_ratio_5_20` - `drawdown_20d` - `volume_z_20d` - `sector_code` - `market_ret_1d_lag` - `market_ret_5d_lag` - `sector_ret_1d_lag` - `sector_ret_5d_lag` - `beta_market_60d` - `beta_sector_60d` All numeric features are fit/scaled on the training split only. ## Label Construction - `sentiment` comes from the source dataset label. - `direction_1d` is generated from future 1-day beta-adjusted abnormal log return after the event anchor date. - `direction_5d` is generated from future 5-day beta-adjusted abnormal log return. - A return is neutral when it falls inside a volatility-adjusted threshold. - `volatility` is based on train-split tertiles of future absolute 5-day return. Event anchoring shifts after-close UTC news to the next calendar day and uses the next available trading date. Duplicate same-symbol same-day event titles are removed before training. ## Test Metrics ```json { "sentiment": { "accuracy": 0.009784735812133072, "macro_precision": 0.0032615786040443573, "macro_recall": 0.3333333333333333, "macro_f1": 0.006459948320413436, "confusion_matrix": [ [ 0, 110, 0 ], [ 0, 15, 0 ], [ 0, 1408, 0 ] ], "predicted_class_counts": { "bearish": 0, "neutral": 1533, "bullish": 0 }, "true_class_counts": { "bearish": 110, "neutral": 15, "bullish": 1408 }, "expected_calibration_error": 0.8247767172447622, "brier_score": 1.5716914553389048 }, "direction_1d": { "accuracy": 0.3333333333333333, "macro_precision": 0.2797514006239241, "macro_recall": 0.30693224852151285, "macro_f1": 0.28541099148120913, "confusion_matrix": [ [ 31, 217, 212 ], [ 54, 138, 244 ], [ 124, 171, 342 ] ], "predicted_class_counts": { "bearish": 209, "neutral": 526, "bullish": 798 }, "true_class_counts": { "bearish": 460, "neutral": 436, "bullish": 637 }, "expected_calibration_error": 0.03496117605077468, "brier_score": 0.6723385830557309 }, "direction_5d": { "accuracy": 0.45857795172863663, "macro_precision": 0.28120269843193446, "macro_recall": 0.33741824434028733, "macro_f1": 0.30491929241175314, "confusion_matrix": [ [ 0, 123, 143 ], [ 0, 553, 311 ], [ 0, 253, 150 ] ], "predicted_class_counts": { "bearish": 0, "neutral": 929, "bullish": 604 }, "true_class_counts": { "bearish": 266, "neutral": 864, "bullish": 403 }, "expected_calibration_error": 0.024249568105288305, "brier_score": 0.633983250156182 }, "volatility": { "accuracy": 0.39921722113502933, "macro_precision": 0.13307240704500978, "macro_recall": 0.3333333333333333, "macro_f1": 0.1902097902097902, "confusion_matrix": [ [ 0, 534, 0 ], [ 0, 612, 0 ], [ 0, 387, 0 ] ], "predicted_class_counts": { "lower_vol": 0, "normal_vol": 1533, "higher_vol": 0 }, "true_class_counts": { "lower_vol": 534, "normal_vol": 612, "higher_vol": 387 }, "expected_calibration_error": 0.1760233100613036, "brier_score": 0.712886643106662 }, "event_backtest": { "split": "test", "transaction_cost_bps": 10.0, "active_1d_fraction": 0.6568819308545336, "hit_ratio_1d_active": 0.5789473684210527, "avg_signal_return_1d_all": 0.0023507131510749455, "avg_signal_return_1d_all_net": 0.0016938312202204116, "avg_signal_return_1d_active": 0.0035785931088360393, "avg_signal_return_1d_active_net": 0.002578593108836038, "avg_abnormal_signal_return_1d_all": 0.0007162017627715418, "avg_abnormal_signal_return_1d_all_net": 5.93198319170076e-05, "avg_abnormal_signal_return_1d_active": 0.0010903051661656142, "avg_abnormal_signal_return_1d_active_net": 9.030516616561321e-05, "soft_signal_backtest_1d": { "mean_abs_signal": 0.049029190093278885, "active_fraction_abs_score_ge_0.10": 0.11545988258317025, "hit_ratio_all_gross": 0.532941943900848, "hit_ratio_active_gross": 0.4463276836158192, "avg_signal_return_all": -4.1903094825102016e-05, "avg_signal_return_all_net": -9.093229164136574e-05, "avg_abnormal_signal_return_all": 6.6492548285168596e-06, "avg_abnormal_signal_return_all_net": -4.237994289724156e-05 }, "active_5d_fraction": 0.39399869536855836, "hit_ratio_5d_active": 0.3708609271523179, "avg_signal_return_5d_all": -0.004762698527096634, "avg_signal_return_5d_active": -0.012088107354369436, "confidence_backtests_1d": { "top_10pct_directional_confidence": { "num_events": 153, "mean_confidence": 0.40472039580345154, "hit_ratio": 0.48366013071895425, "avg_signal_return": -0.0017291086948829782, "avg_signal_return_net": -0.002729108694882979, "median_signal_return": -0.0011537353275343776, "avg_abnormal_signal_return": 0.0023775517351216227, "avg_abnormal_signal_return_net": 0.001377551735121622 }, "top_20pct_directional_confidence": { "num_events": 307, "mean_confidence": 0.39327916502952576, "hit_ratio": 0.46579804560260585, "avg_signal_return": -0.0018346647964980064, "avg_signal_return_net": -0.0028346647964980075, "median_signal_return": -0.001494303229264915, "avg_abnormal_signal_return": 0.00013626769358741198, "avg_abnormal_signal_return_net": -0.0008637323064125889 }, "top_30pct_directional_confidence": { "num_events": 460, "mean_confidence": 0.3858344554901123, "hit_ratio": 0.5021739130434782, "avg_signal_return": 0.000168503345380684, "avg_signal_return_net": -0.0008314966546193169, "median_signal_return": 0.00047751690726727247, "avg_abnormal_signal_return": -0.0006967808645482443, "avg_abnormal_signal_return_net": -0.0016967808645482452 }, "threshold_0.34": { "num_events": 1108, "coverage": 0.7227658186562296, "hit_ratio": 0.5523465703971119, "avg_signal_return": 0.002400788538323842, "avg_signal_return_net": 0.001400788538323841, "median_signal_return": 0.0029742957558482885, "avg_abnormal_signal_return": 0.00043566977963306825, "avg_abnormal_signal_return_net": -0.0005643302203669326 }, "threshold_0.36": { "num_events": 636, "coverage": 0.41487279843444225, "hit_ratio": 0.5471698113207547, "avg_signal_return": 0.001725182487273244, "avg_signal_return_net": 0.000725182487273243, "median_signal_return": 0.0027859483379870653, "avg_abnormal_signal_return": -0.0001395135721791607, "avg_abnormal_signal_return_net": -0.0011395135721791617 }, "threshold_0.38": { "num_events": 247, "coverage": 0.16112198303979125, "hit_ratio": 0.44129554655870445, "avg_signal_return": -0.0028902063559107334, "avg_signal_return_net": -0.0038902063559107343, "median_signal_return": -0.0022296553943306208, "avg_abnormal_signal_return": 0.0008437850360328761, "avg_abnormal_signal_return_net": -0.00015621496396712474 }, "threshold_0.40": { "num_events": 85, "coverage": 0.055446836268754074, "hit_ratio": 0.43529411764705883, "avg_signal_return": -0.0034284473146887168, "avg_signal_return_net": -0.004428447314688717, "median_signal_return": -0.0031941309571266174, "avg_abnormal_signal_return": 0.0008126156158087884, "avg_abnormal_signal_return_net": -0.00018738438419121242 }, "threshold_0.42": { "num_events": 20, "coverage": 0.01304631441617743, "hit_ratio": 0.25, "avg_signal_return": -0.008969856356270612, "avg_signal_return_net": -0.009969856356270613, "median_signal_return": -0.011959618888795376, "avg_abnormal_signal_return": -0.0006033775032847188, "avg_abnormal_signal_return_net": -0.0016033775032847197 }, "threshold_0.45": { "num_events": 2, "coverage": 0.001304631441617743, "hit_ratio": 0.5, "avg_signal_return": 0.0010717622935771942, "avg_signal_return_net": 7.176229357719333e-05, "median_signal_return": 0.0010717622935771942, "avg_abnormal_signal_return": 0.01302456425037235, "avg_abnormal_signal_return_net": 0.01202456425037235 }, "threshold_0.50": { "num_events": 0, "coverage": 0.0, "hit_ratio": null, "avg_signal_return": null, "avg_signal_return_net": null, "median_signal_return": null, "avg_abnormal_signal_return": null, "avg_abnormal_signal_return_net": null } }, "mean_text_gate_weight": 0.506599485874176, "std_text_gate_weight": 0.0016385371563956141 } } ``` The `confidence_backtests_1d` section ranks events by directional confidence, where directional confidence is `max(P(bearish), P(bullish))`. This is the preferred way to inspect whether the model is useful as a signal filter. V4 also reports cost-adjusted backtest fields using `10.0` bps per active directional event. ## Important Limitations This is a research model, not trading advice. Known limitations: - Public news sentiment labels can be noisy. - Daily OHLCV alignment is an approximation; intraday timestamp alignment would be better. - Market-direction labels are derived from future returns and are sensitive to threshold choice. - Results should be evaluated out-of-sample by date and by ticker before any practical use. ## Files - `pytorch_model.bin`: custom gated-fusion model weights. - `training_config.json`: training and dataset configuration. - `feature_schema.json`: numeric feature scaler and schema. - `label_mapping.json`: task label names. - `metrics.json`: train/validation/test metrics. - `test_predictions.csv`: event-level test predictions and returns. - `top_10pct_directional_confidence_1d` in `test_predictions.csv`: marks the highest-confidence directional event subset. - `confusion_matrix_*.csv`: confusion matrices per split/task.