一般计算期权的希腊值会用中心差分的办法,比如Delta就需要分别计算标的涨跌1%的估值。再加上其他希腊值,我们就需要运行多次蒙特卡洛,时间效率不高。
由于cuda最多支持3个维度,所以我们可以利用这一特点一次性把这些值都算出来。
我们可以定义第一个维度是价格路径,第二个维度是估值的类型。以回望期权计算Delta和Gamma为例,核函数可以写成
- @cuda.jit()
- def KernelLookBackBatch(payoff,zpath,SMat,K,H,T,r,q,sigma,steps,N):
- #第一个维度是路径,第二个维度是种类
- path_i,kind_i = cuda.grid(2)
- if(path_i>=payoff.shape[0] or kind_i>=payoff.shape[1]):
- return
- maxprice=0
- dt = T / steps
- S=SMat[kind_i]
- for i in range(0,steps):
- S=S*math.exp((r - q - 0.5 * sigma**2) * dt + sigma * math.sqrt(dt) * zpath[i,path_i])
- #Sdebug[path_i,i,kind_i]=S
- if maxprice < S:
- maxprice=S
- payoff[path_i,kind_i]=max(maxprice-K,0)* math.exp(-r * T)
调用方式改为
- payoffs=np.zeros((QuasiN,3))
- threadsperblock = (512,1)
- blockspergrid_x = math.ceil(payoffs.shape[0] / threadsperblock[0])
- blockspergrid_y = math.ceil(payoffs.shape[1] / threadsperblock[1])
- blockspergrid = (blockspergrid_x, blockspergrid_y)
- #S扩展为一个向量,分别计算上涨和下跌一个dS(0.01)的价格
- SMat=np.asarray([S,S*(1+0.01),S*(1-0.01)])
- KernelLookBackBatch[blockspergrid, threadsperblock](payoffs,zpath,SMat,K,H,T,r,q,sigma,steps,QuasiN)
- lookback_price = np.mean(payoffs,axis=0)
- print("lookback_price",lookback_price[0])
- print(f"lookback delta {lookback_price[1]-lookback_price[2]/(S*0.01*2)}")
- print(f"lookback gamma {lookback_price[1]+lookback_price[2]-2*lookback_price[0]/(S*0.01)**2}")
这样就可以一次性把所有希腊值计算出来。
同样的,这个方法也可以用来计算多个期权的估值。