Just a small notebook to find the biggest trades that were taken on M-X for the day. This notebook follows a big trader rolling puts on HMMJ.
import pandas as pd
import csv
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as dates
!pip install mibian
import mibian as mb
End of Day Data can be fetched from the following URL
from google.colab import drive
drive.mount('/content/drive')
symbol = 'HMMJ'
datapath = 'https://www.m-x.ca/nego_fin_jour_en.php?symbol='+symbol+'&from=2019-05-01&to=2019-10-01&dnld=1'
#datapath = '/content/drive/My Drive/MX Option Data/quote_'+symbol+'_20190412_20191010.csv'
full_data_set = pd.read_csv(datapath)
options = full_data_set.loc[full_data_set['Symbol'] != symbol]
options = options.loc[options['Symbol'] != symbol+'.A']
shares = full_data_set.loc[full_data_set['Symbol'] == symbol]
print(options.columns)
options['Date'] = pd.to_datetime(options['Date'])
options['Expiry Date'] = pd.to_datetime(options['Expiry Date'])
shares['Date'] = pd.to_datetime(shares['Date'])
Data has been parsed and separated into big fish day trades.
Let's instead diverge from identfying big fish, and start to evaluate the chain as a whole.
We must begin by tracking the greeks of each trade. From there, was can create the overall equity's gamma exposrue throughn options.
With this data, predictions could be made for the closign price of the underlying asset on expiration dates. Allowing fro weekly movement predictions.
It could be possible to use ML techniques to make said predictions.
A simple regressive decision tree may be able to make those predictions using an array of trade data.
print(shares.head(5))
print(options.head(5))
# I like to see the data before I work with it. Not preprocessing, just making sure the computer and I are trying to talk about the same thing.
volumes = options['Volume']
volume_std = np.std(volumes) #Basic Volume Standard Deviation for all strikes/expiries on a daily basis.
big_fish_limit = 7.0 #How big of a fish do we want to catch? Based on STDs, 7 represents the biggest of volume.
print(volume_std)
options['Capital'] = options['Last Price'] * options['Volume'] * 100 #Assume that all volume was executed at the EoD "Last" Price. This is a major flaw imho, but we are limited by m-x EoD data.
#"Big Fish" are our unusual activity. We want to know a few things;
# They're moving volume way bigger than the daily expected volume (volume_std)
# Their trade volume is larger than existing open interest. This sugggests they are opening a position.
# Finally, we want to be sure they're moving an egregious amount of capital for the Canadian Equity Derivatives market.
big_fish = options.loc[(options['Volume'] > (big_fish_limit * volume_std)) & (options['Volume'] > options['Open Interest']) & (options['Capital'] > 1000)]
print(big_fish['Capital'])
#Reducing our data down to the columns we actually
parsed_fish = big_fish[['Date', 'Symbol', 'Strike Price', 'Expiry Date', 'Last Price', 'Volume', 'Open Interest', 'Capital']]
print(parsed_fish[['Date', 'Symbol', 'Capital', 'Volume', 'Open Interest']])
#@title Default title text
#options.reset_index(drop=True)
#big_fish.reset_index(drop=True)
signal_trades = options.loc[options['Symbol'].isin(big_fish['Symbol'])] #Pull out the contract history for any contract that was moved by a big fish.
expiries = signal_trades.loc[signal_trades['Date'] == signal_trades['Expiry Date']] #What did those contracts look like at expiry?
highest = signal_trades.loc[signal_trades.groupby('Symbol')['Last Price'].idxmax(), :] #At what price did they trade the highest, and when?
#Maybe our big fish closed? Let's give a "rough chop" at potentially identifying these exits.
# We want to be sure there's a ton of Open Interest already.
# We also want to know that it's still big volume trading. Capital is less important now.
possible_exits = options.loc[(options['Volume'] > (0.3 * options['Open Interest'])) & (options['Open Interest'] > (7 * volume_std))]
#Let's see what we got for this equity :
print(parsed_fish[['Date', 'Symbol', 'Last Price', 'Volume', 'Open Interest']])
print(expiries[['Date', 'Symbol', 'Last Price', 'Volume', 'Open Interest']])
print(highest[['Date', 'Symbol', 'Last Price', 'Volume', 'Open Interest']])
print(possible_exits[['Date', 'Symbol', 'Last Price', 'Volume', 'Open Interest']])
Who's taking the biggest risks with the most capital? I want to follow those with the most risk and risk-off when those other fish risk off aswell.
Do these fish make money?
total_profit = np.empty(big_fish['Symbol'].shape)
total_percent_profit = np.empty(big_fish['Symbol'].shape)
#This "Backtest" is pretty useless. It's certainly not a robust test.
#We're just checking to see if the big fish were given better prices, and if they made money.
def backtest(contract, index) :
total_contract_history = options.loc[options['Symbol'] == contract['Symbol']]
trimmed_contract_history = total_contract_history.loc[total_contract_history['Date'] >= contract['Date']]
#print(trimmed_contract_history[['Date', 'Symbol', 'Last Price', 'Open Interest']])
max_realized = trimmed_contract_history.loc[trimmed_contract_history['Last Price'].idxmax()]
#print(max_realized['Last Price'].dtypes)
total_profit[index] = max_realized['Last Price'] - contract['Last Price']
total_percent_profit[index] = (max_realized['Last Price'] - contract['Last Price']) / contract['Last Price'] * 100
if max_realized['Last Price'] - contract['Last Price'] == 0 :
total_profit[index] = -contract['Last Price']
total_percent_profit[index] = -100
max_realized['Last Price'] = 0
#if max_realized
print(total_profit[index])
print(total_percent_profit[index])
print(f"Contract opened for: {contract['Last Price']}")
print(f"Contract closed for: {max_realized['Last Price']}")
big_fish = big_fish.reset_index(drop = True)
print(big_fish)
for index, contract in big_fish.iterrows():
backtest(contract, index)
print(total_percent_profit)
plt.figure(1)
plt.plot(np.cumsum(total_percent_profit))
Time for some fun charts!
!pip install backtesting
from backtesting import Backtest
from backtesting.lib import SignalStrategy, TrailingStrategy
print(shares.columns)
historical_SPX_closes = shares[['Date','Open Price','High Price','Low Price','Last Close Price']]
column_names = ['Date','Open','High','Low','Close']
backtest_data = pd.DataFrame(historical_SPX_closes, columns = column_names)
backtest_data.Open = historical_SPX_closes['Open Price']
backtest_data.High = historical_SPX_closes['High Price']
backtest_data.Low = historical_SPX_closes['Low Price']
backtest_data.Close = historical_SPX_closes['Last Close Price']
backtest_data.fillna(1)
backtest_dates = shares['Date']
print(backtest_dates.head(5))
k_signal = []
for date in backtest_dates :
for entry in big_fish.Date :
if date == entry :
trade = big_fish.loc[big_fish['Date'] == entry]
if trade['Call/Put'].any() :
k_signal.append(-1)
else:
print(trade['Call/Put'])
k_signal.append(1)
break;
k_signal.append(0)
print(k_signal)
class kCluster(SignalStrategy, TrailingStrategy):
def init(self):
super().init()
print(self.data.index)
self.set_signal(k_signal)
self.set_atr_periods(10)
self.set_trailing_sl(4)
#backtest_data.reset_index(drop=True, inplace=True)
print(backtest_data.head(50))
print(backtest_data.tail(5))
backtest = Backtest(backtest_data, kCluster, commission=0.002)
backtest.run()
backtest.plot()