{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "07a8e0d8",
   "metadata": {},
   "source": [
    "## Modified introduction using forex data"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "db9723dc",
   "metadata": {},
   "source": [
    "This is the trading rule example shown in [the introduction](https://github.com/robcarver17/pysystemtrade/blob/master/docs/introduction.md) but modified to use Interactive Brokers instead of CSV files as data source.  \n",
    "\n",
    "IB requires a minimum equity and a monthly subscription to provide historical data on future contracts.  This example was modified to use FX prices instead futures to make it runnable with free unfunded paper trading accounts.  Note that Rob [does not recommend trading FX spot data with IB due to their high fees](https://github.com/robcarver17/pysystemtrade/issues/517#issuecomment-1010770678)."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d855c448",
   "metadata": {},
   "source": [
    "First, import the required packages and initialize ib_insync.  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "3b6f4071",
   "metadata": {},
   "outputs": [],
   "source": [
    "from sysbrokers.IB.ib_connection import connectionIB\n",
    "from sysbrokers.IB.ib_Fx_prices_data import ibFxPricesData\n",
    "\n",
    "from ib_insync import util\n",
    "util.startLoop() #only required when running inside a notebook"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "70963367",
   "metadata": {},
   "source": [
    "Connecting to Interactive Brokers gateway..."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "4ce91bcf",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "IB broker connection{'ipaddress': 'localhost', 'port': 7497, 'client': 111}"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "conn = connectionIB(111)\n",
    "conn"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "77a3526b",
   "metadata": {},
   "source": [
    "See what fx instruments we have configured.  These are configured in `sysbrokers/IB/ib_config_spot_FX.csv`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "86db67ca",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['AUDUSD',\n",
       " 'CADUSD',\n",
       " 'CHFUSD',\n",
       " 'EURUSD',\n",
       " 'GBPUSD',\n",
       " 'HKDUSD',\n",
       " 'JPYUSD',\n",
       " 'KRWUSD',\n",
       " 'CNHUSD',\n",
       " 'SGDUSD']"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ibfxpricedata = ibFxPricesData(conn)\n",
    "ibfxpricedata.get_list_of_fxcodes()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c2dbdd12",
   "metadata": {},
   "source": [
    "Now we select one instrument (`EURUSD`) and try to fetch historical data for it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "6748a9c6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "index\n",
       "2021-01-13 23:00:00    1.215745\n",
       "2021-01-14 23:00:00    1.215415\n",
       "2021-01-15 23:00:00    1.207550\n",
       "2021-01-18 23:00:00    1.207725\n",
       "2021-01-19 23:00:00    1.212885\n",
       "                         ...   \n",
       "2022-01-06 23:00:00    1.129785\n",
       "2022-01-07 23:00:00    1.136100\n",
       "2022-01-10 23:00:00    1.132565\n",
       "2022-01-11 23:00:00    1.136725\n",
       "2022-01-12 23:00:00    1.144345\n",
       "Name: FINAL, Length: 261, dtype: float64"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ibfxpricedata.get_fx_prices('EURUSD')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b480ed7e",
   "metadata": {},
   "source": [
    "Data can also be indexed as a python dict:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "b05e7852",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "index\n",
       "2021-01-13 23:00:00    0.009627\n",
       "2021-01-14 23:00:00    0.009633\n",
       "2021-01-15 23:00:00    0.009627\n",
       "2021-01-18 23:00:00    0.009644\n",
       "2021-01-19 23:00:00    0.009624\n",
       "                         ...   \n",
       "2022-01-06 23:00:00    0.008633\n",
       "2022-01-07 23:00:00    0.008653\n",
       "2022-01-10 23:00:00    0.008680\n",
       "2022-01-11 23:00:00    0.008673\n",
       "2022-01-12 23:00:00    0.008724\n",
       "Name: FINAL, Length: 261, dtype: float64"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ibfxpricedata['JPYUSD']"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "86a059a1",
   "metadata": {},
   "source": [
    "Create the trading rule"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "ab5b324a",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "from sysquant.estimators.vol import robust_vol_calc\n",
    "\n",
    "\n",
    "def calc_ewmac_forecast(price, Lfast, Lslow=None):\n",
    "    \"\"\"\n",
    "    Calculate the ewmac trading rule forecast, given a price and EWMA speeds Lfast, Lslow and vol_lookback\n",
    "\n",
    "    \"\"\"\n",
    "    if Lslow is None:\n",
    "        Lslow = 4 * Lfast\n",
    "\n",
    "    ## We don't need to calculate the decay parameter, just use the span directly\n",
    "    fast_ewma = price.ewm(span=Lfast).mean()\n",
    "    slow_ewma = price.ewm(span=Lslow).mean()\n",
    "    raw_ewmac = fast_ewma - slow_ewma\n",
    "\n",
    "    vol = robust_vol_calc(price.diff())\n",
    "\n",
    "    return raw_ewmac / vol"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "44f122dc",
   "metadata": {},
   "source": [
    "Run a forecast with the previous rule"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "e09da640",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "index\n",
       "2022-01-06 23:00:00   -5.065233\n",
       "2022-01-07 23:00:00   -4.766807\n",
       "2022-01-10 23:00:00   -4.739162\n",
       "2022-01-11 23:00:00   -4.633853\n",
       "2022-01-12 23:00:00   -4.220275\n",
       "Name: FINAL, dtype: float64"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "price=ibfxpricedata['EURUSD']\n",
    "ewmac=calc_ewmac_forecast(price, 32, 128)\n",
    "ewmac.tail(5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "fd8e9ae2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 45712 characters]\n",
      "text/plain": [
       "<Figure size 864x360 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "plt.figure(figsize=(12,5))\n",
    "\n",
    "ax1 = price.plot(color='blue', grid=True, label='Forecast')\n",
    "ax2 = ewmac.plot(color='red', grid=True, secondary_y=True, label='Price')\n",
    "\n",
    "h1, l1 = ax1.get_legend_handles_labels()\n",
    "h2, l2 = ax2.get_legend_handles_labels()\n",
    "\n",
    "\n",
    "plt.legend(h1+h2, l1+l2, loc=2)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "04d63dc1",
   "metadata": {},
   "source": [
    "The original introduction jumps directly to \"Did we make any money?\".  \n",
    "I would like to see here the orders that were triggered by this forecast, but instead we jump directly into P&L.  Still, these are the P&L numbers for this forecast and data:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "2939bcdd",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[('min', '-1.3'),\n",
       "  ('max', '2.03'),\n",
       "  ('median', '0.001141'),\n",
       "  ('mean', '0.00234'),\n",
       "  ('std', '0.3203'),\n",
       "  ('skew', '0.8017'),\n",
       "  ('ann_mean', '0.5691'),\n",
       "  ('ann_std', '5.125'),\n",
       "  ('sharpe', '0.111'),\n",
       "  ('sortino', '0.1469'),\n",
       "  ('avg_drawdown', '-1.24'),\n",
       "  ('time_in_drawdown', '0.9315'),\n",
       "  ('calmar', '0.1697'),\n",
       "  ('avg_return_to_drawdown', '0.4591'),\n",
       "  ('avg_loss', '-0.1954'),\n",
       "  ('avg_gain', '0.1832'),\n",
       "  ('gaintolossratio', '0.9377'),\n",
       "  ('profitfactor', '1.025'),\n",
       "  ('hitrate', '0.5223'),\n",
       "  ('t_stat', '0.115'),\n",
       "  ('p_value', '0.9085')],\n",
       " ('You can also plot / print:',\n",
       "  ['rolling_ann_std', 'drawdown', 'curve', 'percent'])]"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from systems.accounts.account_forecast import pandl_for_instrument_forecast\n",
    "account = pandl_for_instrument_forecast(forecast = ewmac, price = price)\n",
    "account.percent.stats()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "708c4bfa",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 22740 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "account.curve().plot()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "10a52d1a",
   "metadata": {},
   "outputs": [],
   "source": [
    "conn.close_connection()"
   ]
  }
 ],
 "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.8.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
