{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "1de13e7d",
   "metadata": {},
   "source": [
    "<div style=\"background-color:#000;\"><img src=\"pqn.png\"></img></div>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "85b06070",
   "metadata": {},
   "source": [
    "## Load historical stock data for a given ticker symbol"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d2188a44-6cc3-4440-a64b-a1464dbd285e",
   "metadata": {},
   "source": [
    "We start by loading historical stock data for NVIDIA (ticker symbol \"NVDA\") from Yahoo Finance. This helps us get the historical prices of the stock to perform further analysis."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "286266d9",
   "metadata": {},
   "outputs": [],
   "source": [
    "import math\n",
    "import pandas as pd\n",
    "import yfinance as yf\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "6858d527",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/jason/anaconda3/envs/newsletter/lib/python3.10/site-packages/yfinance/utils.py:775: FutureWarning: The 'unit' keyword in TimedeltaIndex construction is deprecated and will be removed in a future version. Use pd.to_timedelta instead.\n",
      "  df.index += _pd.TimedeltaIndex(dst_error_hours, 'h')\n",
      "[*********************100%%**********************]  1 of 1 completed\n"
     ]
    }
   ],
   "source": [
    "data = yf.download(\"NVDA\", start=\"2023-01-01\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fa664dcd",
   "metadata": {},
   "source": [
    "This code uses the `yfinance` library to download stock data for NVIDIA starting from January 1, 2023. The data is stored in a pandas DataFrame named `data`. This DataFrame contains various columns such as 'Open', 'High', 'Low', 'Close', 'Volume', and 'Adj Close', which represent different aspects of the stock's daily performance."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ea35ec2d",
   "metadata": {},
   "source": [
    "## Display the first few rows of the data"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "226e6fd1-72f2-4fc5-b56c-8280c3770a5b",
   "metadata": {},
   "source": [
    "Next, we display the first few rows of the data to understand its structure and the kind of information it holds."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "d6b459fa",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Open</th>\n",
       "      <th>High</th>\n",
       "      <th>Low</th>\n",
       "      <th>Close</th>\n",
       "      <th>Adj Close</th>\n",
       "      <th>Volume</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Date</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2023-01-03</th>\n",
       "      <td>14.851</td>\n",
       "      <td>14.996</td>\n",
       "      <td>14.096</td>\n",
       "      <td>14.315</td>\n",
       "      <td>14.305580</td>\n",
       "      <td>401277000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2023-01-04</th>\n",
       "      <td>14.567</td>\n",
       "      <td>14.853</td>\n",
       "      <td>14.241</td>\n",
       "      <td>14.749</td>\n",
       "      <td>14.739294</td>\n",
       "      <td>431324000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2023-01-05</th>\n",
       "      <td>14.491</td>\n",
       "      <td>14.564</td>\n",
       "      <td>14.148</td>\n",
       "      <td>14.265</td>\n",
       "      <td>14.255615</td>\n",
       "      <td>389168000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2023-01-06</th>\n",
       "      <td>14.474</td>\n",
       "      <td>15.010</td>\n",
       "      <td>14.034</td>\n",
       "      <td>14.859</td>\n",
       "      <td>14.849223</td>\n",
       "      <td>405044000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2023-01-09</th>\n",
       "      <td>15.284</td>\n",
       "      <td>16.056</td>\n",
       "      <td>15.141</td>\n",
       "      <td>15.628</td>\n",
       "      <td>15.617717</td>\n",
       "      <td>504231000</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "              Open    High     Low   Close  Adj Close     Volume\n",
       "Date                                                            \n",
       "2023-01-03  14.851  14.996  14.096  14.315  14.305580  401277000\n",
       "2023-01-04  14.567  14.853  14.241  14.749  14.739294  431324000\n",
       "2023-01-05  14.491  14.564  14.148  14.265  14.255615  389168000\n",
       "2023-01-06  14.474  15.010  14.034  14.859  14.849223  405044000\n",
       "2023-01-09  15.284  16.056  15.141  15.628  15.617717  504231000"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ebeb8b38",
   "metadata": {},
   "source": [
    "The `head()` function in pandas displays the first five rows of the DataFrame by default. This allows us to quickly inspect the data and verify that it has been loaded correctly. We can see the dates as the index and the columns representing different metrics such as opening price, closing price, highest price, lowest price, and volume for each trading day."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4d8228e5",
   "metadata": {},
   "source": [
    "## Calculate moving averages and other indicators"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "12f70317-3fa2-4a51-a62b-1d7cbfe0adbb",
   "metadata": {},
   "source": [
    "Now, we calculate the 20-day and 50-day simple moving averages (SMA) of the stock's closing price. We also calculate the historical volatility and the percentile rank of the closing prices."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "ed4d183a",
   "metadata": {},
   "outputs": [],
   "source": [
    "data['SMA20'] = data['Close'].rolling(window=20).mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "48c82c04",
   "metadata": {},
   "outputs": [],
   "source": [
    "data['SMA50'] = data['Close'].rolling(window=50).mean()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "d8537299",
   "metadata": {},
   "outputs": [],
   "source": [
    "data['vol'] = data['Close'].pct_change().rolling(window=21).std() * math.sqrt(252)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "73483402",
   "metadata": {},
   "outputs": [],
   "source": [
    "data['pct_rank'] = data['Close'].rolling(window=21).rank(pct=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6d4891ad",
   "metadata": {},
   "source": [
    "We calculate the 20-day and 50-day simple moving averages by using the `rolling` method with a specified window and then applying the `mean` function. These moving averages help identify trends in the stock price. We compute historical volatility by taking the standard deviation of the closing prices over a 21-day window and then annualizing it using the square root of 252 (number of trading days in a year). Finally, the percentile rank of the closing prices over a 21-day window is calculated using the `rank` method with the `pct` parameter set to True, giving us a value between 0 and 1."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "04f8dcba",
   "metadata": {},
   "source": [
    "## Plot the stock's closing price and moving averages"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "276b8ffe-1a30-4feb-88e3-fed30790dce8",
   "metadata": {},
   "source": [
    "Next, we plot the stock's closing price along with the 20-day and 50-day simple moving averages to visualize trends and patterns."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "1b5a28a6",
   "metadata": {},
   "outputs": [],
   "source": [
    "to_plot = [\"Close\", \"SMA20\", \"SMA50\"]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "8e397701",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Axes: xlabel='Date'>"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 54024 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "data[to_plot].plot()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5e175590",
   "metadata": {},
   "source": [
    "We store the columns to be plotted (closing price, 20-day SMA, and 50-day SMA) in a list named `to_plot`. Using pandas' `plot` method, we create a line plot for these columns. This visual representation helps us see how the stock's price moves relative to its short-term and long-term trends defined by the moving averages."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "534be659",
   "metadata": {},
   "source": [
    "## Plot historical volatility"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "af7dd432-f6e8-4dda-99a4-41d182e62011",
   "metadata": {},
   "source": [
    "We then plot the historical volatility of the stock to understand its risk and price fluctuations over time."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "11f60504",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 61968 characters]",
      "text/plain": [
       "<Figure size 640x480 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "ax = data[\"Close\"].plot()\n",
    "data.vol.plot(secondary_y=True, ax=ax)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "80074b64-9fa2-4e71-af9e-38513cbe9e0b",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9503e943-6fdf-4b0e-b179-4f87e2585543",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "ebaca4e2",
   "metadata": {},
   "source": [
    "This code creates a line plot showing both the closing price and the computed historical volatility. By plotting these together, we can see how the stock's volatility changes over time and how it correlates with the price movements. Higher volatility indicates higher risk and larger price swings, while lower volatility suggests more stable price behavior."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "70f3dd1c",
   "metadata": {},
   "source": [
    "## Plot the percentile rank over time"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7a197fa5-bfa0-43c5-83ba-332318f25801",
   "metadata": {},
   "source": [
    "Finally, we plot the percentile rank of the closing prices to see how the current price compares to its historical range."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "8d9891d7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Axes: xlabel='Date'>"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 72384 characters]",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "data['pct_rank'].plot()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3a935d44",
   "metadata": {},
   "source": [
    "We use the `plot` method to visualize the percentile rank of the closing prices. This plot shows how the current price ranks within a specified window of past prices. A high percentile rank indicates that the current price is relatively high compared to its historical range, while a low percentile rank suggests that it is relatively low. This can help identify overbought or oversold conditions in the stock."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "adf2b678",
   "metadata": {},
   "source": [
    "## Your next steps"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c77c3a6a-baac-41ce-bd61-4973f91c6476",
   "metadata": {},
   "source": [
    "To deepen your understanding, try changing the stock ticker symbol to analyze a different company's data. You can also experiment with different time windows for the moving averages and volatility calculations to see how these changes affect the results."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8ff41b94",
   "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"
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
