{ "cells": [ { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "import warnings\n", "import numpy as np\n", "import pandas as pd\n", "import matplotlib.pyplot as plt\n", "from datetime import datetime\n", "from statsmodels.tsa.stattools import grangercausalitytests\n", "from vortexasdk import CargoTimeSeries, Products, Geographies\n", "\n", "warnings.filterwarnings(\"ignore\")\n", "plt.rcParams['figure.figsize'] = (15, 10)\n", "plt.rcParams.update({'font.size': 14})\n", "pd.options.display.max_columns = None" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [], "source": [ "UNIT = 't'\n", "\n", "START_DATE = datetime(2016, 1, 21)\n", "END_DATE = datetime(2020, 1, 21)\n", "\n", "DATE_RANGE = pd.date_range(START_DATE, END_DATE)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Pre-defined functions / variables" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2020-04-21 10:18:20,592 vortexasdk.operations — INFO — Searching Products with params: {'term': ['crude'], 'ids': [], 'product_parent': [], 'allowTopLevelProducts': True}\n", "2020-04-21 10:18:21,011 vortexasdk.client — INFO — 18 Results to retreive. Sending 1 post requests in parallel using 6 threads.\n" ] } ], "source": [ "# Find Crude/Condensates ID, ensuring its uniqueness\n", "crude_and_condensates = [p.id for p in Products().search('crude').to_list() if p.name=='Crude/Condensates']\n", "assert len(crude_and_condensates) == 1" ] }, { "cell_type": "code", "execution_count": 39, "metadata": {}, "outputs": [], "source": [ "def load_nymex_future_prices_from_EIA():\n", " future_prices = pd.read_excel('https://www.eia.gov/dnav/pet/xls/PET_PRI_FUT_S1_D.xls', sheet_name='Data 1', skiprows=[0,1])\n", " future_prices = future_prices.set_index('Date').fillna(method='ffill').reindex(DATE_RANGE, method='ffill')\n", " return future_prices" ] }, { "cell_type": "code", "execution_count": 40, "metadata": {}, "outputs": [], "source": [ "def load_spot_prices_from_EIA():\n", " spot_prices = pd.read_excel('https://www.eia.gov/dnav/pet/xls/PET_PRI_SPT_S1_D.xls', sheet_name='Data 1', skiprows=[0,1])\n", " spot_prices = spot_prices.set_index('Date').fillna(method='ffill').reindex(DATE_RANGE, method='ffill')\n", " return spot_prices" ] }, { "cell_type": "code", "execution_count": 41, "metadata": {}, "outputs": [], "source": [ "def plot_floating_storage(floating_storage):\n", " floating_storage.plot(title='Global crude oil floating storage', grid=True)\n", " plt.xlabel('date')\n", " plt.ylabel('k' + UNIT);" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [], "source": [ "def plot_prices(prices, title):\n", " prices.plot(title=title, grid=True)\n", " plt.xlabel('date')\n", " plt.ylabel('USD'); " ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [], "source": [ "def plot_granger_pvalues(series_x, series_y, maxlag, label_x, label_y, test='ssr_ftest', confidence_level=0.05):\n", " lags = np.arange(1, maxlag+1)\n", "\n", " plt.subplot('211')\n", " gct_x_y = grangercausalitytests(pd.concat([series_y, series_x], axis=1), maxlag=maxlag, verbose=False)\n", " pvalue_x_y = pd.Series([gct_x_y[lag][0][test][1] for lag in lags], index=lags)\n", " pvalue_x_y.plot(title=f'{label_x} -> {label_y}', grid=True)\n", " plt.plot((0, maxlag),(confidence_level, confidence_level),'--r')\n", " plt.ylabel('p-value')\n", "\n", " plt.subplot('210')\n", " gct_y_x = grangercausalitytests(pd.concat([series_x, series_y], axis=1), maxlag=maxlag, verbose=False)\n", " pvalue_y_x = pd.Series([gct_y_x[lag][0][test][1] for lag in lags], index=lags)\n", " pvalue_y_x.plot(title=f'{label_y} -> {label_x}', grid=True)\n", " plt.plot((0, maxlag),(confidence_level, confidence_level),'--r')\n", " plt.xlabel('lag [days]')\n", " plt.ylabel('p-value')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Load Data" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [], "source": [ "def fetch_global_crude_floating_storage_timeseries(start_date, end_date, unit='t'): \n", " \n", " df = CargoTimeSeries().search(timeseries_frequency='day',\n", " timeseries_unit=unit,\n", " disable_geographic_exclusion_rules=True,\n", " filter_products=crude_and_condensates,\n", " filter_activity=\"storing_state\",\n", " filter_time_min=start_date,\n", " filter_time_max=end_date).to_df()\n", "\n", " df = df.rename(columns={'key': 'date',\n", " 'value': unit,\n", " 'count': 'number_of_cargo_movements'})\n", " \n", "\n", " df['date'] = pd.to_datetime(df['date']).dt.tz_localize(None)\n", " \n", " return df" ] }, { "cell_type": "code", "execution_count": 45, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2020-04-21 10:18:24,383 vortexasdk.operations — INFO — Searching CargoTimeSeries with params: {'filter_activity': 'storing_state', 'filter_time_min': '2016-01-21T00:00:00.000Z', 'filter_time_max': '2020-01-21T00:00:00.000Z', 'timeseries_activity_time_span_min': None, 'timeseries_activity_time_span_max': None, 'filter_charterers': [], 'filter_owners': [], 'filter_products': ['54af755a090118dcf9b0724c9a4e9f14745c26165385ffa7f1445bc768f06f11'], 'filter_vessels': [], 'filter_destinations': [], 'filter_origins': [], 'filter_storage_locations': [], 'filter_ship_to_ship_locations': [], 'filter_waypoints': [], 'disable_geographic_exclusion_rules': True, 'timeseries_frequency': 'day', 'timeseries_unit': 't', 'timeseries_activity': 'storing_state', 'size': 500}\n" ] } ], "source": [ "df_fs = fetch_global_crude_floating_storage_timeseries(START_DATE, END_DATE, UNIT)" ] }, { "cell_type": "code", "execution_count": 46, "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", " | date | \n", "t | \n", "number_of_cargo_movements | \n", "
---|---|---|---|
1457 | \n", "2020-01-17 | \n", "8276023 | \n", "110 | \n", "
1458 | \n", "2020-01-18 | \n", "8759042 | \n", "120 | \n", "
1459 | \n", "2020-01-19 | \n", "9257589 | \n", "134 | \n", "
1460 | \n", "2020-01-20 | \n", "7952018 | \n", "127 | \n", "
1461 | \n", "2020-01-21 | \n", "6987858 | \n", "111 | \n", "