mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-11-04 00:12:29 +00:00
Add sheetnames and improve mret
This commit is contained in:
@@ -1004,6 +1004,23 @@ class PortfolioController(BaseController):
|
||||
help="Period to select start end of the year returns",
|
||||
metavar="PERIOD",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-i",
|
||||
"--instrument",
|
||||
type=str,
|
||||
dest="instrument",
|
||||
default="both",
|
||||
choices=["both", "portfolio", "benchmark"],
|
||||
help="Whether to show portfolio or benchmark monthly returns. By default both are shown in one table.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-g",
|
||||
"--graph",
|
||||
action="store_true",
|
||||
default=False,
|
||||
dest="graph",
|
||||
help="Plot the monthly returns on a heatmap",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-s",
|
||||
"--show",
|
||||
@@ -1018,7 +1035,7 @@ class PortfolioController(BaseController):
|
||||
parser,
|
||||
other_args,
|
||||
raw=True,
|
||||
export_allowed=EXPORT_ONLY_FIGURES_ALLOWED,
|
||||
export_allowed=EXPORT_ONLY_RAW_DATA_ALLOWED,
|
||||
)
|
||||
|
||||
if ns_parser and self.portfolio is not None:
|
||||
@@ -1028,10 +1045,13 @@ class PortfolioController(BaseController):
|
||||
portfolio_view.display_monthly_returns(
|
||||
self.portfolio,
|
||||
ns_parser.period,
|
||||
ns_parser.raw,
|
||||
ns_parser.instrument,
|
||||
ns_parser.graph,
|
||||
ns_parser.show_vals,
|
||||
ns_parser.export,
|
||||
ns_parser.sheet_name,
|
||||
sheet_name=" ".join(ns_parser.sheet_name)
|
||||
if ns_parser.sheet_name
|
||||
else None,
|
||||
)
|
||||
|
||||
@log_start_end(log=logger)
|
||||
@@ -1073,7 +1093,9 @@ class PortfolioController(BaseController):
|
||||
ns_parser.raw,
|
||||
ns_parser.limit,
|
||||
ns_parser.export,
|
||||
ns_parser.sheet_name,
|
||||
sheet_name=" ".join(ns_parser.sheet_name)
|
||||
if ns_parser.sheet_name
|
||||
else None,
|
||||
)
|
||||
|
||||
@log_start_end(log=logger)
|
||||
@@ -1095,9 +1117,6 @@ class PortfolioController(BaseController):
|
||||
portfolio_view.display_maximum_drawdown(
|
||||
self.portfolio,
|
||||
export=ns_parser.export,
|
||||
sheet_name=" ".join(ns_parser.sheet_name)
|
||||
if ns_parser.sheet_name
|
||||
else None,
|
||||
)
|
||||
|
||||
@log_start_end(log=logger)
|
||||
@@ -1331,18 +1350,26 @@ class PortfolioController(BaseController):
|
||||
self.portfolio,
|
||||
ns_parser.risk_free_rate / 100,
|
||||
ns_parser.export,
|
||||
ns_parser.sheet_name,
|
||||
sheet_name=" ".join(ns_parser.sheet_name)
|
||||
if ns_parser.sheet_name
|
||||
else None,
|
||||
)
|
||||
elif ns_parser.metric == "sortino":
|
||||
portfolio_view.display_sortino_ratio(
|
||||
self.portfolio,
|
||||
ns_parser.risk_free_rate / 100,
|
||||
ns_parser.export,
|
||||
ns_parser.sheet_name,
|
||||
sheet_name=" ".join(ns_parser.sheet_name)
|
||||
if ns_parser.sheet_name
|
||||
else None,
|
||||
)
|
||||
elif ns_parser.metric == "maxdrawdown":
|
||||
portfolio_view.display_maximum_drawdown_ratio(
|
||||
self.portfolio, ns_parser.export, ns_parser.sheet_name
|
||||
self.portfolio,
|
||||
ns_parser.export,
|
||||
sheet_name=" ".join(ns_parser.sheet_name)
|
||||
if ns_parser.sheet_name
|
||||
else None,
|
||||
)
|
||||
elif ns_parser.metric == "rsquare":
|
||||
portfolio_view.display_rsquare(
|
||||
@@ -1354,15 +1381,27 @@ class PortfolioController(BaseController):
|
||||
)
|
||||
elif ns_parser.metric == "gaintopain":
|
||||
portfolio_view.display_gaintopain_ratio(
|
||||
self.portfolio, ns_parser.export, ns_parser.sheet_name
|
||||
self.portfolio,
|
||||
ns_parser.export,
|
||||
sheet_name=" ".join(ns_parser.sheet_name)
|
||||
if ns_parser.sheet_name
|
||||
else None,
|
||||
)
|
||||
elif ns_parser.metric == "trackerr":
|
||||
portfolio_view.display_tracking_error(
|
||||
self.portfolio, ns_parser.export, ns_parser.sheet_name
|
||||
self.portfolio,
|
||||
ns_parser.export,
|
||||
sheet_name=" ".join(ns_parser.sheet_name)
|
||||
if ns_parser.sheet_name
|
||||
else None,
|
||||
)
|
||||
elif ns_parser.metric == "information":
|
||||
portfolio_view.display_information_ratio(
|
||||
self.portfolio, ns_parser.export, ns_parser.sheet_name
|
||||
self.portfolio,
|
||||
ns_parser.export,
|
||||
sheet_name=" ".join(ns_parser.sheet_name)
|
||||
if ns_parser.sheet_name
|
||||
else None,
|
||||
)
|
||||
elif ns_parser.metric == "tail":
|
||||
portfolio_view.display_tail_ratio(
|
||||
@@ -1374,30 +1413,52 @@ class PortfolioController(BaseController):
|
||||
)
|
||||
elif ns_parser.metric == "commonsense":
|
||||
portfolio_view.display_common_sense_ratio(
|
||||
self.portfolio, ns_parser.export, ns_parser.sheet_name
|
||||
self.portfolio,
|
||||
ns_parser.export,
|
||||
sheet_name=" ".join(ns_parser.sheet_name)
|
||||
if ns_parser.sheet_name
|
||||
else None,
|
||||
)
|
||||
elif ns_parser.metric == "jensens":
|
||||
portfolio_view.display_jensens_alpha(
|
||||
self.portfolio,
|
||||
ns_parser.risk_free_rate / 100,
|
||||
ns_parser.export,
|
||||
ns_parser.sheet_name,
|
||||
sheet_name=" ".join(ns_parser.sheet_name)
|
||||
if ns_parser.sheet_name
|
||||
else None,
|
||||
)
|
||||
elif ns_parser.metric == "calmar":
|
||||
portfolio_view.display_calmar_ratio(
|
||||
self.portfolio, ns_parser.export, ns_parser.sheet_name
|
||||
self.portfolio,
|
||||
ns_parser.export,
|
||||
sheet_name=" ".join(ns_parser.sheet_name)
|
||||
if ns_parser.sheet_name
|
||||
else None,
|
||||
)
|
||||
elif ns_parser.metric == "kelly":
|
||||
portfolio_view.display_kelly_criterion(
|
||||
self.portfolio, ns_parser.export, ns_parser.sheet_name
|
||||
self.portfolio,
|
||||
ns_parser.export,
|
||||
sheet_name=" ".join(ns_parser.sheet_name)
|
||||
if ns_parser.sheet_name
|
||||
else None,
|
||||
)
|
||||
elif ns_parser.metric == "payoff" and self.portfolio is not None:
|
||||
portfolio_view.display_payoff_ratio(
|
||||
self.portfolio, ns_parser.export, ns_parser.sheet_name
|
||||
self.portfolio,
|
||||
ns_parser.export,
|
||||
sheet_name=" ".join(ns_parser.sheet_name)
|
||||
if ns_parser.sheet_name
|
||||
else None,
|
||||
)
|
||||
elif ns_parser.metric == "profitfactor" and self.portfolio is not None:
|
||||
portfolio_view.display_profit_factor(
|
||||
self.portfolio, ns_parser.export, ns_parser.sheet_name
|
||||
self.portfolio,
|
||||
ns_parser.export,
|
||||
sheet_name=" ".join(ns_parser.sheet_name)
|
||||
if ns_parser.sheet_name
|
||||
else None,
|
||||
)
|
||||
|
||||
@log_start_end(log=logger)
|
||||
@@ -1437,7 +1498,9 @@ class PortfolioController(BaseController):
|
||||
ns_parser.period,
|
||||
ns_parser.raw,
|
||||
ns_parser.export,
|
||||
ns_parser.sheet_name,
|
||||
sheet_name=" ".join(ns_parser.sheet_name)
|
||||
if ns_parser.sheet_name
|
||||
else None,
|
||||
)
|
||||
|
||||
@log_start_end(log=logger)
|
||||
@@ -1484,7 +1547,9 @@ class PortfolioController(BaseController):
|
||||
ns_parser.period,
|
||||
ns_parser.risk_free_rate / 100,
|
||||
ns_parser.export,
|
||||
ns_parser.sheet_name,
|
||||
sheet_name=" ".join(ns_parser.sheet_name)
|
||||
if ns_parser.sheet_name
|
||||
else None,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -371,7 +371,36 @@ def get_monthly_returns(
|
||||
],
|
||||
)
|
||||
|
||||
return monthly_returns, bench_monthly_returns
|
||||
years = [
|
||||
(year, instrument)
|
||||
for year in monthly_returns.index
|
||||
for instrument in ["Portfolio", "Benchmark", "Alpha"]
|
||||
]
|
||||
total_monthly_returns = pd.DataFrame(
|
||||
np.nan,
|
||||
columns=monthly_returns.columns,
|
||||
index=pd.MultiIndex.from_tuples(years, names=["Year", "Instrument"]),
|
||||
)
|
||||
|
||||
for year in monthly_returns.index:
|
||||
for instrument in ["Portfolio", "Benchmark", "Alpha"]:
|
||||
if instrument == "Portfolio":
|
||||
total_monthly_returns.loc[
|
||||
(year, instrument), monthly_returns.columns
|
||||
] = monthly_returns.loc[year].values
|
||||
elif instrument == "Benchmark":
|
||||
total_monthly_returns.loc[
|
||||
(year, instrument), monthly_returns.columns
|
||||
] = bench_monthly_returns.loc[year].values
|
||||
elif instrument == "Alpha":
|
||||
total_monthly_returns.loc[
|
||||
(year, instrument), monthly_returns.columns
|
||||
] = (
|
||||
monthly_returns.loc[year].values
|
||||
- bench_monthly_returns.loc[year].values
|
||||
)
|
||||
|
||||
return monthly_returns, bench_monthly_returns, total_monthly_returns
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
|
||||
@@ -475,7 +475,8 @@ def display_yearly_returns(
|
||||
def display_monthly_returns(
|
||||
portfolio_engine: PortfolioEngine,
|
||||
window: str = "all",
|
||||
raw: bool = False,
|
||||
instrument: str = "both",
|
||||
graph: bool = False,
|
||||
show_vals: bool = False,
|
||||
export: str = "",
|
||||
sheet_name: str = None,
|
||||
@@ -490,27 +491,38 @@ def display_monthly_returns(
|
||||
Use `portfolio.load` to create a PortfolioEngine.
|
||||
window : str
|
||||
interval to compare cumulative returns and benchmark
|
||||
raw : False
|
||||
Display raw data from cumulative return
|
||||
instrument : str
|
||||
Display raw data from cumulative return, default is showing both the portfolio and benchmark in one table
|
||||
show_vals : False
|
||||
Show values on heatmap
|
||||
export : str
|
||||
Export certain type of data
|
||||
sheet_name : str
|
||||
Whether to export to a specific sheet name in an Excel file
|
||||
external_axes: plt.Axes
|
||||
Optional axes to display plot on
|
||||
"""
|
||||
|
||||
portfolio_returns, benchmark_returns = get_monthly_returns(portfolio_engine, window)
|
||||
portfolio_returns, benchmark_returns, total_monthly_returns = get_monthly_returns(
|
||||
portfolio_engine, window
|
||||
)
|
||||
|
||||
if raw:
|
||||
if instrument == "portfolio":
|
||||
print_rich_table(
|
||||
portfolio_returns,
|
||||
title="Monthly returns - portfolio [%]",
|
||||
headers=portfolio_returns.columns,
|
||||
show_index=True,
|
||||
)
|
||||
console.print("\n")
|
||||
|
||||
export_data(
|
||||
export,
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"mret_portfolio",
|
||||
portfolio_returns,
|
||||
sheet_name,
|
||||
)
|
||||
elif instrument == "benchmark":
|
||||
print_rich_table(
|
||||
benchmark_returns,
|
||||
title="Monthly returns - benchmark [%]",
|
||||
@@ -518,7 +530,49 @@ def display_monthly_returns(
|
||||
show_index=True,
|
||||
)
|
||||
|
||||
else:
|
||||
export_data(
|
||||
export,
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"mret_benchmark",
|
||||
benchmark_returns,
|
||||
sheet_name,
|
||||
)
|
||||
elif instrument == "both":
|
||||
# Converts multi-index into readable rich table while keeping the multi-index intact for export
|
||||
total_monthly_returns_rich = total_monthly_returns.copy()
|
||||
total_monthly_returns_rich.insert(
|
||||
0, "Instruments", total_monthly_returns_rich.index.get_level_values(1)
|
||||
)
|
||||
total_monthly_returns_rich.insert(
|
||||
0,
|
||||
"Year",
|
||||
sum(
|
||||
[
|
||||
[year, "", ""]
|
||||
for year in total_monthly_returns_rich.index.get_level_values(
|
||||
0
|
||||
).unique()
|
||||
],
|
||||
[],
|
||||
),
|
||||
)
|
||||
|
||||
print_rich_table(
|
||||
total_monthly_returns_rich,
|
||||
title="Total Monthly returns [%]",
|
||||
headers=total_monthly_returns_rich.columns,
|
||||
show_index=False,
|
||||
)
|
||||
|
||||
export_data(
|
||||
export,
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"mret_total",
|
||||
total_monthly_returns,
|
||||
sheet_name,
|
||||
)
|
||||
|
||||
if graph or show_vals:
|
||||
if external_axes is None:
|
||||
_, ax = plt.subplots(
|
||||
2,
|
||||
@@ -564,14 +618,6 @@ def display_monthly_returns(
|
||||
if external_axes is None:
|
||||
theme.visualize_output()
|
||||
|
||||
export_data(
|
||||
export,
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
"mret",
|
||||
portfolio_returns,
|
||||
sheet_name,
|
||||
)
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def display_daily_returns(
|
||||
|
||||
Reference in New Issue
Block a user