用Python计算分析实现波动率和隐含波动率

今天又敲了一个volatility_pricer.py,可以分别计算给定股票的实现波动率,和用Black-Scholes算出的隐含波动率。
Python代码可以详见:
class VolatilityPricer():
    """
    Realized vol:
    Same as Black-Scholes, we assume the underlying follows a Geometric Brownian Motion.
    Then its log return follows a Normal distribution, with mean as 0.
    We take as input the historical daily underlying prices.
    Annualization factor is 252.
    Degree of Freedom is 0 as we are calculating the exact realized vol for the given historical period.
 
    Implied vol:
    Use Black-Scholes to back out the implied volatility from the given market option price.
 
    """
 
    def __init__(self):
        self.historicalDataBySymbol = dict()
        self.dataHub = DataHub()
        self.realizedVolBySymbol = dict()
 
    def _loadHistoricalUnderlyingData(self, startDate, endDate, symbols):
        self.historicalDataBySymbol = self.dataHub.downloadDataFromYahoo(startDate, endDate, symbols)
 
    def _calculateRealizedVol(self, ts):
        """ Calculate the realized vol from given time series """
        pctChange = ts.pct_change().dropna()
        logReturns = np.log(1+pctChange)
        vol = np.sqrt(np.sum(np.square(logReturns)) / logReturns.size)
        annualizedVol = vol * np.sqrt(252)
 
        return annualizedVol
 
    def getRealizedVol(self, startDate=datetime.date.today()-datetime.timedelta(days=30), endDate=datetime.date.today(), symbols=['SPY']):
        """ Calculate the realized volatility from historical market data """
        self._loadHistoricalUnderlyingData(startDate, endDate, symbols)
 
        for symbol, df in self.historicalDataBySymbol.iteritems():
            # Use daily Close to calculate realized vols
            realizedVol = self._calculateRealizedVol(df.loc[:, 'Close'])
            self.realizedVolBySymbol[symbol] = realizedVol
 
        return self.realizedVolBySymbol
 
    def getImpliedVol(self, optionPrice=17.5, callPut='Call', spot=586.08, strike=585.0, tenor=0.109589, rate=0.0002):
        """ Calculate the implied volatility from option market price """
        return blackScholesSolveImpliedVol(optionPrice, callPut, spot, strike, tenor, rate)

计算股票的实现波动率

这个我们也是假设股票的价格遵循Geometric Browian Motion,进而它的log return就服从Normal Distribution。
我的pricer可以自动从Yahoo Finance抓取历史数据,并以此构建时间序列。这样我们就可以算出股票的log returns序列,进而就可以算出它的方差,最后把波动率年化。
使用方法:
from volatility_pricer import VolatilityPricer
vp = VolatilityPricer()
vp.getRealizedVol()
{'SPY': 0.086197389793546381}
vp.getRealizedVol(startDate=datetime.date(2018,1,1))
{'SPY': 0.16562165494524139}

计算给定期权的隐含波动率

这个原理就很简单了,用Black-Scholes已知期权价格back out波动率。
但是没有公式可以直接进行计算,所以我用了牛顿导数方法来不断求最优解。我们在每一步需要计算一个当前波动率下的期权价格以及对应的Vega,然后不断缩小误差,直到满意的误差范围。
使用方法:
from volatility_pricer import VolatilityPricer
vp = VolatilityPricer()
vp.getImpliedVol()
0.21921387741959775
哈哈,我还是一如既往地太懒写细节,大家就自己看code吧。
如果有问题或者需要交流,欢迎关注和联系我哈。