Files
OpenBB/openbb_terminal/portfolio/portfolio_optimization/excel_model.py
Riskfolio 34bc290dde New portfolio optimization menu (#1642)
* New-Portfolio-Optimization-Menu

* New-Portfolio-Optimization-Menu

* New-Portfolio-Optimization-Menu

* Update _index.md

* New-Portfolio-Optimization-Menu

* New-Portfolio-Optimization-Menu

* configure portfolio optimization parameters ini

* minor improvement

* Revert "New-Portfolio-Optimization-Menu"

This reverts commit b4b7169cfb.

* Add in Excel functionality and improve the capabilities

* Add Excel load function

* Tidying up the functions

* New-Portfolio-Optimization-Menu

* New-Portfolio-Optimization-Menu

* New-Portfolio-Optimization-Menu

* Re-add my code

* Some spacing and details

* Add folder structure for portfolio

* Update terminal file loading

* New-Portfolio-Optimization-Menu

* Make it possible to move from params to po with loaded file

* New-Portfolio-Optimization-Menu

* New-Portfolio-Optimization-Menu

* Making the connection between the parameters file and the functions

* Add in allocation and new params files

* Improve params default settings

* New-Portfolio-Optimization-Menu

* Update Portfolios and Params sheets

* Update sheets

* Update command to load in correct sheet

* Adjust function to only read specific columns

* Update portfolio

* Small correction

* New-Portfolio-Optimization-Menu

* New-Portfolio-Optimization-Menu

* New-Portfolio-Optimization-Menu

* Patched up show error

* Add Equity portfolio

* Make functions more robust

* New-Portfolio-Optimization-Menu

* New-Portfolio-Optimization-Menu

* Add in Params documentation

* Fixing Linting

* Add in Requirements and Poetry Updates

* Update website

* linting

* Update tests

* Minor fix

* remove unneccesary READMEs

* Remove expected variable type

* Improve documentation

* Clean up the code

* Refractoring

* Adjust names to make it OS friendly

Co-authored-by: Jeroen Bouma <jer.bouma@gmail.com>
Co-authored-by: jmaslek <jmaslek11@gmail.com>
Co-authored-by: Colin Delahunty <72827203+colin99d@users.noreply.github.com>
Co-authored-by: DidierRLopes <dro.lopes@campus.fct.unl.pt>
2022-05-03 13:54:01 +02:00

180 lines
5.1 KiB
Python

"""Excel Model"""
__docformat__ = "numpy"
# pylint: disable=abstract-class-instantiated
import logging
import pandas as pd
from openbb_terminal.decorators import log_start_end
from openbb_terminal.rich_config import console
logger = logging.getLogger(__name__)
@log_start_end(log=logger)
def load_configuration(excel_file: str):
"""
Load in the Excel file to determine the configuration that needs to be set.
Parameters
----------
excel_file: str
The location of the Excel file that needs to be loaded.
Returns
-------
configuration: dictionary
Returns a dictionary with the configurations set.
"""
# Read in the Optimization template
df = pd.read_excel(
excel_file,
sheet_name="Optimization",
skiprows=2,
usecols="B:D",
names=["Parameter", "Value", "Description"],
index_col="Parameter",
)
# Remove completely empty NaN rows
cleaned_df = df.dropna(axis="rows", thresh=2)
# Filter out any general columns
filtered_df = cleaned_df[cleaned_df["Description"] != "Description"]
# Convert to Dictionary
configuration = filtered_df.to_dict()
return configuration["Value"], configuration["Description"]
@log_start_end(log=logger)
def load_allocation(excel_file: str):
"""
Load in the Excel file to determine the allocation that needs to be set.
Parameters
----------
excel_file: str
The location of the Excel file that needs to be loaded.
Returns
-------
tickers: list
Returns a list with ticker symbols
categories: dictionary
Returns a dictionary that specifies each category
"""
if str(excel_file).endswith(".xlsx"):
categories = pd.read_excel(excel_file, sheet_name="Allocation", usecols="A:G")
categories = categories.dropna(axis="rows")
elif str(excel_file).endswith(".csv"):
categories = pd.read_excel(excel_file)
categories = categories.dropna(axis="rows")
else:
console.print("Only Excel (.xlsx and .csv) files are accepted.\n")
return [], {}
categories.columns = [
col.upper().strip().replace(" ", "_") for col in categories.columns
]
categories = categories.apply(lambda x: x.astype(str).str.upper())
categories = categories[~categories.index.duplicated(keep="first")]
try:
categories.set_index("TICKER", inplace=True)
categories.sort_index(inplace=True)
except KeyError:
console.print("Allocation table needs a TICKER column\n")
return [], {}
tickers = list(categories.index)
tickers.sort()
categories = categories.to_dict()
return tickers, categories
@log_start_end(log=logger)
def load_bl_views(excel_file: str):
"""
Load a Excel file with views for Black Litterman model.
Parameters
----------
excel_file: str
The location of the Excel file that needs to be loaded.
Returns
-------
p_views: list
Returns a list with p_views matrix
q_views: list
Returns a list with q_views matrix
"""
if str(excel_file).endswith(".xlsx"):
try:
p_views = pd.read_excel(excel_file, sheet_name="p_views", index_col=0)
p_views = p_views.fillna(0)
p_views = p_views.dropna(axis="rows")
except KeyError:
console.print("Excel file needs a p_views sheet\n")
return {}, {}
try:
q_views = pd.read_excel(excel_file, sheet_name="q_views", index_col=0)
q_views = q_views.dropna(axis="rows")
except KeyError:
console.print("Excel file needs a p_views sheet\n")
return {}, {}
else:
console.print("Only Excel (.xlsx) files are accepted.\n")
return {}, {}
p_views = p_views.T.sort_index()
p_views = p_views.T.to_csv(index=False, header=0).replace("\n", ";")
p_views = p_views[:-1]
p_views = [[float(item) for item in row.split(",")] for row in p_views.split(";")]
q_views = q_views.to_csv(index=False, header=0).replace("\n", ",")
q_views = q_views[:-1]
q_views = [float(item) for item in q_views.split(",")]
return p_views, q_views
@log_start_end(log=logger)
def excel_bl_views(file: str, stocks: str, n: int = 3):
"""
Create an Excel file with required format to build n views for Black Litterman cmd.
Parameters
----------
stocks: str
List of stocks used to build the Black Litterman model views.
n: int
The number of views that will be created.
Returns
-------
file: excel
Returns a list with ticker symbols
"""
if len(stocks) < 2:
console.print("Please have at least 2 loaded tickers to create views.\n")
p_views = [[""] * len(stocks) for i in range(n)]
p_views_df = pd.DataFrame(p_views, columns=stocks)
q_views = [[""] for i in range(n)]
q_views_df = pd.DataFrame(q_views, columns=["Returns"])
if file.endswith(".xlsx"):
pass
else:
file += ".xlsx"
with pd.ExcelWriter(file) as writer:
p_views_df.to_excel(writer, sheet_name="p_views")
q_views_df.to_excel(writer, sheet_name="q_views")