{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "b7d86319",
   "metadata": {},
   "source": [
    "<div style=\"background-color:#000;\"><img src=\"pqn.png\"></img></div>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "59c0ce89",
   "metadata": {},
   "source": [
    "This code acquires stock price data, calculates financial indicators, and analyzes their relationships with future returns. It uses OpenBB SDK to fetch stock data, filters it, and computes the Average True Range (ATR) as a volatility measure. The code then calculates historical returns over multiple time lags and sets up target variables for future returns. Finally, it visualizes the relationship between ATR and future returns and computes their correlation. This workflow is useful for quantitative analysis in financial markets."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ddc92576",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "from openbb_terminal.sdk import openbb\n",
    "from talib import ATR\n",
    "from scipy.stats import spearmanr\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "47f42114",
   "metadata": {},
   "source": [
    "Acquire stock data using OpenBB SDK and filter based on country and price criteria"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "73be12b2",
   "metadata": {},
   "outputs": [],
   "source": [
    "data = openbb.stocks.screener.screener_data(preset_loaded=\"most_volatile\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1407bbe9",
   "metadata": {},
   "outputs": [],
   "source": [
    "universe = data[(data.Country == \"USA\") & (data.Price > 5)]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "36d938a6",
   "metadata": {},
   "source": [
    "Fetch historical price data for each ticker and store in a list of DataFrames"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "eb90090d",
   "metadata": {},
   "outputs": [],
   "source": [
    "stocks = []\n",
    "for ticker in universe.Ticker.tolist():\n",
    "    df = openbb.stocks.load(ticker, start_date=\"2010-01-01\", verbose=False).drop(\"Close\", axis=1)\n",
    "    df[\"ticker\"] = ticker\n",
    "    stocks.append(df)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "97e1c7aa",
   "metadata": {},
   "source": [
    "Concatenate all DataFrames into a single DataFrame and rename columns"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "95b04c04",
   "metadata": {},
   "outputs": [],
   "source": [
    "prices = pd.concat(stocks)\n",
    "prices.columns = [\"open\", \"high\", \"low\", \"close\", \"volume\", \"ticker\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "badcbca5",
   "metadata": {},
   "source": [
    "Filter out stocks with insufficient data and remove duplicate entries"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bcb8ae26",
   "metadata": {},
   "outputs": [],
   "source": [
    "nobs = prices.groupby(\"ticker\").size()\n",
    "mask = nobs[nobs > 2 * 12 * 21].index\n",
    "prices = prices[prices.ticker.isin(mask)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "469ec0d5",
   "metadata": {},
   "outputs": [],
   "source": [
    "prices = prices.set_index(\"ticker\", append=True).reorder_levels([\"ticker\", \"date\"]).drop_duplicates()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e31308f2",
   "metadata": {
    "lines_to_next_cell": 1
   },
   "outputs": [],
   "source": [
    "prices.drop_duplicates()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2db6025a",
   "metadata": {},
   "source": [
    "Calculate Average True Range (ATR) for each stock and standardize it"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "55211855",
   "metadata": {
    "lines_to_next_cell": 1
   },
   "outputs": [],
   "source": [
    "def atr(data):\n",
    "    \"\"\"Calculate and standardize ATR.\n",
    "    \n",
    "    Parameters\n",
    "    ----------\n",
    "    data : DataFrame\n",
    "        Data containing high, low, and close prices.\n",
    "    \n",
    "    Returns\n",
    "    -------\n",
    "    DataFrame\n",
    "        Standardized ATR values.\n",
    "    \"\"\"\n",
    "    df = ATR(data.high, data.low, data.close, timeperiod=14)\n",
    "    return df.sub(df.mean()).div(df.std())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3f03ebd4",
   "metadata": {},
   "outputs": [],
   "source": [
    "prices[\"atr\"] = prices.groupby('ticker', group_keys=False).apply(atr)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "55ed7582",
   "metadata": {},
   "source": [
    "Calculate historical returns over different time lags and add them to the DataFrame"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3d96a26d",
   "metadata": {},
   "outputs": [],
   "source": [
    "lags = [1, 5, 10, 21, 42, 63]\n",
    "for lag in lags:\n",
    "    prices[f\"return_{lag}d\"] = prices.groupby(level=\"ticker\").close.pct_change(lag)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7d161381",
   "metadata": {},
   "source": [
    "Set up target variables for future returns by shifting historical returns"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "112b42a8",
   "metadata": {},
   "outputs": [],
   "source": [
    "for t in [1, 5, 10, 21]:\n",
    "    prices[f\"target_{t}d\"] = prices.groupby(level=\"ticker\")[f\"return_{t}d\"].shift(-t)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e97c0708",
   "metadata": {},
   "source": [
    "Visualize the relationship between ATR and future 1-day returns using Seaborn"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e7740b40",
   "metadata": {},
   "outputs": [],
   "source": [
    "target = \"target_1d\"\n",
    "metric = \"atr\"\n",
    "j = sns.jointplot(x=metric, y=target, data=prices)\n",
    "plt.tight_layout()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3578ee83",
   "metadata": {},
   "source": [
    "Calculate and print the Spearman correlation between ATR and future 1-day returns"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "18751214",
   "metadata": {},
   "outputs": [],
   "source": [
    "df = prices[[metric, target]].dropna()\n",
    "r, p = spearmanr(df[metric], df[target])\n",
    "print(f\"{r:,.2%} ({p:.2%})\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "69e275a0",
   "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
}
