Spotting TSX Gamma

This is just a small notebook/back I run on the cloud to compute the Gamma on XIU/TSX for the day. This take a helluva long time to run, so I should switch to a lighter option model.

In [0]:
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers

import numpy as np

import re
import pandas as pd
from pprint import pprint
import networkx as nx

import json

import matplotlib.pyplot as plt

#Sci-Kit Learn Classification Trees
import sklearn as skl
from sklearn.tree import DecisionTreeClassifier
from sklearn.tree import DecisionTreeRegressor
from sklearn.linear_model import LinearRegression
from sklearn.linear_model import PassiveAggressiveRegressor
from sklearn.linear_model import PassiveAggressiveClassifier
from sklearn.linear_model import LogisticRegression


from sklearn.ensemble import VotingClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score

from sklearn.model_selection import train_test_split

from sklearn import tree


# Gensim
import gensim
import gensim.corpora as corpora
from gensim.utils import simple_preprocess
from gensim.models import CoherenceModel
from gensim.test.utils import datapath

import spacy

import csv


!pip install mibian
import mibian as mb
Collecting mibian
  Downloading https://files.pythonhosted.org/packages/e5/74/25719d1f66b84561f209692947980660268cf601dc92766547b626eb03d5/mibian-0.1.3.tar.gz
Building wheels for collected packages: mibian
  Building wheel for mibian (setup.py) ... done
  Created wheel for mibian: filename=mibian-0.1.3-cp36-none-any.whl size=4041 sha256=a9087ef7a08844f31972965fe8bcbc1ee1165f63f9536b24a230039a65e44303
  Stored in directory: /root/.cache/pip/wheels/34/c7/51/22486b811445a01dab50193c9748e94242e55a4ce686a24240
Successfully built mibian
Installing collected packages: mibian
Successfully installed mibian-0.1.3
In [0]:
from google.colab import drive
drive.mount('/content/gdrive')
Go to this URL in a browser: https://accounts.google.com/o/oauth2/auth?client_id=947318989803-6bn6qk8qdgf4n4g3pfee6491hc0brc4i.apps.googleusercontent.com&redirect_uri=urn%3aietf%3awg%3aoauth%3a2.0%3aoob&response_type=code&scope=email%20https%3a%2f%2fwww.googleapis.com%2fauth%2fdocs.test%20https%3a%2f%2fwww.googleapis.com%2fauth%2fdrive%20https%3a%2f%2fwww.googleapis.com%2fauth%2fdrive.photos.readonly%20https%3a%2f%2fwww.googleapis.com%2fauth%2fpeopleapi.readonly

Enter your authorization code:
··········
Mounted at /content/gdrive
In [0]:
symbol = 'XIU'

datapath = 'https://www.m-x.ca/nego_fin_jour_en.php?symbol='+symbol+'&from=2020-05-05&to=2020-05-05&dnld=1'

raw_dataset = pd.read_csv(datapath)

print(raw_dataset
      )
           Date              Symbol  ... Open Interest Implied Volatility
0    2020-05-05                 XIU  ...             0              0.000
1    2020-05-05  XIU   200508C18.25  ...             0            110.695
2    2020-05-05  XIU   200508C18.50  ...            30            110.554
3    2020-05-05  XIU   200508C18.75  ...           150            104.245
4    2020-05-05  XIU   200508C19.00  ...             0             97.981
..          ...                 ...  ...           ...                ...
714  2020-05-05  XIU   220318P25.00  ...             2             14.869
715  2020-05-05  XIU   220318P26.00  ...             5             32.786
716  2020-05-05  XIU   220318P27.00  ...             0             33.200
717  2020-05-05  XIU   220318P28.00  ...             5             33.636
718  2020-05-05  XIU   220318P29.00  ...            65             34.169

[719 rows x 25 columns]
In [0]:
dataset = raw_dataset.iloc[1:]

print(dataset.columns)


sharesFilter = dataset['Symbol'] == symbol
share_data = dataset[sharesFilter]



optionsFilter = dataset['Symbol'] != symbol
option_data = dataset[optionsFilter]

share_data['Date'] = pd.to_datetime(share_data['Date'], unit = 'ns')
option_data['Date'] = pd.to_datetime(option_data['Date'], unit = 'ns')
option_data['Expiry'] = pd.to_datetime(option_data['Expiry Date'], unit = 'ns')

#share_data.set_index('Date')
#option_data.set_index('Date')

option_data['Time_To_Expiry'] = (option_data['Expiry'] - option_data['Date']).dt.days + 1

option_data.loc[(option_data['Time_To_Expiry'] < 1)] = 1

print(raw_dataset['Last Close Price'][0])

#print(option_data[['Symbol', 'Call/Put']])

option_data['Underlying'] = raw_dataset['Last Close Price'][0]

option_data['Call/Put'].loc[option_data['Call/Put'] == 1] = -1 #Set PUTS to -1
option_data['Call/Put'].loc[option_data['Call/Put'] == 0] = 1  #Set CALLS to 1


#share_data = share_data[['Date','Last Close Price']]
option_data = option_data[['Date', 'Symbol', 'Last Close Price','Time_To_Expiry', 'Strike Price',	'Call/Put', 'Underlying', 'Implied Volatility', 'Open Interest']]

print(share_data.tail())
print(option_data.tail())
Index(['Date', 'Symbol', 'Class Symbol', 'Root Symbol', 'Underlying Symbol',
       'Strike Price', 'Expiry Date', 'Call/Put', 'Ins. Type', 'Bid Price',
       'Ask Price', 'Bid Size', 'Ask Size', 'Last Price', 'Volume',
       'Last Close Price', 'Net Change', 'Open Price', 'High Price',
       'Low Price', 'Total Value', 'Nb. Trades', 'Settlement Price',
       'Open Interest', 'Implied Volatility'],
      dtype='object')
22.58
Empty DataFrame
Columns: [Date, Symbol, Class Symbol, Root Symbol, Underlying Symbol, Strike Price, Expiry Date, Call/Put, Ins. Type, Bid Price, Ask Price, Bid Size, Ask Size, Last Price, Volume, Last Close Price, Net Change, Open Price, High Price, Low Price, Total Value, Nb. Trades, Settlement Price, Open Interest, Implied Volatility]
Index: []
                    Date              Symbol  ...  Implied Volatility  Open Interest
714  2020-05-05 00:00:00  XIU   220318P25.00  ...              14.869              2
715  2020-05-05 00:00:00  XIU   220318P26.00  ...              32.786              5
716  2020-05-05 00:00:00  XIU   220318P27.00  ...              33.200              0
717  2020-05-05 00:00:00  XIU   220318P28.00  ...              33.636              5
718  2020-05-05 00:00:00  XIU   220318P29.00  ...              34.169             65

[5 rows x 9 columns]
/usr/local/lib/python3.6/dist-packages/pandas/core/indexing.py:671: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  self._setitem_with_indexer(indexer, value)
In [0]:
def parse_gamma(date) :

  today_options = option_data.loc[option_data['Date'] == date]

  today_options['Delta'] = today_options.apply(lambda a: mb.BS([a['Underlying'], a['Strike Price'], 0, a['Time_To_Expiry']], volatility = a['Implied Volatility']).callDelta, axis = 1)
  today_options['Theta'] = today_options.apply(lambda a: mb.BS([a['Underlying'], a['Strike Price'], 0, a['Time_To_Expiry']], volatility = a['Implied Volatility']).callTheta, axis = 1)
  today_options['Gamma'] = today_options.apply(lambda a: mb.BS([a['Underlying'], a['Strike Price'], 0, a['Time_To_Expiry']], volatility = a['Implied Volatility']).gamma, axis = 1)
  today_options['Vega']  = today_options.apply(lambda a: mb.BS([a['Underlying'], a['Strike Price'], 0, a['Time_To_Expiry']], volatility = a['Implied Volatility']).vega, axis = 1)

  today_options['Dollar Gamma'] = today_options['Open Interest'] * today_options['Gamma'] * today_options['Call/Put'] * 100

  print(today_options['Dollar Gamma'].cumsum())

  return today_options['Dollar Gamma']


def parse_strike_gamma(strike) :

  strike_options = option_data.loc[option_data['Strike Price'] == strike]

  strike_options['Delta'] = strike_options.apply(lambda a: mb.BS([a['Underlying'], a['Strike Price'], 0, a['Time_To_Expiry']], volatility = a['Implied Volatility']).callDelta, axis = 1)
  strike_options['Theta'] = strike_options.apply(lambda a: mb.BS([a['Underlying'], a['Strike Price'], 0, a['Time_To_Expiry']], volatility = a['Implied Volatility']).callTheta, axis = 1)
  strike_options['Gamma'] = strike_options.apply(lambda a: mb.BS([a['Underlying'], a['Strike Price'], 0, a['Time_To_Expiry']], volatility = a['Implied Volatility']).gamma, axis = 1)
  strike_options['Vega']  = strike_options.apply(lambda a: mb.BS([a['Underlying'], a['Strike Price'], 0, a['Time_To_Expiry']], volatility = a['Implied Volatility']).vega, axis = 1)


  strike_options['Dollar Gamma'] = strike_options['Open Interest'] * strike_options['Gamma'] * strike_options['Call/Put'] * 100

  print('Strike: %f', strike)
  print(strike_options['Dollar Gamma'].sum())

  return strike_options['Dollar Gamma']


full_gex = []
day_gex = []

def find_gex() :
  for date in share_data['Date'] :
  
    mask = (option_data['Date'] < date)

    prior_options = option_data[mask]

    for strike in prior_options['Strike Price'] :

      strike_gex = parse_strike_gamma(strike)
      gex = strike_gex.sum()
      day_gex.append(gex)

    day_gex_sum = np.sum(day_gex)
    full_gex.append(day_gex_sum)


find_gex()

day_gex = parse_gamma(option_data['Date'])

dayGEX = pd.DataFrame(day_gex)
dayGEX['Date'] = share_data['Date']

share_data['GEX'] = day_gex


print(share_data['GEX'])

for date in share_data['Date'] : day_gex = parse_gamma(date)

gex = day_gex.sum()

full_gex.append(gex)

share_data['GEX'].loc[share_data['Date'] == date] = day_gex.cumsum

print('Moving through dates!')

In [0]:
share_data['Day Move'] = share_data['Last Price'] - share_data['Open Price']
share_data['Day P/L'] = share_data['Day Move'] / share_data['Open Price'] * 100
/usr/local/lib/python3.6/dist-packages/ipykernel_launcher.py:1: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  """Entry point for launching an IPython kernel.
/usr/local/lib/python3.6/dist-packages/ipykernel_launcher.py:2: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  
In [0]:
x = share_data['GEX']
y = share_data['Day P/L']

plt.figure(0)

plt.scatter(x, y)

plt.xlabel('Market Gamma (Billions)')
plt.ylabel('Market P/L (%)')
plt.grid(color='g', linestyle='-', linewidth=0.3)
plt.show()
In [0]:
option_data['Delta'] = option_data.apply(lambda a: mb.BS([a['Underlying'], a['Strike Price'], 0, a['Time_To_Expiry']], volatility = a['Implied Volatility']).callDelta, axis = 1)
option_data['Theta'] = option_data.apply(lambda a: mb.BS([a['Underlying'], a['Strike Price'], 0, a['Time_To_Expiry']], volatility = a['Implied Volatility']).callTheta, axis = 1)
option_data['Gamma'] = option_data.apply(lambda a: mb.BS([a['Underlying'], a['Strike Price'], 0, a['Time_To_Expiry']], volatility = a['Implied Volatility']).gamma, axis = 1)
option_data['Vega']  = option_data.apply(lambda a: mb.BS([a['Underlying'], a['Strike Price'], 0, a['Time_To_Expiry']], volatility = a['Implied Volatility']).vega, axis = 1)

print(option_data[['Delta', 'Theta', 'Vega', 'Gamma']])
        Delta     Theta      Vega     Gamma
1    0.970965 -0.021659  0.001565  0.025308
2    0.962452 -0.026735  0.001935  0.031319
3    0.960608 -0.026214  0.002012  0.034538
4    0.958565 -0.025672  0.002096  0.038287
5    0.956285 -0.025105  0.002189  0.042694
..        ...       ...       ...       ...
714  0.345000 -0.001239  0.113803  0.080222
715  0.464058 -0.002946  0.122724  0.039234
716  0.433857 -0.002954  0.121527  0.038367
717  0.406127 -0.002950  0.119797  0.037331
718  0.381457 -0.002945  0.117744  0.036119

[718 rows x 4 columns]
In [0]:
option_data['Dollar Gamma'] = option_data['Open Interest'] * option_data['Gamma'] * option_data['Call/Put'] * 100

#(option_data['Open Interest'] * 100 * option_data['Gamma']) * (option_data['Underlying'] ^ 2 / 100)

print(option_data.dtypes)
print(option_data[['Symbol', 'Delta', 'Theta', 'Gamma', 'Dollar Gamma']])
print(option_data['Dollar Gamma'].cumsum())


strike_data = option_data.groupby('Strike Price').cumsum()

print(strike_data['Dollar Gamma'])

output_datapath = '/content/gdrive/My Drive/MX Option Data/TSX_Gamma.csv'
strike_data.to_csv(path_or_buf=output_datapath)
Date                   object
Symbol                 object
Last Close Price      float64
Time_To_Expiry          int64
Strike Price          float64
Call/Put                int64
Underlying            float64
Implied Volatility    float64
Open Interest           int64
Delta                 float64
Theta                 float64
Gamma                 float64
Vega                  float64
Dollar Gamma          float64
dtype: object
                 Symbol     Delta     Theta     Gamma  Dollar Gamma
1    XIU   200508C18.25  0.970965 -0.021659  0.025308      0.000000
2    XIU   200508C18.50  0.962452 -0.026735  0.031319     93.958258
3    XIU   200508C18.75  0.960608 -0.026214  0.034538    518.072924
4    XIU   200508C19.00  0.958565 -0.025672  0.038287      0.000000
5    XIU   200508C19.25  0.956285 -0.025105  0.042694      0.000000
..                  ...       ...       ...       ...           ...
714  XIU   220318P25.00  0.345000 -0.001239  0.080222    -16.044479
715  XIU   220318P26.00  0.464058 -0.002946  0.039234    -19.617175
716  XIU   220318P27.00  0.433857 -0.002954  0.038367     -0.000000
717  XIU   220318P28.00  0.406127 -0.002950  0.037331    -18.665410
718  XIU   220318P29.00  0.381457 -0.002945  0.036119   -234.770638

[718 rows x 5 columns]
1      0.000000e+00
2      9.395826e+01
3      6.120312e+02
4      6.120312e+02
5      6.120312e+02
           ...     
714   -2.216976e+06
715   -2.216996e+06
716   -2.216996e+06
717   -2.217014e+06
718   -2.217249e+06
Name: Dollar Gamma, Length: 718, dtype: float64
1           0.000000
2          93.958258
3         518.072924
4           0.000000
5           0.000000
           ...      
714    111712.267354
715     87525.802033
716     74439.594612
717     30902.708403
718      -162.272082
Name: Dollar Gamma, Length: 718, dtype: float64
Good Coder, Bad Trader 2020