Skip to content

Instantly share code, notes, and snippets.

@ezl
Last active December 31, 2021 10:31
Show Gist options
  • Save ezl/11127434 to your computer and use it in GitHub Desktop.
Save ezl/11127434 to your computer and use it in GitHub Desktop.
Are there any put-call parity opportunities? Lets check facebook options
"""
Checking for put-call parity mispricings in facebook.
fb is American, so put call parity doesn't actually apply, but
this is a short term option, with no dividends between now and the
expiration (apr 17, 1 week option), in a low interest rate environment
so you can expect the trees to act almost european.
easier to find this data on yahoo than actual european data and
everyone knows what facebook is so i went with it.
"""
spot = 58.94 # current Facebook price
rate = 0.0075 # fed funds
t = 5 / 252.0
class Option(object):
def __init__(self, strike, call_bid, call_offer, put_bid, put_offer):
self.strike = strike
self.call_bid = call_bid
self.call_offer = call_offer
self.put_bid = put_bid
self.put_offer = put_offer
# options prices taken from http://finance.yahoo.com/q/os?s=FB&m=2014-04-25 on 4/20/2014
# http://i.imgur.com/4pVwBUn.png
options = [
Option(strike=45.00, call_bid=13.85, call_offer=14.25, put_bid=0.10, put_offer=0.13),
Option(strike=48.00, call_bid=11.10, call_offer=11.50, put_bid=0.28, put_offer=0.31),
Option(strike=50.00, call_bid=9.40, call_offer=9.65, put_bid=0.52, put_offer=0.55),
Option(strike=52.50, call_bid=7.40, call_offer=7.55, put_bid=1.00, put_offer=1.02),
Option(strike=55.00, call_bid=5.60, call_offer=5.70, put_bid=1.72, put_offer=1.73),
Option(strike=57.50, call_bid=4.10, call_offer=4.20, put_bid=2.69, put_offer=2.74),
Option(strike=59.00, call_bid=3.35, call_offer=3.40, put_bid=3.35, put_offer=3.45),
Option(strike=60.00, call_bid=2.86, call_offer=2.90, put_bid=3.90, put_offer=4.00),
Option(strike=61.00, call_bid=2.41, call_offer=2.47, put_bid=4.45, put_offer=4.55),
Option(strike=62.00, call_bid=2.02, call_offer=2.07, put_bid=5.05, put_offer=5.15),
Option(strike=63.00, call_bid=1.67, call_offer=1.71, put_bid=5.70, put_offer=5.80),
Option(strike=64.00, call_bid=1.36, call_offer=1.38, put_bid=6.40, put_offer=6.50),
Option(strike=65.00, call_bid=1.10, call_offer=1.13, put_bid=7.10, put_offer=7.25),
Option(strike=65.50, call_bid=0.97, call_offer=1.02, put_bid=7.45, put_offer=7.65),
Option(strike=66.00, call_bid=0.86, call_offer=0.91, put_bid=7.85, put_offer=8.00),
Option(strike=66.50, call_bid=0.76, call_offer=0.81, put_bid=8.25, put_offer=8.40),
Option(strike=67.00, call_bid=0.67, call_offer=0.72, put_bid=8.65, put_offer=8.90),
Option(strike=67.50, call_bid=0.59, call_offer=0.64, put_bid=9.05, put_offer=9.25),
Option(strike=68.00, call_bid=0.51, call_offer=0.56, put_bid=9.45, put_offer=9.70),
Option(strike=68.50, call_bid=0.45, call_offer=0.49, put_bid=9.90, put_offer=10.15),
Option(strike=69.00, call_bid=0.39, call_offer=0.43, put_bid=10.35, put_offer=10.60),
Option(strike=69.50, call_bid=0.33, call_offer=0.38, put_bid=10.80, put_offer=11.05),
Option(strike=70.00, call_bid=0.29, call_offer=0.33, put_bid=11.25, put_offer=11.50),
Option(strike=70.50, call_bid=0.25, call_offer=0.29, put_bid=11.55, put_offer=12.15),
Option(strike=71.00, call_bid=0.22, call_offer=0.25, put_bid=12.00, put_offer=12.45),
Option(strike=71.50, call_bid=0.18, call_offer=0.21, put_bid=12.50, put_offer=12.90),
Option(strike=72.00, call_bid=0.15, call_offer=0.19, put_bid=12.95, put_offer=13.45),
Option(strike=72.50, call_bid=0.13, call_offer=0.16, put_bid=13.45, put_offer=13.90),
Option(strike=73.00, call_bid=0.11, call_offer=0.14, put_bid=13.90, put_offer=14.40),
Option(strike=73.50, call_bid=0.11, call_offer=0.12, put_bid=14.40, put_offer=14.90),
Option(strike=74.00, call_bid=0.08, call_offer=0.12, put_bid=14.90, put_offer=15.30),
Option(strike=74.50, call_bid=0.07, call_offer=0.10, put_bid=15.40, put_offer=15.80),
Option(strike=75.00, call_bid=0.06, call_offer=0.10, put_bid=16.05, put_offer=16.20),
Option(strike=76.00, call_bid=0.03, call_offer=0.08, put_bid=16.85, put_offer=17.30),
Option(strike=77.00, call_bid=0.03, call_offer=0.06, put_bid=17.85, put_offer=18.25),
Option(strike=78.00, call_bid=0.01, call_offer=0.06, put_bid=18.85, put_offer=19.25),
Option(strike=79.00, call_bid=0.01, call_offer=0.05, put_bid=19.80, put_offer=20.30),
]
for option in options:
# conversion
# you want these numbers to be greater than zero for there to be an arb,
# because you are trying to sell the synthetic forward for better than the fair price (0)
# (you're trying to sell the call in the synthetic forward by selling call and buying put,
# so you need to use the call bid (thats the price you sell it at to the market
conversion = option.call_bid - option.put_offer - spot + option.strike
# reversal
# you want these numbers to be greater than zero for there to be an arb
# because you are trying to buy the synthetic forward for better than the fair price (0)
reversal = option.call_offer - option.put_bid - spot + option.strike
print "Strike: %s | Conversion: %s | Reversal: %s" % (option.strike, conversion, reversal)
# also note that i'm assuming a single price for stock, but there's realistically also a bid ask on stock
# these are the listed markets for each option, but if you were to call a broker and price it as a package,
# as a customer, the options pits will probably do this for as little as 3-4 cents of "edge".
"""
The output looks like this (unsurprisngly, no opportunities):
Strike: 45.0 | Conversion: -0.22 | Reversal: 0.21
Strike: 48.0 | Conversion: -0.15 | Reversal: 0.28
Strike: 50.0 | Conversion: -0.09 | Reversal: 0.19
Strike: 52.5 | Conversion: -0.06 | Reversal: 0.11
Strike: 55.0 | Conversion: -0.07 | Reversal: 0.04
Strike: 57.5 | Conversion: -0.08 | Reversal: 0.07
Strike: 59.0 | Conversion: -0.04 | Reversal: 0.11
Strike: 60.0 | Conversion: -0.08 | Reversal: 0.06
Strike: 61.0 | Conversion: -0.08 | Reversal: 0.08
Strike: 62.0 | Conversion: -0.07 | Reversal: 0.08
Strike: 63.0 | Conversion: -0.07 | Reversal: 0.07
Strike: 64.0 | Conversion: -0.08 | Reversal: 0.04
Strike: 65.0 | Conversion: -0.09 | Reversal: 0.09
Strike: 65.5 | Conversion: -0.12 | Reversal: 0.13
Strike: 66.0 | Conversion: -0.08 | Reversal: 0.12
Strike: 66.5 | Conversion: -0.08 | Reversal: 0.12
Strike: 67.0 | Conversion: -0.17 | Reversal: 0.13
Strike: 67.5 | Conversion: -0.1 | Reversal: 0.15
Strike: 68.0 | Conversion: -0.13 | Reversal: 0.17
Strike: 68.5 | Conversion: -0.14 | Reversal: 0.15
Strike: 69.0 | Conversion: -0.15 | Reversal: 0.14
Strike: 69.5 | Conversion: -0.16 | Reversal: 0.14
Strike: 70.0 | Conversion: -0.15 | Reversal: 0.14
Strike: 70.5 | Conversion: -0.34 | Reversal: 0.3
Strike: 71.0 | Conversion: -0.17 | Reversal: 0.31
Strike: 71.5 | Conversion: -0.16 | Reversal: 0.27
Strike: 72.0 | Conversion: -0.24 | Reversal: 0.3
Strike: 72.5 | Conversion: -0.21 | Reversal: 0.27
Strike: 73.0 | Conversion: -0.23 | Reversal: 0.3
Strike: 73.5 | Conversion: -0.23 | Reversal: 0.28
Strike: 74.0 | Conversion: -0.16 | Reversal: 0.28
Strike: 74.5 | Conversion: -0.17 | Reversal: 0.26
Strike: 75.0 | Conversion: -0.08 | Reversal: 0.11
Strike: 76.0 | Conversion: -0.21 | Reversal: 0.29
Strike: 77.0 | Conversion: -0.16 | Reversal: 0.27
Strike: 78.0 | Conversion: -0.18 | Reversal: 0.27
Strike: 79.0 | Conversion: -0.23 | Reversal: 0.31
"""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment