def save(self, *args, **kwargs): days_per_year = self.days_till_exp/ 365 position = self.convert_position() option = BS(self.stock_price, self.strike_price, days_per_year, self.traded_price, self.interest_rate, str(self.option_type)) self.iv = round(option.impvol, 5) self.delta = round(option.delta(), 5) * position * self.quantity self.gamma = round(option.gamma(), 5) * position * self.quantity self.vega = round(option.vega(), 5) * position * self.quantity self.theta = round(option.theta(), 5) * position * self.quantity self.rho = round(option.rho(), 5) * position * self.quantity super().save(*args, **kwargs)
class Call(Option): Option_type = 'Call' def __init__(self, quote, d=date.today().day, m=date.today().month, y=date.today().year, strike=None, strict=False, source='google'): quote = quote.upper() kw = {'d': d, 'm': m, 'y': y, 'strict': strict, 'source': source} super().__init__(quote, self.__class__.Option_type, **kw) self.T = (self._expiration - date.today()).days / 365 self.q = self.underlying.dy self.ticker = quote self.strike = None self.strikes = tuple( parse(dic['strike']) for dic in self.data if dic.get('p') != '-') if strike: if strike in self.strikes: self.set_strike(strike) else: if strict: raise LookupError( 'No options listed for given strike price.') else: closest_strike = min(self.strikes, key=lambda x: abs(x - strike)) print('No option for given strike, using %s instead' % closest_strike) self.set_strike(closest_strike) def set_strike(self, val): """ Specifies a strike price """ d = {} for dic in self.data: if parse(dic['strike']) == val and val in self.strikes: d = dic break if d: self._price = parse(d.get('p')) or d.get('lastPrice') self.id = d.get('cid') self.exchange = d.get('e') self._bid = parse(d.get('b')) or d.get('bid', 0) self._ask = parse(d.get('a')) or d.get('ask', 0) self.strike = parse(d['strike']) self._change = parse(d.get('c')) or d.get('change', 0) # change in currency self._cp = parse(d.get('cp', 0)) or d.get('percentChange', 0) # percentage change self._volume = parse(d.get('vol')) or d.get('volume', 0) self._open_interest = parse(d.get('oi')) or d.get( 'openInterest', 0) self.code = d.get('s') or d.get('contractSymbol') self.itm = ( (self.__class__.Option_type == 'Call' and self.underlying.price > self.strike) or (self.__class__.Option_type == 'Put' and self.underlying.price < self.strike)) # in the money self.BandS = BlackandScholes(self.underlying.price, self.strike, self.T, self._price, self.rate(self.T), self.__class__.Option_type, self.q) else: raise LookupError('No options listed for given strike price.') def __repr__(self): if self.strike: return self.__class__.Option_type + "(ticker=%s, expiration=%s, strike=%s)" % ( self.ticker, self.expiration, self.strike) else: return self.__class__.Option_type + "(ticker=%s, expiration=%s)" % ( self.ticker, self.expiration) def update(self): self.__init__(self.ticker, self._expiration.day, self._expiration.month, self._expiration.year, self.strike, source=self.source) @property @strike_required def bid(self): return self._bid @property @strike_required def ask(self): return self._ask @property @strike_required def price(self): return self._price @property @strike_required def change(self): return self._change @property @strike_required def cp(self): return self._cp @property @strike_required def open_interest(self): return self._open_interest @property @strike_required def volume(self): return self._volume @strike_required def implied_volatility(self): return self.BandS.impvol @strike_required def delta(self): return self.BandS.delta() @strike_required def gamma(self): return self.BandS.gamma() @strike_required def vega(self): return self.BandS.vega() @strike_required def rho(self): return self.BandS.rho() @strike_required def theta(self): return self.BandS.theta()
class Call(Option): Option_type = 'Call' def __init__(self, quote, d=date.today().day, m=date.today().month, y=date.today().year, strike=None, strict=False): quote = quote.upper() kw = {'d': d, 'm': m, 'y': y, 'strict': strict} super().__init__(quote, **kw) if self.__class__.Option_type == 'Call': self.data = self.calls elif self.__class__.Option_type == 'Put': self.data = self.puts self.T = (self._expiration - date.today()).days/365 self.q = 0 self.ticker = quote self.strike = None self.strikes = tuple(parse(dic['strike']) for dic in self.data if dic.get('p') != '-' ) if strike: if strike in self.strikes: self.set_strike(strike) else: if strict: raise LookupError('No options listed for given strike price.') else: closest_strike = min(self.strikes, key=lambda x: abs(x - strike)) print('No option for given strike, using %s instead' % closest_strike) self.set_strike(closest_strike) def set_strike(self, val): d = {} for dic in self.data: if parse(dic['strike']) == val and val in self.strikes: d = dic break if d: self._price = parse(d['p']) self.id = d['cid'] self.exchange = d['e'] self._bid = parse(d['b']) self._ask = parse(d['a']) self.strike = parse(d['strike']) self._change = parse(d.get('c', 0)) # change in currency self._cp = parse(d.get('cp', 0)) # percentage change self._volume = parse(d['vol']) self._open_interest = parse(d['oi']) self.code = d['s'] self.ticker = self.code[:-15] self.BandS = BlackandScholes( self.underlying.price, self.strike, self.T, self._price, rate(self.T), self.__class__.Option_type, self.q ) else: raise LookupError('No options listed for given strike price.') def __repr__(self): if self.strike: return self.__class__.Option_type + "(ticker=%s, expiration=%s, strike=%s)" % (self.ticker, self.expiration, self.strike) else: return self.__class__.Option_type + "(ticker=%s, expiration=%s)" % (self.ticker, self.expiration) def update(self): self.__init__(self.ticker, self._expiration.day, self._expiration.month, self._expiration.year, self.strike) @property @strike_required def bid(self): return self._bid @property @strike_required def ask(self): return self._ask @property @strike_required def price(self): return self._price @property @strike_required def change(self): return self._change @property @strike_required def cp(self): return self._cp @property @strike_required def open_interest(self): return self._open_interest @property @strike_required def volume(self): return self._volume @strike_required def implied_volatility(self): return self.BandS.impvol @strike_required def delta(self): return self.BandS.delta() @strike_required def gamma(self): return self.BandS.gamma() @strike_required def vega(self): return self.BandS.vega() @strike_required def rho(self): return self.BandS.rho() @strike_required def theta(self): return self.BandS.theta()
class Call(Option): Option_type = "Call" def __init__( self, quote, d=date.today().day, m=date.today().month, y=date.today().year, strike=None, strict=False, source="google", ): quote = quote.upper() kw = {"d": d, "m": m, "y": y, "strict": strict, "source": source} super().__init__(quote, **kw) if self.__class__.Option_type == "Call": self.data = self.calls elif self.__class__.Option_type == "Put": self.data = self.puts self.T = (self._expiration - date.today()).days / 365 self.q = 0 self.ticker = quote self.strike = None self.strikes = tuple(parse(dic["strike"]) for dic in self.data if dic.get("p") != "-") if strike: if strike in self.strikes: self.set_strike(strike) else: if strict: raise LookupError("No options listed for given strike price.") else: closest_strike = min(self.strikes, key=lambda x: abs(x - strike)) print("No option for given strike, using %s instead" % closest_strike) self.set_strike(closest_strike) def set_strike(self, val): """ Specifies a specific strike price of the option chain""" d = {} for dic in self.data: if parse(dic["strike"]) == val and val in self.strikes: d = dic break if d: self._price = parse(d.get("p")) or d.get("lastPrice") self.id = d.get("cid") self.exchange = d.get("e") self._bid = parse(d.get("b")) or d.get("bid", 0) self._ask = parse(d.get("a")) or d.get("ask", 0) self.strike = parse(d["strike"]) self._change = parse(d.get("c")) or d.get("change", 0) # change in currency self._cp = parse(d.get("cp", 0)) or d.get("percentChange", 0) # percentage change self._volume = parse(d.get("vol")) or d.get("volume", 0) self._open_interest = parse(d.get("oi")) or d.get("openInterest", 0) self.code = d.get("s") or d.get("contractSymbol") self.itm = (self.__class__.Option_type == "Call" and self.underlying.price > self.strike) or ( self.__class__.Option_type == "Put" and self.underlying.price < self.strike ) # in the money self.BandS = BlackandScholes( self.underlying.price, self.strike, self.T, self._price, rate(self.T), self.__class__.Option_type, self.q, ) else: raise LookupError("No options listed for given strike price.") def __repr__(self): if self.strike: return self.__class__.Option_type + "(ticker=%s, expiration=%s, strike=%s)" % ( self.ticker, self.expiration, self.strike, ) else: return self.__class__.Option_type + "(ticker=%s, expiration=%s)" % (self.ticker, self.expiration) def update(self): self.__init__( self.ticker, self._expiration.day, self._expiration.month, self._expiration.year, self.strike, source=self.source, ) @property @strike_required def bid(self): return self._bid @property @strike_required def ask(self): return self._ask @property @strike_required def price(self): return self._price @property @strike_required def change(self): return self._change @property @strike_required def cp(self): return self._cp @property @strike_required def open_interest(self): return self._open_interest @property @strike_required def volume(self): return self._volume @strike_required def implied_volatility(self): return self.BandS.impvol @strike_required def delta(self): return self.BandS.delta() @strike_required def gamma(self): return self.BandS.gamma() @strike_required def vega(self): return self.BandS.vega() @strike_required def rho(self): return self.BandS.rho() @strike_required def theta(self): return self.BandS.theta()