예제 #1
0
 def test_prices(self):
     while self.tdi.has_next():
         row = self.tdi.next_row()
         S, K, t, r, sigma = row['S'], row['K'], row['t'], row['R'], row[
             'v']
         self.assertAlmostEqual(black_scholes('c', S, K, t, r, sigma),
                                row['bs_call'],
                                delta=0.000001)
         self.assertAlmostEqual(black_scholes('p', S, K, t, r, sigma),
                                row['bs_put'],
                                delta=0.000001)
예제 #2
0
def bs_option_price(connector,
                    underlying,
                    expiration,
                    option_type,
                    strike,
                    current_date,
                    include_riskfree=True):

    price = None

    while price is None:

        current_quote = connector.query_midprice_underlying(
            underlying, current_date)
        if current_quote is None:
            current_date = current_date - timedelta(1)
            continue

        expiration_time = datetime.combine(expiration, time(16))
        remaining_time_in_years = remaining_time(current_date, expiration_time)

        rf = interest
        if include_riskfree:
            rf = get_riskfree_libor(current_date, remaining_time_in_years)

        price = black_scholes.black_scholes(option_type, current_quote, strike,
                                            remaining_time_in_years, rf, 0.151)

    return float(price)
예제 #3
0
    def generate_limit_order(self,
                             asset_code,
                             measured_price,
                             volatility,
                             best_ask,
                             best_bid,
                             min_spread=MIN_SPREAD):
        bs_price = bs.black_scholes(asset_code[0].lower(),
                                    self.underlying_price,
                                    self.asset_codes[asset_code]["strike"],
                                    self.get_time_to_exp(), 0, volatility)
        # spread, base_price = self.get_spread(bs_price, measured_price, best_ask, best_bid, method="scaled")
        # spread, base_price = (self.get_spread(volatility, measured_price, method="logistic"), measured_price) # can switch to stoikov easily
        base_price = measured_price
        curr_best_spread = best_ask - best_bid
        spread = _get_spread_logistic(self.asset_codes[asset_code]["vol"],
                                      curr_best_spread)
        # spread = curr_best_spread + 0.02

        if spread < min_spread: return
        # print(spread - curr_best_spread)

        qty = min(get_qty(spread, abs(base_price - bs_price)), 5) + 1

        self.send_order(asset_code, qty, base_price, spread, self.tick)
        try:
            self.asset_codes[asset_code][
                "vol"] = bs.implied_volatility.implied_volatility(
                    measured_price, self.underlying_price,
                    self.asset_codes[asset_code]["strike"],
                    self.get_time_to_exp(), 0, asset_code[0].lower())
        except:
            pass
예제 #4
0
 def test_implied_volatility(self):
     while self.tdi.has_next():
         row = self.tdi.next_row()
         S, K, t, r, sigma = row['S'], row['K'], row['t'], row['R'], row[
             'v']
         C, P = black_scholes('c', S, K, t, r,
                              sigma), black_scholes('p', S, K, t, r, sigma)
         try:
             iv = implied_volatility(C, S, K, t, r, 'c')
             self.assertAlmostEqual(sigma, iv, delta=0.0001)
         except:
             print('could not calculate iv for ', C, S, K, t, r, 'c')
         iv = implied_volatility(P, S, K, t, r, 'p')
         self.assertTrue(
             iv == 0.0) if iv == 0.0 else self.assertAlmostEqual(
                 sigma, iv, delta=0.001)
예제 #5
0
    def generate_limit_order(self,
                             asset_code,
                             measured_price,
                             volatility,
                             best_ask,
                             best_bid,
                             min_spread=MIN_SPREAD):
        HIST = 4
        bs_price = bs.black_scholes(asset_code[0].lower(),
                                    self.underlying_price,
                                    self.asset_codes[asset_code]["strike"],
                                    self.get_time_to_exp(), 0, volatility)
        # spread, base_price = self.get_spread(bs_price, measured_price, best_ask, best_bid, method="scaled")
        spread, base_price = (self.get_spread(volatility,
                                              measured_price,
                                              method="logistic"),
                              measured_price)  # can switch to stoikov easily
        # print(asset_code, spread)

        if spread < min_spread: return

        self.send_order(asset_code, get_qty(spread,
                                            abs(base_price - bs_price)),
                        base_price, spread, self.tick)
        self.asset_codes[asset_code][
            "vol"] = bs.implied_volatility.implied_volatility(
                measured_price,
                self.underlying_price, self.asset_codes[asset_code]["strike"],
                self.get_time_to_exp(), 0, asset_code[0].lower())
예제 #6
0
def get_price(row):
    try:
        return round(
            black_scholes('c', row.Price, row.Excercise, row.Date / 360,
                          risk_free, get_volatility(row.Symbol, price_df)), 3)
    except:
        return np.nan
예제 #7
0
def getLowerBreakpointGroup(group, current_date, expiration): 
    
    expiration_time = datetime.combine(expiration, time(16, 00))
    remaining_time_in_years = util.remaining_time(current_date, expiration_time)

    lowest = group.getLowest().lowerlongposition.option.strike 
    highest = group.getHighest().upperlongposition.option.strike  
        
    quote = lowest 
    while quote < highest: 
        
        sum_guv = 0
        
        combos = group.getButterflies() 
        for combo in combos: 
            positions = combo.getPositions()
            for position in positions:   
                value = black_scholes.black_scholes(position.option.type, quote, position.option.strike, remaining_time_in_years, util.interest, 0)
                guv = ((value - position.entry_price) * util.ratio * position.amount)
                sum_guv += guv
        
        if (sum_guv > 0): 
            return quote
        
        quote += 0.1
        
        
예제 #8
0
def getLowerBreakpoint(combo, current_date, include_riskfree=True):

    lowest = combo.lowerlongposition.option.strike
    highest = combo.upperlongposition.option.strike

    quote = lowest
    while quote < highest:

        sum_guv = 0
        positions = combo.getPositions()
        for position in positions:

            expiration_time = datetime.combine(position.option.expiration,
                                               time(16))
            remaining_time_in_years = remaining_time(current_date,
                                                     expiration_time)

            rf = interest
            if include_riskfree:
                rf = get_riskfree_libor(current_date, remaining_time_in_years)

            value = black_scholes.black_scholes(position.option.type,
                                                float(quote),
                                                position.option.strike,
                                                remaining_time_in_years, rf, 0)
            guv = ((value - position.entry_price) * ratio * position.amount)
            sum_guv += guv

        if (sum_guv > 0):
            return quote

        quote += 1
예제 #9
0
def get_price(attrs):
    ul_price = attrs['ul_price']
    dte = attrs['dte']
    strike = attrs['strike']
    flag = attrs['flag']
    iv = attrs['iv']
    price = black_scholes(flag, ul_price, strike, dte/365, interest, iv)
    return price
예제 #10
0
 def __init_asset_codes(self):
     asset_codes = {}
     for code in self.codes:
         asset_codes[code] = {}
         asset_codes[code]["strike"] = int(code[1:-3])
         asset_codes[code]["vol"] = 8. * abs(
             math.log(100. / asset_codes[code]["strike"]))
         asset_codes[code]["price"] = bs.black_scholes(
             code[0].lower(), 100, asset_codes[code]["strike"], 0.25, 0,
             asset_codes[code]["vol"])
     return asset_codes
def pd_apply(N):
    from py_vollib.black_scholes.implied_volatility import implied_volatility
    from py_vollib.black_scholes import black_scholes

    tt = big_test_df.iloc[:N]
    tt["price"] = tt.apply(lambda row: black_scholes(row["flag"], row[
        "S"], row["K"], row["t"], row["R"], row["v"]),
                           axis=1)
    tt.apply(lambda row: implied_volatility(row["price"], row["S"], row["K"],
                                            row["t"], row["R"], row["flag"]),
             axis=1)
예제 #12
0
 def test_vs_py_vollib(self):
     for sigma, r, s0, tm, sk, call in itertools.product(
             self.sigmas, self.rates, self.spots, self.maturities,
             self.strikes, self.call):
         with self.subTest():
             np.testing.assert_almost_equal(
                 BlackScholes._option_price(sigma, r, s0, tm, sk, call),
                 black_scholes(flag='c' if call else 'p',
                               S=s0,
                               K=sk,
                               t=tm,
                               r=r,
                               sigma=sigma))
예제 #13
0
def getUpperExpiration(combo):

    upper_expiration_line = 0
    positions = combo.getPositions()

    for position in positions:
        upper_value = black_scholes.black_scholes(position.option.type,
                                                  upper_ul,
                                                  position.option.strike, 0,
                                                  interest, 0)
        upper_expiration = ((upper_value - position.entry_price) * ratio *
                            position.amount)
        upper_expiration_line += upper_expiration

    return upper_expiration_line
def iterrows(N):
    from py_vollib.black_scholes.implied_volatility import implied_volatility
    from py_vollib.black_scholes import black_scholes

    tt = big_test_df.iloc[:N]

    prices = []
    for _, row in tt.iterrows():
        prices.append(
            black_scholes(row["flag"], row["S"], row["K"], row["t"], row["R"],
                          row["v"]))

    tt["price"] = prices

    ivs = []
    for _, row in tt.iterrows():
        ivs.append(
            implied_volatility(row["price"], row["S"], row["K"], row["t"],
                               row["R"], row["flag"]))
def listcomp(N):
    from py_vollib.black_scholes.implied_volatility import implied_volatility
    from py_vollib.black_scholes import black_scholes

    tt = big_test_df.iloc[:N]

    prices = [
        black_scholes(tt.iloc[i]["flag"], tt.iloc[i]["S"], tt.iloc[i]["K"],
                      tt.iloc[i]["t"], tt.iloc[i]["R"], tt.iloc[i]["v"])
        for i in range(len(tt))
    ]

    tt["price"] = prices

    ivs = [
        implied_volatility(tt.iloc[i]["price"], tt.iloc[i]["S"],
                           tt.iloc[i]["K"], tt.iloc[i]["t"], tt.iloc[i]["R"],
                           tt.iloc[i]["flag"]) for i in range(len(tt))
    ]
예제 #16
0
def getUpperExpiration(combo, include_riskfree = True):
        
    upper_expiration_line = 0
    positions = combo.getPositions()
    
    for position in positions:
        
        if (position is None) or (position.entry_price is None):
            return None

        rf = interest
        if include_riskfree: 
            rf = get_riskfree_libor(position.option.expiration, 0)
            
        upper_value = black_scholes.black_scholes(position.option.type, upper_ul, position.option.strike, 0, rf, 0)
        upper_expiration = ((upper_value - position.entry_price) * ratio * position.amount)
        upper_expiration_line += upper_expiration
    
    return upper_expiration_line
def for_loop(N):
    from py_vollib.black_scholes.implied_volatility import implied_volatility
    from py_vollib.black_scholes import black_scholes

    tt = big_test_df.iloc[:N]

    prices = []
    for i in range(len(tt)):
        prices.append(
            black_scholes(tt.iloc[i]["flag"], tt.iloc[i]["S"], tt.iloc[i]["K"],
                          tt.iloc[i]["t"], tt.iloc[i]["R"], tt.iloc[i]["v"]))

    tt["price"] = prices

    ivs = []
    for i in range(len(tt)):
        ivs.append(
            implied_volatility(tt.iloc[i]["price"], tt.iloc[i]["S"],
                               tt.iloc[i]["K"], tt.iloc[i]["t"],
                               tt.iloc[i]["R"], tt.iloc[i]["flag"]))
예제 #18
0
def on_update(msg, order):
    now = time.time()
    global tick
    ms = msg['market_state']
    tck = ms['ticker']
    last_price = msg['market_state']['last_price']
    tickers[tck]['price'].append(last_price)

    tick += 1

    if tck == fut:
        return

    S = tickers[fut]['price'][-1] if len(tickers[fut]['price']) > 0 else None
    K = int(tck[1:4]) if len(tck) == 5 else int(tck[1:3])
    t = (450 - tick) / 450 * 1 / 12
    flag = 'c' if tck[-1] == 'C' else 'p'

    if S is not None:
        try:
            iv = implied_volatility.implied_volatility(last_price, S, K, t, r,
                                                       flag)
            theo_p = black_scholes.black_scholes(flag, S, K, t, r, iv)
            delta = analytical.delta(flag, S, K, t, r, iv)
            gamma = analytical.gamma(flag, S, K, t, r, iv)
            # vega = analytical.vega(flag,S,K,t,r,iv)
            tickers[tck]['vol'].append(vol)
            tickers[tck]['delta'].append(delta)
            tickers[tck]['gamma'].append(gamma)
            # tickers[tck]['vega'].append(vega)

            if len(tickers[tck]['vol']) > 5:
                vol_sma = np.mean(np.array(ticker[tck]['vol'][-6:-1]))
                if abs(iv - vol_sma) / vol_sma > .015:
                    if iv > vol_sma: order.addSell(tck, 10, last_price + dx)
                    else: order.addBuy(tck, 10, last_price - dx)

        except:
            print(S, K, last_price, flag)
예제 #19
0
def getExpiration(combo, underlying_value, include_riskfree=True):

    expiration_line = 0
    positions = combo.getPositions()

    for position in positions:

        if (position is None) or (position.entry_price is None):
            return None

        rf = interest
        if include_riskfree:
            rf = get_riskfree_libor(position.option.expiration, 0)

        value = black_scholes.black_scholes(position.option.type,
                                            underlying_value,
                                            position.option.strike, 0, rf, 0)

        expiration = (
            (value - position.entry_price) * ratio * position.amount -
            (commissions * (abs(position.amount))))
        expiration_line += expiration

    return expiration_line
예제 #20
0
def precompute(table, computedate, underlying, include_riskfree):

    db = psycopg2.connect(host="localhost",
                          user=settings.db_username,
                          password=settings.db_password,
                          database="optiondata")
    cur2 = db.cursor()

    underlying_fragment = ""
    if (underlying != "*"):
        underlying_fragment = "underlying_symbol = '" + underlying + "' AND "

    date_fragment = ""
    if (computedate != "*"):
        date_fragment = "quote_date = '" + str(computedate) + "' AND "

    query = "SELECT id, quote_date, underlying_mid_1545, mid_1545, expiration, strike, option_type FROM " + \
        table + " WHERE " + underlying_fragment + date_fragment + "iv IS NULL"

    cur2.execute(query)
    result = cur2.fetchall()

    print(
        str(computedate) + " " + str(underlying) + ": " + str(len(result)) +
        " results")

    bulkrows = []
    if (len(result) > 0):
        for row in result:

            rowid = row[0]
            quote_date = row[1]
            underlying_mid_1545 = float(row[2])
            mid_1545 = float(row[3])
            expiration = row[4]
            strike = float(row[5])
            option_type = row[6]

            expiration_time = datetime.datetime.combine(
                expiration, datetime.time(16, 0))
            remaining_time_in_years = util.remaining_time(
                quote_date, expiration_time)

            rf = util.interest
            if include_riskfree:
                rf = util.get_riskfree_libor(quote_date,
                                             remaining_time_in_years)

            try:
                iv = implied_volatility.implied_volatility(
                    mid_1545, underlying_mid_1545, int(strike),
                    remaining_time_in_years, rf, option_type)
            except:
                iv = 0.001

            try:
                bs_price_bid_ask = black_scholes(option_type,
                                                 underlying_mid_1545, strike,
                                                 remaining_time_in_years, rf,
                                                 iv)
            except:
                bs_price_bid_ask = 0.001

            try:
                delta = analytical.delta(option_type, underlying_mid_1545,
                                         strike, remaining_time_in_years, rf,
                                         iv) * 100
            except:
                delta = 0.001

            try:
                theta = analytical.theta(option_type, underlying_mid_1545,
                                         strike, remaining_time_in_years, rf,
                                         iv) * 100
            except:
                theta = 0.001

            try:
                vega = analytical.vega(option_type, underlying_mid_1545,
                                       strike, remaining_time_in_years, rf,
                                       iv) * 100
            except:
                vega = 0.001

            bulkrows.append({
                'iv': iv,
                'bs_price_bid_ask': bs_price_bid_ask,
                'delta': delta,
                'theta': theta,
                'vega': vega,
                'rowid': rowid
            })

        psycopg2.extras.execute_batch(
            cur2,
            """UPDATE """ + table +
            """ SET iv=%(iv)s, bs_price_bid_ask=%(bs_price_bid_ask)s, delta=%(delta)s, theta=%(theta)s, vega=%(vega)s WHERE id=%(rowid)s""",
            bulkrows,
            page_size=100)
        db.commit()

        db.close()
예제 #21
0
def getExpectedValue(connector, underlying, combo, current_date, expiration):

    current_quote = connector.query_midprice_underlying(
        underlying, current_date)

    expiration_time = datetime.combine(expiration, time(16))
    remaining_time_in_years = util.remaining_time(current_date,
                                                  expiration_time)

    ul_for_ew = []
    sum_legs = []
    prob_touch = []

    if (current_quote % 10) < 5:
        atm_strike = int(current_quote / 10) * 10
    else:
        atm_strike = int((current_quote + 10) / 10) * 10

    try:
        atm_option = util.Option(connector, current_date, underlying,
                                 atm_strike, expiration, "p")
    except ValueError:
        return "missing data"
    midprice = connector.query_midprice(current_date, atm_option)

    try:
        atm_iv = implied_volatility.implied_volatility(
            midprice, current_quote, atm_strike, remaining_time_in_years,
            util.interest, atm_option.type)

    except pyex.BelowIntrinsicException:
        atm_iv = 0.01
    if (atm_iv == 0): atm_iv = 0.01

    #     print atm_iv

    one_sd = (atm_iv / math.sqrt(
        util.yeartradingdays /
        (remaining_time_in_years * util.yeartradingdays))) * current_quote

    lower_ul = current_quote - e_spanne * one_sd
    upper_ul = current_quote + e_spanne * one_sd
    step = (upper_ul - lower_ul) / 24  # war 1000

    for i in range(25):  # war 1001

        ul_for_ew.insert(i, lower_ul + (i * step))

        sum_legs_i = 0
        positions = combo.getPositions()
        for position in positions:

            #             param sigma: annualized standard deviation, or volatility
            #             https://www.etfreplay.com/etf/iwm.aspx

            value = black_scholes.black_scholes(position.option.type,
                                                ul_for_ew[i],
                                                position.option.strike,
                                                remaining_time_in_years,
                                                util.interest, 0)
            guv = (value - position.entry_price) * ratio * position.amount
            sum_legs_i += guv

        sum_legs.insert(i, sum_legs_i)

        prob = util.prob_hit(current_quote, ul_for_ew[i],
                             remaining_time_in_years, 0, atm_iv)
        prob_touch.insert(i, prob)

    sumproduct = sum([a * b for a, b in zip(sum_legs, prob_touch)])
    expected_value = round((sumproduct / sum(prob_touch)), 2)
    return expected_value
예제 #22
0
def precompute(table, computedate, underlying, include_riskfree):
    
#     start = time.time()
        
    db = psycopg2.connect(host="localhost", user=settings.db_username, password=settings.db_password, database="optiondata") 
    cur2 = db.cursor()
    
    underlying_fragment = ""
    if (underlying != "*"): 
        underlying_fragment = "underlying_symbol = '" + underlying + "' AND "
        
    date_fragment = ""
    if (computedate != "*"): 
        date_fragment = "quote_date = '" + str(computedate) + "' AND "
        
    query = "SELECT id, quote_date, underlying_mid_1545, mid_1545, expiration, strike, option_type FROM " + table + " WHERE " + underlying_fragment + date_fragment + "bs_price_bid_ask IS NULL" 
    
    
    cur2.execute(query)
    result = cur2.fetchall()
    
    print (str(computedate) + " " + str(underlying) + ": " + str(len(result)) + " results")
    
    bulkrows = []
    if (len(result) > 0): 
        for row in result:
            rowid = row[0]
            quote_date = row[1]
            underlying_mid_1545 = float(row[2])
            mid_1545 = float(row[3])
            expiration = row[4]
            strike = float(row[5])
            option_type = row[6]
            
            expiration_time = datetime.datetime.combine(expiration, datetime.time(16, 0))
            remaining_time_in_years = util.remaining_time(quote_date, expiration_time)
            
            rf = util.interest
            if include_riskfree: 
                rf = util.get_riskfree_libor(quote_date, remaining_time_in_years)
                
            try: iv = implied_volatility.implied_volatility(mid_1545, underlying_mid_1545, int(strike), remaining_time_in_years, rf, option_type)
            except: iv = 0.001
            
            if underlying_mid_1545 == 0: underlying_mid_1545 = 0.01
            
            bs_price_bid_ask = black_scholes(option_type, underlying_mid_1545, strike, remaining_time_in_years, rf, iv)
#             print (bs_price_bid_ask)
    
            bulkrows.append({'bs_price_bid_ask': bs_price_bid_ask, 'rowid': rowid}) 
                        
        try: 
            psycopg2.extras.execute_batch(cur2, """UPDATE """ + table + """ SET bs_price_bid_ask=%(bs_price_bid_ask)s WHERE id=%(rowid)s""", bulkrows, page_size=100)
            db.commit()
            
        except Exception as e: 
            print("an exception occurred")
            print(e)
            print (query)
    
#         end = time.time() 
#         print (end - start)
        print ()
                    
        db.close()
예제 #23
0
def getExpectedValue(underlying,
                     combo,
                     current_date,
                     expiration,
                     use_precomputed=True,
                     include_riskfree=True):

    current_quote_original = util.connector.query_midprice_underlying(
        underlying, current_date)

    if (current_quote_original is None):
        return None

    current_quote = float(current_quote_original)
    if (current_quote == 0.0):
        return None

    expiration_time = datetime.combine(expiration, time(16))
    remaining_time_in_years = util.remaining_time(current_date,
                                                  expiration_time)

    ul_for_ew = []
    sum_legs = []
    prob_touch = []

    if (current_quote % 10) < 5:
        atm_strike = int(current_quote / 10) * 10
    else:
        atm_strike = int((current_quote + 10) / 10) * 10

    if use_precomputed:
        try:
            atm_iv = float(
                util.connector.select_iv(current_date, underlying, expiration,
                                         "p", atm_strike))
        except:
            atm_iv = 0.01

    else:

        try:
            atm_option = util.Option(current_date, underlying, atm_strike,
                                     expiration, "p")
        except ValueError:
            return None
        midprice = util.connector.query_midprice(current_date, atm_option)

        rf = util.interest
        if include_riskfree:
            rf = util.get_riskfree_libor(current_date, remaining_time_in_years)

        try:
            atm_iv = float(
                implied_volatility.implied_volatility(midprice, current_quote,
                                                      atm_strike,
                                                      remaining_time_in_years,
                                                      rf, atm_option.type))
        except:
            atm_iv = 0.01

        if (atm_iv == 0):
            atm_iv = 0.01

    one_sd = (atm_iv / math.sqrt(
        util.yeartradingdays /
        (remaining_time_in_years * util.yeartradingdays))) * current_quote

    lower_ul = current_quote - e_spanne * one_sd
    upper_ul = current_quote + e_spanne * one_sd
    step = (upper_ul - lower_ul) / 24  # war 1000

    for i in range(25):  # war 1001

        ul_for_ew.insert(i, lower_ul + (i * step))

        sum_legs_i = 0
        positions = combo.getPositions()
        for position in positions:

            #             param sigma: annualized standard deviation, or volatility
            #             https://www.etfreplay.com/etf/iwm.aspx

            rf = util.interest
            if include_riskfree:
                rf = util.get_riskfree_libor(current_date,
                                             remaining_time_in_years)

            value = black_scholes.black_scholes(position.option.type,
                                                ul_for_ew[i],
                                                position.option.strike,
                                                remaining_time_in_years, rf, 0)
            guv = (value - position.entry_price) * ratio * position.amount
            sum_legs_i += guv

        sum_legs.insert(i, sum_legs_i)

        prob = util.prob_hit(current_quote, ul_for_ew[i],
                             remaining_time_in_years, 0, atm_iv)
        prob_touch.insert(i, prob)

    sumproduct = sum([a * b for a, b in zip(sum_legs, prob_touch)])
    expected_value = round((sumproduct / sum(prob_touch)), 2)
    return expected_value
예제 #24
0
def plot_risk_graph(options_data, S, r, save_png=False):
    '''
    Creates a risk graph for the combination of options provided
    in the input list of options for the different times to
    expiration provided

    inputs:
    options_data -> options data composing the strategy. It is important
        to provide this list ordered by near-term expiries first
    S -> current underlying price
    r -> interest rate on a 3-month U.S. Treasury bill or similar
    save_png -> determines if the plot is saved as a PNG file (default False)
    returns:
        list of tuples (x, (datetime, y))
    '''
    # Get the list of options from options_data
    options_list = options_data['options']

    # First get the graph bounds, 10% apart from the min and max strikes
    min_strike = None
    max_strike = None
    for opt in options_list:
        if (min_strike is None) or (opt['strike'] < min_strike):
            min_strike = opt['strike']
        if (max_strike is None) or (opt['strike'] > max_strike):
            max_strike = opt['strike']
    # Make sure current underlying price is into the range
    if min_strike > S:
        min_strike = S
    if max_strike < S:
        max_strike = S

    # Determine front expiration date
    front_expiration = None
    back_expiration = None
    for opt in options_list:
        aux_date = datetime.strptime(opt['expiration_date'], '%d/%m/%Y')
        if (front_expiration is None) or (aux_date < front_expiration):
            front_expiration = aux_date
        if (back_expiration is None) or (aux_date > back_expiration):
            back_expiration = aux_date

    # Prices vector
    strike_spread = max_strike - min_strike
    x_vector = np.linspace(min_strike - strike_spread * 0.1,
                           max_strike + strike_spread * 0.1, 500)

    # Now plot the risk graph for the different time values provided
    return_values = []
    y = []
    for t in [datetime.today(), front_expiration, back_expiration]:
        y_vector = np.zeros(len(x_vector))
        y_vector.fill(options_data['meta']['amount'] *
                      options_data['meta']['multiplier'] *
                      options_data['meta']['premium'] -
                      options_data['meta']['commisions'])
        y.append(y_vector)
        # Create the discrete values of P/L to plot against xrange
        for opt in options_list:
            # Get time to expiration in years
            days_to_expire = (
                datetime.strptime(opt['expiration_date'], '%d/%m/%Y') - t).days
            t_exp = days_to_expire / 365.
            if t_exp >= 0:
                # Calculate IV from latest option price
                iv = bsiv.implied_volatility(opt['last_price'], S,
                                             opt['strike'], t_exp, r,
                                             opt['right'].lower())

                # Calculate option price using black-scholes given that IV
                y[-1] += np.array([
                    options_data['meta']['amount'] *
                    options_data['meta']['multiplier'] * opt['amount'] *
                    bs.black_scholes(opt['right'].lower(), x, opt['strike'],
                                     t_exp, r, iv) for x in x_vector
                ])

        # Get the number of days to expiration from today for plot's legend
        plt.plot(x_vector, y[-1], label='t: ' + str(days_to_expire))
        return_values.append((t, y[-1]))

    # Plot a vertical line where the underlying is currently trading at
    plt.axvline(S, color='r')

    # Plot zero horizontal line
    plt.axhline(0, color='k', linestyle='dashed')

    plt.legend()
    plt.xlabel('Price')
    plt.ylabel('P/L')
    # Save the plot as a PNG if required, or show plot in a window
    if save_png:
        plt.savefig(datetime.today().strftime(options_data.meta.ticker +
                                              '_%d%b%y.png'))
    else:
        # Show the plot
        plt.show()

    # Return the values calculated TODO for what? to calculate breakevens?
    return (x_vector, return_values)
예제 #25
0
from py_vollib.black_scholes.greeks.analytical import *
from py_vollib.black_scholes import black_scholes
import datetime
import pandas as pd

tday = datetime.date.today()
expiry = datetime.date(2020, 9, 18)
output = []
multiplier = 1000
for t in range(1, (expiry - tday).days):
    for S in range(200, 351):
        delta_calc = delta("c", S, 280, t / 365, 0.05, 0.3) * multiplier
        gamma_calc = gamma("c", S, 280, t / 365, 0.05, 0.3) * multiplier
        theta_calc = theta("c", S, 280, t / 365, 0.05, 0.3) * multiplier
        vega_calc = vega("c", S, 280, t / 365, 0.05, 0.3) * multiplier
        value = black_scholes("c", S, 280, t / 365, 0.05, 0.3) * multiplier
        output.append((delta_calc, gamma_calc, theta_calc, vega_calc, value,
                       expiry - datetime.timedelta(days=t), S))

output = pd.DataFrame(
    output, columns=['delta', 'gamma', 'theta', 'vega', 'value', 't', 'spot'])
output.index = [output['t'], output['spot']]
output = output.stack().reset_index()
output.columns = ['date', 'spot', 'plot_type', 'value']
output.to_csv("spx_test.csv")
예제 #26
0
from py_vollib.black_scholes import black_scholes
from py_vollib.helpers.numerical_greeks import delta as numerical_delta
from py_vollib.helpers.numerical_greeks import vega as numerical_vega
from py_vollib.helpers.numerical_greeks import theta as numerical_theta
from py_vollib.helpers.numerical_greeks import rho as numerical_rho
from py_vollib.helpers.numerical_greeks import gamma as numerical_gamma
from py_vollib.black_scholes.greeks.analytical import gamma as agamma
from py_vollib.black_scholes.greeks.analytical import delta as adelta
from py_vollib.black_scholes.greeks.analytical import vega as avega
from py_vollib.black_scholes.greeks.analytical import rho as arho
from py_vollib.black_scholes.greeks.analytical import theta as atheta

# -----------------------------------------------------------------------------
# FUNCTIONS - NUMERICAL GREEK CALCULATION

f = lambda flag, S, K, t, r, sigma, b: black_scholes(flag, S, K, t, r, sigma)


def delta(flag, S, K, t, r, sigma):
    """Return Black-Scholes delta of an option.
    
    :param S: underlying asset price
    :type S: float
    :param K: strike price
    :type K: float
    :param sigma: annualized standard deviation, or volatility
    :type sigma: float
    :param t: time to expiration in years
    :type t: float
    :param r: risk-free interest rate
    :type r: float