Dmitry Beresnev commited on
Commit ·
8e87652
1
Parent(s): 3610f46
fix portfolio calculator
Browse files- 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 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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)
|