わーい!ブラック・ショールズ式を使ってオプション価格とか出してみたよー

Pythonの勉強を兼ねて、日経先物オプションに関連して、使えそうな関数を書いてみたよー!
何か微妙に値が違っているっぽいんで、課題は残っています…。


ちなみに、前もってscipyモジュールを入れておいてください。
http://www.scipy.org/


#!/usr/bin/python
# -*- coding: utf-8 -*-
# bs.py

import sys
from scipy.stats import norm
import math

def callprices(strike,nowprice,interest,restdays,IV):
	"""
	callpricesはCALLのプレミアムの価格をBS式の公式に準じて計算します。
	
	引数:
	strike:算定CALLオプションのストライク価格
	nowprice:原資産価格
	interest:金利(日経225OPの場合は日銀の無担保コール1ヶ月物の金利?)
	restdays:残りの日
	IV:算定するIV(25%なら0.25と入力)
	
	戻り値:
	プレミアム価格
	"""
	r = math.log(1+interest)
	d1 = (math.log(nowprice/strike,)+(r+IV*IV/2)*restdays/365)/IV/math.sqrt(restdays/365)
	d2 = (math.log(nowprice/strike,)+(r-IV*IV/2)*restdays/365)/IV/math.sqrt(restdays/365)

	Nd1 = norm.cdf(d1,)
	Nd2 = norm.cdf(d2,)

	cp = nowprice*Nd1-strike*Nd2*math.exp(-r*restdays/365)

	return cp


def putprices(strike,nowprice,interest,restdays,IV):
	"""
	putpricesはPUTのプレミアムの価格をBS式の公式に準じて計算します。
	
	引数:
	strike:算定PUTオプションのストライク価格
	nowprice:原資産価格
	interest:金利(日経225OPの場合は日銀の無担保コール1ヶ月物の金利?)
	restdays:残りの日
	IV:算定するIV(25%なら0.25と入力)
	
	戻り値:
	プレミアム価格
	"""
	r = math.log(1+interest)
	d1 = (math.log(nowprice/strike,)+(r+IV*IV/2)*restdays/365)/IV/math.sqrt(restdays/365)
	d2 = (math.log(nowprice/strike,)+(r-IV*IV/2)*restdays/365)/IV/math.sqrt(restdays/365)

	Nmd1 = norm.cdf(-d1,)
	Nmd2 = norm.cdf(-d2,)

	pp = -nowprice*Nmd1+strike*Nmd2*math.exp(-r*restdays/365)

	return pp

def callIV(strike,nowprice,interest,restdays,prices):
	"""
	callIVはCALLのプレミアムの価格からIVを計算します。
	
	引数:
	strike:算定CALLオプションのストライク価格
	nowprice:原資産価格
	interest:金利(日経225OPの場合は日銀の無担保コール1ヶ月物の金利?)
	restdays:残りの日
	price:プレミアム価格
	
	戻り値:
	IV(0.2478なら24.78%のこと)。計算不能の場合は-99999.99が返ってくる(IV>327.69%)
	"""
	return calcIV(strike,nowprice,interest,restdays,prices,1,32769,True)

def putIV(strike,nowprice,interest,restdays,prices):
	"""
	putIVはPUTのプレミアムの価格からIVを計算します。
	
	引数:
	strike:算定PUTオプションのストライク価格
	nowprice:原資産価格
	interest:金利(日経225OPの場合は日銀の無担保コール1ヶ月物の金利?)
	restdays:残りの日
	price:プレミアム価格
	
	戻り値:
	IV(0.2478なら24.78%のこと)。計算不能の場合は-99999.99が返ってくる(IV>327.69%)
	"""
	return calcIV(strike,nowprice,interest,restdays,prices,1,32769,False)

def calcIV(strike,nowprice,interest,restdays,prices,fromIV,toIV,iscall):
	centerIV=(fromIV+toIV)/2
	if iscall:
		Lp = callprices(strike,nowprice,interest,restdays,fromIV/10000.0)
		Mp = callprices(strike,nowprice,interest,restdays,centerIV/10000.0)
		Hp = callprices(strike,nowprice,interest,restdays,toIV/10000.0)
	else:
		Lp = putprices(strike,nowprice,interest,restdays,fromIV/10000.0)
		Mp = putprices(strike,nowprice,interest,restdays,centerIV/10000.0)
		Hp = putprices(strike,nowprice,interest,restdays,toIV/10000.0)

	if toIV-fromIV == 2:
		if Lp < prices <= Mp:
			return centerIV/10000.0
		else:
			return toIV/10000.0
	else:
		if Lp < prices <= Mp:
			return calcIV(strike,nowprice,interest,restdays,prices,fromIV,centerIV,iscall)
		elif Mp < prices <= Hp:
			return calcIV(strike,nowprice,interest,restdays,prices,centerIV,toIV,iscall)
		else:
			return -99999.9

#OPのストライク(権利行使価格)が10750円,期近の日経先物価格が10180円,
#日銀の無担保コール1ヶ月物金利が0.063%,次のSQまで残28日の場合…
#
#IV=15.0%のコールのプレミアム価格を出す場合
#print callprices(10750.0,10180.0,0.000063,28.0,0.15)
#
#プットのプレミアムの価格が600円だった場合のIVを出す場合
#print putIV(strike=10750.0,nowprice=10180.0,interest=0.000063,restdays=28.0,prices=600.0)