202 lines
5.1 KiB
Plaintext
202 lines
5.1 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "8addf00f",
|
|
"metadata": {},
|
|
"source": [
|
|
"<div style=\"background-color:#000;\"><img src=\"pqn.png\"></img></div>"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "e5202c9f",
|
|
"metadata": {},
|
|
"source": [
|
|
"This code calculates the downside deviation of stock returns for Apple Inc. (AAPL).\n",
|
|
"It imports necessary libraries and loads historical adjusted closing prices.\n",
|
|
"The downside deviation is computed to measure risk by focusing on negative returns.\n",
|
|
"This metric is useful for investors aiming to quantify the volatility of negative returns.\n",
|
|
"The downside deviation is annualized for practical financial analysis."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "eba3a353",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import numpy as np"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "cf45199f",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from openbb_terminal.sdk import openbb"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "fee9bac4",
|
|
"metadata": {},
|
|
"source": [
|
|
"Load historical adjusted closing prices for Apple Inc. (AAPL)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "0ccc7c3f",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"data = openbb.stocks.load(\"AAPL\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "98ac41af",
|
|
"metadata": {},
|
|
"source": [
|
|
"Calculate daily percentage change in adjusted closing prices to obtain returns"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "f39cd038",
|
|
"metadata": {
|
|
"lines_to_next_cell": 1
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"returns = data[\"Adj Close\"].pct_change()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "7e8c9c93",
|
|
"metadata": {},
|
|
"source": [
|
|
"Calculate the downside deviation of the returns"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "beb978c6",
|
|
"metadata": {
|
|
"lines_to_next_cell": 1
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"def downside_deviation(returns):\n",
|
|
" \"\"\"Calculate downside deviation of returns\n",
|
|
" \n",
|
|
" Parameters\n",
|
|
" ----------\n",
|
|
" returns : np.ndarray\n",
|
|
" Array of daily percentage returns\n",
|
|
" \n",
|
|
" Returns\n",
|
|
" -------\n",
|
|
" downside_deviation : float\n",
|
|
" Annualized downside deviation of returns\n",
|
|
" \n",
|
|
" Notes\n",
|
|
" -----\n",
|
|
" This function calculates the downside deviation, \n",
|
|
" which measures the volatility of negative returns. \n",
|
|
" It annualizes the deviation for practical financial analysis.\n",
|
|
" \"\"\"\n",
|
|
"\n",
|
|
" # Initialize an empty array to store downside deviation values\n",
|
|
"\n",
|
|
" out = np.empty(returns.shape[1:])\n",
|
|
"\n",
|
|
" # Clip returns at zero to focus on negative returns\n",
|
|
"\n",
|
|
" downside_diff = np.clip(returns, np.NINF, 0)\n",
|
|
"\n",
|
|
" # Square the clipped values to calculate the squared deviations\n",
|
|
"\n",
|
|
" np.square(downside_diff, out=downside_diff)\n",
|
|
"\n",
|
|
" # Calculate the mean of squared deviations ignoring NaNs\n",
|
|
"\n",
|
|
" np.nanmean(downside_diff, axis=0, out=out)\n",
|
|
"\n",
|
|
" # Take the square root of the mean squared deviations\n",
|
|
"\n",
|
|
" np.sqrt(out, out=out)\n",
|
|
"\n",
|
|
" # Annualize the downside deviation by multiplying by the square root of 252\n",
|
|
"\n",
|
|
" np.multiply(out, np.sqrt(252), out=out)\n",
|
|
"\n",
|
|
" # Return the annualized downside deviation as a single value\n",
|
|
"\n",
|
|
" return out.item()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "28a2ce36",
|
|
"metadata": {},
|
|
"source": [
|
|
"Calculate and output the downside deviation of the returns"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "470ebf6d",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"downside_deviation(returns)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "f26cc8cd",
|
|
"metadata": {},
|
|
"source": [
|
|
"Calculate the annualized standard deviation of returns for comparison"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "fb6d47b4",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"np.sqrt(np.square(returns).mean()) * np.sqrt(252)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "fa64ff0c",
|
|
"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
|
|
}
|