Spaces:
Running
Running
Commit History
-
yfinance's impliedVolatility field is a placeholder; back IV out of the traded straddle Running
Verified signatureWiring the HAR forecast against implied vol produced NVDA: forecast 38.7 percent vs implied 12.5 percent, a -26 point premium. Not credible, and the same field had read 90.63 for NVDA earlier in the session. Cause: implied_vol_pct was the MEDIAN IV ACROSS THE WHOLE NEAREST-EXPIRY CHAIN, which averages deep out-of-the-money strikes. Switching to the ATM strike made it worse -- 0.78 percent -- which is what exposed the real problem: yfinance returns the placeholder 0.00001 for impliedVolatility at the ATM strike, with bid and ask both 0.0 and openInterest 0, on a strike that traded 38,104 contracts. Only lastPrice and volume are real. So IV is now inverted from the traded ATM straddle via Brenner-Subrahmanyam. Results are credible and premiums land at a few vol points: SPY 9.1 vs 11.3 (+2.2), NVDA 38.7 vs 36.3 (-2.4), TSLA 45.6 vs 46.5 (+0.8), KO 17.2 vs 21.6 (+4.4). The chain median is kept as implied_vol_chain_median_pct, diagnostic only, and the card now states the IV provenance --…c441543 -
Replace the dead TFT slot with a HAR forecast that actually works
Verified signatureThe app carried a 398,854-parameter TFT that had collapsed to its prior and returned the same answer for every symbol. This adds a SIX-parameter HAR volatility forecast, fitted per symbol on that symbol own daily bars, and shows it against the implied vol from the option chain. Their difference is the variance risk premium. Two things that are corrections rather than refinements: Garman-Klass measures only the intraday range and is blind to the close-to-open gap, so bare GK understates full-session variance while implied vol prices close-to-close INCLUDING overnight. Comparing them would inflate the premium by exactly the risk the estimator cannot see. The overnight term is added. exp(x @ beta) on a log-space fit is the conditional MEDIAN, not the mean. Without the exp(s2/2) factor the forecast ran ~40 percent below an independent close-to-close check. The same omission in the research code turned an implied-beats-HAR result from p=0.023 into p=0.583 once fixed. The card carries th…f2d8184
-
Search by company name; show price; keep icons on their ligature font
Verified signatureA visitor who knows "Nvidia" but not "NVDA" could not use this. 285 symbols with company names are BUNDLED and searched locally -- no network, no key, no entitlement, because the app has enough vendor-dependent failure modes already. Free-text entry is enabled by probing selectbox's signature, with a second input as the fallback on builds that lack it. Added price / day change / day range: a signal with no price is ungrounded -- the reader cannot tell whether "bearish" means down 0.2% or down 6%. Company name now shown beside the ticker, so a mistyped symbol is obvious.551aca9 -
Icons are a ligature font; stop forcing Montserrat on them
Verified signatureStreamlit draws expander arrows and alert icons with a LIGATURE font: the element literally contains the text "keyboard_arrow_right" and the font substitutes a glyph. The Montserrat rule matched span/div, broke the substitution, and the raw glyph name rendered on top of every expander label. Icons keep their own family now.9901fbd -
Montserrat, and reclaim the dead band above the title
Verified signatureStreamlit reserves ~6rem at the top of .block-container for a toolbar this app never uses, so the title sat a third of the way down the fold. Cut to 1.2rem and collapsed stHeader. Font applied by CSS selector rather than [theme] config, which only accepts sans serif / serif / monospace.51cad15 -
Use emoji icons; :material/ names rendered as literal text
Verified signaturerequirements.txt pins no streamlit version and the resolved build does not support the :material/name: icon syntax, so the alert boxes rendered the raw strings "trending_up" and "help" next to their messages.ea25a5e -
Make the result card explain its own verdict
Verified signatureposition_size is a FRACTION OF CAPITAL, not a share count, and the same name carries three different values at three nesting levels. A unitless 0.00 on every HOLD, duplicating options_strategy.contracts, is noise. Shown only when there is a position, labelled. HOLD 17% cannot distinguish nothing-happening from timeframes-disagree from missed-the-gate-by-two. The API now returns verdict.blocking_reason and the gates it measured against, naming only the condition that actually blocked. TSLA 1h turns out to sit two points under its gate, which was invisible before. The 200-line JSON dump is still there, with a per-timeframe table above it. Also fixed two dead branches in _generate_options_strategy: one gated on 1m/5m+scalp (all removed earlier, unreachable) and one on confidence > 70 against a value whose ceiling is 52 -- the same unreachable-gate defect fixed elsewhere and missed here. 4h and 1d had no branch and fell through to CONSERVATIVE.1549350 -
Say which session the bars are from; timeframes 15m/1h/4h/1d
Verified signatureReported at 22:22 ET on 2026-09-07 as stale results. It was Labor Day -- a full closure -- so the newest bar was Fridays, and nothing said so. Note 2026-09-07 is a MONDAY: a weekday check calls it a session, so the exchange calendar is the only thing that knows better. trading_days.py is copied in and held against drift. market_status() gives state / reason / reference session, rendered as a banner before any request so it survives a dead backend. Early closes handled; missing tzdata degrades to unknown rather than closed. The calendars claim is cross-checked against the newest bar actually fetched, and a mismatch surfaces as a warning. Timeframes are now 15m/1h/4h/1d. 1m and 5m removed: yfinance caps 1m at 7 days, too few bars to warm up a 20-period indicator. 4h is folded from hourly one session at a time -- resample(4h) would splice the overnight gap into an intraday range. min_confidence re-measured for the new set: 36/36/37/38, fires 8.8%. Confidence is strategy-invariant by de…113b714 -
Replace scalp with reversal: a strategy option that changes the logic
Verified signaturescalp was byte-identical to momentum in all 36 measured symbol x timeframe rows -- its only effect was threshold *= 0.8, and the score is never near the threshold. It was a hold-time preference, not a strategy. Removed; callers fall through to momentum. reversal fades an extended move instead of following it, so it can take the opposite side on the same bars. Gated on an RSI extreme the move is running into; when nothing is extended it says so and stands down rather than silently degrading into momentum. Uses RSI / volume_exhaustion / near_resistance, all already computed and discarded. Permutation lift over shuffled bars: momentum 3.18x, gap 3.53x, reversal 5.00x. reversal disagrees with momentum on 19% of pairs. n=64 real, so these move around -- they show the modes are not noise and not each other, not that there is an edge.e795d13 -
Document the HOLD-only bug class and the permutation calibration
Verified signature629b8da -
Make the signal reachable, directional, and timeframe-aware
Verified signatureThe app could only ever answer HOLD. Four defects, each sufficient alone: 1. min_confidence was 70/65/60/55 against a quantity whose measured max was 47 -- it fired on 0 of 80 observations. Recalibrated to 40/38/36/34, percentiles of the real distribution; fires ~9%, so HOLD stays the common answer. 2. A component with no reading was scored as 0 confidence instead of abstaining, spending 30% of the budget on a constant zero and pinning output near 25. 3. momentum_score is a magnitude and _convert_signal_format hardcoded CALLS, so PUTS was unreachable for any input and a selloff read as a bullish setup. Direction recovered from directional_bias, which was computed then discarded. 4. The selected timeframe never reached the momentum engine, which hardcoded its weights -- every timeframe analysed identical data. 5m bars added so the fast settings have real data to weight. Gap mode was gated on the TFT gap_probability (~67.1 for every symbol, never cleared its own >7…3ebcf0e
-
Delete 5 unloadable pickle checkpoints (fail torch.load weights_only=True)
Verified signature6bca33e -
Remove the TFT from the decision path; drop 5 unloadable pickle checkpoints
Verified signatureThe TFT checkpoints load and are structurally intact. They carry no signal. Measured, not assumed: * Fed the NVDA checkpoint six different symbols' full price histories, gap_probability moved 0.10 on a 0-100 scale and no class probability deviated from 1/3 by more than 0.0077. The model has collapsed to the prior. * Walking the last 120 sessions out of sample, it emitted ONE constant direction per symbol -- NVDA DOWN 119/119, SPY and QQQ UP 119/119 -- with hit rates matching the majority-class baseline to the decimal (SPY/QQQ 54.6% vs 54.6%; NVDA 48.7% vs 51.3%, i.e. below it). * scaler_static in the checkpoint has every scale_ == 1.0: the static branch saw zero variance during training. That confirms the repo's "trained on a constant placeholder" note directly from the artifact. signal_scores["tft"] was +-0.7 by direction, so a constant direction made it a FIXED per-symbol bias of +-0.105 on weighted_score -- it looked like an input and was an offs…33ea2ed -
Confidence formula: 60% of its weight was two dead terms
Verified signatureReported: every ticker showed nearly the same number (25/25/27/27). Not a constant any more, but a fair complaint. The underlying analysis WAS varying by 3x (measured TSLA daily momentum 0.638 vs SPY 0.183); the compression was downstream: weighted_confidence = momentum_conf*0.4 + llm.get('conviction', 50)*0.3 + (sentiment == 'HIGH')*80*0.3 * On CPU the LLM ensemble is skipped and the rule-based fallback returns 'confidence', not 'conviction' -- 40 base, 65 on momentum, -10 on high VIX. .get() never found the key and fell through to the literal 50, contributing a CONSTANT 15. * Sentiment HIGH requires std_dev < 0.2 AND mean_abs > 0.3; headline scores cluster near 0 and 1, so that gate effectively never passes: a CONSTANT 0. 60% of the weight could not move. Both are now read honestly and MEDIUM is graded rather than discarded. WEIGHTS DELIBERATELY UNCHANGED -- widening the spread by reweighting would make the demo …a16406c -
Add scikit-learn, actually load the TFT checkpoints, never train in a request
Verified signatureThe build went green and the app then returned 500 "No module named 'sklearn'". sklearn was never in requirements, yet tft_model.py does `from sklearn.preprocessing import StandardScaler` and the .joblib checkpoints ARE pickled sklearn scalers. It never failed because the TFT is gated on `len(daily_df) >= 96` and the old data layer returned ONE row -- the import sat on a path that had never executed in production. Fixing the data layer reached it for the first time. Chasing that exposed three more things on the same dead path: * enhanced_api startup built a bare GapPredictionTFT and left the weight loading as the comment "(The rest of your TFT loading logic...)". Every instance had is_trained=False. * so the request handler took its else-branch: tft_model.train(daily_df, epochs=20) -- training a neural network inside an HTTP handler on cpu-basic. Merely adding sklearn would have converted a fast 500 into a hanging request. Removed; an unloaded model now degrades …c41df06 -
Fix build: drop pandas_ta, pin pandas<3, replace removed fillna(method=)
Verified signatureFollow-up to d6c7413, which failed to build. Pinning pandas>=2.0,<2.3 (to keep pandas_ta working under numpy<2) let pip backtrack to pandas 2.1.0, which predates Python 3.12 and ships no cp312 wheels. python:3.12-slim has no C compiler, so pip tried to build it from source: ERROR: Unknown compiler(s): [['cc'], ['gcc'], ['clang'], ...] Fixed by removing pandas_ta entirely rather than pinning numpy back to keep an abandoned 2021 beta alive. The Wilder ADX/ATR/RSI in indicators.py already replaced everything it provided and is verified against a dependency-free reference to ~1e-14. Removing it then resolved to pandas 3.0.5, which REMOVED DataFrame.fillna(method=...) -- called on every request in enrich_with_indicators. That image would have built cleanly and raised TypeError on every analyze. So those calls are now .bfill()/.ffill(), and pandas<3 stays as a justified ceiling (pandas 3 also changes copy-on-write and default string dtype, neither validated here). Also: dotenv -> py…ff0245c -
Fix: fetch real multi-timeframe OHLCV; app no longer returns a constant HOLD/15%
Verified signatureThe deployed app returned HOLD at exactly 15% confidence for every ticker. That was a constant, not a cautious model. Root cause: data.py's fetch_multi_timeframe_stock_data called Finnhub's /quote endpoint ("historical candle data is a premium feature") and returned a ONE-ROW DataFrame with Volume hardcoded to 0. indicators.identify_current_setup opens with `if df.empty or len(df) < 2` and returns {"adx": 0, "rsi": 50, "error": "Insufficient data"} -- so that branch fired 100% of the time. The momentum engine then reported confidence 0, and enhanced_api computed 0*0.4 + 50*0.3 + 0*0.3 = 15.0, where 50 is the default from llm_analysis.get("conviction", 50), a key that layer never sets. Now fetches real 15m/hourly/daily history via yfinance (already in requirements, already imported by three other modules -- just not the one deciding every signal). Also fixed, all found by following the first: * fetch_news(symbol, client) bound an httpx.AsyncClient to the `days` parameter, so any …d6c7413
-
Update README.md
Verified signature1ed989b -
Update Dockerfile
Verified signaturea4123a3 -
Update trade_analysis/data.py
Verified signatureedf18c6 -
Update requirements.txt
Verified signature476afee -
Update trade_analysis/data.py
Verified signaturebfda30f -
Update trade_analysis/data.py
Verified signature29c6f86 -
Update trade_analysis/data.py
Verified signaturebe3dd72 -
Update trade_analysis/data.py
Verified signaturef272a95 -
Update trade_analysis/data.py
Verified signature669de56 -
Update trade_analysis/data.py
Verified signatured0e39b7 -
Update trade_analysis/data.py
Verified signature82b46eb -
Update trade_analysis/enhanced_sentiment.py
Verified signatureeed5e46 -
Update trade_analysis/data.py
Verified signature0713532 -
Update trade_analysis/enhanced_sentiment.py
Verified signatureff2bcc3 -
Update trade_analysis/enhanced_sentiment.py
Verified signaturef9178a0 -
Update trade_analysis/agent.py
Verified signature3779256 -
Update trade_analysis/enhanced_sentiment.py
Verified signature9606d57 -
Update trade_analysis/agent.py
Verified signature461b81a
-
Update requirements.txt
Verified signature4173db7 -
Update Dockerfile
Verified signature033d63c -
Create run.sh
Verified signature3a12bf8 -
Update trade_analysis/enhanced_api.py
Verified signature0342bed -
Update Dockerfile
Verified signature7706725 -
Update Dockerfile
Verified signature8ac6e22 -
Update trade_analysis/agent.py
Verified signature9879eff -
Update streamlit_app.py
Verified signature6a9fb3f -
Create streamlit_app.py
Verified signature22e34f0 -
Upload indicators.py
Verified signaturebf1c8d9 -
Update requirements.txt
Verified signature8e1b1dc -
Update requirements.txt
Verified signature0bf9149 -
Update trade_analysis/cache.py
Verified signature58413ce -
Update requirements.txt
Verified signature2b77f9a -
Update requirements.txt
Verified signature8051dec