Dmitry Beresnev commited on
Commit
8e87652
·
1 Parent(s): 3610f46

fix portfolio calculator

Browse files
Files changed (1) hide show
  1. portfolio_calculator.py +51 -20
portfolio_calculator.py CHANGED
@@ -15,6 +15,7 @@ import numpy as np
15
  import pandas as pd
16
  import yfinance as yf
17
  import streamlit as st
 
18
 
19
 
20
  # Constants
@@ -74,32 +75,62 @@ def fetch_historical_data(
74
  # Log the error but continue to fallback strategy
75
  print(f"Batch download failed: {str(e)}, trying individual downloads...")
76
 
77
- # Strategy 2: Download one ticker at a time
78
- st.info("Fetching data individually for each ticker...")
79
  individual_prices = {}
80
  failed_tickers = []
81
 
82
- for ticker in ticker_list:
83
- try:
84
- # Use Ticker object for more reliable downloads
85
- ticker_obj = yf.Ticker(ticker)
86
- hist = ticker_obj.history(period=period)
87
-
88
- if hist.empty:
89
- failed_tickers.append(ticker)
90
- continue
91
-
92
- # Extract close prices
93
- individual_prices[ticker] = hist['Close']
94
-
95
- except Exception as e:
96
- failed_tickers.append(ticker)
97
- print(f"Failed to fetch {ticker}: {str(e)}")
98
- continue
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
 
100
  # Check if we got any data
101
  if not individual_prices:
102
- return None, f"Could not fetch data for any tickers. Failed: {', '.join(failed_tickers)}"
103
 
104
  # Combine all individual price series
105
  prices_df = pd.DataFrame(individual_prices)
 
15
  import pandas as pd
16
  import yfinance as yf
17
  import streamlit as st
18
+ import time
19
 
20
 
21
  # Constants
 
75
  # Log the error but continue to fallback strategy
76
  print(f"Batch download failed: {str(e)}, trying individual downloads...")
77
 
78
+ # Strategy 2: Download one ticker at a time with retries
79
+ st.info("Fetching data individually for each ticker (this may take a moment)...")
80
  individual_prices = {}
81
  failed_tickers = []
82
 
83
+ for idx, ticker in enumerate(ticker_list):
84
+ max_retries = 3
85
+ retry_delay = 2 # seconds
86
+
87
+ for attempt in range(max_retries):
88
+ try:
89
+ # Add delay between requests to avoid rate limiting (except first ticker)
90
+ if idx > 0 or attempt > 0:
91
+ time.sleep(retry_delay)
92
+
93
+ # Use Ticker object for more reliable downloads
94
+ ticker_obj = yf.Ticker(ticker)
95
+
96
+ # Try different methods
97
+ if attempt == 0:
98
+ # Method 1: history with period
99
+ hist = ticker_obj.history(period=period)
100
+ elif attempt == 1:
101
+ # Method 2: Try shorter period
102
+ hist = ticker_obj.history(period="6mo")
103
+ else:
104
+ # Method 3: Try start/end dates
105
+ import datetime
106
+ end_date = datetime.datetime.now()
107
+ start_date = end_date - datetime.timedelta(days=365)
108
+ hist = ticker_obj.history(start=start_date, end=end_date)
109
+
110
+ if not hist.empty:
111
+ # Extract close prices
112
+ individual_prices[ticker] = hist['Close']
113
+ st.success(f"✅ {ticker}: {len(hist)} days of data")
114
+ break # Success, exit retry loop
115
+ else:
116
+ if attempt < max_retries - 1:
117
+ st.warning(f"⚠️ {ticker}: No data, retrying... (attempt {attempt + 1}/{max_retries})")
118
+ else:
119
+ st.error(f"❌ {ticker}: No data after {max_retries} attempts")
120
+ failed_tickers.append(ticker)
121
+
122
+ except Exception as e:
123
+ if attempt < max_retries - 1:
124
+ st.warning(f"⚠️ {ticker}: Error, retrying... (attempt {attempt + 1}/{max_retries})")
125
+ retry_delay *= 2 # Exponential backoff
126
+ else:
127
+ failed_tickers.append(ticker)
128
+ st.error(f"❌ {ticker}: Failed after {max_retries} attempts")
129
+ print(f"Failed to fetch {ticker}: {str(e)}")
130
 
131
  # Check if we got any data
132
  if not individual_prices:
133
+ return None, f"Could not fetch data for any tickers. Failed: {', '.join(failed_tickers)}\n\nTip: Try using the JSON editor to enter a smaller portfolio first, or try again in a few minutes."
134
 
135
  # Combine all individual price series
136
  prices_df = pd.DataFrame(individual_prices)