{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from datetime import datetime\n",
    "from datetime import timedelta\n",
    "from pandas.plotting import register_matplotlib_converters\n",
    "from statsmodels.tsa.stattools import acf, pacf\n",
    "from statsmodels.tsa.arima_model import ARMA\n",
    "register_matplotlib_converters()\n",
    "from time import time"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Catfish Sales Data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "def parser(s):\n",
    "    return datetime.strptime(s, '%Y-%m-%d')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "#read data\n",
    "catfish_sales = pd.read_csv('catfish.csv', parse_dates=[0], index_col=0, squeeze=True, date_parser=parser)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "#infer the frequency of the data\n",
    "catfish_sales = catfish_sales.asfreq(pd.infer_freq(catfish_sales.index))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [],
   "source": [
    "start_date = datetime(2000,1,1)\n",
    "end_date = datetime(2004,1,1)\n",
    "lim_catfish_sales = catfish_sales[start_date:end_date]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 94,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.lines.Line2D at 0x1e8323fd408>"
      ]
     },
     "execution_count": 94,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 43024 characters]\n",
      "text/plain": [
       "<Figure size 720x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=(10,4))\n",
    "plt.plot(lim_catfish_sales)\n",
    "plt.title('Catfish Sales in 1000s of Pounds', fontsize=20)\n",
    "plt.ylabel('Sales', fontsize=16)\n",
    "for year in range(start_date.year,end_date.year):\n",
    "    plt.axvline(pd.to_datetime(str(year)+'-01-01'), color='k', linestyle='--', alpha=0.2)\n",
    "plt.axhline(lim_catfish_sales.mean(), color='r', alpha=0.2, linestyle='--')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "metadata": {},
   "outputs": [],
   "source": [
    "first_diff = lim_catfish_sales.diff()[1:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.lines.Line2D at 0x1e831e40888>"
      ]
     },
     "execution_count": 102,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 49532 characters]\n",
      "text/plain": [
       "<Figure size 720x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=(10,4))\n",
    "plt.plot(first_diff)\n",
    "plt.title('First Difference of Catfish Sales', fontsize=20)\n",
    "plt.ylabel('Sales', fontsize=16)\n",
    "for year in range(start_date.year,end_date.year):\n",
    "    plt.axvline(pd.to_datetime(str(year)+'-01-01'), color='k', linestyle='--', alpha=0.2)\n",
    "plt.axhline(first_diff.mean(), color='r', alpha=0.2, linestyle='--')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# ACF"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<BarContainer object of 20 artists>"
      ]
     },
     "execution_count": 103,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 6164 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "acf_vals = acf(first_diff)\n",
    "plt.bar(range(num_lags), acf_vals[:num_lags])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Based on ACF, we should start with a MA(1) process"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# PACF"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 105,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<BarContainer object of 15 artists>"
      ]
     },
     "execution_count": 105,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 5188 characters]\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "pacf_vals = pacf(first_diff)\n",
    "plt.bar(range(num_lags), pacf_vals[:num_lags])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Based on PACF, we should start with a AR(4) process"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Get training and testing sets"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 148,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_end = datetime(2003,7,1)\n",
    "test_end = datetime(2004,1,1)\n",
    "\n",
    "train_data = first_diff[:train_end]\n",
    "test_data = first_diff[train_end + timedelta(days=1):test_end]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Fit the ARMA Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 197,
   "metadata": {},
   "outputs": [],
   "source": [
    "# define model\n",
    "model = ARMA(train_data, order=(4,1))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 198,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Model Fitting Time: 0.6803164482116699\n"
     ]
    }
   ],
   "source": [
    "#fit the model\n",
    "start = time()\n",
    "model_fit = model.fit()\n",
    "end = time()\n",
    "print('Model Fitting Time:', end - start)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 199,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "                              ARMA Model Results                              \n",
      "==============================================================================\n",
      "Dep. Variable:                  Total   No. Observations:                   42\n",
      "Model:                     ARMA(4, 1)   Log Likelihood                -376.584\n",
      "Method:                       css-mle   S.D. of innovations           1850.781\n",
      "Date:                Mon, 13 Apr 2020   AIC                            767.167\n",
      "Time:                        10:47:08   BIC                            779.331\n",
      "Sample:                    02-01-2000   HQIC                           771.626\n",
      "                         - 07-01-2003                                         \n",
      "===============================================================================\n",
      "                  coef    std err          z      P>|z|      [0.025      0.975]\n",
      "-------------------------------------------------------------------------------\n",
      "const          37.3039    129.751      0.288      0.775    -217.003     291.611\n",
      "ar.L1.Total    -0.8666      0.185     -4.692      0.000      -1.229      -0.505\n",
      "ar.L2.Total    -0.4236      0.166     -2.547      0.015      -0.750      -0.098\n",
      "ar.L3.Total    -0.5584      0.156     -3.579      0.001      -0.864      -0.253\n",
      "ar.L4.Total    -0.6144      0.126     -4.894      0.000      -0.861      -0.368\n",
      "ma.L1.Total     0.5197      0.219      2.370      0.023       0.090       0.950\n",
      "                                    Roots                                    \n",
      "=============================================================================\n",
      "                  Real          Imaginary           Modulus         Frequency\n",
      "-----------------------------------------------------------------------------\n",
      "AR.1            0.4929           -1.0592j            1.1683           -0.1807\n",
      "AR.2            0.4929           +1.0592j            1.1683            0.1807\n",
      "AR.3           -0.9473           -0.5431j            1.0920           -0.4171\n",
      "AR.4           -0.9473           +0.5431j            1.0920            0.4171\n",
      "MA.1           -1.9240           +0.0000j            1.9240            0.5000\n",
      "-----------------------------------------------------------------------------\n"
     ]
    }
   ],
   "source": [
    "#summary of the model\n",
    "print(model_fit.summary())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## So the ARMA(4,1) model is:\n",
    "\n",
    "## $\\hat{y_t} = -0.87y_{t-1} - 0.42y_{t-2} - 0.56y_{t-3} - 0.61y_{t-4} + 0.52\\varepsilon_{t-1}$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 200,
   "metadata": {},
   "outputs": [],
   "source": [
    "#get prediction start and end dates\n",
    "pred_start_date = test_data.index[0]\n",
    "pred_end_date = test_data.index[-1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 201,
   "metadata": {},
   "outputs": [],
   "source": [
    "#get the predictions and residuals\n",
    "predictions = model_fit.predict(start=pred_start_date, end=pred_end_date)\n",
    "residuals = test_data - predictions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 202,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.lines.Line2D at 0x1e8346fe588>"
      ]
     },
     "execution_count": 202,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 24348 characters]\n",
      "text/plain": [
       "<Figure size 720x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=(10,4))\n",
    "plt.plot(residuals)\n",
    "plt.title('Residuals from AR Model', fontsize=20)\n",
    "plt.ylabel('Error', fontsize=16)\n",
    "plt.axhline(0, color='r', linestyle='--', alpha=0.2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 203,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0, 0.5, 'Sales')"
      ]
     },
     "execution_count": 203,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 36232 characters]\n",
      "text/plain": [
       "<Figure size 720x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize=(10,4))\n",
    "\n",
    "plt.plot(test_data)\n",
    "plt.plot(predictions)\n",
    "\n",
    "plt.legend(('Data', 'Predictions'), fontsize=16)\n",
    "\n",
    "plt.title('First Difference of Catfish Sales', fontsize=20)\n",
    "plt.ylabel('Sales', fontsize=16)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 204,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Root Mean Squared Error: 2210.267116397745\n"
     ]
    }
   ],
   "source": [
    "print('Root Mean Squared Error:', np.sqrt(np.mean(residuals**2)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "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.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
