handle some error cases

This commit is contained in:
Diogo Sousa
2023-02-05 13:11:47 +00:00
parent 2ccc503ddf
commit db693be042
5 changed files with 83 additions and 47 deletions

View File

@@ -2,6 +2,8 @@ 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

View File

@@ -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"]
@@ -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
@@ -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(
@@ -305,7 +313,7 @@ def get_symbol_allocation(
Returns
-------
pd.DataFrame
Dictionary with country allocations
Dictionary with category allocations
"""
if category == "Region":
@@ -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):

View File

@@ -141,6 +141,7 @@ class PortfolioController(BaseController):
self.portfolio_name: str = ""
self.benchmark_name: str = ""
self.original_benchmark_ticker = ""
self.recalculate_alloc = False
self.risk_free_rate = 0
self.portlist: List[str] = os.listdir(self.DEFAULT_HOLDINGS_PATH)
self.portfolio = None
@@ -447,6 +448,7 @@ class PortfolioController(BaseController):
ns_parser.benchmark, ns_parser.benchmark
)
self.original_benchmark_ticker = ns_parser.benchmark
self.recalculate_alloc = True
@log_start_end(log=logger)
def call_alloc(self, other_args: List[str]):
@@ -488,27 +490,31 @@ class PortfolioController(BaseController):
):
if ns_parser.agg == "assets":
portfolio_view.display_assets_allocation(
self.portfolio,
ns_parser.limit,
ns_parser.tables,
portfolio_engine=self.portfolio,
limit=ns_parser.limit,
tables=ns_parser.tables,
recalculate=self.recalculate_alloc,
)
elif ns_parser.agg == "sectors":
portfolio_view.display_sectors_allocation(
self.portfolio,
ns_parser.limit,
ns_parser.tables,
portfolio_engine=self.portfolio,
limit=ns_parser.limit,
tables=ns_parser.tables,
recalculate=self.recalculate_alloc,
)
elif ns_parser.agg == "countries":
portfolio_view.display_countries_allocation(
self.portfolio,
ns_parser.limit,
ns_parser.tables,
portfolio_engine=self.portfolio,
limit=ns_parser.limit,
tables=ns_parser.tables,
recalculate=self.recalculate_alloc,
)
elif ns_parser.agg == "regions":
portfolio_view.display_regions_allocation(
self.portfolio,
ns_parser.limit,
ns_parser.tables,
portfolio_engine=self.portfolio,
limit=ns_parser.limit,
tables=ns_parser.tables,
recalculate=self.recalculate_alloc,
)
else:
console.print(

View File

@@ -118,7 +118,7 @@ class PortfolioEngine:
self.tickers_list = None
self.tickers: Dict[Any, Any] = {}
self.benchmark_ticker: str = ""
self.benchmark_info = None
self.benchmark_info: Dict[Any, Any] = {}
self.historical_trade_data = pd.DataFrame()
# Portfolio
@@ -560,7 +560,8 @@ class PortfolioEngine:
p_bar.refresh()
try:
self.benchmark_info = yf.Ticker(symbol).info
self.benchmark_info = dict(yf.Ticker(symbol).info)
self.benchmark_info["symbol"] = symbol
except Exception as _: # noqa
console.print(
f"[red]\n\nCould not get info for {symbol}."

View File

@@ -145,6 +145,7 @@ def display_assets_allocation(
portfolio_engine: PortfolioEngine,
limit: int = 10,
tables: bool = False,
recalculate: bool = False,
):
"""Display portfolio asset allocation compared to the benchmark
@@ -152,16 +153,19 @@ def display_assets_allocation(
----------
portfolio_engine: PortfolioEngine
Instance of PortfolioEngine class
tables: bool
Whether to include separate asset allocation tables
limit: int
The amount of assets you wish to show, by default this is set to 10
tables: bool
Whether to include separate asset allocation tables
recalculate: bool
Whether to recalculate the allocation
"""
combined, portfolio_allocation, benchmark_allocation = get_assets_allocation(
portfolio_engine=portfolio_engine,
limit=limit,
tables=True,
recalculate=recalculate,
)
display_category(
@@ -179,6 +183,7 @@ def display_sectors_allocation(
portfolio_engine: PortfolioEngine,
limit: int = 10,
tables: bool = False,
recalculate: bool = False,
):
"""Display portfolio sector allocation compared to the benchmark
@@ -190,12 +195,15 @@ def display_sectors_allocation(
The amount of assets you wish to show, by default this is set to 10
tables: bool
Whether to include separate asset allocation tables
recalculate: bool
Whether to recalculate the allocation
"""
combined, portfolio_allocation, benchmark_allocation = get_sectors_allocation(
portfolio_engine=portfolio_engine,
limit=limit,
tables=True,
recalculate=recalculate,
)
display_category(
@@ -213,6 +221,7 @@ def display_countries_allocation(
portfolio_engine: PortfolioEngine,
limit: int = 10,
tables: bool = False,
recalculate: bool = False,
):
"""Display portfolio country allocation compared to the benchmark
@@ -224,12 +233,15 @@ def display_countries_allocation(
The amount of assets you wish to show, by default this is set to 10
tables: bool
Whether to include separate asset allocation tables
recalculate: bool
Whether to recalculate the allocation
"""
combined, portfolio_allocation, benchmark_allocation = get_countries_allocation(
portfolio_engine=portfolio_engine,
limit=limit,
tables=True,
recalculate=recalculate,
)
display_category(
@@ -247,6 +259,7 @@ def display_regions_allocation(
portfolio_engine: PortfolioEngine,
limit: int = 10,
tables: bool = False,
recalculate: bool = False,
):
"""Display portfolio region allocation compared to the benchmark
@@ -258,12 +271,15 @@ def display_regions_allocation(
The amount of assets you wish to show, by default this is set to 10
tables: bool
Whether to include separate asset allocation tables
recalculate: bool
Whether to recalculate the allocation
"""
combined, portfolio_allocation, benchmark_allocation = get_regions_allocation(
portfolio_engine=portfolio_engine,
limit=limit,
tables=True,
recalculate=recalculate,
)
display_category(