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

217 lines
5.5 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"id": "0b8df441",
"metadata": {},
"source": [
"<div style=\"background-color:#000;\"><img src=\"pqn.png\"></img></div>"
]
},
{
"cell_type": "markdown",
"id": "f07fab33",
"metadata": {},
"source": [
"This code downloads historical stock data for SPY from Yahoo Finance, calculates daily returns, and analyzes drawdowns. It defines functions to compute drawdowns and maximum drawdowns, which are essential for risk management. The drawdown function calculates the percentage decline from a peak in the cumulative return series. The max_drawdown function identifies the largest drawdown over the period. These metrics are visualized to evaluate the stock's risk."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ef1f1af7",
"metadata": {},
"outputs": [],
"source": [
"import yfinance as yf\n",
"import numpy as np"
]
},
{
"cell_type": "markdown",
"id": "e5a113e5",
"metadata": {},
"source": [
"Download historical stock data for SPY from Yahoo Finance"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a63d13bb",
"metadata": {},
"outputs": [],
"source": [
"data = yf.download(\"SPY\", start=\"2020-01-01\", end=\"2022-07-31\")"
]
},
{
"cell_type": "markdown",
"id": "8adb54ef",
"metadata": {},
"source": [
"Calculate daily returns from the adjusted closing prices"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "649d8b88",
"metadata": {
"lines_to_next_cell": 1
},
"outputs": [],
"source": [
"returns = data[\"Adj Close\"].pct_change()"
]
},
{
"cell_type": "markdown",
"id": "4adb0254",
"metadata": {},
"source": [
"Define a function to determine the drawdown from daily returns"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0d2c6022",
"metadata": {
"lines_to_next_cell": 1
},
"outputs": [],
"source": [
"def drawdown(returns):\n",
" \"\"\"Determines the drawdown\n",
" \n",
" Parameters\n",
" ----------\n",
" returns : pd.Series\n",
" Daily returns of an asset, noncumulative\n",
" \n",
" Returns\n",
" -------\n",
" drawdown : pd.Series\n",
" \n",
" Notes\n",
" -----\n",
" This function calculates the percentage decline \n",
" from the peak value of cumulative returns.\n",
" \"\"\"\n",
"\n",
" # Replace the first NaN value with 0.0 for accurate calculations\n",
"\n",
" returns.fillna(0.0, inplace=True)\n",
"\n",
" # Create a series of cumulative returns over time\n",
"\n",
" cumulative = (returns + 1).cumprod()\n",
"\n",
" # Calculate the running maximum value of cumulative returns\n",
"\n",
" running_max = np.maximum.accumulate(cumulative)\n",
"\n",
" # Compute the drawdown as the percentage decline from the running maximum\n",
"\n",
" return (cumulative - running_max) / running_max"
]
},
{
"cell_type": "markdown",
"id": "1261aa32",
"metadata": {},
"source": [
"Plot the drawdown over time as an area chart"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "72cffa58",
"metadata": {
"lines_to_next_cell": 1
},
"outputs": [],
"source": [
"drawdown(returns).plot(kind=\"area\", color=\"salmon\", alpha=0.5)"
]
},
{
"cell_type": "markdown",
"id": "a4aa9724",
"metadata": {},
"source": [
"Define a function to determine the maximum drawdown from daily returns"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "136eda22",
"metadata": {
"lines_to_next_cell": 1
},
"outputs": [],
"source": [
"def max_drawdown(returns):\n",
" \"\"\"Determines the maximum drawdown\n",
" \n",
" Parameters\n",
" ----------\n",
" returns : pd.Series\n",
" Daily returns of an asset, noncumulative\n",
" \n",
" Returns\n",
" -------\n",
" max_drawdown : float\n",
" \n",
" Notes\n",
" -----\n",
" This function identifies the largest \n",
" drawdown over the specified period.\n",
" \"\"\"\n",
"\n",
" # Calculate the drawdown and return the minimum value as the max drawdown\n",
"\n",
" return np.min(drawdown(returns))"
]
},
{
"cell_type": "markdown",
"id": "8e5f427b",
"metadata": {},
"source": [
"Calculate the rolling maximum drawdown over a 30-day window and plot it"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "9a79e6e8",
"metadata": {},
"outputs": [],
"source": [
"returns.rolling(30).apply(max_drawdown).plot(kind=\"area\", color=\"salmon\", alpha=0.5)"
]
},
{
"cell_type": "markdown",
"id": "c46cc0e5",
"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
}