Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix load a benchmark that isn't in the list of limited choices + yf.Ticker().info bugs #4079

Merged
merged 16 commits into from
Feb 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@ portfolio
load --example
show
bench QQQ
bench FAKE_BENCH
bench TSLA
alloc assets -t -l 4
alloc sectors -t -l 4
alloc countries -t -l 4
alloc regions -t -l 4
bench SPY
alloc assets -t -l 4
alloc sectors -t -l 4
alloc countries -t -l 4
Expand Down
73 changes: 42 additions & 31 deletions openbb_terminal/portfolio/allocation_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,16 @@ def get_assets_allocation(
pd.DataFrame
DataFrame with the portfolio's asset allocations
"""
benchmark_assets_allocation = pd.DataFrame(benchmark_info["holdings"])
benchmark_assets_allocation.rename(
columns={"symbol": "Symbol", "holdingPercent": "Benchmark"}, inplace=True
)
benchmark_assets_allocation.drop(columns=["holdingName"], inplace=True)
if "holdings" in benchmark_info:
benchmark_assets_allocation = pd.DataFrame(benchmark_info["holdings"])
benchmark_assets_allocation.rename(
columns={"symbol": "Symbol", "holdingPercent": "Benchmark"}, inplace=True
)
benchmark_assets_allocation.drop(columns=["holdingName"], inplace=True)
else:
benchmark_assets_allocation = pd.DataFrame(
columns=["Symbol", "Benchmark", "Sector", "Country"]
)

portfolio_assets_allocation = (
portfolio_trades[portfolio_trades["Type"] != "CASH"]
Expand Down Expand Up @@ -109,34 +114,37 @@ def get_sectors_allocation(
Returns
-------
pd.DataFrame
DataFrame with regional allocations.
DataFrame with benchmark allocations.
pd.DataFrame
DataFrame with country allocations
DataFrame with portfolio allocations
"""

benchmark_sectors_allocation = (
pd.DataFrame.from_dict(
data={
sector_name: allocation
for sector in benchmark_info["sectorWeightings"]
for sector_name, allocation in sector.items()
},
orient="index",
if "sectorWeightings" in benchmark_info:
benchmark_sectors_allocation = (
pd.DataFrame.from_dict(
data={
sector_name: allocation
for sector in benchmark_info["sectorWeightings"]
for sector_name, allocation in sector.items()
},
orient="index",
)
.squeeze()
.sort_values(ascending=False)
)
.squeeze()
.sort_values(ascending=False)
)

# Prettify sector allocations of benchmark to align with Portfolio Excel
prettified = [
sector.replace("_", " ").title()
for sector in benchmark_sectors_allocation.index
]
# Prettify sector allocations of benchmark to align with Portfolio Excel
prettified = [
sector.replace("_", " ").title()
for sector in benchmark_sectors_allocation.index
]

benchmark_sectors_allocation.index = prettified
benchmark_sectors_allocation = pd.DataFrame(benchmark_sectors_allocation)
benchmark_sectors_allocation.reset_index(inplace=True)
benchmark_sectors_allocation.columns = ["Sector", "Benchmark"]
benchmark_sectors_allocation.index = prettified
benchmark_sectors_allocation = pd.DataFrame(benchmark_sectors_allocation)
benchmark_sectors_allocation.reset_index(inplace=True)
benchmark_sectors_allocation.columns = ["Sector", "Benchmark"]
else:
benchmark_sectors_allocation = pd.DataFrame(columns=["Sector", "Benchmark"])

# Define portfolio sector allocation
# Aggregate sector value for stocks and crypto
Expand Down Expand Up @@ -243,9 +251,9 @@ def get_countries_allocation(
Returns
-------
pd.DataFrame
DataFrame with regional allocations.
DataFrame with benchmark allocations.
pd.DataFrame
DataFrame with country allocations
DataFrame with portfolio allocations
"""

benchmark_allocation = get_symbol_allocation(
Expand Down Expand Up @@ -305,7 +313,7 @@ def get_symbol_allocation(
Returns
-------
pd.DataFrame
Dictionary with country allocations
Dictionary with category allocations
"""

if category == "Region":
Expand All @@ -332,7 +340,10 @@ def get_symbol_allocation(
# Collect data from Fidelity about the portfolio composition of the benchmark
URL = f"https://screener.fidelity.com/ftgw/etf/goto/snapshot/portfolioComposition.jhtml?symbols={symbol}"
html = request(URL).content
df_list = pd.read_html(html)
try:
df_list = pd.read_html(html)
except ValueError:
return pd.DataFrame(columns=[category, col_name])

# Find the ones that contain regions and countries
for index, item in enumerate(df_list):
Expand Down
7 changes: 6 additions & 1 deletion openbb_terminal/portfolio/attribution_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import yfinance as yf

from openbb_terminal.decorators import log_start_end
from openbb_terminal.rich_config import console

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -68,7 +69,11 @@ def get_spy_sector_contributions(

# Load in info
sp500_tickers_data = get_daily_sector_prices(start_date, end_date)
weight_data = yf.Ticker(sectors_ticker).info["sectorWeightings"]
try:
weight_data = yf.Ticker(sectors_ticker).info["sectorWeightings"]
except Exception as _: # noqa
console.print("[red]Could not get info for S&P 500.")
return pd.DataFrame()

# reformat Data
weights: Dict[str, dict] = {"SPY": {}}
Expand Down
Loading