summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormontezdesousa <79287829+montezdesousa@users.noreply.github.com>2022-11-25 23:10:48 +0000
committerGitHub <noreply@github.com>2022-11-25 18:10:48 -0500
commit7480c5efe01dd800fe466e648786a9c16efb90e5 (patch)
treec60258dcac8632200769c1440d1e946795202078
parent79046608b603bf07d6666151ffbb00413a21787c (diff)
Fix portfolio optimization SDK bugs (#3582)
* Small improvement to text handling * fix plot and engine * change msg * fix po engine * fix rc * fix error * opt pytest * bug fix Co-authored-by: colin99d <colin99delahunty@gmail.com> Co-authored-by: minhhoang1023 <40023817+minhhoang1023@users.noreply.github.com> Co-authored-by: James Maslek <jmaslek11@gmail.com>
-rw-r--r--openbb_terminal/portfolio/portfolio_optimization/po_engine.py88
-rw-r--r--openbb_terminal/portfolio/portfolio_optimization/po_model.py679
-rw-r--r--openbb_terminal/portfolio/portfolio_optimization/po_view.py99
-rw-r--r--tests/conftest.py5
-rw-r--r--tests/openbb_terminal/portfolio/portfolio_optimization/conftest.py7
5 files changed, 560 insertions, 318 deletions
diff --git a/openbb_terminal/portfolio/portfolio_optimization/po_engine.py b/openbb_terminal/portfolio/portfolio_optimization/po_engine.py
index 8a201bbe138..d46854f4c4c 100644
--- a/openbb_terminal/portfolio/portfolio_optimization/po_engine.py
+++ b/openbb_terminal/portfolio/portfolio_optimization/po_engine.py
@@ -1,4 +1,4 @@
-from typing import Dict, List
+from typing import Dict, List, Tuple
import pandas as pd
from openbb_terminal.portfolio.portfolio_optimization import (
excel_model,
@@ -14,8 +14,7 @@ class PoEngine:
def __init__(
self,
- symbols: List[str] = None,
- categories: Dict[str, Dict[str, str]] = None,
+ symbols_categories: Dict[str, Dict[str, str]] = None,
symbols_file_path: str = None,
parameters_file_path: str = None,
):
@@ -23,9 +22,7 @@ class PoEngine:
Parameters
----------
- symbols : List[str]
- List of symbols
- categories : Dict[str, float], optional
+ symbols_categories : Dict[str, float], optional
Categories, by default None
symbols_file_path : str, optional
Symbols file path, by default None
@@ -33,14 +30,18 @@ class PoEngine:
Parameters file path, by default None
"""
- self._categories: Dict[str, Dict[str, str]] = categories or {}
+ self._categories: Dict[str, Dict[str, str]] = {}
+ self._symbols: List[str] = []
self._weights: Dict[str, float] = {}
self._returns: pd.DataFrame = None
self._params: Dict[str, float] = {}
self._current_model: str
- if symbols is not None:
- self._symbols: List[str] = symbols
+ if symbols_categories is not None:
+ self._symbols, self._categories = PoEngine.__parse_dictionary(
+ symbols_categories
+ )
+
elif symbols_file_path is not None:
self._symbols, self._categories = excel_model.load_allocation(
symbols_file_path
@@ -53,6 +54,65 @@ class PoEngine:
parameters_file_path
)
+ @staticmethod
+ def __parse_dictionary(
+ symbols_categories: Dict[str, Dict[str, str]]
+ ) -> Tuple[List[str], Dict[str, Dict[str, str]]]:
+ """Parse the categories dictionary
+
+ Parameters
+ ----------
+ symbols_categories : Dict[str, Dict[str, str]]
+ Categories
+
+ Returns
+ -------
+ Tuple[List[str], Dict[str, Dict[str, str]]]
+ Symbols and categories
+ """
+ if isinstance(symbols_categories, dict):
+ symbols = PoEngine.__get_symbols_from_categories(symbols_categories)
+ else:
+ raise TypeError("'symbols_categories' must be a dictionary.")
+
+ for symbol in symbols:
+ symbols_categories["CURRENCY"].setdefault(symbol, "USD")
+ symbols_categories["CURRENT_INVESTED_AMOUNT"].setdefault(symbol, "0")
+
+ return symbols, symbols_categories
+
+ @staticmethod
+ def __get_symbols_from_categories(
+ symbols_categories: Dict[str, Dict[str, str]]
+ ) -> List[str]:
+ """Get the symbols from the categories dictionary
+
+ Parameters
+ ----------
+ symbols_categories : Dict[str, Dict[str, str]], optional
+ Categories
+
+ Returns
+ -------
+ List[str]
+ List of symbols
+ """
+
+ try:
+ symbols = []
+ for item in symbols_categories.items():
+ _, values = item
+ for v in values.keys():
+ symbols.append(v)
+
+ return list(set(symbols))
+
+ except Exception:
+ console.print(
+ "Unsupported dictionary format. See `portfolio.po.load` examples for correct format."
+ )
+ return []
+
def get_symbols(self):
return self._symbols
@@ -66,16 +126,6 @@ class PoEngine:
"""
return list(self._categories.keys())
- def set_categories_dict(self, categories: Dict[str, Dict[str, str]]):
- """Set the categories
-
- Parameters
- ----------
- categories : Dict[str, Dict[str, str]]
- Categories
- """
- self._categories = categories
-
def get_category(self, category: str = None) -> Dict[str, str]:
"""Get the category
diff --git a/openbb_terminal/portfolio/portfolio_optimization/po_model.py b/openbb_terminal/portfolio/portfolio_optimization/po_model.py
index ce1ed827cb5..fbe77182ef6 100644
--- a/openbb_terminal/portfolio/portfolio_optimization/po_model.py
+++ b/openbb_terminal/portfolio/portfolio_optimization/po_model.py
@@ -59,7 +59,7 @@ def validate_parameters_type(parameters):
@log_start_end(log=logger)
def generate_portfolio(
- symbols: List[str] = None,
+ symbols_categories: Dict[str, Dict[str, str]] = None,
symbols_file_path: str = None,
parameters_file_path: str = None,
) -> Union[PoEngine, None]:
@@ -67,8 +67,8 @@ def generate_portfolio(
Parameters
----------
- symbols : List[str], optional
- List of symbols, by default None
+ symbols_categories: Dict[str, Dict[str, str]] = None
+ Categories, by default None
symbols_file_path : str, optional
Symbols file full path, by default None
parameters_file_path : str, optional
@@ -82,25 +82,44 @@ def generate_portfolio(
Examples
--------
>>> from openbb_terminal.sdk import openbb
- >>> p = openbb.portfolio.po.load(symbols_file_path="~/openbb_terminal/miscellaneous/portfolio_examples/allocation/60_40_Portfolio.xlsx")
+ >>> d = {
+ "SECTOR": {
+ "AAPL": "INFORMATION TECHNOLOGY",
+ "MSFT": "INFORMATION TECHNOLOGY",
+ "AMZN": "CONSUMER DISCRETIONARY",
+ },
+ "CURRENT_INVESTED_AMOUNT": {
+ "AAPL": "100000.0",
+ "MSFT": "200000.0",
+ "AMZN": "300000.0",
+ },
+ "CURRENCY": {
+ "AAPL": "USD",
+ "MSFT": "USD",
+ "AMZN": "USD",
+ },
+ }
+ >>> p = openbb.portfolio.po.load(symbols_categories=d)
>>> weights, performance = openbb.portfolio.po.equal(portfolio_engine=p)
>>> from openbb_terminal.sdk import openbb
- >>> p = openbb.portfolio.po.load(symbols=["AAPL", "MSFT", "AMZN"])
+ >>> p = openbb.portfolio.po.load(symbols_file_path="~/openbb_terminal/miscellaneous/portfolio_examples/allocation/60_40_Portfolio.xlsx")
>>> weights, performance = openbb.portfolio.po.equal(portfolio_engine=p)
"""
- if symbols:
+ if symbols_file_path:
return PoEngine(
- symbols=symbols,
+ symbols_file_path=symbols_file_path,
parameters_file_path=parameters_file_path,
)
- if symbols_file_path:
+
+ if symbols_categories:
return PoEngine(
- symbols_file_path=symbols_file_path,
+ symbols_categories=symbols_categories,
parameters_file_path=parameters_file_path,
)
- console.print("No file or symbols provided")
+
+ console.print("No 'symbols_file_path' or 'symbols_categories' provided.")
return None
@@ -163,14 +182,12 @@ def load_parameters_file(
@log_start_end(log=logger)
def validate_inputs(
- symbols=None, portfolio_engine=None, kwargs=None
+ portfolio_engine=None, kwargs=None
) -> Tuple[List[str], PoEngine, dict]:
"""Check valid inputs
Parameters
----------
- symbols : List[str], optional
- List of symbols, by default None
portfolio_engine : PoEngine, optional
Portfolio optimization engine, by default None
Use `portfolio.po.load` to load a portfolio engine
@@ -183,15 +200,12 @@ def validate_inputs(
List of symbols, Portfolio optimization engine, Keyword arguments
"""
- if symbols:
- portfolio_engine = PoEngine(symbols=symbols)
- parameters = kwargs
- elif portfolio_engine:
+ if portfolio_engine:
symbols = portfolio_engine.get_symbols()
parameters = portfolio_engine.get_params().copy()
parameters.update(kwargs)
else:
- console.print("No 'symbols' or 'portfolio_engine' provided.")
+ console.print("No 'portfolio_engine' provided.")
validate_parameters_type(parameters)
@@ -263,7 +277,7 @@ def get_portfolio_performance(weights: Dict, data: pd.DataFrame, **kwargs) -> Di
@log_start_end(log=logger)
def get_maxsharpe(
- portfolio_engine: PoEngine = None, symbols: List[str] = None, **kwargs
+ portfolio_engine: PoEngine = None, **kwargs
) -> Tuple[pd.DataFrame, Dict]:
"""Optimize Sharpe ratio weights
@@ -272,8 +286,6 @@ def get_maxsharpe(
portfolio_engine : PoEngine, optional
Portfolio optimization engine, by default None
Use `portfolio.po.load` to load a portfolio engine
- symbols : List[str], optional
- List of symbols, by default None
interval : str, optional
Interval to get data, by default '3y'
start_date : str, optional
@@ -367,14 +379,25 @@ def get_maxsharpe(
Examples
--------
>>> from openbb_terminal.sdk import openbb
- >>> openbb.portfolio.po.maxsharpe(symbols=["AAPL", "MSFT", "AMZN"])
- ( value
- AAPL 1.0
- MSFT 0.0
- AMZN 0.0,
- {'Return': 0.3448948339574538,
- 'Volatility': 0.36513261935342495,
- 'Sharpe ratio': 0.9445741510802071})
+ >>> d = {
+ "SECTOR": {
+ "AAPL": "INFORMATION TECHNOLOGY",
+ "MSFT": "INFORMATION TECHNOLOGY",
+ "AMZN": "CONSUMER DISCRETIONARY",
+ },
+ "CURRENT_INVESTED_AMOUNT": {
+ "AAPL": "100000.0",
+ "MSFT": "200000.0",
+ "AMZN": "300000.0",
+ },
+ "CURRENCY": {
+ "AAPL": "USD",
+ "MSFT": "USD",
+ "AMZN": "USD",
+ },
+ }
+ >>> p = openbb.portfolio.po.load(symbols_categories=d)
+ >>> weights, performance = openbb.portfolio.po.maxsharpe(portfolio_engine=p)
>>> from openbb_terminal.sdk import openbb
>>> p = openbb.portfolio.po.load(symbols_file_path="~/openbb_terminal/miscellaneous/portfolio_examples/allocation/60_40_Portfolio.xlsx")
@@ -382,7 +405,7 @@ def get_maxsharpe(
"""
valid_symbols, valid_portfolio_engine, valid_kwargs = validate_inputs(
- symbols, portfolio_engine, kwargs
+ portfolio_engine, kwargs
)
if not valid_symbols:
return pd.DataFrame()
@@ -400,7 +423,7 @@ def get_maxsharpe(
@log_start_end(log=logger)
def get_minrisk(
- portfolio_engine: PoEngine = None, symbols: List[str] = None, **kwargs
+ portfolio_engine: PoEngine = None, **kwargs
) -> Tuple[pd.DataFrame, Dict]:
"""Optimize minimum risk weights
@@ -409,8 +432,6 @@ def get_minrisk(
portfolio_engine : PoEngine, optional
Portfolio optimization engine, by default None
Use `portfolio.po.load` to load a portfolio engine
- symbols : List[str], optional
- List of symbols, by default None
interval : str, optional
Interval to get data, by default '3y'
start_date : str, optional
@@ -504,14 +525,25 @@ def get_minrisk(
Examples
--------
>>> from openbb_terminal.sdk import openbb
- >>> openbb.portfolio.po.minrisk(symbols=["AAPL", "MSFT", "AMZN"])
- ( value
- AAPL 0.25044
- MSFT 0.49509
- AMZN 0.25447,
- {'Return': 0.2248615963428331,
- 'Volatility': 0.32736590080425004,
- 'Sharpe ratio': 0.6868815468880802})
+ >>> d = {
+ "SECTOR": {
+ "AAPL": "INFORMATION TECHNOLOGY",
+ "MSFT": "INFORMATION TECHNOLOGY",
+ "AMZN": "CONSUMER DISCRETIONARY",
+ },
+ "CURRENT_INVESTED_AMOUNT": {
+ "AAPL": "100000.0",
+ "MSFT": "200000.0",
+ "AMZN": "300000.0",
+ },
+ "CURRENCY": {
+ "AAPL": "USD",
+ "MSFT": "USD",
+ "AMZN": "USD",
+ },
+ }
+ >>> p = openbb.portfolio.po.load(symbols_categories=d)
+ >>> weights, performance = openbb.portfolio.po.minrisk(portfolio_engine=p)
>>> from openbb_terminal.sdk import openbb
>>> p = openbb.portfolio.po.load(symbols_file_path="~/openbb_terminal/miscellaneous/portfolio_examples/allocation/60_40_Portfolio.xlsx")
@@ -519,7 +551,7 @@ def get_minrisk(
"""
valid_symbols, valid_portfolio_engine, valid_kwargs = validate_inputs(
- symbols, portfolio_engine, kwargs
+ portfolio_engine, kwargs
)
if not valid_symbols:
return pd.DataFrame()
@@ -537,7 +569,7 @@ def get_minrisk(
@log_start_end(log=logger)
def get_maxutil(
- portfolio_engine: PoEngine = None, symbols: List[str] = None, **kwargs
+ portfolio_engine: PoEngine = None, **kwargs
) -> Tuple[pd.DataFrame, Dict]:
"""Optimize maximum utility weights
@@ -546,8 +578,6 @@ def get_maxutil(
portfolio_engine : PoEngine, optional
Portfolio optimization engine, by default None
Use `portfolio.po.load` to load a portfolio engine
- symbols : List[str], optional
- List of symbols, by default None
interval : str, optional
Interval to get data, by default '3y'
start_date : str, optional
@@ -641,14 +671,25 @@ def get_maxutil(
Examples
--------
>>> from openbb_terminal.sdk import openbb
- >>> openbb.portfolio.po.maxutil(symbols=["AAPL", "MSFT", "AMZN"])
- ( value
- AAPL 1.0
- MSFT 0.0
- AMZN 0.0,
- {'Return': 0.3448948339574538,
- 'Volatility': 0.36513261935342495,
- 'Sharpe ratio': 0.9445741510802071})
+ >>> d = {
+ "SECTOR": {
+ "AAPL": "INFORMATION TECHNOLOGY",
+ "MSFT": "INFORMATION TECHNOLOGY",
+ "AMZN": "CONSUMER DISCRETIONARY",
+ },
+ "CURRENT_INVESTED_AMOUNT": {
+ "AAPL": "100000.0",
+ "MSFT": "200000.0",
+ "AMZN": "300000.0",
+ },
+ "CURRENCY": {
+ "AAPL": "USD",
+ "MSFT": "USD",
+ "AMZN": "USD",
+ },
+ }
+ >>> p = openbb.portfolio.po.load(symbols_categories=d)
+ >>> weights, performance = openbb.portfolio.po.maxutil(portfolio_engine=p)
>>> from openbb_terminal.sdk import openbb
>>> p = openbb.portfolio.po.load(symbols_file_path="~/openbb_terminal/miscellaneous/portfolio_examples/allocation/60_40_Portfolio.xlsx")
@@ -656,7 +697,7 @@ def get_maxutil(
"""
valid_symbols, valid_portfolio_engine, valid_kwargs = validate_inputs(
- symbols, portfolio_engine, kwargs
+ portfolio_engine, kwargs
)
if not valid_symbols:
return pd.DataFrame()
@@ -674,7 +715,7 @@ def get_maxutil(
@log_start_end(log=logger)
def get_maxret(
- portfolio_engine: PoEngine = None, symbols: List[str] = None, **kwargs
+ portfolio_engine: PoEngine = None, **kwargs
) -> Tuple[pd.DataFrame, Dict]:
"""Optimize maximum return weights
@@ -683,8 +724,6 @@ def get_maxret(
portfolio_engine : PoEngine, optional
Portfolio optimization engine, by default None
Use `portfolio.po.load` to load a portfolio engine
- symbols : List[str], optional
- List of symbols, by default None
interval : str, optional
Interval to get data, by default '3y'
start_date : str, optional
@@ -778,14 +817,25 @@ def get_maxret(
Examples
--------
>>> from openbb_terminal.sdk import openbb
- >>> openbb.portfolio.po.maxret(symbols=["AAPL", "MSFT", "AMZN"])
- ( value
- AAPL 1.0
- MSFT 0.0
- AMZN 0.0,
- {'Return': 0.3448948339574538,
- 'Volatility': 0.36513261935342495,
- 'Sharpe ratio': 0.9445741510802071})
+ >>> d = {
+ "SECTOR": {
+ "AAPL": "INFORMATION TECHNOLOGY",
+ "MSFT": "INFORMATION TECHNOLOGY",
+ "AMZN": "CONSUMER DISCRETIONARY",
+ },
+ "CURRENT_INVESTED_AMOUNT": {
+ "AAPL": "100000.0",
+ "MSFT": "200000.0",
+ "AMZN": "300000.0",
+ },
+ "CURRENCY": {
+ "AAPL": "USD",
+ "MSFT": "USD",
+ "AMZN": "USD",
+ },
+ }
+ >>> p = openbb.portfolio.po.load(symbols_categories=d)
+ >>> weights, performance = openbb.portfolio.po.maxret(portfolio_engine=p)
>>> from openbb_terminal.sdk import openbb
>>> p = openbb.portfolio.po.load(symbols_file_path="~/openbb_terminal/miscellaneous/portfolio_examples/allocation/60_40_Portfolio.xlsx")
@@ -793,7 +843,7 @@ def get_maxret(
"""
valid_symbols, valid_portfolio_engine, valid_kwargs = validate_inputs(
- symbols, portfolio_engine, kwargs
+ portfolio_engine, kwargs
)
if not valid_symbols:
return pd.DataFrame()
@@ -811,7 +861,7 @@ def get_maxret(
@log_start_end(log=logger)
def get_maxdiv(
- portfolio_engine: PoEngine = None, symbols: List[str] = None, **kwargs
+ portfolio_engine: PoEngine = None, **kwargs
) -> Tuple[pd.DataFrame, Dict]:
"""Optimize diversification weights
@@ -820,8 +870,6 @@ def get_maxdiv(
portfolio_engine : PoEngine, optional
Portfolio optimization engine, by default None
Use `portfolio.po.load` to load a portfolio engine
- symbols : List[str], optional
- List of symbols, by default None
interval : str, optional
Interval to get data, by default '3y'
start_date : str, optional
@@ -892,14 +940,25 @@ def get_maxdiv(
Examples
--------
>>> from openbb_terminal.sdk import openbb
- >>> openbb.portfolio.po.maxdiv(symbols=["AAPL", "MSFT", "AMZN"])
- ( value
- AAPL 0.33696
- MSFT 0.26766
- AMZN 0.39538,
- {'Return': 0.21717206203731806,
- 'Volatility': 0.3310292858117002,
- 'Sharpe ratio': 0.6560509034866852})
+ >>> d = {
+ "SECTOR": {
+ "AAPL": "INFORMATION TECHNOLOGY",
+ "MSFT": "INFORMATION TECHNOLOGY",
+ "AMZN": "CONSUMER DISCRETIONARY",
+ },
+ "CURRENT_INVESTED_AMOUNT": {
+ "AAPL": "100000.0",
+ "MSFT": "200000.0",
+ "AMZN": "300000.0",
+ },
+ "CURRENCY": {
+ "AAPL": "USD",
+ "MSFT": "USD",
+ "AMZN": "USD",
+ },
+ }
+ >>> p = openbb.portfolio.po.load(symbols_categories=d)
+ >>> weights, performance = openbb.portfolio.po.maxdiv(portfolio_engine=p)
>>> from openbb_terminal.sdk import openbb
>>> p = openbb.portfolio.po.load(symbols_file_path="~/openbb_terminal/miscellaneous/portfolio_examples/allocation/60_40_Portfolio.xlsx")
@@ -907,7 +966,7 @@ def get_maxdiv(
"""
valid_symbols, valid_portfolio_engine, valid_kwargs = validate_inputs(
- symbols, portfolio_engine, kwargs
+ portfolio_engine, kwargs
)
if not valid_symbols:
return pd.DataFrame()
@@ -925,7 +984,7 @@ def get_maxdiv(
@log_start_end(log=logger)
def get_maxdecorr(
- portfolio_engine: PoEngine = None, symbols: List[str] = None, **kwargs
+ portfolio_engine: PoEngine = None, **kwargs
) -> Tuple[pd.DataFrame, Dict]:
"""Optimize decorrelation weights
@@ -934,8 +993,6 @@ def get_maxdecorr(
portfolio_engine : PoEngine, optional
Portfolio optimization engine, by default None
Use `portfolio.po.load` to load a portfolio engine
- symbols : List[str], optional
- List of symbols, by default None
interval : str, optional
Interval to get data, by default '3y'
start_date : str, optional
@@ -984,14 +1041,25 @@ def get_maxdecorr(
Examples
--------
>>> from openbb_terminal.sdk import openbb
- >>> openbb.portfolio.po.maxdecorr(symbols=["AAPL", "MSFT", "AMZN"])
- ( value
- AAPL 0.33444
- MSFT 0.24963
- AMZN 0.41593,
- {'Return': 0.2142767096699773,
- 'Volatility': 0.33184082287769623,
- 'Sharpe ratio': 0.6457213666835423})
+ >>> d = {
+ "SECTOR": {
+ "AAPL": "INFORMATION TECHNOLOGY",
+ "MSFT": "INFORMATION TECHNOLOGY",
+ "AMZN": "CONSUMER DISCRETIONARY",
+ },
+ "CURRENT_INVESTED_AMOUNT": {
+ "AAPL": "100000.0",
+ "MSFT": "200000.0",
+ "AMZN": "300000.0",
+ },
+ "CURRENCY": {
+ "AAPL": "USD",
+ "MSFT": "USD",
+ "AMZN": "USD",
+ },
+ }
+ >>> p = openbb.portfolio.po.load(symbols_categories=d)
+ >>> weights, performance = openbb.portfolio.po.maxdecorr(portfolio_engine=p)
>>> from openbb_terminal.sdk import openbb
>>> p = openbb.portfolio.po.load(symbols_file_path="~/openbb_terminal/miscellaneous/portfolio_examples/allocation/60_40_Portfolio.xlsx")
@@ -999,7 +1067,7 @@ def get_maxdecorr(
"""
valid_symbols, valid_portfolio_engine, valid_kwargs = validate_inputs(
- symbols, portfolio_engine, kwargs
+ portfolio_engine, kwargs
)
if not valid_symbols:
return pd.DataFrame()
@@ -1017,7 +1085,7 @@ def get_maxdecorr(
@log_start_end(log=logger)
def get_blacklitterman(
- portfolio_engine: PoEngine = None, symbols: List[str] = None, **kwargs
+ portfolio_engine: PoEngine = None, **kwargs
) -> Tuple[pd.DataFrame, Dict]:
"""Optimize decorrelation weights
@@ -1026,8 +1094,6 @@ def get_blacklitterman(
portfolio_engine : PoEngine, optional
Portfolio optimization engine, by default None
Use `portfolio.po.load` to load a portfolio engine
- symbols : List[str], optional
- List of symbols, by default None
interval : str, optional
Interval to get data, by default '3y'
start_date : str, optional
@@ -1085,14 +1151,25 @@ def get_blacklitterman(
Examples
--------
>>> from openbb_terminal.sdk import openbb
- >>> openbb.portfolio.po.blacklitterman(symbols=["AAPL", "MSFT", "AMZN"])
- ( value
- AAPL 0.48920
- MSFT 0.28391
- AMZN 0.22689,
- {'Return': 0.2563301105112327,
- 'Volatility': 0.33132073874339424,
- 'Sharpe ratio': 0.7736615325784322})
+ >>> d = {
+ "SECTOR": {
+ "AAPL": "INFORMATION TECHNOLOGY",
+ "MSFT": "INFORMATION TECHNOLOGY",
+ "AMZN": "CONSUMER DISCRETIONARY",
+ },
+ "CURRENT_INVESTED_AMOUNT": {
+ "AAPL": "100000.0",
+ "MSFT": "200000.0",
+ "AMZN": "300000.0",
+ },
+ "CURRENCY": {
+ "AAPL": "USD",
+ "MSFT": "USD",
+ "AMZN": "USD",
+ },
+ }
+ >>> p = openbb.portfolio.po.load(symbols_categories=d)
+ >>> weights, performance = openbb.portfolio.po.blacklitterman(portfolio_engine=p)
>>> from openbb_terminal.sdk import openbb
>>> p = openbb.portfolio.po.load(symbols_file_path="~/openbb_terminal/miscellaneous/portfolio_examples/allocation/60_40_Portfolio.xlsx")
@@ -1100,7 +1177,7 @@ def get_blacklitterman(
"""
valid_symbols, valid_portfolio_engine, valid_kwargs = validate_inputs(
- symbols, portfolio_engine, kwargs
+ portfolio_engine, kwargs
)
if not valid_symbols:
return pd.DataFrame()
@@ -1118,7 +1195,7 @@ def get_blacklitterman(
@log_start_end(log=logger)
def get_ef(
- portfolio_engine: PoEngine = None, symbols: List[str] = None, **kwargs
+ portfolio_engine: PoEngine = None, **kwargs
) -> Tuple[
pd.DataFrame,
pd.DataFrame,
@@ -1136,8 +1213,6 @@ def get_ef(
portfolio_engine : PoEngine, optional
Portfolio optimization engine, by default None
Use `portfolio.po.load` to load a portfolio engine
- symbols : List[str], optional
- List of symbols, by default None
interval : str, optional
Interval to get data, by default '3y'
start_date : str, optional
@@ -1202,7 +1277,25 @@ def get_ef(
Examples
--------
>>> from openbb_terminal.sdk import openbb
- >>> frontier = openbb.portfolio.po.ef(symbols=["AAPL", "MSFT", "AMZN"])
+ >>> d = {
+ "SECTOR": {
+ "AAPL": "INFORMATION TECHNOLOGY",
+ "MSFT": "INFORMATION TECHNOLOGY",
+ "AMZN": "CONSUMER DISCRETIONARY",
+ },
+ "CURRENT_INVESTED_AMOUNT": {
+ "AAPL": "100000.0",
+ "MSFT": "200000.0",
+ "AMZN": "300000.0",
+ },
+ "CURRENCY": {
+ "AAPL": "USD",
+ "MSFT": "USD",
+ "AMZN": "USD",
+ },
+ }
+ >>> p = openbb.portfolio.po.load(symbols_categories=d)
+ >>> weights, performance = openbb.portfolio.po.ef(portfolio_engine=p)
>>> from openbb_terminal.sdk import openbb
>>> p = openbb.portfolio.po.load(symbols_file_path="~/openbb_terminal/miscellaneous/portfolio_examples/allocation/60_40_Portfolio.xlsx")
@@ -1210,7 +1303,7 @@ def get_ef(
"""
valid_symbols, valid_portfolio_engine, valid_kwargs = validate_inputs(
- symbols, portfolio_engine, kwargs
+ portfolio_engine, kwargs
)
if not valid_symbols:
return pd.DataFrame()
@@ -1218,7 +1311,7 @@ def get_ef(
frontier, mu, cov, returns, weights, X1, Y1, port = optimizer_model.get_ef(
symbols=valid_symbols, **valid_kwargs
)
- valid_portfolio_engine.set_weights(weights=weights)
+ valid_portfolio_engine.set_weights(weights=weights.to_dict()["weights"])
valid_portfolio_engine.set_returns(returns=returns)
return frontier, mu, cov, returns, weights, X1, Y1, port
@@ -1226,7 +1319,7 @@ def get_ef(
@log_start_end(log=logger)
def get_riskparity(
- portfolio_engine: PoEngine = None, symbols: List[str] = None, **kwargs
+ portfolio_engine: PoEngine = None, **kwargs
) -> Tuple[pd.DataFrame, Dict]:
"""Optimize with Risk Parity using the risk budgeting approach
@@ -1235,8 +1