Tonic commited on
Commit
4e83a78
·
unverified ·
1 Parent(s): cb59e63

fix news sentiment covariate , volume prediction , yfinance fallbacks, adds advanced trading signals

Browse files
Files changed (1) hide show
  1. app.py +109 -22
app.py CHANGED
@@ -385,7 +385,7 @@ ECONOMIC_INDICATORS = {
385
 
386
  def retry_yfinance_request(func, max_retries=3, initial_delay=1):
387
  """
388
- Retry mechanism for yfinance requests with exponential backoff.
389
 
390
  Args:
391
  func: Function to retry
@@ -399,12 +399,36 @@ def retry_yfinance_request(func, max_retries=3, initial_delay=1):
399
  try:
400
  return func()
401
  except Exception as e:
402
- if "401" in str(e) and attempt < max_retries - 1:
403
- # Calculate delay with exponential backoff and jitter
404
- delay = initial_delay * (2 ** attempt) + random.uniform(0, 1)
405
- time.sleep(delay)
406
- continue
407
- raise e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
408
 
409
  def clear_gpu_memory():
410
  """Clear GPU memory cache"""
@@ -1453,6 +1477,12 @@ def make_prediction_enhanced(symbol: str, timeframe: str = "1d", prediction_days
1453
  df, mean_pred, covariate_data
1454
  )
1455
 
 
 
 
 
 
 
1456
  # Predict technical indicators
1457
  print("Predicting technical indicators...")
1458
  technical_predictions = predict_technical_indicators(df, mean_pred, timeframe)
@@ -1549,6 +1579,12 @@ def make_prediction_enhanced(symbol: str, timeframe: str = "1d", prediction_days
1549
  df, final_pred, covariate_data
1550
  )
1551
 
 
 
 
 
 
 
1552
  # Predict technical indicators
1553
  print("Predicting technical indicators for technical strategy...")
1554
  technical_predictions = predict_technical_indicators(df, final_pred, timeframe)
@@ -1804,6 +1840,38 @@ def make_prediction_enhanced(symbol: str, timeframe: str = "1d", prediction_days
1804
  'covariate_data_available': len(covariate_data) > 0
1805
  }
1806
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1807
  return trading_signals, fig
1808
 
1809
  except Exception as e:
@@ -3552,6 +3620,7 @@ def get_enhanced_covariate_data(symbol: str, timeframe: str = "1d", lookback_day
3552
  print(f" No data for {index}")
3553
  except Exception as e:
3554
  print(f" Error fetching {index}: {str(e)}")
 
3555
 
3556
  if market_data:
3557
  covariate_data['market_indices'] = pd.DataFrame(market_data)
@@ -3575,6 +3644,7 @@ def get_enhanced_covariate_data(symbol: str, timeframe: str = "1d", lookback_day
3575
  print(f" No data for {sector}")
3576
  except Exception as e:
3577
  print(f" Error fetching {sector}: {str(e)}")
 
3578
 
3579
  if sector_data:
3580
  covariate_data['sectors'] = pd.DataFrame(sector_data)
@@ -3598,6 +3668,7 @@ def get_enhanced_covariate_data(symbol: str, timeframe: str = "1d", lookback_day
3598
  print(f" No data for {indicator} ({ticker_symbol})")
3599
  except Exception as e:
3600
  print(f" Error fetching {indicator} ({ticker_symbol}): {str(e)}")
 
3601
 
3602
  if economic_data:
3603
  covariate_data['economic_indicators'] = pd.DataFrame(economic_data)
@@ -3605,10 +3676,15 @@ def get_enhanced_covariate_data(symbol: str, timeframe: str = "1d", lookback_day
3605
  else:
3606
  print("No economic indicators data collected")
3607
 
 
 
 
 
3608
  return covariate_data
3609
 
3610
  except Exception as e:
3611
  print(f"Error collecting covariate data: {str(e)}")
 
3612
  return {}
3613
 
3614
  def calculate_market_sentiment(symbol: str, lookback_days: int = 30) -> Dict[str, float]:
@@ -3631,7 +3707,7 @@ def calculate_market_sentiment(symbol: str, lookback_days: int = 30) -> Dict[str
3631
  # Get news sentiment (simplified approach using yfinance news)
3632
  try:
3633
  ticker = yf.Ticker(symbol)
3634
- news = ticker.news
3635
 
3636
  if news:
3637
  for article in news[:10]: # Analyze last 10 news articles
@@ -3644,6 +3720,7 @@ def calculate_market_sentiment(symbol: str, lookback_days: int = 30) -> Dict[str
3644
  sentiment_scores.append(blob.sentiment.polarity)
3645
  except Exception as e:
3646
  print(f"Error fetching news sentiment: {str(e)}")
 
3647
 
3648
  # Calculate average sentiment
3649
  if sentiment_scores:
@@ -3661,7 +3738,13 @@ def calculate_market_sentiment(symbol: str, lookback_days: int = 30) -> Dict[str
3661
 
3662
  except Exception as e:
3663
  print(f"Error calculating sentiment: {str(e)}")
3664
- return {'sentiment_score': 0.0, 'sentiment_confidence': 0.0}
 
 
 
 
 
 
3665
 
3666
  def calculate_advanced_uncertainty(quantiles: np.ndarray, historical_volatility: float,
3667
  market_conditions: Dict = None, confidence_level: float = 0.9) -> Dict[str, np.ndarray]:
@@ -4261,11 +4344,11 @@ def get_market_info_from_yfinance(symbol: str) -> Dict:
4261
  try:
4262
  ticker = yf.Ticker(symbol)
4263
 
4264
- # Get basic info
4265
- info = ticker.info
4266
 
4267
- # Get current market data
4268
- hist = ticker.history(period="1d")
4269
 
4270
  # Get additional market data
4271
  market_data = {}
@@ -4281,25 +4364,28 @@ def get_market_info_from_yfinance(symbol: str) -> Dict:
4281
  'change_percent': ((hist['Close'].iloc[-1] - hist['Open'].iloc[-1]) / hist['Open'].iloc[-1]) * 100
4282
  })
4283
 
4284
- # Get news if available
4285
  try:
4286
- news = ticker.news
4287
  market_data['news_count'] = len(news) if news else 0
4288
- except:
 
4289
  market_data['news_count'] = 0
4290
 
4291
- # Get recommendations if available
4292
  try:
4293
- recommendations = ticker.recommendations
4294
  market_data['recommendations'] = recommendations.tail(5).to_dict('records') if not recommendations.empty else []
4295
- except:
 
4296
  market_data['recommendations'] = []
4297
 
4298
- # Get earnings info if available
4299
  try:
4300
- earnings = ticker.earnings
4301
  market_data['earnings'] = earnings.tail(4).to_dict('records') if not earnings.empty else []
4302
- except:
 
4303
  market_data['earnings'] = []
4304
 
4305
  # Combine all data
@@ -4313,6 +4399,7 @@ def get_market_info_from_yfinance(symbol: str) -> Dict:
4313
  return result
4314
 
4315
  except Exception as e:
 
4316
  return {
4317
  'symbol': symbol,
4318
  'error': str(e),
 
385
 
386
  def retry_yfinance_request(func, max_retries=3, initial_delay=1):
387
  """
388
+ Retry mechanism for yfinance requests with exponential backoff up to 8 seconds.
389
 
390
  Args:
391
  func: Function to retry
 
399
  try:
400
  return func()
401
  except Exception as e:
402
+ error_str = str(e).lower()
403
+
404
+ # Check if this is the last attempt
405
+ if attempt == max_retries - 1:
406
+ print(f"Final attempt failed after {max_retries} retries: {str(e)}")
407
+ raise e
408
+
409
+ # Determine delay based on error type and attempt number
410
+ if "401" in error_str or "unauthorized" in error_str:
411
+ # Authentication errors - longer delay
412
+ delay = min(8.0, initial_delay * (2 ** attempt) + random.uniform(0, 2))
413
+ print(f"Authentication error (attempt {attempt + 1}/{max_retries}), retrying in {delay:.2f}s: {str(e)}")
414
+ elif "429" in error_str or "rate limit" in error_str or "too many requests" in error_str:
415
+ # Rate limiting - longer delay
416
+ delay = min(8.0, initial_delay * (2 ** attempt) + random.uniform(1, 3))
417
+ print(f"Rate limit error (attempt {attempt + 1}/{max_retries}), retrying in {delay:.2f}s: {str(e)}")
418
+ elif "500" in error_str or "502" in error_str or "503" in error_str or "504" in error_str:
419
+ # Server errors - moderate delay
420
+ delay = min(8.0, initial_delay * (2 ** attempt) + random.uniform(0.5, 1.5))
421
+ print(f"Server error (attempt {attempt + 1}/{max_retries}), retrying in {delay:.2f}s: {str(e)}")
422
+ elif "timeout" in error_str or "connection" in error_str:
423
+ # Network errors - shorter delay
424
+ delay = min(8.0, initial_delay * (2 ** attempt) + random.uniform(0, 1))
425
+ print(f"Network error (attempt {attempt + 1}/{max_retries}), retrying in {delay:.2f}s: {str(e)}")
426
+ else:
427
+ # Generic errors - standard exponential backoff
428
+ delay = min(8.0, initial_delay * (2 ** attempt) + random.uniform(0, 1))
429
+ print(f"Generic error (attempt {attempt + 1}/{max_retries}), retrying in {delay:.2f}s: {str(e)}")
430
+
431
+ time.sleep(delay)
432
 
433
  def clear_gpu_memory():
434
  """Clear GPU memory cache"""
 
1477
  df, mean_pred, covariate_data
1478
  )
1479
 
1480
+ # Ensure volume prediction is properly handled
1481
+ if volume_pred is None or len(volume_pred) == 0:
1482
+ print("Warning: Volume prediction failed, using fallback")
1483
+ volume_pred = np.full(len(mean_pred), df['Volume'].iloc[-1])
1484
+ volume_uncertainty = np.full(len(mean_pred), df['Volume'].iloc[-1] * 0.2)
1485
+
1486
  # Predict technical indicators
1487
  print("Predicting technical indicators...")
1488
  technical_predictions = predict_technical_indicators(df, mean_pred, timeframe)
 
1579
  df, final_pred, covariate_data
1580
  )
1581
 
1582
+ # Ensure volume prediction is properly handled
1583
+ if volume_pred is None or len(volume_pred) == 0:
1584
+ print("Warning: Volume prediction failed in technical strategy, using fallback")
1585
+ volume_pred = np.full(len(final_pred), df['Volume'].iloc[-1])
1586
+ volume_uncertainty = np.full(len(final_pred), df['Volume'].iloc[-1] * 0.2)
1587
+
1588
  # Predict technical indicators
1589
  print("Predicting technical indicators for technical strategy...")
1590
  technical_predictions = predict_technical_indicators(df, final_pred, timeframe)
 
1840
  'covariate_data_available': len(covariate_data) > 0
1841
  }
1842
 
1843
+ # Add stress testing results if enabled
1844
+ stress_test_results = {}
1845
+ if use_stress_testing:
1846
+ try:
1847
+ print("Performing stress testing...")
1848
+ stress_test_results = stress_test_scenarios(df, final_pred)
1849
+ trading_signals['stress_test_results'] = stress_test_results
1850
+ except Exception as stress_error:
1851
+ print(f"Stress testing failed: {str(stress_error)}")
1852
+ trading_signals['stress_test_results'] = {"error": str(stress_error)}
1853
+
1854
+ # Add advanced trading signals
1855
+ try:
1856
+ print("Generating advanced trading signals...")
1857
+ advanced_signals = advanced_trading_signals(df, regime_info)
1858
+ trading_signals['advanced_signals'] = advanced_signals
1859
+ except Exception as advanced_error:
1860
+ print(f"Advanced trading signals failed: {str(advanced_error)}")
1861
+ trading_signals['advanced_signals'] = {"error": str(advanced_error)}
1862
+
1863
+ # Add basic trading signals
1864
+ try:
1865
+ basic_signals = calculate_trading_signals(df)
1866
+ trading_signals.update(basic_signals)
1867
+ trading_signals['symbol'] = symbol
1868
+ trading_signals['timeframe'] = timeframe
1869
+ trading_signals['strategy_used'] = strategy
1870
+ trading_signals['ensemble_used'] = use_ensemble
1871
+ except Exception as basic_error:
1872
+ print(f"Basic trading signals failed: {str(basic_error)}")
1873
+ trading_signals['error'] = str(basic_error)
1874
+
1875
  return trading_signals, fig
1876
 
1877
  except Exception as e:
 
3620
  print(f" No data for {index}")
3621
  except Exception as e:
3622
  print(f" Error fetching {index}: {str(e)}")
3623
+ # Continue with other indices even if one fails
3624
 
3625
  if market_data:
3626
  covariate_data['market_indices'] = pd.DataFrame(market_data)
 
3644
  print(f" No data for {sector}")
3645
  except Exception as e:
3646
  print(f" Error fetching {sector}: {str(e)}")
3647
+ # Continue with other sectors even if one fails
3648
 
3649
  if sector_data:
3650
  covariate_data['sectors'] = pd.DataFrame(sector_data)
 
3668
  print(f" No data for {indicator} ({ticker_symbol})")
3669
  except Exception as e:
3670
  print(f" Error fetching {indicator} ({ticker_symbol}): {str(e)}")
3671
+ # Continue with other indicators even if one fails
3672
 
3673
  if economic_data:
3674
  covariate_data['economic_indicators'] = pd.DataFrame(economic_data)
 
3676
  else:
3677
  print("No economic indicators data collected")
3678
 
3679
+ # Return whatever data we were able to collect
3680
+ if not covariate_data:
3681
+ print("Warning: No covariate data collected, returning empty dict")
3682
+
3683
  return covariate_data
3684
 
3685
  except Exception as e:
3686
  print(f"Error collecting covariate data: {str(e)}")
3687
+ # Return empty dict instead of failing completely
3688
  return {}
3689
 
3690
  def calculate_market_sentiment(symbol: str, lookback_days: int = 30) -> Dict[str, float]:
 
3707
  # Get news sentiment (simplified approach using yfinance news)
3708
  try:
3709
  ticker = yf.Ticker(symbol)
3710
+ news = retry_yfinance_request(lambda: ticker.news)
3711
 
3712
  if news:
3713
  for article in news[:10]: # Analyze last 10 news articles
 
3720
  sentiment_scores.append(blob.sentiment.polarity)
3721
  except Exception as e:
3722
  print(f"Error fetching news sentiment: {str(e)}")
3723
+ # Don't fail completely, just log the error
3724
 
3725
  # Calculate average sentiment
3726
  if sentiment_scores:
 
3738
 
3739
  except Exception as e:
3740
  print(f"Error calculating sentiment: {str(e)}")
3741
+ # Return neutral sentiment on error
3742
+ return {
3743
+ 'sentiment_score': 0.0,
3744
+ 'sentiment_confidence': 0.0,
3745
+ 'sentiment_samples': 0,
3746
+ 'error': str(e)
3747
+ }
3748
 
3749
  def calculate_advanced_uncertainty(quantiles: np.ndarray, historical_volatility: float,
3750
  market_conditions: Dict = None, confidence_level: float = 0.9) -> Dict[str, np.ndarray]:
 
4344
  try:
4345
  ticker = yf.Ticker(symbol)
4346
 
4347
+ # Get basic info with retry
4348
+ info = retry_yfinance_request(lambda: ticker.info)
4349
 
4350
+ # Get current market data with retry
4351
+ hist = retry_yfinance_request(lambda: ticker.history(period="1d"))
4352
 
4353
  # Get additional market data
4354
  market_data = {}
 
4364
  'change_percent': ((hist['Close'].iloc[-1] - hist['Open'].iloc[-1]) / hist['Open'].iloc[-1]) * 100
4365
  })
4366
 
4367
+ # Get news if available with retry
4368
  try:
4369
+ news = retry_yfinance_request(lambda: ticker.news)
4370
  market_data['news_count'] = len(news) if news else 0
4371
+ except Exception as e:
4372
+ print(f"Error fetching news for {symbol}: {str(e)}")
4373
  market_data['news_count'] = 0
4374
 
4375
+ # Get recommendations if available with retry
4376
  try:
4377
+ recommendations = retry_yfinance_request(lambda: ticker.recommendations)
4378
  market_data['recommendations'] = recommendations.tail(5).to_dict('records') if not recommendations.empty else []
4379
+ except Exception as e:
4380
+ print(f"Error fetching recommendations for {symbol}: {str(e)}")
4381
  market_data['recommendations'] = []
4382
 
4383
+ # Get earnings info if available with retry
4384
  try:
4385
+ earnings = retry_yfinance_request(lambda: ticker.earnings)
4386
  market_data['earnings'] = earnings.tail(4).to_dict('records') if not earnings.empty else []
4387
+ except Exception as e:
4388
+ print(f"Error fetching earnings for {symbol}: {str(e)}")
4389
  market_data['earnings'] = []
4390
 
4391
  # Combine all data
 
4399
  return result
4400
 
4401
  except Exception as e:
4402
+ print(f"Error fetching market info for {symbol}: {str(e)}")
4403
  return {
4404
  'symbol': symbol,
4405
  'error': str(e),