一般计算期权的希腊值会用中心差分的办法,比如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=0dt = T / stepsS=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]=Sif maxprice < S:maxprice=Spayoff[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}")
这样就可以一次性把所有希腊值计算出来。
同样的,这个方法也可以用来计算多个期权的估值。