Files
strategy-lab/to_explore/pyquantnews/56_UpsideCapture.ipynb
David Brazda e3da60c647 daily update
2024-10-21 20:57:56 +02:00

215 lines
5.7 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"id": "7b39d6ef",
"metadata": {},
"source": [
"<div style=\"background-color:#000;\"><img src=\"pqn.png\"></img></div>"
]
},
{
"cell_type": "markdown",
"id": "09b6a2a7",
"metadata": {},
"source": [
"This code fetches historical stock prices for AAPL, WMT, and SPY, calculates daily returns, and constructs a portfolio. It defines functions to compute the annual return and upside capture ratio of the portfolio compared to a benchmark. The upside capture ratio measures the portfolio's performance relative to the benchmark when the benchmark is up. This is useful in practice for portfolio performance analysis and risk management."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7589769e",
"metadata": {},
"outputs": [],
"source": [
"from openbb_terminal.sdk import openbb"
]
},
{
"cell_type": "markdown",
"id": "d7af040b",
"metadata": {},
"source": [
"Fetch historical stock prices for AAPL, WMT, and SPY starting from 2020-01-01"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "01ac1e2a",
"metadata": {},
"outputs": [],
"source": [
"prices = openbb.economy.index(\n",
" [\"AAPL\", \"WMT\", \"SPY\"], \n",
" start_date=\"2020-01-01\"\n",
")"
]
},
{
"cell_type": "markdown",
"id": "6cf5e1ea",
"metadata": {},
"source": [
"Calculate daily returns by taking the percentage change and dropping any NaN values"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "fdd82c4a",
"metadata": {},
"outputs": [],
"source": [
"returns = prices.pct_change().dropna()"
]
},
{
"cell_type": "markdown",
"id": "859f62ce",
"metadata": {},
"source": [
"Construct a portfolio's returns by summing the returns of AAPL and WMT, and selecting SPY and portfolio columns"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1138bf9a",
"metadata": {
"lines_to_next_cell": 1
},
"outputs": [],
"source": [
"data = returns.assign(\n",
" port=returns[[\"AAPL\", \"WMT\"]].sum(axis=1)\n",
")[[\"SPY\", \"port\"]]"
]
},
{
"cell_type": "markdown",
"id": "a8b57c5b",
"metadata": {},
"source": [
"Compute annualized return for a series of returns"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a4341da4",
"metadata": {
"lines_to_next_cell": 1
},
"outputs": [],
"source": [
"def annual_return(returns):\n",
" \"\"\"Compute annualized return.\n",
" \n",
" This function calculates the annualized return of a series of returns.\n",
" \n",
" Parameters\n",
" ----------\n",
" returns : pd.Series\n",
" Series of daily returns.\n",
" \n",
" Returns\n",
" -------\n",
" float\n",
" Annualized return.\n",
" \"\"\"\n",
" \n",
" # Calculate the number of years by dividing total days by 252 (trading days in a year)\n",
" num_years = len(returns) / 252\n",
" \n",
" # Calculate the annualized return using the geometric average\n",
" return (returns + 1).prod() ** (1 / num_years) - 1"
]
},
{
"cell_type": "markdown",
"id": "567d5ef4",
"metadata": {},
"source": [
"Compute upside capture ratio comparing portfolio returns to benchmark returns"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1dea9509",
"metadata": {
"lines_to_next_cell": 1
},
"outputs": [],
"source": [
"def upside_capture(port_returns, bench_returns):\n",
" \"\"\"Compute upside capture ratio.\n",
" \n",
" This function calculates the upside capture ratio of portfolio returns \n",
" compared to benchmark returns.\n",
" \n",
" Parameters\n",
" ----------\n",
" port_returns : pd.Series\n",
" Series of portfolio returns.\n",
" bench_returns : pd.Series\n",
" Series of benchmark returns.\n",
" \n",
" Returns\n",
" -------\n",
" float\n",
" Upside capture ratio.\n",
" \"\"\"\n",
" \n",
" # Filter portfolio and benchmark returns where benchmark returns are positive\n",
" mask = bench_returns > 0\n",
" port_returns = port_returns[mask]\n",
" bench_returns = bench_returns[mask]\n",
" \n",
" # Calculate the upside capture ratio by dividing annualized portfolio return by annualized benchmark return\n",
" return (\n",
" annual_return(port_returns) \n",
" / annual_return(bench_returns)\n",
" )"
]
},
{
"cell_type": "markdown",
"id": "600cd3ac",
"metadata": {},
"source": [
"Calculate the upside capture ratio for the constructed portfolio compared to SPY"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "47239c60",
"metadata": {},
"outputs": [],
"source": [
"upside_capture(data.port, data.SPY)"
]
},
{
"cell_type": "markdown",
"id": "4d6184fc",
"metadata": {},
"source": [
"<a href=\"https://pyquantnews.com/\">PyQuant News</a> is where finance practitioners level up with Python for quant finance, algorithmic trading, and market data analysis. Looking to get started? Check out the fastest growing, top-selling course to <a href=\"https://gettingstartedwithpythonforquantfinance.com/\">get started with Python for quant finance</a>. For educational purposes. Not investment advise. Use at your own risk."
]
}
],
"metadata": {
"jupytext": {
"cell_metadata_filter": "-all",
"main_language": "python",
"notebook_metadata_filter": "-all"
}
},
"nbformat": 4,
"nbformat_minor": 5
}