In [1]:
    
%matplotlib inline
import requests
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
import numpy as np
import pandas as pd
import datetime as dt
from matplotlib import pyplot as plt
import uqer
from PyFin.api import *
from uqer import DataAPI as api
from QuantLib import *
plt.style.use('fivethirtyeight')
uqer.Client(token='f1b9bea1d0b4e489c5ab9b69c3e2326a1bee6057af858067dbd1546453f428b2')
    
    
    Out[1]:
In [3]:
    
start_date = '2017-04-01'
end_date = '2017-08-01'
dates = makeSchedule(start_date, end_date, '4m', 'china.sse', )
mkt_start_date = advanceDateByCalendar('china.sse', start_date, '-30b').strftime('%Y-%m-%d')
contract = 'ru1709'
    
In [4]:
    
def get_contracts(contract, start_date, end_date):
    data = api.MktFutdGet(ticker=contract, beginDate=start_date, endDate=end_date, field='tradeDate,closePrice')
    data['tradeDate'] = pd.to_datetime(data.tradeDate)
    data.set_index('tradeDate', inplace=True)
    data['closePrice'] = data['closePrice'].astype(float)
    data['ret'] = data.closePrice.diff() / data.closePrice.shift(1)
    data['vol'] = data['ret'].rolling(window=22).std() * np.sqrt(249)
    return data
    
In [5]:
    
def get_contracts_bar(constract, start_date, end_date, unit=60):
    start_date = dt.datetime.strptime(start_date, '%Y-%m-%d')
    end_date = dt.datetime.strptime(end_date, '%Y-%m-%d')
    
    datas = []
    while start_date < end_date:
        this_end_date = advanceDateByCalendar('china.sse', start_date, '10b')
        df = api.MktFutureBarHistDateRangeGet(instrumentID=contract,
                                              startDate=start_date.strftime('%Y%m%d'),
                                              endDate=this_end_date.strftime('%Y%m%d'),
                                              unit=unit,
                                              field='dataDate,barTime,closePrice')
        datas.append(df)
        start_date = this_end_date
    data = pd.concat(datas)
    data = data[(data.barTime >= '09:00') & (data.barTime <= '16:00')]
    data['tradeDate'] = pd.to_datetime(data.dataDate + 'T' +  data.barTime)
    data['closePrice'] = data['closePrice'].astype(float)
    data['ret'] = data.closePrice.diff() / data.closePrice.shift(1)
    data['vol'] = data['ret'].rolling(window=int(22 * 4 * 60 / unit)).std() * np.sqrt(249) * np.sqrt(4 * 60 / unit)
    data.set_index('tradeDate', inplace=True)
    return data[['closePrice', 'ret', 'vol']]
    
In [6]:
    
mkt_data = get_contracts_bar(contract, mkt_start_date, end_date)
    
In [7]:
    
strangle_width = 400.
lower_protect_area = 1000.
upper_protect_area = 800.
volatility = 0.42
risk_free_rate = 0.
dividend_rate = 0.
    
In [10]:
    
dates
    
    Out[10]:
In [128]:
    
def cal_naive_delta(spot, pp1, pp2, cp1, cp2):
    
    if spot <= pp2.strike():
        return 0.
    elif spot <= pp1.strike():
        return -1.
    elif spot <= cp1.strike():
        return 0.
    elif spot <= cp2.strike():
        return 1.
    else:
        return 0.
    
def composite_payoff(spot, pp1, pp2, cp1, cp2):
    return pp1(spot) - pp2(spot) + cp1(spot) - cp2(spot)
def hedging_contract(start_date, maturity_date, mkt_data, premium=None, naive_hedge=False, american_exercise=False):
    spot_price = mkt_data[mkt_data.index < start_date.ISO()]['closePrice']
    
    if hasattr(spot_price, '__iter__'):
        spot_price = spot_price[-1]
    
    lower_strike = spot_price
    lower_bound = lower_strike - lower_protect_area
    upper_strike = lower_strike + strangle_width
    upper_bound = upper_strike + upper_protect_area
    
    day_count = Actual365Fixed()
    calendar = China(China.SSE)
    
    calculation_date = start_date
    Settings.instance().evaluationDate = calculation_date
    spot_handle = RelinkableQuoteHandle(SimpleQuote(spot_price))
    vol_handle =  RelinkableQuoteHandle(SimpleQuote(volatility))
    flat_ts = YieldTermStructureHandle(FlatForward(calculation_date, risk_free_rate, day_count))
    dividend_yield = YieldTermStructureHandle(FlatForward(calculation_date, dividend_rate, day_count))
    flat_vol_ts = BlackVolTermStructureHandle(BlackConstantVol(calculation_date, calendar, vol_handle, day_count))
    bsm_process = BlackScholesMertonProcess(spot_handle, dividend_yield, flat_ts, flat_vol_ts)
    
    put_payoff1 = PlainVanillaPayoff(Option.Put, lower_strike)
    put_payoff2 = PlainVanillaPayoff(Option.Put, lower_bound)
    call_payoff1 = PlainVanillaPayoff(Option.Call, upper_strike)
    call_payoff2 = PlainVanillaPayoff(Option.Call, upper_bound)
    exercise = EuropeanExercise(maturity_date)
    put_option1 = VanillaOption(put_payoff1, exercise)
    put_option2 = VanillaOption(put_payoff2, exercise)
    call_option1 = VanillaOption(call_payoff1, exercise)
    call_option2 = VanillaOption(call_payoff2, exercise)
    engine = AnalyticEuropeanEngine(bsm_process)
    put_option1.setPricingEngine(engine)
    put_option2.setPricingEngine(engine)
    call_option1.setPricingEngine(engine)
    call_option2.setPricingEngine(engine)
    
    if not premium:
        premium = put_option1.NPV() - put_option2.NPV() + call_option1.NPV() - call_option2.NPV()
    
    price_series = mkt_data.loc[start_date.ISO(): maturity_date.ISO()]
    previous_delta = 0.
    previous_price = 0.
    trading_pnl = 0.
    trading_cost = 0.
    for p in price_series.iterrows():
        date = Date.from_date(p[0])
        price = p[1]['closePrice']
        vol = p[1]['vol']
        if date != maturity_date:
            Settings.instance().evaluationDate = date
        spot_handle.linkTo(SimpleQuote(price))
        vol_handle.linkTo(SimpleQuote(vol))
        bsm_delta = put_option1.delta() - put_option2.delta() + call_option1.delta() - call_option2.delta()
        
        if naive_hedge:
            delta = cal_naive_delta(price, put_payoff1, put_payoff2, call_payoff1, call_payoff2)
        else:
            delta = bsm_delta
        
        trading_pnl += (price - previous_price) * previous_delta
        trading_cost += np.abs(delta - previous_delta) * 0.5 * (price + previous_price) * 0.0015     
        if american_exercise:
            payoff = composite_payoff(price,
                                      put_payoff1,
                                      put_payoff2,
                                      call_payoff1,
                                      call_payoff2)
            
            if price >= call_payoff2.strike() - 25.0 and payoff >= upper_protect_area - 25.:
                break
            elif price <= put_payoff2.strike() + 25.0 and payoff >= upper_protect_area - 25.:
                break
        
        previous_price = price
        previous_delta = delta
        
    final_price = mkt_data.loc[date.ISO()]['closePrice']
    if hasattr(final_price, '__iter__'):
        final_price = final_price[-1]
    final_payoff = composite_payoff(final_price,
                                    put_payoff1,
                                    put_payoff2,
                                    call_payoff1,
                                    call_payoff2)
    
    pnl_final = -final_payoff + premium + trading_pnl - trading_cost
    
    return spot_price, final_price, vol, final_payoff, premium, trading_pnl, pnl_final, trading_cost
    
In [129]:
    
maturity_date = Date.from_date(advanceDateByCalendar('china.sse', dates[1], '-1b'))
start_date = Date.from_date(dates[0])
hedging_contract(start_date, maturity_date, mkt_data, 646.)
    
    Out[129]:
In [130]:
    
strangle_width = 400.
lower_protect_area = 1000.
upper_protect_area = 800.
volatility = 0.42
risk_free_rate = 0.
dividend_rate = 0.
premium = 769.
    
In [228]:
    
contract_definition = {
    'ru0509': {
        'start_date': '2005-04-01',
        'end_date': '2005-08-01'
    },
    'ru0609': {
        'start_date': '2006-04-01',
        'end_date': '2006-08-01'
    },
    'ru0709': {
        'start_date': '2007-04-01',
        'end_date': '2007-08-01'
    },
    'ru0809': {
        'start_date': '2008-04-01',
        'end_date': '2008-08-01'
    },
    'ru0909': {
        'start_date': '2009-04-01',
        'end_date': '2009-08-01'
    },
    'ru1009': {
        'start_date': '2010-04-01',
        'end_date': '2010-08-01'
    },
    'ru1109': {
        'start_date': '2011-04-01',
        'end_date': '2011-08-01'
    },
    'ru1209': {
        'start_date': '2012-04-01',
        'end_date': '2012-08-01'
    },
    'ru1309': {
        'start_date': '2013-04-01',
        'end_date': '2013-08-01'
    },
    'ru1409': {
        'start_date': '2014-04-01',
        'end_date': '2014-08-01'
    },
    'ru1509': {
        'start_date': '2015-04-01',
        'end_date': '2015-08-01'
    },
    'ru1609': {
        'start_date': '2016-04-01',
        'end_date': '2016-08-01'
    },
    'ru1709': {
        'start_date': '2017-04-01',
        'end_date': '2017-08-01'
    },
}
    
In [268]:
    
%%time
cols = ['合约', '到期日', '初始价', '收盘价', '实现波动率', '赔付', '期权费', '交易损益', '对冲损益' , '对冲交易成本', 'delta 1 交易损益', 'delta 1 对冲损益', 'delta 1 对冲交易成本']
df = pd.DataFrame(columns=cols)
for contract in contract_definition:
    start_date = contract_definition[contract]['start_date']
    end_date = contract_definition[contract]['end_date']
    dates = makeSchedule(start_date, end_date, '4m', 'china.sse')
    mkt_start_date = advanceDateByCalendar('china.sse', start_date, '-30b').strftime('%Y-%m-%d')
    mkt_data = get_contracts(contract, mkt_start_date, end_date)
    
    for i, s_date in enumerate(dates[:-1]):
        maturity_date = Date.from_date(advanceDateByCalendar('china.sse', dates[i+1], '-1b'))
        start_date = Date.from_date(s_date)
        hedge = hedging_contract(start_date, maturity_date, mkt_data, premium)
        delta1_hedge = hedging_contract(start_date, maturity_date, mkt_data, premium, True)
        py_dt = dt.datetime(maturity_date.year(), maturity_date.month(), maturity_date.dayOfMonth())
        df = df.append(dict(zip(cols, (contract, py_dt) + hedge + delta1_hedge[-3:])), ignore_index=True)
    
    
In [269]:
    
df['不对冲损益'] = -df['赔付'] + df['期权费']
    
In [270]:
    
df
    
    Out[270]:
In [271]:
    
print("欧式行权: 2005 - 2017")
df.groupby(df['到期日'].dt.year).mean()
    
    
    Out[271]:
In [233]:
    
df.std()
    
    Out[233]:
In [234]:
    
df.mean()
    
    Out[234]:
In [272]:
    
%%time
cols = ['合约', '到期日', '初始价', '收盘价', '实现波动率', '赔付', '期权费', '交易损益', '对冲损益' , '对冲交易成本', 'delta 1 交易损益', 'delta 1 对冲损益', 'delta 1 对冲交易成本']
df2 = pd.DataFrame(columns=cols)
for contract in list(contract_definition.keys())[5:]:
    start_date = contract_definition[contract]['start_date']
    end_date = contract_definition[contract]['end_date']
    dates = makeSchedule(start_date, end_date, '4m', 'china.sse')
    mkt_start_date = advanceDateByCalendar('china.sse', start_date, '-30b').strftime('%Y-%m-%d')
    mkt_data = get_contracts_bar(contract, mkt_start_date, end_date, unit=60)
    
    for i, s_date in enumerate(dates[:-1]):
        maturity_date = Date.from_date(advanceDateByCalendar('china.sse', dates[i+1], '-1b'))
        start_date = Date.from_date(s_date)
        hedge = hedging_contract(start_date, maturity_date, mkt_data, premium)
        delta1_hedge = hedging_contract(start_date, maturity_date, mkt_data, premium, True)
        py_dt = dt.datetime(maturity_date.year(), maturity_date.month(), maturity_date.dayOfMonth())
        df2 = df2.append(dict(zip(cols, (contract, py_dt) + hedge + delta1_hedge[-3:])), ignore_index=True)
    
    
In [273]:
    
df2['不对冲损益'] = -df2['赔付'] + df2['期权费']
    
In [274]:
    
df2
    
    Out[274]:
In [275]:
    
df2.groupby(df2['到期日'].dt.year).mean()
    
    Out[275]:
In [276]:
    
df2.std()
    
    Out[276]:
In [277]:
    
df2.mean()
    
    Out[277]:
In [278]:
    
df = df[df['合约'].isin(df2['合约'])].reset_index(drop=True)
    
In [279]:
    
s = df['不对冲损益'] - df2['不对冲损益']
    
In [280]:
    
df['diff'] = s
    
In [281]:
    
df[df['diff'] != 0]
    
    Out[281]:
In [282]:
    
df2[df['diff'] != 0]
    
    Out[282]:
In [283]:
    
%%time
cols = ['合约', '到期日', '初始价', '收盘价', '实现波动率', '赔付', '期权费', '交易损益', '对冲损益' , '对冲交易成本', 'delta 1 交易损益', 'delta 1 对冲损益', 'delta 1 对冲交易成本']
df = pd.DataFrame(columns=cols)
for contract in contract_definition:
    start_date = contract_definition[contract]['start_date']
    end_date = contract_definition[contract]['end_date']
    dates = makeSchedule(start_date, end_date, '4m', 'china.sse')
    mkt_start_date = advanceDateByCalendar('china.sse', start_date, '-30b').strftime('%Y-%m-%d')
    mkt_data = get_contracts(contract, mkt_start_date, end_date)
    
    for i, s_date in enumerate(dates[:-1]):
        maturity_date = Date.from_date(advanceDateByCalendar('china.sse', dates[i+1], '-1b'))
        start_date = Date.from_date(s_date)
        hedge = hedging_contract(start_date, maturity_date, mkt_data, premium, american_exercise=True)
        delta1_hedge = hedging_contract(start_date, maturity_date, mkt_data, premium, True, american_exercise=True)
        py_dt = dt.datetime(maturity_date.year(), maturity_date.month(), maturity_date.dayOfMonth())
        df = df.append(dict(zip(cols, (contract, py_dt) + hedge + delta1_hedge[-3:])), ignore_index=True)
    
    
In [284]:
    
df['不对冲损益'] = -df['赔付'] + df['期权费']
    
In [285]:
    
df
    
    Out[285]:
In [286]:
    
print("近似美式行权: 2013 - 2017")
df.groupby(df['到期日'].dt.year).mean()
    
    
    Out[286]:
In [287]:
    
df.std()
    
    Out[287]:
In [288]:
    
df.mean()
    
    Out[288]:
In [ ]:
    
    
In [ ]: