{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "7711dedc",
   "metadata": {},
   "source": [
    "<div style=\"background-color:#000;\"><img src=\"pqn.png\"></img></div>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6ebec8a8",
   "metadata": {},
   "source": [
    "This code utilizes the VectorBT PRO library to detect historical price patterns and project them into the future. It identifies segments of price history similar to the latest price trend and extrapolates these patterns for statistical analysis. The code retrieves price data, finds similar historical patterns, and generates projections to visualize potential future price movements. Additionally, it creates an animated GIF to demonstrate how these projections evolve over time. This is useful for market analysis, forecasting, and real-time decision-making."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7ebd6203",
   "metadata": {},
   "outputs": [],
   "source": [
    "import vectorbtpro as vbt\n",
    "vbt.settings.set_theme(\"dark\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7385ee7b",
   "metadata": {},
   "source": [
    "Configure the settings to set global defaults for Plotly figures."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5a41fa11",
   "metadata": {},
   "outputs": [],
   "source": [
    "# vbt.settings.plotting.layout[\"width\"] = 900\n",
    "# vbt.settings.plotting.layout[\"height\"] = 450\n",
    "# vbt.settings.plotting.layout[\"images\"] = [dict(\n",
    "#     source=\"https://vectorbt.pro/assets/logo/logo.svg\",\n",
    "#     xref=\"paper\", yref=\"paper\",\n",
    "#     x=0, y=0.95,\n",
    "#     sizex=0.15, sizey=0.15,\n",
    "#     xanchor=\"center\", yanchor=\"bottom\"\n",
    "# )]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f606be4c",
   "metadata": {},
   "source": [
    "Define variables for the analysis including symbol, timeframe, and other parameters."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e29f7952",
   "metadata": {},
   "outputs": [],
   "source": [
    "SYMBOL = \"BTC-USD\"\n",
    "TIMEFRAME = \"1 hour\"\n",
    "START = \"one year ago\"\n",
    "\n",
    "LAST_N_BARS = 66\n",
    "PRED_N_BARS = 12\n",
    "\n",
    "GIF_FNAME = \"projections.gif\"\n",
    "GIF_N_BARS = 72\n",
    "GIF_FPS = 4\n",
    "GIF_PAD = 0.01"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d56a4058",
   "metadata": {},
   "source": [
    "Retrieve price data from Yahoo Finance based on the defined parameters."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f1e009c2",
   "metadata": {
    "lines_to_next_cell": 1
   },
   "outputs": [],
   "source": [
    "data = vbt.YFData.pull(SYMBOL, timeframe=TIMEFRAME, start=START)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8185c650",
   "metadata": {},
   "source": [
    "Analyze the most recent price trend and identify similar historical price segments."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f21739ae",
   "metadata": {},
   "outputs": [],
   "source": [
    "def find_patterns(data):\n",
    "    \"\"\"Identify historical price segments similar to the latest trend.\n",
    "    \n",
    "    This function finds price patterns in historical data that match the most recent price trend.\n",
    "    \n",
    "    Parameters\n",
    "    ----------\n",
    "    data : vbt.YFData\n",
    "        The data containing historical price information.\n",
    "    \n",
    "    Returns\n",
    "    -------\n",
    "    pattern_ranges : vbt.PatternRanges\n",
    "        The identified historical price segments similar to the latest trend.\n",
    "    \"\"\"\n",
    "    price = data.hlc3\n",
    "    pattern = price.values[-LAST_N_BARS:]\n",
    "    pattern_ranges = price.vbt.find_pattern(\n",
    "        pattern=pattern,\n",
    "        rescale_mode=\"rebase\",\n",
    "        overlap_mode=\"allow\",\n",
    "        wrapper_kwargs=dict(freq=TIMEFRAME)\n",
    "    )\n",
    "    pattern_ranges = pattern_ranges.status_closed\n",
    "    return pattern_ranges\n",
    "\n",
    "pattern_ranges = find_patterns(data)\n",
    "print(pattern_ranges.count())\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4d02c58a",
   "metadata": {},
   "source": [
    "Identify and plot projections from the identified price segments."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5486c907",
   "metadata": {},
   "outputs": [],
   "source": [
    "def plot_projections(data, pattern_ranges, **kwargs):\n",
    "    \"\"\"Plot projections of historical price segments.\n",
    "    \n",
    "    This function extracts and plots the price data following each identified segment.\n",
    "    \n",
    "    Parameters\n",
    "    ----------\n",
    "    data : vbt.YFData\n",
    "        The data containing historical price information.\n",
    "    pattern_ranges : vbt.PatternRanges\n",
    "        The identified historical price segments.\n",
    "    \n",
    "    Returns\n",
    "    -------\n",
    "    plot : vbt.Figure\n",
    "        The plot of projections.\n",
    "    \"\"\"\n",
    "    projection_ranges = pattern_ranges.with_delta(\n",
    "        PRED_N_BARS,\n",
    "        open=data.open,\n",
    "        high=data.high,\n",
    "        low=data.low,\n",
    "        close=data.close,\n",
    "    )\n",
    "    projection_ranges = projection_ranges.status_closed\n",
    "    return projection_ranges.plot_projections(\n",
    "        plot_past_period=LAST_N_BARS, \n",
    "        **kwargs,\n",
    "    )\n",
    "\n",
    "plot_projections(data, pattern_ranges, plot_bands=False).show_png()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "440dd86c",
   "metadata": {},
   "source": [
    "Display confidence bands for a visually compelling and statistically robust forecast."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b477c463",
   "metadata": {
    "lines_to_next_cell": 1
   },
   "outputs": [],
   "source": [
    "plot_projections(data, pattern_ranges, plot_bands=True).show_png()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "97e0ee8d",
   "metadata": {},
   "source": [
    "Generate a GIF animation that iterates through a specified range of bars."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "850758bd",
   "metadata": {},
   "outputs": [],
   "source": [
    "def plot_frame(frame_index, **kwargs):\n",
    "    \"\"\"Plot a single frame for the GIF animation.\n",
    "    \n",
    "    This function applies the pattern recognition procedure to each bar within the specified range.\n",
    "    \n",
    "    Parameters\n",
    "    ----------\n",
    "    frame_index : pd.Index\n",
    "        Index of the data frame.\n",
    "    \n",
    "    Returns\n",
    "    -------\n",
    "    plot : vbt.Figure or None\n",
    "        The plot of projections or None if conditions are not met.\n",
    "    \"\"\"\n",
    "    sub_data = data.loc[:frame_index[-1]]\n",
    "    pattern_ranges = find_patterns(sub_data)\n",
    "    if pattern_ranges.count() < 3:\n",
    "        return None\n",
    "    return plot_projections(sub_data, pattern_ranges, **kwargs)\n",
    "\n",
    "vbt.save_animation(\n",
    "    GIF_FNAME,\n",
    "    data.index[-GIF_N_BARS:],\n",
    "    plot_frame,\n",
    "    plot_projections=False,\n",
    "    delta=1,\n",
    "    fps=GIF_FPS,\n",
    "    writer_kwargs=dict(loop=0),\n",
    "    yaxis_range=[\n",
    "        data.low.iloc[-GIF_N_BARS:].min() * (1 - GIF_PAD), \n",
    "        data.high.iloc[-GIF_N_BARS:].max() * (1 + GIF_PAD)\n",
    "    ],\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e4c94a20",
   "metadata": {},
   "source": [
    "Display the generated GIF animation to visualize the projections over time."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "33d0cac8",
   "metadata": {},
   "source": [
    "![projections.gif](projections.gif)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dec39a10",
   "metadata": {},
   "source": [
    "Confidence bands describe past performance but are not guarantees of future results."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "014acdeb",
   "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
}
