{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "e8501022-fcc2-4413-8d96-a808daf447da",
   "metadata": {},
   "source": [
    "# Backtesting with [**vectorbt**](https://github.com/polakowo/vectorbt)\n",
    "* Data Acquisition (**yfinance**)\n",
    "* Statistical and Technical Analysis (**pandas_ta**)\n",
    "* Backtesting Analysis and Results (**vectorbt**)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0f4f31b7-b37c-482c-a65b-d3cb21fd57f0",
   "metadata": {},
   "source": [
    "### Initializations"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "208299e0-da6e-4631-85f8-c10e7a499792",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Package Versions:\n",
      "Numpy v1.20.3\n",
      "Pandas v1.3.0\n",
      "vectorbt v0.23.1\n",
      "\n",
      "Pandas TA v0.3.63b0\n",
      "To install the Latest Version:\n",
      "$ pip install -U git+https://github.com/twopirllc/pandas-ta\n",
      "\n"
     ]
    }
   ],
   "source": [
    "import asyncio\n",
    "import itertools\n",
    "from datetime import datetime\n",
    "\n",
    "from IPython import display\n",
    "\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import pandas_ta as ta\n",
    "import vectorbt as vbt\n",
    "\n",
    "import plotly.graph_objects as go\n",
    "\n",
    "print(\"Package Versions:\")\n",
    "print(f\"Numpy v{np.__version__}\")\n",
    "print(f\"Pandas v{pd.__version__}\")\n",
    "print(f\"vectorbt v{vbt.__version__}\")\n",
    "print(f\"\\nPandas TA v{ta.version}\\nTo install the Latest Version:\\n$ pip install -U git+https://github.com/twopirllc/pandas-ta\\n\")\n",
    "\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e4f0ed8c-a6d4-4843-877c-a200e47fc9d0",
   "metadata": {},
   "source": [
    "# **vectorbt** Theme and Portfolio Settings"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "35f829c2-1890-443f-9608-c1ba0893226c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Portfolio Settings [Initial]\n"
     ]
    },
    {
     "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>Value</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Option</th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>call_seq</th>\n",
       "      <td>default</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>init_cash</th>\n",
       "      <td>100000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>size</th>\n",
       "      <td>inf</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>size_type</th>\n",
       "      <td>amount</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>fees</th>\n",
       "      <td>0.0025</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>fixed_fees</th>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>slippage</th>\n",
       "      <td>0.0025</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>reject_prob</th>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>min_size</th>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>max_size</th>\n",
       "      <td>inf</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>size_granularity</th>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>lock_cash</th>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>allow_partial</th>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>raise_reject</th>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>val_price</th>\n",
       "      <td>inf</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>accumulate</th>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>sl_stop</th>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>sl_trail</th>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>tp_stop</th>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>stop_entry_price</th>\n",
       "      <td>close</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>stop_exit_price</th>\n",
       "      <td>stoplimit</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>stop_conflict_mode</th>\n",
       "      <td>exit</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>upon_stop_exit</th>\n",
       "      <td>close</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>upon_stop_update</th>\n",
       "      <td>override</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>use_stops</th>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>log</th>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>upon_long_conflict</th>\n",
       "      <td>ignore</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>upon_short_conflict</th>\n",
       "      <td>ignore</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>upon_dir_conflict</th>\n",
       "      <td>ignore</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>upon_opposite_entry</th>\n",
       "      <td>reversereduce</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>signal_direction</th>\n",
       "      <td>both</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>order_direction</th>\n",
       "      <td>both</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>cash_sharing</th>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>call_pre_segment</th>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>call_post_segment</th>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>ffill_val_price</th>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>update_value</th>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>fill_pos_record</th>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>row_wise</th>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>flexible</th>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>use_numba</th>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>seed</th>\n",
       "      <td>None</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>freq</th>\n",
       "      <td>1D</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>attach_call_seq</th>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>fillna_close</th>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>trades_type</th>\n",
       "      <td>exittrades</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>stats</th>\n",
       "      <td>{'filters': {'has_year_freq': {'filter_func': ...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>plots</th>\n",
       "      <td>{'subplots': ['orders', 'trade_pnl', 'cum_retu...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                                                 Value\n",
       "Option                                                                \n",
       "call_seq                                                       default\n",
       "init_cash                                                       100000\n",
       "size                                                               inf\n",
       "size_type                                                       amount\n",
       "fees                                                            0.0025\n",
       "fixed_fees                                                         0.0\n",
       "slippage                                                        0.0025\n",
       "reject_prob                                                        0.0\n",
       "min_size                                                           0.0\n",
       "max_size                                                           inf\n",
       "size_granularity                                                   NaN\n",
       "lock_cash                                                        False\n",
       "allow_partial                                                    False\n",
       "raise_reject                                                     False\n",
       "val_price                                                          inf\n",
       "accumulate                                                       False\n",
       "sl_stop                                                            NaN\n",
       "sl_trail                                                         False\n",
       "tp_stop                                                            NaN\n",
       "stop_entry_price                                                 close\n",
       "stop_exit_price                                              stoplimit\n",
       "stop_conflict_mode                                                exit\n",
       "upon_stop_exit                                                   close\n",
       "upon_stop_update                                              override\n",
       "use_stops                                                         None\n",
       "log                                                              False\n",
       "upon_long_conflict                                              ignore\n",
       "upon_short_conflict                                             ignore\n",
       "upon_dir_conflict                                               ignore\n",
       "upon_opposite_entry                                      reversereduce\n",
       "signal_direction                                                  both\n",
       "order_direction                                                   both\n",
       "cash_sharing                                                     False\n",
       "call_pre_segment                                                 False\n",
       "call_post_segment                                                False\n",
       "ffill_val_price                                                   True\n",
       "update_value                                                     False\n",
       "fill_pos_record                                                   True\n",
       "row_wise                                                         False\n",
       "flexible                                                         False\n",
       "use_numba                                                         True\n",
       "seed                                                              None\n",
       "freq                                                                1D\n",
       "attach_call_seq                                                  False\n",
       "fillna_close                                                      True\n",
       "trades_type                                                 exittrades\n",
       "stats                {'filters': {'has_year_freq': {'filter_func': ...\n",
       "plots                {'subplots': ['orders', 'trade_pnl', 'cum_retu..."
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cheight, cwidth = 500, 1000 # Adjust as needed for Chart Height and Width\n",
    "vbt.settings.set_theme(\"dark\") # Options: \"light\" (Default), \"dark\" (my fav), \"seaborn\"\n",
    "\n",
    "# Must be set\n",
    "vbt.settings.portfolio[\"freq\"] = \"1D\" # Daily\n",
    "\n",
    "# Predefine vectorbt Portfolio settings\n",
    "vbt.settings.portfolio[\"init_cash\"] = 100_000\n",
    "vbt.settings.portfolio[\"fees\"] = 0.0025 # 0.25%\n",
    "vbt.settings.portfolio[\"slippage\"] = 0.0025 # 0.25%\n",
    "# vbt.settings.portfolio[\"size\"] = 100\n",
    "# vbt.settings.portfolio[\"accumulate\"] = False\n",
    "vbt.settings.portfolio[\"allow_partial\"] = False\n",
    "vbt.settings.portfolio[\"signal_direction\"] = \"both\"\n",
    "\n",
    "pf_settings = pd.DataFrame(vbt.settings.portfolio.items(), columns=[\"Option\", \"Value\"])\n",
    "pf_settings.set_index(\"Option\", inplace=True)\n",
    "\n",
    "print(f\"Portfolio Settings [Initial]\")\n",
    "pf_settings"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bc8fc1e3-f3cc-487c-b11f-7df03eb64420",
   "metadata": {},
   "source": [
    "## Helper Methods"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "d292b3b0-9186-4cf0-b618-64c6c9d8c1db",
   "metadata": {},
   "outputs": [],
   "source": [
    "def combine_stats(pf: vbt.portfolio.base.Portfolio, ticker: str, strategy: str, mode: int = 0):\n",
    "    header = pd.Series({\n",
    "        \"Run Time\": ta.get_time(full=False, to_string=True),\n",
    "        \"Mode\": \"LIVE\" if mode else \"TEST\",\n",
    "        \"Strategy\": strategy,\n",
    "        \"Direction\": vbt.settings.portfolio[\"signal_direction\"],\n",
    "        \"Symbol\": ticker.upper(),\n",
    "        \"Fees [%]\": 100 * vbt.settings.portfolio[\"fees\"],\n",
    "        \"Slippage [%]\": 100 * vbt.settings.portfolio[\"slippage\"],\n",
    "        \"Accumulate\": vbt.settings.portfolio[\"accumulate\"],\n",
    "    })\n",
    "    rstats = pf.returns_stats().dropna(axis=0).T\n",
    "    stats = pf.stats().dropna(axis=0).T\n",
    "    joint = pd.concat([header, stats, rstats])\n",
    "    return joint[~joint.index.duplicated(keep=\"first\")]\n",
    "\n",
    "def earliest_common_index(d: dict):\n",
    "    \"\"\"Returns index of the earliest common index of all DataFrames in the dict\"\"\"\n",
    "    min_date = None\n",
    "    for df in d.values():\n",
    "        if min_date is None:\n",
    "            min_date = df.index[0]\n",
    "        elif min_date < df.index[0]:\n",
    "            min_date = df.index[0]\n",
    "    return min_date\n",
    "\n",
    "def dl(tickers: list, same_start: bool = False, **kwargs):\n",
    "    if isinstance(tickers, str):\n",
    "        tickers = [tickers]\n",
    "    \n",
    "    if not isinstance(tickers, list) or len(tickers) == 0:\n",
    "        print(\"Must be a non-empty list of tickers or symbols\")\n",
    "        return\n",
    "\n",
    "    if \"limit\" in kwargs and kwargs[\"limit\"] and len(tickers) > kwargs[\"limit\"]:\n",
    "        from itertools import islice            \n",
    "        tickers = list(islice(tickers, kwargs[\"limit\"]))\n",
    "        print(f\"[!] Too many assets to compare. Using the first {kwargs['limit']}: {', '.join(tickers)}\")\n",
    "\n",
    "    print(f\"[i] Downloading: {', '.join(tickers)}\")\n",
    "\n",
    "    received = {}\n",
    "    if len(tickers):\n",
    "        _df = pd.DataFrame()\n",
    "        for ticker in tickers:\n",
    "            received[ticker] = _df.ta.ticker(ticker, **kwargs)\n",
    "            print(f\"[+] {ta.get_time(full=False, to_string=True)}\")\n",
    "    \n",
    "    if same_start and len(tickers) > 1:\n",
    "        earliestci = earliest_common_index(received)\n",
    "        print(f\"[i] Earliest Common Date: {earliestci}\")\n",
    "        result = {ticker:df[df.index > earliestci].copy() for ticker,df in received.items()}\n",
    "    else:\n",
    "        result = received\n",
    "    print(f\"[*] Download Complete\\n\")\n",
    "    return result\n",
    "\n",
    "def dtmask(df: pd.DataFrame, start: datetime, end: datetime):\n",
    "    return df.loc[(df.index >= start) & (df.index <= end), :].copy()\n",
    "\n",
    "def show_data(d: dict):\n",
    "    [print(f\"{t}[{df.index[0]} - {df.index[-1]}]: {df.shape} {df.ta.time_range:.2f} years\") for t,df in d.items()]\n",
    "    \n",
    "def trade_table(pf: vbt.portfolio.base.Portfolio, k: int = 1, total_fees: bool = False):\n",
    "    if not isinstance(pf, vbt.portfolio.base.Portfolio): return\n",
    "    k = int(k) if isinstance(k, int) and k > 0 else 1\n",
    "\n",
    "    df = pf.trades.records[[\"status\", \"direction\", \"size\", \"entry_price\", \"exit_price\", \"return\", \"pnl\", \"entry_fees\", \"exit_fees\"]]\n",
    "    if total_fees:\n",
    "        df[\"total_fees\"] = df[\"entry_fees\"] + df[\"exit_fees\"]\n",
    "\n",
    "    print(f\"\\nLast {k} of {df.shape[0]} Trades\\n{df.tail(k)}\\n\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5296f5e7-6752-43f4-b47d-d359da0d0145",
   "metadata": {},
   "source": [
    "# Data Acquisition"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8c770d31-a015-49f2-b1ad-5bced3520d55",
   "metadata": {},
   "source": [
    "#### Specify Symbols for Benchmarks and Assets"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "edf274ec-9813-469b-b1e5-129a4e8fe7ed",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Tickers by index #\n",
      "====================================================================================================\n",
      "Benchmarks: 0: SPY, 1: QQQ\n",
      "    Assets: 0: AAPL, 1: TSLA, 2: TWTR\n",
      "       All: 0: SPY, 1: QQQ, 2: AAPL, 3: TSLA, 4: TWTR\n"
     ]
    }
   ],
   "source": [
    "benchmark_tickers = [\"SPY\", \"QQQ\"]\n",
    "asset_tickers = [\"AAPL\", \"TSLA\", \"TWTR\"]\n",
    "all_tickers = benchmark_tickers + asset_tickers\n",
    "\n",
    "print(\"Tickers by index #\")\n",
    "print(\"=\"*100)\n",
    "print(f\"Benchmarks: {', '.join([f'{k}: {v}' for k,v in enumerate(benchmark_tickers)])}\")\n",
    "print(f\"    Assets: {', '.join([f'{k}: {v}' for k,v in enumerate(asset_tickers)])}\")\n",
    "print(f\"       All: {', '.join([f'{k}: {v}' for k,v in enumerate(all_tickers)])}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "c4c7072a-2c93-4a40-81b4-e18563f81e44",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Selected Benchmark | Asset: SPY | TWTR\n"
     ]
    }
   ],
   "source": [
    "benchmark = benchmark_tickers[0] # Change index for different benchmark\n",
    "asset = asset_tickers[2] # Change index for different symbol\n",
    "print(f\"Selected Benchmark | Asset: {benchmark} | {asset}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "57a1ded8-fe41-4416-8a54-ac94e9306975",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[i] Downloading: SPY, QQQ\n",
      "[+] yf | SPY(7367, 7): 3810.4675 ms (3.8105 s)\n",
      "[+] Sunday May 1, 2022, NYSE: 14:17:10\n",
      "[+] yf | QQQ(5825, 7): 3371.7531 ms (3.3718 s)\n",
      "[+] Sunday May 1, 2022, NYSE: 14:17:14\n",
      "[*] Download Complete\n",
      "\n"
     ]
    }
   ],
   "source": [
    "benchmarks = dl(benchmark_tickers, timed=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "eeb57c0a-677a-4fcf-8a0f-08338c04bf03",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[i] Downloading: AAPL, TSLA, TWTR\n",
      "[+] yf | AAPL(10434, 7): 3390.6886 ms (3.3907 s)\n",
      "[+] Sunday May 1, 2022, NYSE: 14:17:17\n",
      "[+] yf | TSLA(2981, 7): 3219.1295 ms (3.2191 s)\n",
      "[+] Sunday May 1, 2022, NYSE: 14:17:20\n",
      "[+] yf | TWTR(2134, 7): 3016.2403 ms (3.0162 s)\n",
      "[+] Sunday May 1, 2022, NYSE: 14:17:23\n",
      "[*] Download Complete\n",
      "\n"
     ]
    }
   ],
   "source": [
    "assets = dl(asset_tickers, timed=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "68d36f39-b55b-4ff6-9b73-ec7e6cf9e502",
   "metadata": {},
   "source": [
    "### Define Testing Dates and Ranges"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "f3b1fafb-e0e6-41b8-85af-4b8a78a00c85",
   "metadata": {},
   "outputs": [],
   "source": [
    "start_date = datetime(2005, 1, 1) # Adjust as needed\n",
    "end_date = datetime(2010, 1, 1)   # Adjust as needed"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cf392c49-9325-4cd5-81c3-ac7285bb7100",
   "metadata": {},
   "source": [
    "### Select and Benchmark and Asset to Backtest"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "844bec64-4547-414f-8c89-00d66f08f5d4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Available Data:\n",
      "====================================================================================================\n",
      "Benchmarks: SPY, QQQ\n",
      "Assets: AAPL, TSLA, TWTR\n"
     ]
    }
   ],
   "source": [
    "print(\"Available Data:\")\n",
    "print(\"=\"*100)\n",
    "print(f\"Benchmarks: {', '.join(benchmarks.keys())}\")\n",
    "print(f\"Assets: {', '.join(assets.keys())}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "d1fea600-8460-441a-b933-94fbd2456930",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Analysis of: SPY and AAPL from 2005-01-01 00:00:00 to 2010-01-01 00:00:00\n"
     ]
    }
   ],
   "source": [
    "benchmark_name = \"SPY\" # Select a Benchmark\n",
    "asset_name = \"AAPL\" # Select an Asset\n",
    "\n",
    "benchmarkdf = benchmarks[benchmark_name]\n",
    "assetdf     = assets[asset_name]\n",
    "\n",
    "# Set True if you want to constrain Data between start_date & end_date\n",
    "common_range = True\n",
    "if common_range:\n",
    "    crs = f\" from {start_date} to {end_date}\"\n",
    "    benchmarkdf = dtmask(benchmarkdf, start_date, end_date)\n",
    "    assetdf = dtmask(assetdf, start_date, end_date)\n",
    "\n",
    "# Update DataFrame names\n",
    "benchmarkdf.name = benchmark_name\n",
    "assetdf.name = asset_name\n",
    "print(f\"Analysis of: {benchmarkdf.name} and {assetdf.name}{crs if common_range else ''}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0e0c3328-783c-4cf2-82fe-d8772948289a",
   "metadata": {},
   "source": [
    "#### Sanity Check"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "5449cbc0-8050-4b1b-9357-eac975fbbb3c",
   "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>Volume</th>\n",
       "      <th>Dividends</th>\n",
       "      <th>Stock Splits</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",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2005-01-03</th>\n",
       "      <td>86.905223</td>\n",
       "      <td>87.048210</td>\n",
       "      <td>85.718465</td>\n",
       "      <td>86.004433</td>\n",
       "      <td>55748000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2005-01-04</th>\n",
       "      <td>86.118795</td>\n",
       "      <td>86.175989</td>\n",
       "      <td>84.674667</td>\n",
       "      <td>84.953484</td>\n",
       "      <td>69167600</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2005-01-05</th>\n",
       "      <td>84.889173</td>\n",
       "      <td>85.253781</td>\n",
       "      <td>84.360136</td>\n",
       "      <td>84.367287</td>\n",
       "      <td>65667300</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2005-01-06</th>\n",
       "      <td>84.674677</td>\n",
       "      <td>85.182267</td>\n",
       "      <td>84.545992</td>\n",
       "      <td>84.796211</td>\n",
       "      <td>47814700</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2005-01-07</th>\n",
       "      <td>85.053580</td>\n",
       "      <td>85.239459</td>\n",
       "      <td>84.453047</td>\n",
       "      <td>84.674675</td>\n",
       "      <td>55847700</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2009-12-24</th>\n",
       "      <td>88.709400</td>\n",
       "      <td>89.033586</td>\n",
       "      <td>88.559164</td>\n",
       "      <td>88.938705</td>\n",
       "      <td>39677500</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2009-12-28</th>\n",
       "      <td>89.270845</td>\n",
       "      <td>89.342005</td>\n",
       "      <td>88.812233</td>\n",
       "      <td>89.128517</td>\n",
       "      <td>87508500</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2009-12-29</th>\n",
       "      <td>89.357828</td>\n",
       "      <td>89.373640</td>\n",
       "      <td>88.994104</td>\n",
       "      <td>89.002007</td>\n",
       "      <td>80572500</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2009-12-30</th>\n",
       "      <td>88.741052</td>\n",
       "      <td>89.073148</td>\n",
       "      <td>88.693606</td>\n",
       "      <td>88.970352</td>\n",
       "      <td>73138400</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2009-12-31</th>\n",
       "      <td>89.168022</td>\n",
       "      <td>89.191748</td>\n",
       "      <td>88.076849</td>\n",
       "      <td>88.116386</td>\n",
       "      <td>90637900</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>1259 rows × 7 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                 Open       High        Low      Close    Volume  Dividends  \\\n",
       "Date                                                                          \n",
       "2005-01-03  86.905223  87.048210  85.718465  86.004433  55748000        0.0   \n",
       "2005-01-04  86.118795  86.175989  84.674667  84.953484  69167600        0.0   \n",
       "2005-01-05  84.889173  85.253781  84.360136  84.367287  65667300        0.0   \n",
       "2005-01-06  84.674677  85.182267  84.545992  84.796211  47814700        0.0   \n",
       "2005-01-07  85.053580  85.239459  84.453047  84.674675  55847700        0.0   \n",
       "...               ...        ...        ...        ...       ...        ...   \n",
       "2009-12-24  88.709400  89.033586  88.559164  88.938705  39677500        0.0   \n",
       "2009-12-28  89.270845  89.342005  88.812233  89.128517  87508500        0.0   \n",
       "2009-12-29  89.357828  89.373640  88.994104  89.002007  80572500        0.0   \n",
       "2009-12-30  88.741052  89.073148  88.693606  88.970352  73138400        0.0   \n",
       "2009-12-31  89.168022  89.191748  88.076849  88.116386  90637900        0.0   \n",
       "\n",
       "            Stock Splits  \n",
       "Date                      \n",
       "2005-01-03             0  \n",
       "2005-01-04             0  \n",
       "2005-01-05             0  \n",
       "2005-01-06             0  \n",
       "2005-01-07             0  \n",
       "...                  ...  \n",
       "2009-12-24             0  \n",
       "2009-12-28             0  \n",
       "2009-12-29             0  \n",
       "2009-12-30             0  \n",
       "2009-12-31             0  \n",
       "\n",
       "[1259 rows x 7 columns]"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "benchmarkdf"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "3adaeb5e-dfc4-4eed-970f-f465035c7a89",
   "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>Volume</th>\n",
       "      <th>Dividends</th>\n",
       "      <th>Stock Splits</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",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2005-01-03</th>\n",
       "      <td>0.990526</td>\n",
       "      <td>0.995572</td>\n",
       "      <td>0.957192</td>\n",
       "      <td>0.967743</td>\n",
       "      <td>691992000</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2005-01-04</th>\n",
       "      <td>0.975388</td>\n",
       "      <td>1.001076</td>\n",
       "      <td>0.962850</td>\n",
       "      <td>0.977682</td>\n",
       "      <td>1096810400</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2005-01-05</th>\n",
       "      <td>0.985632</td>\n",
       "      <td>0.997713</td>\n",
       "      <td>0.979363</td>\n",
       "      <td>0.986244</td>\n",
       "      <td>680433600</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2005-01-06</th>\n",
       "      <td>0.988843</td>\n",
       "      <td>0.992513</td>\n",
       "      <td>0.968354</td>\n",
       "      <td>0.987009</td>\n",
       "      <td>705555200</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2005-01-07</th>\n",
       "      <td>0.993889</td>\n",
       "      <td>1.064685</td>\n",
       "      <td>0.990067</td>\n",
       "      <td>1.058874</td>\n",
       "      <td>2227450400</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2009-12-24</th>\n",
       "      <td>6.224809</td>\n",
       "      <td>6.402180</td>\n",
       "      <td>6.218692</td>\n",
       "      <td>6.392699</td>\n",
       "      <td>500889200</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2009-12-28</th>\n",
       "      <td>6.474657</td>\n",
       "      <td>6.542852</td>\n",
       "      <td>6.410130</td>\n",
       "      <td>6.471292</td>\n",
       "      <td>644565600</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2009-12-29</th>\n",
       "      <td>6.502485</td>\n",
       "      <td>6.505237</td>\n",
       "      <td>6.383218</td>\n",
       "      <td>6.394533</td>\n",
       "      <td>445205600</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2009-12-30</th>\n",
       "      <td>6.386275</td>\n",
       "      <td>6.483218</td>\n",
       "      <td>6.370373</td>\n",
       "      <td>6.472208</td>\n",
       "      <td>412084400</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2009-12-31</th>\n",
       "      <td>6.517777</td>\n",
       "      <td>6.524505</td>\n",
       "      <td>6.439183</td>\n",
       "      <td>6.444382</td>\n",
       "      <td>352410800</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>1259 rows × 7 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                Open      High       Low     Close      Volume  Dividends  \\\n",
       "Date                                                                        \n",
       "2005-01-03  0.990526  0.995572  0.957192  0.967743   691992000        0.0   \n",
       "2005-01-04  0.975388  1.001076  0.962850  0.977682  1096810400        0.0   \n",
       "2005-01-05  0.985632  0.997713  0.979363  0.986244   680433600        0.0   \n",
       "2005-01-06  0.988843  0.992513  0.968354  0.987009   705555200        0.0   \n",
       "2005-01-07  0.993889  1.064685  0.990067  1.058874  2227450400        0.0   \n",
       "...              ...       ...       ...       ...         ...        ...   \n",
       "2009-12-24  6.224809  6.402180  6.218692  6.392699   500889200        0.0   \n",
       "2009-12-28  6.474657  6.542852  6.410130  6.471292   644565600        0.0   \n",
       "2009-12-29  6.502485  6.505237  6.383218  6.394533   445205600        0.0   \n",
       "2009-12-30  6.386275  6.483218  6.370373  6.472208   412084400        0.0   \n",
       "2009-12-31  6.517777  6.524505  6.439183  6.444382   352410800        0.0   \n",
       "\n",
       "            Stock Splits  \n",
       "Date                      \n",
       "2005-01-03           0.0  \n",
       "2005-01-04           0.0  \n",
       "2005-01-05           0.0  \n",
       "2005-01-06           0.0  \n",
       "2005-01-07           0.0  \n",
       "...                  ...  \n",
       "2009-12-24           0.0  \n",
       "2009-12-28           0.0  \n",
       "2009-12-29           0.0  \n",
       "2009-12-30           0.0  \n",
       "2009-12-31           0.0  \n",
       "\n",
       "[1259 rows x 7 columns]"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "assetdf"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a71574b2-5e32-45d1-beb9-48a0cb4eadfe",
   "metadata": {},
   "source": [
    "## Creating Trading Signals for **vectorbt**\n",
    "**vectorbt** can create a Backtest using ```vbt.Portfolio.from_signals(*args, **kwargs)``` based on trends that you create with **Pandas TA**."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "19c0ab8b-fcbe-4a07-9a77-e904b970e6ca",
   "metadata": {},
   "source": [
    "### Trend Creation\n",
    "A **Trend** is the result of some calculation or condition of one or more indicators. For simplicity, a _Trend_ is either ```True``` or ```1``` and _No Trend_ is ```False``` or ```0```. Using the **Hello World** of Trends, the **Golden/Death Cross**, it's Trend is _Long_ when ```long = ma(close, 50) > ma(close, 200) ``` and _Short_ when ```short = ma(close, 50) < ma(close, 200) ```. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "775842c7-ea0e-42a0-b287-cc56487520c0",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Example Long Trends for the selected Asset\n",
    "# * Uncomment others for exploration or replace them with your own TA Trend Strategy\n",
    "def trends(df: pd.DataFrame, mamode: str = \"sma\", fast: int = 50, slow: int = 200):\n",
    "    return ta.ma(mamode, df.Close, length=fast) > ta.ma(mamode, df.Close, length=slow) # SMA(fast) > SMA(slow) \"Golden/Death Cross\"\n",
    "#     return ta.increasing(ta.ma(mamode, df.Close, length=fast)) # Increasing MA(fast)\n",
    "#     return ta.macd(df.Close, fast, slow).iloc[:,1] > 0 # MACD Histogram is positive"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "eab7e842-0cc9-420a-a22e-069ecc86e879",
   "metadata": {},
   "source": [
    "### Display Trends"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "8c13e23e-6c2a-47e9-94b8-90dcb79f9191",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "trend_kwargs = {\"mamode\": \"ema\", \"fast\": 20, \"slow\": 50}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "ef5a755c-ce2b-4bb1-a72f-51f5afbf537a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.lines.Line2D at 0x156c5ab50>"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 10800 characters]\n",
      "text/plain": [
       "<Figure size 1152x72 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "benchmark_trends = trends(benchmarkdf, **trend_kwargs)\n",
    "benchmark_trends.copy().astype(int).plot(figsize=(16, 1), kind=\"area\", color=[\"limegreen\"], alpha=0.9, title=f\"{benchmarkdf.name} Trends\", grid=True).axhline(0, color=\"black\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "bc51e2ca-8784-48a5-a55e-8f32212b9560",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.lines.Line2D at 0x157201400>"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 11212 characters]\n",
      "text/plain": [
       "<Figure size 1152x72 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "asset_trends = trends(assetdf, **trend_kwargs)\n",
    "asset_trends.copy().astype(int).plot(figsize=(16, 1), kind=\"area\", color=[\"limegreen\"], alpha=0.98, title=f\"{assetdf.name} Trends\", grid=True).axhline(0, color=\"black\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ba1888d0-10a9-44d4-bc8a-b8ea1c1faa0e",
   "metadata": {},
   "source": [
    "### **Trend Signals** \n",
    "Given a _Trend_, **Trend Signals** returns the _Trend_, _Trades_, _Entries_ and _Exits_ as boolean integers. When ```asbool=True```, it returns _Trends_, _Entries_ and _Exits_ as boolean values which is helpful when combined with the [**vectorbt**](https://github.com/polakowo/vectorbt) backtesting package."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "75bd0f52-ebe0-4fe1-b8e0-475320d3557f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tsignals\n"
     ]
    },
    {
     "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>TS_Trends</th>\n",
       "      <th>TS_Trades</th>\n",
       "      <th>TS_Entries</th>\n",
       "      <th>TS_Exits</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Date</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2009-12-24</th>\n",
       "      <td>True</td>\n",
       "      <td>0</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2009-12-28</th>\n",
       "      <td>True</td>\n",
       "      <td>0</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2009-12-29</th>\n",
       "      <td>True</td>\n",
       "      <td>0</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2009-12-30</th>\n",
       "      <td>True</td>\n",
       "      <td>0</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2009-12-31</th>\n",
       "      <td>True</td>\n",
       "      <td>0</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "            TS_Trends  TS_Trades  TS_Entries  TS_Exits\n",
       "Date                                                  \n",
       "2009-12-24       True          0       False     False\n",
       "2009-12-28       True          0       False     False\n",
       "2009-12-29       True          0       False     False\n",
       "2009-12-30       True          0       False     False\n",
       "2009-12-31       True          0       False     False"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# trade_offset = 0 for Live Signals (close is last price)\n",
    "# trade_offset = 1 for Backtesting\n",
    "LIVE = 0\n",
    "\n",
    "benchmark_signals = assetdf.ta.tsignals(benchmark_trends, asbool=True, trade_offset=LIVE, append=True)\n",
    "benchmark_signals.tail()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "3fceb4ec-b564-47fc-9568-301d1e517440",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tsignals\n"
     ]
    },
    {
     "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>TS_Trends</th>\n",
       "      <th>TS_Trades</th>\n",
       "      <th>TS_Entries</th>\n",
       "      <th>TS_Exits</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Date</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2009-12-24</th>\n",
       "      <td>True</td>\n",
       "      <td>0</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2009-12-28</th>\n",
       "      <td>True</td>\n",
       "      <td>0</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2009-12-29</th>\n",
       "      <td>True</td>\n",
       "      <td>0</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2009-12-30</th>\n",
       "      <td>True</td>\n",
       "      <td>0</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2009-12-31</th>\n",
       "      <td>True</td>\n",
       "      <td>0</td>\n",
       "      <td>False</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "            TS_Trends  TS_Trades  TS_Entries  TS_Exits\n",
       "Date                                                  \n",
       "2009-12-24       True          0       False     False\n",
       "2009-12-28       True          0       False     False\n",
       "2009-12-29       True          0       False     False\n",
       "2009-12-30       True          0       False     False\n",
       "2009-12-31       True          0       False     False"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "asset_signals = assetdf.ta.tsignals(asset_trends, asbool=True, trade_offset=LIVE, append=True)\n",
    "asset_signals.tail()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "58fee2e0-dc54-45cd-89e7-939c0646e1cd",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "5155f6c5-2256-4abd-8945-3201e3963613",
   "metadata": {},
   "source": [
    "## Creating **vectorbt** Portfolios\n",
    "* [**vectorbt** Portfolio Options](https://polakowo.io/vectorbt/docs/portfolio/base.html)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "40085839-77af-4cf8-ad94-25ed5a9a8bc1",
   "metadata": {},
   "source": [
    "### Buy 'N Hold Portfolios with their Single Trade and Performance Statistics"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "237cbd18-dfc5-4982-bc5c-2427cfa2ab6d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Last 1 of 1 Trades\n",
      "   status  direction         size  entry_price  exit_price    return  \\\n",
      "0       0          0  1156.938842    86.219444   88.116386  0.019501   \n",
      "\n",
      "           pnl  entry_fees  exit_fees  \n",
      "0  1945.270079  249.376559        0.0  \n",
      "\n",
      "None\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "Run Time                     Sunday May 1, 2022, NYSE: 14:17:27\n",
       "Mode                                                       TEST\n",
       "Strategy                                           Buy and Hold\n",
       "Direction                                                  both\n",
       "Symbol                                                      SPY\n",
       "Fees [%]                                                   0.25\n",
       "Slippage [%]                                               0.25\n",
       "Accumulate                                                False\n",
       "Start                                       2005-01-03 00:00:00\n",
       "End                                         2009-12-31 00:00:00\n",
       "Period                                       1259 days 00:00:00\n",
       "Start Value                                            100000.0\n",
       "End Value                                         101945.270079\n",
       "Total Return [%]                                        1.94527\n",
       "Benchmark Return [%]                                   2.455634\n",
       "Max Gross Exposure [%]                                    100.0\n",
       "Total Fees Paid                                      249.376559\n",
       "Max Drawdown [%]                                      55.189427\n",
       "Max Drawdown Duration                         562 days 00:00:00\n",
       "Total Trades                                                  1\n",
       "Total Closed Trades                                           0\n",
       "Total Open Trades                                             1\n",
       "Open Trade PnL                                      1945.270079\n",
       "Sharpe Ratio                                           0.163325\n",
       "Calmar Ratio                                           0.010149\n",
       "Omega Ratio                                            1.028442\n",
       "Sortino Ratio                                          0.231223\n",
       "Annualized Return [%]                                  0.560106\n",
       "Annualized Volatility [%]                             28.894497\n",
       "Skew                                                   0.426797\n",
       "Kurtosis                                              14.955984\n",
       "Tail Ratio                                             0.881903\n",
       "Common Sense Ratio                                     0.886842\n",
       "Value at Risk                                          -0.02229\n",
       "Alpha                                                 -0.001443\n",
       "Beta                                                   1.000002\n",
       "dtype: object"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Benchmark Buy and Hold (BnH) Strategy\n",
    "benchmarkpf_bnh = vbt.Portfolio.from_holding(benchmarkdf.Close)\n",
    "print(trade_table(benchmarkpf_bnh))\n",
    "combine_stats(benchmarkpf_bnh, benchmarkdf.name, \"Buy and Hold\", LIVE)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "79667a6e-cd9b-424e-bec8-02435a8e38d3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Last 1 of 1 Trades\n",
      "   status  direction           size  entry_price  exit_price    return  \\\n",
      "0       0          0  102818.493136     0.970162    6.444382  5.640081   \n",
      "\n",
      "             pnl  entry_fees  exit_fees  \n",
      "0  562601.617014  249.376559        0.0  \n",
      "\n",
      "None\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "Run Time                     Sunday May 1, 2022, NYSE: 14:17:28\n",
       "Mode                                                       TEST\n",
       "Strategy                                           Buy and Hold\n",
       "Direction                                                  both\n",
       "Symbol                                                     AAPL\n",
       "Fees [%]                                                   0.25\n",
       "Slippage [%]                                               0.25\n",
       "Accumulate                                                False\n",
       "Start                                       2005-01-03 00:00:00\n",
       "End                                         2009-12-31 00:00:00\n",
       "Period                                       1259 days 00:00:00\n",
       "Start Value                                            100000.0\n",
       "End Value                                         662601.617014\n",
       "Total Return [%]                                     562.601617\n",
       "Benchmark Return [%]                                 565.918766\n",
       "Max Gross Exposure [%]                                    100.0\n",
       "Total Fees Paid                                      249.376559\n",
       "Max Drawdown [%]                                      60.866735\n",
       "Max Drawdown Duration                         456 days 00:00:00\n",
       "Total Trades                                                  1\n",
       "Total Closed Trades                                           0\n",
       "Total Open Trades                                             1\n",
       "Open Trade PnL                                    562601.617014\n",
       "Sharpe Ratio                                           1.329387\n",
       "Calmar Ratio                                           1.199638\n",
       "Omega Ratio                                            1.209774\n",
       "Sortino Ratio                                          1.982725\n",
       "Annualized Return [%]                                 73.018072\n",
       "Annualized Volatility [%]                             51.088458\n",
       "Skew                                                  -0.037599\n",
       "Kurtosis                                                3.43526\n",
       "Tail Ratio                                              1.03789\n",
       "Common Sense Ratio                                     1.795738\n",
       "Value at Risk                                         -0.041247\n",
       "Alpha                                                  -0.00145\n",
       "Beta                                                    1.00001\n",
       "dtype: object"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Asset Buy and Hold (BnH) Strategy\n",
    "assetpf_bnh = vbt.Portfolio.from_holding(assetdf.Close)\n",
    "print(trade_table(assetpf_bnh))\n",
    "combine_stats(assetpf_bnh, assetdf.name, \"Buy and Hold\", LIVE)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6549488f-31df-4de3-a6b8-0034b4be591a",
   "metadata": {},
   "source": [
    "### Signal Portfolios with their Last 'k' Trades and Performance Statistics"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "ab11d9a6-05a3-49e5-9c2c-d339e26e9b23",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Last 5 of 15 Trades\n",
      "    status  direction         size  entry_price  exit_price    return  \\\n",
      "10       1          0   797.770311   114.865419  108.679631 -0.058718   \n",
      "11       1          1   793.791407   108.679631  105.284168  0.026321   \n",
      "12       1          0   840.904944   105.284168  101.710388 -0.038859   \n",
      "13       1          1   836.710904   101.710388   63.711012  0.369538   \n",
      "14       0          0  1828.133472    63.711012   88.116386  0.380564   \n",
      "\n",
      "             pnl  entry_fees   exit_fees  \n",
      "10  -5380.682196  229.090553  216.753458  \n",
      "11   2270.682765  215.672393  208.934170  \n",
      "12  -3440.366007  221.334944  213.821921  \n",
      "13  31448.467750  212.755477  133.269246  \n",
      "14  44325.101312  291.180584    0.000000  \n",
      "\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "Run Time                      Sunday May 1, 2022, NYSE: 14:17:31\n",
       "Mode                                                        TEST\n",
       "Strategy                                           Long Strategy\n",
       "Direction                                                   both\n",
       "Symbol                                                       SPY\n",
       "Fees [%]                                                    0.25\n",
       "Slippage [%]                                                0.25\n",
       "Accumulate                                                 False\n",
       "Start                                        2005-01-03 00:00:00\n",
       "End                                          2009-12-31 00:00:00\n",
       "Period                                        1259 days 00:00:00\n",
       "Start Value                                             100000.0\n",
       "End Value                                          161088.515438\n",
       "Total Return [%]                                       61.088515\n",
       "Benchmark Return [%]                                    2.455634\n",
       "Max Gross Exposure [%]                                     100.0\n",
       "Total Fees Paid                                      6786.593906\n",
       "Max Drawdown [%]                                       21.642411\n",
       "Max Drawdown Duration                          411 days 00:00:00\n",
       "Total Trades                                                  15\n",
       "Total Closed Trades                                           14\n",
       "Total Open Trades                                              1\n",
       "Open Trade PnL                                      44325.101312\n",
       "Win Rate [%]                                           35.714286\n",
       "Best Trade [%]                                          36.95377\n",
       "Worst Trade [%]                                        -5.871785\n",
       "Avg Winning Trade [%]                                  10.694623\n",
       "Avg Losing Trade [%]                                   -3.476782\n",
       "Avg Winning Trade Duration                     136 days 14:24:00\n",
       "Avg Losing Trade Duration                       37 days 18:40:00\n",
       "Profit Factor                                           1.564774\n",
       "Expectancy                                           1197.386723\n",
       "Sharpe Ratio                                             0.76285\n",
       "Calmar Ratio                                            0.684927\n",
       "Omega Ratio                                             1.124145\n",
       "Sortino Ratio                                           1.111297\n",
       "Annualized Return [%]                                  14.823462\n",
       "Annualized Volatility [%]                              21.015086\n",
       "Skew                                                    0.013949\n",
       "Kurtosis                                                4.710068\n",
       "Tail Ratio                                              1.023206\n",
       "Common Sense Ratio                                      1.174881\n",
       "Value at Risk                                          -0.017307\n",
       "Alpha                                                   0.191159\n",
       "Beta                                                   -0.301324\n",
       "dtype: object"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Benchmark Portfolio from Trade Signals\n",
    "benchmarkpf_signals = vbt.Portfolio.from_signals(\n",
    "    benchmarkdf.Close,\n",
    "    entries=benchmark_signals.TS_Entries,\n",
    "    exits=benchmark_signals.TS_Exits,\n",
    ")\n",
    "trade_table(benchmarkpf_signals, k=5)\n",
    "combine_stats(benchmarkpf_signals, benchmarkdf.name, \"Long Strategy\", LIVE)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "d8eaf793-f18b-41e1-92d2-d27baa166371",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Last 5 of 19 Trades\n",
      "    status  direction          size  entry_price  exit_price    return  \\\n",
      "14       1          0  29355.566042     5.320024    4.917979 -0.080383   \n",
      "15       1          1  29209.154242     4.917979    3.043387  0.377124   \n",
      "16       1          0  64956.830347     3.043387    2.652390 -0.133153   \n",
      "17       1          1  64632.856130     2.652390    3.112366 -0.178853   \n",
      "18       0          0  45253.946608     3.112366    6.444382  1.068073   \n",
      "\n",
      "              pnl  entry_fees   exit_fees  \n",
      "14  -12553.631451  390.430815  360.925126  \n",
      "15   54173.875496  359.125001  222.236907  \n",
      "16  -26322.911779  494.221947  430.727040  \n",
      "17  -30661.105740  428.578776  502.902836  \n",
      "18  150434.722694  352.117165    0.000000  \n",
      "\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "Run Time                      Sunday May 1, 2022, NYSE: 14:17:32\n",
       "Mode                                                        TEST\n",
       "Strategy                                           Long Strategy\n",
       "Direction                                                   both\n",
       "Symbol                                                      AAPL\n",
       "Fees [%]                                                    0.25\n",
       "Slippage [%]                                                0.25\n",
       "Accumulate                                                 False\n",
       "Start                                        2005-01-03 00:00:00\n",
       "End                                          2009-12-31 00:00:00\n",
       "Period                                        1259 days 00:00:00\n",
       "Start Value                                             100000.0\n",
       "End Value                                          291633.706004\n",
       "Total Return [%]                                      191.633706\n",
       "Benchmark Return [%]                                  565.918766\n",
       "Max Gross Exposure [%]                                     100.0\n",
       "Total Fees Paid                                     10631.091236\n",
       "Max Drawdown [%]                                       46.106062\n",
       "Max Drawdown Duration                          368 days 00:00:00\n",
       "Total Trades                                                  19\n",
       "Total Closed Trades                                           18\n",
       "Total Open Trades                                              1\n",
       "Open Trade PnL                                     150434.722694\n",
       "Win Rate [%]                                           33.333333\n",
       "Best Trade [%]                                         78.771666\n",
       "Worst Trade [%]                                       -17.885338\n",
       "Avg Winning Trade [%]                                  34.907989\n",
       "Avg Losing Trade [%]                                  -10.451628\n",
       "Avg Winning Trade Duration                     124 days 12:00:00\n",
       "Avg Losing Trade Duration                       21 days 20:00:00\n",
       "Profit Factor                                             1.2815\n",
       "Expectancy                                           2288.832406\n",
       "Sharpe Ratio                                            0.926132\n",
       "Calmar Ratio                                             0.78913\n",
       "Omega Ratio                                             1.141239\n",
       "Sortino Ratio                                           1.339789\n",
       "Annualized Return [%]                                  36.383655\n",
       "Annualized Volatility [%]                              43.942062\n",
       "Skew                                                   -0.036486\n",
       "Kurtosis                                                1.988356\n",
       "Tail Ratio                                              0.968328\n",
       "Common Sense Ratio                                      1.320641\n",
       "Value at Risk                                          -0.038211\n",
       "Alpha                                                   0.353838\n",
       "Beta                                                    0.152646\n",
       "dtype: object"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Asset Portfolio from Trade Signals\n",
    "assetpf_signals = vbt.Portfolio.from_signals(\n",
    "    assetdf.Close,\n",
    "    entries=asset_signals.TS_Entries,\n",
    "    exits=asset_signals.TS_Exits,\n",
    ")\n",
    "trade_table(assetpf_signals, k=5)\n",
    "combine_stats(assetpf_signals, assetdf.name, \"Long Strategy\", LIVE)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "056574e2-0e68-4055-92ba-d8893e153619",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "758ab259-f6f8-4dfc-8c2d-5aaf429cea42",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "79249c48-7cb6-41a1-ad8d-4aa928d7cd90",
   "metadata": {},
   "source": [
    "## Buy and Hold Plots"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "f386b63d-38f0-401a-ae0e-48bfb65e561a",
   "metadata": {},
   "outputs": [],
   "source": [
    "vbt.settings.set_theme(\"seaborn\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "000dbee0-dd23-45b9-b298-5e9805e99dd5",
   "metadata": {},
   "source": [
    "### Benchmark"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "8d3be988-8ab0-4160-8954-2e5989b3c75f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 75188 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "benchmarkpf_bnh.trades.plot(title=f\"{benchmarkdf.name} | Trades\", height=cheight, width=cwidth).show_png()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "de6ef303-a1a8-4ff9-8722-4e50cdde28d9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 51388 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "benchmarkpf_bnh.value().vbt.plot(title=f\"{benchmarkdf.name} | Equity Curve\", trace_kwargs=dict(name=u\"\\u00A4\"), height=cheight // 2, width=cwidth).show_png()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "f38fa715-186c-40fb-aecb-177c39480600",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 46924 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "benchmarkpf_bnh.drawdown().vbt.plot(title=f\"{benchmarkdf.name} | Drawdown\", trace_kwargs=dict(name=\"%\"), height=cheight // 2, width=cwidth).show_png()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "aab9e899-5115-4395-bc1a-c79e75a87583",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 27632 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "benchmarkpf_bnh.trades.plot_pnl(title=f\"{benchmarkdf.name} | PnL\", height=cheight // 2, width=cwidth).show_png()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "4612fa22-363c-4351-9748-1204c26817f3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 49924 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "benchmarkpf_bnh.asset_returns().vbt.plot(title=f\"{benchmarkdf.name} | Asset Returns\", trace_kwargs=dict(name=\"%\"), height=cheight // 2, width=cwidth).show_png()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "61e0a14e-72ef-49fd-a610-7a7f2a47ec59",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 26260 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "benchmarkpf_bnh.cash().vbt.plot(title=f\"{benchmarkdf.name} | Cash\", trace_kwargs=dict(name=u\"\\u00A4\"), height=cheight // 2, width=cwidth).show_png()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "8ff2049b-7d65-4ee3-aeda-f246d3f78990",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 20912 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "total_assetfees = benchmarkpf_bnh.trades.records_readable[\"Entry Fees\"] + benchmarkpf_bnh.trades.records_readable[\"Exit Fees\"]\n",
    "total_assetfees.vbt.plot(title=f\"{benchmarkdf.name} | Total Fees\", trace_kwargs=dict(name=u\"\\u00A4\"), height=cheight // 2, width=cwidth).show_png()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b1763326-6e9d-476b-978c-9ef0f4230023",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "d2ee8078-2c50-456b-91b7-bce90ab837d7",
   "metadata": {},
   "source": [
    "### Asset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "39d91c0e-85aa-41d1-8be4-db4950fbd072",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 71276 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "assetpf_bnh.trades.plot(title=f\"{assetdf.name} | Trades\", height=cheight, width=cwidth).show_png()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "e8b1c77d-b699-4531-8226-bc9c33a465eb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 49252 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "assetpf_bnh.value().vbt.plot(title=f\"{assetdf.name} | Equity Curve\", trace_kwargs=dict(name=u\"\\u00A4\"), height=cheight // 2, width=cwidth).show_png()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "3afeecfb-6732-4811-9bbc-d731705096df",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 52928 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "assetpf_bnh.drawdown().vbt.plot(title=f\"{assetdf.name} | Drawdown\", trace_kwargs=dict(name=\"%\"), height=cheight // 2, width=cwidth).show_png()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "0b66f1f8-1155-4759-aba0-b3762dfca7d8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 27328 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "assetpf_bnh.trades.plot_pnl(title=f\"{assetdf.name} | PnL\", height=cheight // 2, width=cwidth).show_png()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "f1b5e490-b99b-4613-be46-72b41076a45f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 57096 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "assetpf_bnh.asset_returns().vbt.plot(title=f\"{assetdf.name} | Asset Returns\", trace_kwargs=dict(name=\"%\"), height=cheight // 2, width=cwidth).show_png()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "061f2fbe-b6c0-49e6-8523-d2a895609427",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 26284 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "assetpf_bnh.cash().vbt.plot(title=f\"{assetdf.name} | Cash\", trace_kwargs=dict(name=u\"\\u00A4\"), height=cheight // 2, width=cwidth).show_png()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "e9968dcd-f488-4093-816d-059488617a1f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 20748 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "total_assetfees = assetpf_bnh.trades.records_readable[\"Entry Fees\"] + assetpf_bnh.trades.records_readable[\"Exit Fees\"]\n",
    "total_assetfees.vbt.plot(title=f\"{assetdf.name} | Total Fees\", trace_kwargs=dict(name=u\"\\u00A4\"), height=cheight // 2, width=cwidth).show_png()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c4ac309d-b834-43c0-b99e-05458f5eba55",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "698c7cd9-dec0-42c0-90e1-edf6cf43113e",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "2f1db047-adfc-4095-9c58-c782fd0085d1",
   "metadata": {},
   "source": [
    "## Signal Plots"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "26f2e079-ffc7-4047-908f-3badf0ce94fe",
   "metadata": {},
   "outputs": [],
   "source": [
    "vbt.settings.set_theme(\"dark\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "56c982d5-f6a1-4ed0-94b4-97b492cea01f",
   "metadata": {},
   "source": [
    "### Benchmark"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "a7c9675c-0019-490f-a230-689aecba1c0f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 86664 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "benchmarkpf_signals.trades.plot(title=f\"{benchmarkdf.name} | Trades\", height=cheight, width=cwidth).show_png()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "d7aba265-f0d9-4377-810c-23877e849ee4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 49688 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "benchmarkpf_signals.value().vbt.plot(title=f\"{benchmarkdf.name} | Equity Curve\", trace_kwargs=dict(name=u\"\\u00A4\"), height=cheight // 2, width=cwidth).show_png()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "59fbacad-e920-4b1d-81de-34dbb4fe772a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 58952 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "benchmarkpf_signals.drawdown().vbt.plot(title=f\"{benchmarkdf.name} | Drawdown\", trace_kwargs=dict(name=\"%\"), height=cheight // 2, width=cwidth).show_png()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "efa2a030-d345-4253-82cd-d41644ab3d19",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 39292 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "benchmarkpf_signals.trades.plot_pnl(title=f\"{benchmarkdf.name} | PnL\", height=cheight // 2, width=cwidth).show_png()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "0152d91e-c129-4e10-897f-fc9f832bbb5e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 52256 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "benchmarkpf_signals.asset_returns().vbt.plot(title=f\"{benchmarkdf.name} | Asset Returns\", trace_kwargs=dict(name=\"%\"), height=cheight // 2, width=cwidth).show_png()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "7b3ea536-cb90-4eef-aa3d-d37a0639a6f2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 58464 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "benchmarkpf_signals.cash().vbt.plot(title=f\"{benchmarkdf.name} | Cash\", trace_kwargs=dict(name=u\"\\u00A4\"), height=cheight // 2, width=cwidth).show_png()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "6305826c-d02c-4d3c-b754-1623f3e1f37f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 37060 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "total_assetfees = benchmarkpf_signals.trades.records_readable[\"Entry Fees\"] + benchmarkpf_signals.trades.records_readable[\"Exit Fees\"]\n",
    "total_assetfees.vbt.plot(title=f\"{benchmarkdf.name} | Total Fees\", trace_kwargs=dict(name=u\"\\u00A4\"), height=cheight // 2, width=cwidth).show_png()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "de460913-d69d-4fe1-8d5f-21f107c334e9",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "aac6ae83-46b5-447c-99ed-0d30fd64cb0f",
   "metadata": {},
   "source": [
    "### Asset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "d52dc534-ba16-4dc6-a8ab-fa358e3b1e7a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 82756 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "assetpf_signals.trades.plot(title=f\"{assetdf.name} | Trades\", height=cheight, width=cwidth).show_png()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "46e75cf4-78ea-46ff-a9e4-bd56c9d946e8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 52028 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "assetpf_signals.value().vbt.plot(title=f\"{assetdf.name} | Equity Curve\", trace_kwargs=dict(name=u\"\\u00A4\"), height=cheight // 2, width=cwidth).show_png()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "id": "153347c4-d673-498e-b14e-cdbdf4753562",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 60304 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "assetpf_signals.drawdown().vbt.plot(title=f\"{assetdf.name} | Drawdown\", trace_kwargs=dict(name=\"%\"), height=cheight // 2, width=cwidth).show_png()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "id": "57cfbcaa-2796-4161-815f-54a74c4379cd",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 35184 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "assetpf_signals.trades.plot_pnl(title=f\"{assetdf.name} | PnL\", height=cheight // 2, width=cwidth).show_png()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "id": "812803e3-5448-4f59-81ce-20ed154f1ac7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 59736 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "assetpf_signals.asset_returns().vbt.plot(title=f\"{assetdf.name} | Asset Returns\", trace_kwargs=dict(name=\"%\"), height=cheight // 2, width=cwidth).show_png()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "id": "7c8bc78b-7d7b-40e7-a4e0-817389efbc36",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 56376 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "assetpf_signals.cash().vbt.plot(title=f\"{assetdf.name} | Cash\", trace_kwargs=dict(name=u\"\\u00A4\"), height=cheight // 2, width=cwidth).show_png()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "e492d13a-4493-4dc9-a5c5-7e0727a36746",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 36076 characters]"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "total_assetfees = assetpf_signals.trades.records_readable[\"Entry Fees\"] + assetpf_signals.trades.records_readable[\"Exit Fees\"]\n",
    "total_assetfees.vbt.plot(title=f\"{assetdf.name} | Total Fees\", trace_kwargs=dict(name=u\"\\u00A4\"), height=cheight // 2, width=cwidth).show_png()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1343a6b8-8e70-426e-9b58-a091b114b465",
   "metadata": {},
   "source": [
    "# Disclaimer\n",
    "* All investments involve risk, and the past performance of a security, industry, sector, market, financial product, trading strategy, or individual’s trading does not guarantee future results or returns. Investors are fully responsible for any investment decisions they make. Such decisions should be based solely on an evaluation of their financial circumstances, investment objectives, risk tolerance, and liquidity needs.\n",
    "\n",
    "* Any opinions, news, research, analyses, prices, or other information offered is provided as general market commentary, and does not constitute investment advice. I will not accept liability for any loss or damage, including without limitation any loss of profit, which may arise directly or indirectly from use of or reliance on such information."
   ]
  }
 ],
 "metadata": {
  "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.9.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
