Last active
May 29, 2018 16:11
-
-
Save kpmiller/0d73a6d3e35e2777443569ef4cc2fb3a to your computer and use it in GitHub Desktop.
python 2.7 code for parsing CSV files saved from thinkorswim
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
import csv, json, sys, re, os | |
import glob | |
try: | |
loglevel = int(os.environ["LOGLEVEL"]) | |
except: | |
loglevel = 1 | |
def Log(s, level=1): | |
if level <= loglevel: | |
print s | |
def CheckFile(filename = None, volumefilter = 100): | |
optcsv = [] | |
f = open(filename, "r") | |
for line in csv.reader(f): | |
optcsv.append(line) | |
f.close() | |
symbol = "" | |
optd = {} | |
key = "" | |
opts = {} | |
underlying = 0.0 | |
state=0 | |
for line in optcsv: | |
#state 0: looking for first line for quote symbol | |
#state 10: looking for "UNDERLYING" | |
#state 11: eating underlying header | |
#state 12: taking underlying | |
#state 1: looking for a date line with a () days to exp | |
#state 2: eat header | |
#state 3: eating lines until empty line, then end date, reset key and opts | |
Log(str(line), 20) | |
Log(str(state), 20) | |
if state == 0: | |
m = re.match(".*option quote for (\w*) on ", line[0]) | |
if m != None: | |
symbol = m.group(1) | |
Log("\nScanning " + symbol, level = 1) | |
state = 10 | |
elif state == 10: | |
if len(line)>0 and line[0].rfind ("UNDERLYING") != -1: | |
state = 11 | |
elif state == 11: | |
state = 12 | |
elif state == 12: | |
underlying = float(line[0]) | |
Log("Quote " + str(underlying), level = 1) | |
state = 1 | |
elif state == 1: | |
if len(line)>0: | |
m = re.match("\d* ... .. \((\d*)\)", line[0]) | |
if m != None: | |
key = line[0] | |
state = 2 | |
elif state == 2: | |
if len(line) == 0: | |
state = 1 | |
else: | |
state = 3 | |
elif state == 3: | |
if len(line) == 0: | |
optd[key] = opts | |
opts = {} | |
key = "" | |
state = 1 | |
else: | |
# ['', '', 'Mark', 'Volume', 'Open.Int', 'Prob.ITM', 'Delta', 'BID', 'BX', 'ASK', 'AX', 'Exp', 'Strike', 'BID', 'BX', 'ASK', 'AX', 'Mark', 'Volume', 'Open.Int', 'Prob.ITM', 'Delta', '', ''] | |
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | |
if line[2] != "<empty>": | |
probcall = line[5].replace("%","") | |
probput = line[20].replace("%","") | |
try: | |
opts[float(line[12])] = { | |
"strike" : float(line[12]), | |
"callmark" : float(line[2]), | |
"probcall" : float(probcall), | |
"callvol" : int(line[4].replace(',','')), | |
"putmark" : float(line[17]), | |
"probput" : float(probput), | |
"putvol" : int(line[19].replace(',','')) | |
} | |
except: | |
pass | |
for key in optd.keys(): | |
m = re.match("\d* ... .. \((\d*)\)", key) | |
#skip if over 75 days out | |
if int(m.group(1)) > 75: | |
continue | |
print key | |
strikes = optd[key] | |
strikeskeys = strikes.keys() | |
strikeskeys.sort() | |
format = "%-10s %-10s %-10s %-10s %-10s" | |
print format % ("strike", "put mark", "put vol", "call mark", "call vol") | |
for strikekey in strikeskeys: | |
info = strikes[strikekey] | |
if info["callvol"] >= volumefilter or info["putvol"] >= volumefilter: | |
print format % (strikekey, info["putmark"], info ["putvol"], info["callmark"], info["callvol"]) | |
print "\n\n\n" | |
if len(sys.argv) == 1: | |
scandir = os.path.abspath(os.path.expanduser("~/Desktop")) | |
else: | |
scandir = os.path.abspath(os.path.expanduser(sys.argv[1])) | |
files = glob.glob(scandir+"/*.csv") | |
for f in files: | |
CheckFile(f) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment