コード例 #1
0
ファイル: OptionQuotes.py プロジェクト: ChinaQuants/pyql
 def impvol(cp, strike, premium):
     try:
         vol = blackFormulaImpliedStdDev(cp, strike,
             forward=Fwd, blackPrice=premium, discount=discountFactor,
             TTM=timeToMaturity)
     except:
         vol = np.nan
     return vol/np.sqrt(timeToMaturity)
コード例 #2
0
 def impvol(cp, strike, premium):
     try:
         vol = blackFormulaImpliedStdDev(cp, strike,
                 forward=Fwd, blackPrice=premium, discount=discountFactor,
             TTM=timeToMaturity)
     except RuntimeError:
         vol = np.nan
     return vol/np.sqrt(timeToMaturity)
コード例 #3
0
ファイル: process_SPX_options.py プロジェクト: bondgeek/pyql
def ATM_Vol(premium, discountFactor, forward, strike):
    """
    Aproximate std dev, for calls close to the money
    """
    vol = (premium/discountFactor - .5*(forward-strike))*5.0/(forward+strike) 

    return vol

    # get spot and option data frame
    
    (spot, optionDataFrame) = read_SPX_file(option_data_file)

    grouped = optionDataFrame.groupby('dtExpiry') 

    isFirst = True
    for spec, group in grouped:
        print('processing group %s' % spec)

        # implied vol for this type/expiry group

        indx = group.index
        
        dtTrade = group['dtTrade'][indx[0]]
        dtExpiry = group['dtExpiry'][indx[0]]
        daysToExpiry = (dtExpiry-dtTrade).days
        timeToMaturity = daysToExpiry/365.0

        # exclude groups with too few data points 
        # or too short maturity

        if timeToMaturity < tMin:
            continue
            
        # valid call and put quotes
        df_call = group[(group['Type'] == 'C') & (group['Bid']>0) \
                    & (group['Ask']>0)]
        df_put = group[(group['Type'] == 'P') &  (group['Bid']>0) \
                    & (group['Ask']>0)]
        if (len(df_call) == 0) | (len(df_put) == 0):
            continue

        # calculate forward, implied interest rate and implied div. yield
            
        df_call['Mid'] = (df_call['Bid']+df_call['Ask'])/2
        df_put['Mid'] = (df_put['Bid']+df_put['Ask'])/2
    
        df_C = DataFrame.filter(df_call, items=['Strike', 'Mid'])
        df_C.columns = ['Strike', 'PremiumC']
        to_join = DataFrame(df_put['Mid'], index=df_put['Strike'],
            columns=['PremiumP']) 

        # use 'inner' join because some strikes are not quoted for C and P
        df_all = df_C.join(to_join, on='Strike', how='inner')
    
        df_all['C-P'] = df_all['PremiumC'] - df_all['PremiumP']
    
        model = ols(y=df_all['C-P'], x=df_all.ix[:,'Strike'])
        b = model.beta 
    
        # intercept is last coef
        iRate = -np.log(-b[0])/timeToMaturity
        dRate = np.log(spot/b[1])/timeToMaturity
        discountFactor = np.exp(-iRate*timeToMaturity)
        Fwd = spot * np.exp((iRate-dRate)*timeToMaturity)

        print('Fwd: %f int rate: %f div yield: %f' % (Fwd, iRate, dRate))

        # interpolate ATM premium and vol: used to compute Quick Delta
        f_call = interp1d(df_all['Strike'].values, df_all['PremiumC'].values)
        f_put = interp1d(df_all['Strike'].values, df_all['PremiumP'].values)

        atmPremium = (f_call(Fwd)+f_put(Fwd))/2
        atmVol = blackFormulaImpliedStdDev('C', strike=Fwd,
                 forward=Fwd, blackPrice=atmPremium,
                 discount=discountFactor,
                 TTM=timeToMaturity)/np.sqrt(timeToMaturity)
                    
        print('ATM vol: %f' % atmVol)

        # Quick Delta, computed with ATM vol
        rv = norm()
        df_call['QuickDelta'] = [rv.cdf(np.log(Fwd/strike)/(atmVol*np.sqrt(timeToMaturity))) \
        for strike in df_call['Strike']]
        df_put['QuickDelta'] = [rv.cdf(np.log(Fwd/strike)/(atmVol*np.sqrt(timeToMaturity))) \
        for strike in df_put['Strike']]

        # implied bid/ask vol for all options
    
        def impvol(strike, premium):
            try:
                vol = blackFormulaImpliedStdDev(cp, strike,
                    forward=Fwd, blackPrice=premium, discount=discountFactor,
                    TTM=timeToMaturity)
            except:
                vol = np.nan
                return vol/np.sqrt(timeToMaturity)
        
        cp = 'C'
        df_call['IVBid'] = [impvol(strike, price) for strike, price in zip(df_call['Strike'], df_call['Bid'])]
    df_call['IVAsk'] = [impvol(strike, price) for strike, price in zip(df_call['Strike'], df_call['Ask'])]
    # QD computed with ATM vol 
        
    cp = 'P'
    df_put['IVBid'] = [impvol(strike, price) for strike, price in zip(df_put['Strike'], df_put['Bid'])]
    df_put['IVAsk'] = [impvol(strike, price) for strike, price in zip(df_put['Strike'], df_put['Ask'])]

    # keep OTM data for options within QD range
    
    df_call = df_call[  (df_call['Strike'] >= Fwd) & \
                        (df_call['QuickDelta'] >= QDMin) & \
                        (df_call['QuickDelta'] <= QDMax) ]
                        
    df_put = df_put[  (df_put['Strike'] < Fwd) & \
                        (df_put['QuickDelta'] >= QDMin) & \
                        (df_put['QuickDelta'] <= QDMax) ]

    # final assembly...

    df_cp = df_call.append(df_put,  ignore_index=True)
    df_cp['R'] = iRate 
    df_cp['D'] = dRate 
    df_cp['ATMVol'] = atmVol 
    df_cp['F'] = Fwd
    df_cp['T'] = timeToMaturity
    df_cp = df_cp.rename(columns=
                         {'IVBid': 'VB',
                          'IVAsk': 'VA',
                          'Strike': 'K'})
    df_cp['CP'] = [1 if t == 'C' else -1 for t in df_cp['Type']]
                         
    if isFirst:
        df_final = df_cp
        isFirst = False 
    else:
        df_final = df_final.append(df_cp, ignore_index=True)