Premchan369 commited on
Commit
3c447d0
·
verified ·
1 Parent(s): 63c5d37

V3.0: Add rate-limit resilience (cache+retry) for HF Spaces

Browse files
Files changed (1) hide show
  1. app.py +53 -27
app.py CHANGED
@@ -7,7 +7,7 @@ Risk Engine, Sentiment, Macro, Research Desk, Technical Analysis.
7
  Bloomberg Terminal aesthetic: black + orange + green + cyan.
8
  Powered by K2 Think V2 (MBZUAI) for AI analysis.
9
  """
10
- import os, json, warnings, math, random
11
  from datetime import datetime, timedelta
12
  warnings.filterwarnings('ignore')
13
 
@@ -56,7 +56,7 @@ class K2ThinkClient:
56
  return f"🔴 Error: {str(e)[:300]}"
57
 
58
  # =============================================================================
59
- # MARKET DATA
60
  # =============================================================================
61
  MARKETS = {
62
  "US Equities": {"suffix": "", "ex": "AAPL, TSLA, NVDA, SPY, QQQ"},
@@ -72,15 +72,41 @@ MARKETS = {
72
  "Indices": {"suffix": "", "ex": "^GSPC, ^DJI, ^IXIC, ^FTSE"},
73
  }
74
 
 
 
 
 
 
 
 
 
75
  def fetch(ticker, period="1y", interval="1d"):
76
- try:
77
- stock = yf.Ticker(ticker.upper().strip())
78
- df = stock.history(period=period, interval=interval)
79
- if df.empty:
80
- return None, f"No data for '{ticker}'."
81
- return df, stock.info
82
- except Exception as e:
83
- return None, f"Error: {str(e)[:200]}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
 
85
  # =============================================================================
86
  # TECHNICAL INDICATORS
@@ -538,7 +564,8 @@ def crypto_arbitrage(coins):
538
  if not coin: continue
539
  sym = f"{coin}-USD"
540
  try:
541
- df = yf.Ticker(sym).history(period="1d", interval="1m")
 
542
  if not df.empty:
543
  results.append({
544
  'Coin': coin,
@@ -549,11 +576,12 @@ def crypto_arbitrage(coins):
549
  'Volume': f"{df['Volume'].sum():,.0f}",
550
  'Spread %': f"{((df['High'].iloc[-1]/df['Low'].iloc[-1]-1)*100):.3f}%"
551
  })
552
- except:
553
- pass
 
554
 
555
  if not results:
556
- return None, "Could not fetch crypto data. Try BTC, ETH, SOL."
557
 
558
  df = pd.DataFrame(results)
559
  # Arbitrage heatmap (simulated cross-exchange spreads)
@@ -736,15 +764,13 @@ def sentiment_analyzer(ticker):
736
  def macro_analysis():
737
  macros = {}
738
  for t, name in [('^GSPC','S&P 500'),('^IXIC','Nasdaq'),('^TNX','10Y Treasury'),('GC=F','Gold'),('CL=F','Oil'),('EURUSD=X','EUR/USD'),('DX-Y.NYB','DXY Dollar'),('BTC-USD','Bitcoin')]:
739
- try:
740
- df = yf.Ticker(t).history(period='3mo')
741
- if not df.empty:
742
- macros[name] = {'price': df['Close'].iloc[-1], '1m': (df['Close'].iloc[-1]/df['Close'].iloc[0]-1)*100,
743
- '3m': (df['Close'].iloc[-1]/df['Close'].iloc[max(0,len(df)-63)]-1)*100 if len(df)>63 else 0}
744
- except: pass
745
 
746
  if not macros:
747
- return "Could not fetch macro data."
748
 
749
  fig = go.Figure()
750
  names = list(macros.keys())
@@ -1113,7 +1139,7 @@ def build_app():
1113
  ### 6. RISK ENGINE
1114
  | Feature | Jane Street Practice |
1115
  |---------|---------------------|
1116
- | Parametric + Historical VaR | Dual methodology for compliance |
1117
  | Stress testing | 2008, COVID-2020, 2022 rate hike scenarios |
1118
  | Correlation breakdown | Crisis: correlations -> 1 |
1119
  | Student-t tails | Fat-tail distribution modeling |
@@ -1121,17 +1147,17 @@ def build_app():
1121
  ### 7. SENTIMENT ANALYZER
1122
  | Feature | Jane Street Practice |
1123
  |---------|---------------------|
1124
- | Multi-source NLP | Bloomberg, SEC filings, Twitter, Reddit |
1125
- | NER | Company/executive/product mention extraction |
1126
- | Temporal momentum | Improving vs deteriorating sentiment |
1127
  | Alpha factor | Sentiment surprise IC = 0.3-0.5 |
1128
 
1129
  ### 8. MACRO DASHBOARD
1130
  | Feature | Jane Street Practice |
1131
  |---------|---------------------|
1132
  | Growth/Inflation quadrant | Bridgewater All Weather framework |
1133
- | Dollar regime | DXY >100 = risk-off, EM stress |
1134
- | Yield curve | 10Y-2Y inversion = recession (9/10) |
1135
  | Cross-asset momentum | Asness value/momentum factors |
1136
 
1137
  ### Stack
 
7
  Bloomberg Terminal aesthetic: black + orange + green + cyan.
8
  Powered by K2 Think V2 (MBZUAI) for AI analysis.
9
  """
10
+ import os, json, warnings, math, random, time, hashlib, threading
11
  from datetime import datetime, timedelta
12
  warnings.filterwarnings('ignore')
13
 
 
56
  return f"🔴 Error: {str(e)[:300]}"
57
 
58
  # =============================================================================
59
+ # MARKET DATA (with caching + retry to handle HF Spaces shared-IP rate limits)
60
  # =============================================================================
61
  MARKETS = {
62
  "US Equities": {"suffix": "", "ex": "AAPL, TSLA, NVDA, SPY, QQQ"},
 
72
  "Indices": {"suffix": "", "ex": "^GSPC, ^DJI, ^IXIC, ^FTSE"},
73
  }
74
 
75
+ # In-memory cache with TTL for yfinance data (mitigates HF Spaces shared-IP rate limits)
76
+ _FETCH_CACHE = {}
77
+ _FETCH_LOCK = threading.Lock()
78
+
79
+ def _cache_key(ticker, period, interval):
80
+ import hashlib
81
+ return hashlib.md5(f"{ticker.upper().strip()}|{period}|{interval}".encode()).hexdigest()
82
+
83
  def fetch(ticker, period="1y", interval="1d"):
84
+ key = _cache_key(ticker, period, interval)
85
+ with _FETCH_LOCK:
86
+ if key in _FETCH_CACHE:
87
+ entry = _FETCH_CACHE[key]
88
+ if time.time() - entry['ts'] < 60:
89
+ return entry['data'], entry['info']
90
+
91
+ t = ticker.upper().strip()
92
+ last_err = ""
93
+ for attempt in range(3):
94
+ try:
95
+ time.sleep(attempt * 1.5)
96
+ stock = yf.Ticker(t)
97
+ df = stock.history(period=period, interval=interval, auto_adjust=False)
98
+ if df.empty:
99
+ return None, f"No data for '{ticker}'."
100
+ info = stock.info if hasattr(stock, 'info') else {}
101
+ with _FETCH_LOCK:
102
+ _FETCH_CACHE[key] = {'ts': time.time(), 'data': df.copy(), 'info': info}
103
+ return df, info
104
+ except Exception as e:
105
+ last_err = str(e)
106
+ if 'Too Many Requests' in last_err or 'Rate limited' in last_err:
107
+ continue
108
+ break
109
+ return None, f"Error fetching '{ticker}': {last_err[:200]}. Yahoo Finance rate-limits shared IPs (HF Spaces). Try again in 30s."
110
 
111
  # =============================================================================
112
  # TECHNICAL INDICATORS
 
564
  if not coin: continue
565
  sym = f"{coin}-USD"
566
  try:
567
+ time.sleep(0.5)
568
+ df = yf.Ticker(sym).history(period="1d", interval="1m", auto_adjust=False)
569
  if not df.empty:
570
  results.append({
571
  'Coin': coin,
 
576
  'Volume': f"{df['Volume'].sum():,.0f}",
577
  'Spread %': f"{((df['High'].iloc[-1]/df['Low'].iloc[-1]-1)*100):.3f}%"
578
  })
579
+ except Exception as e:
580
+ if 'Rate' not in str(e) and 'Too Many' not in str(e):
581
+ pass # ignore other errors
582
 
583
  if not results:
584
+ return None, "Could not fetch crypto data. Yahoo Finance may be rate-limiting. Try BTC, ETH, SOL, or wait 30s."
585
 
586
  df = pd.DataFrame(results)
587
  # Arbitrage heatmap (simulated cross-exchange spreads)
 
764
  def macro_analysis():
765
  macros = {}
766
  for t, name in [('^GSPC','S&P 500'),('^IXIC','Nasdaq'),('^TNX','10Y Treasury'),('GC=F','Gold'),('CL=F','Oil'),('EURUSD=X','EUR/USD'),('DX-Y.NYB','DXY Dollar'),('BTC-USD','Bitcoin')]:
767
+ df, info, err = fetch(t, "3mo")
768
+ if df is not None and not df.empty:
769
+ macros[name] = {'price': df['Close'].iloc[-1], '1m': (df['Close'].iloc[-1]/df['Close'].iloc[0]-1)*100,
770
+ '3m': (df['Close'].iloc[-1]/df['Close'].iloc[max(0,len(df)-63)]-1)*100 if len(df)>63 else 0}
 
 
771
 
772
  if not macros:
773
+ return None, "Could not fetch macro data."
774
 
775
  fig = go.Figure()
776
  names = list(macros.keys())
 
1139
  ### 6. RISK ENGINE
1140
  | Feature | Jane Street Practice |
1141
  |---------|---------------------|
1142
+ | Parametric + Historical VaR | Dual methodology for regulatory compliance |
1143
  | Stress testing | 2008, COVID-2020, 2022 rate hike scenarios |
1144
  | Correlation breakdown | Crisis: correlations -> 1 |
1145
  | Student-t tails | Fat-tail distribution modeling |
 
1147
  ### 7. SENTIMENT ANALYZER
1148
  | Feature | Jane Street Practice |
1149
  |---------|---------------------|
1150
+ | Multi-source NLP pipeline | Bloomberg headlines, SEC filings, Twitter, Reddit |
1151
+ | Named Entity Recognition | Company/executive/product mention extraction |
1152
+ | Temporal analysis | Improving vs deteriorating sentiment |
1153
  | Alpha factor | Sentiment surprise IC = 0.3-0.5 |
1154
 
1155
  ### 8. MACRO DASHBOARD
1156
  | Feature | Jane Street Practice |
1157
  |---------|---------------------|
1158
  | Growth/Inflation quadrant | Bridgewater All Weather framework |
1159
+ | Dollar regime | DXY > 100 = risk-off, EM stress |
1160
+ | Yield curve | 10Y-2Y inversion = recession (9/10 accuracy) |
1161
  | Cross-asset momentum | Asness value/momentum factors |
1162
 
1163
  ### Stack