使用GPU ARRAYFUN进行蒙特卡罗模拟

这个例子展示了如何在GPU上使用蒙特卡罗方法计算金融期权的价格。我们用三种简单的奇异期权作为例子,但是更复杂的期权可以用类似的方式定价。

此示例是一个函数,以便帮助程序可以嵌套在其中。

函数paralleldemo_gpu_optionpricing

本例使用长时间运行的内核,因此如果在GPU上的内核执行可能超时,则无法运行。超时通常只在选择的GPU也在驱动显示时才有效。

dev = gpuDevice ();如果dev.KernelExecutionTimeout错误(“pctexample: gpuoptionpricing: KernelTimeout”,...(如果GPU上的内核执行可以,这个例子就不能运行。,...“超时”。]);结束

股票价格演变

我们假设价格是按照与无风险利率、股息收益率(如果有的话)和市场波动性相关的对数正态分布演变的。所有这些数量都假定在期权的有效期内是固定的。这就给出了如下的价格随机微分方程:

$${\rm d}S = S \times
左\ [& # xA;(r d) {} \ rm d t + \σ\ε\ sqrt {{\ rm d} t} & # xA;\]$ $

在哪里年代美元为股票价格,r美元为无风险利率,$ d $为股票的年度股息收益率,\σ美元是价格的波动和\ε美元表示高斯白噪声过程。假设美元(S + \δS) / S $为对数正态分布,可离散化为:

$$S_{t+1} = S_{t} \times \exp{
左\ [& # xA;\离开(r - d - \压裂{1}{2}\σ^ 2 \)\δt # xA;+ sigma - epsilon - sqrt{t}
正确\]& # xA;} $ $

举个例子,我们用100美元的股票,每年产生1%的股息。中央政府利率假定为0.5%。我们研究了大约每天取样的两年时间窗口。市场波动率假定为每年20%。

上涨空间= 100;股票价格从100美元起。股息= 0.01;年股息率% 1%。riskFreeRate = 0.005;% 0.5%。timeToExpiry = 2;%期权的有效期限(以年为单位)。sampleRate = 1/250;%假设每年250个工作日。波动率= 0.20;% 20%波动。

我们重新设置随机数生成器,以确保结果是可重复的。

种子= 1234;rng(种子);重置CPU随机数生成器。gpurng(种子);重置GPU随机数生成器。

我们现在可以循环时间来模拟股票价格的路径:

价格=上涨空间;时间= 0;持有;时间<到期时间=时间+采样时间;漂移= (riskFreeRate -股息-波动率*波动率/2)*样本;微扰=挥发度*sqrt(采样)*randn();价格=价格*exp(漂移+扰动);情节(时间、价格、“。”);结束;网格;包含(的时间(年));ylabel (的股票价格($));

在GPU上运行

为了在GPU上运行股票价格模拟,我们首先需要把模拟循环放在一个辅助函数中:

函数finalStockPrice = simulateStockPrice(S,r,d,v,T,dT) T = 0;t < t t = t + dT;dr = (r - d - v*v/2)*dT;pert = v*sqrt(dT)*randn();S = S*exp(dr + pert);结束finalStockPrice = S;结束

然后我们可以调用它上千次arrayfun。为了确保计算发生在GPU上,我们使输入价格为GPU矢量,每个模拟一个元素。为了准确地测量计算时间在GPU上我们使用gputimeit函数。

创建输入数据。N = 1000000;startStockPrices =上涨空间*的(N, 1“gpuArray”);%运行模拟。finalStockPrices = arrayfun(@simulateStockPrice,...开始股价,风险自由,股息,波动,...timeToExpiry sampleRate);meanFinalPrice =意味着(finalStockPrices);%使用gputimeit来测量函数在GPU上的执行时间。这要求我们将|arrayfun|调用存储在函数句柄中。functionToTime = @() arrayfun(@ simulatestockprice,...开始股价,风险自由,股息,波动,...timeToExpiry sampleRate);timeTaken = gputimeit (functionToTime);流(计算平均价格为$%1.4f(以%1.3f秒计算),...meanFinalPrice timeTaken);clf;hist(最终股价,100);包含(的股票价格($))ylabel (“频率”网格);
计算平均价格$98.9563在0.283秒。

亚洲期权的定价

作为一个例子,让我们使用一个基于股票价格在期权有效期内的算术平均值的欧亚期权。我们可以通过模拟过程中价格的累加来计算平均价格。对于看涨期权,如果期权的平均价格高于执行价,那么期权就会被执行,而支付的金额是两者之间的差额:

函数optionPrice = asianCallOption(S,r,d,v,x,T,dT)cumulativePrice = 0;t < t t = t + dT;dr = (r - d - v*v/2)*dT;pert = v*sqrt(dT)*randn();S = S*exp(dr + pert);累积价格=累积价格+ S;结束numSteps = (T / dT);meanPrice =累计价格/ numSteps;用今天的货币来表示最后的价格。。optionPrice = exp(-r*T) * max(0,均值价格- x);结束

我们再次使用GPU运行数千条模拟路径arrayfun。每个模拟路径给出了一个独立的期权价格估计,因此我们取平均值作为我们的结果。

罢工= 95;%期权执行价格($)。optionPrices = arrayfun(@asianCallOption,...开始股价,风险自由,股息,波动,罢工,...timeToExpiry sampleRate);meanOptionPrice =意味着(optionPrices);测量GPU上的执行时间并显示结果。functionToTime = @() arrayfun(@ asiancalloption,...开始股价,风险自由,股息,波动,罢工,...timeToExpiry sampleRate);timeTaken = gputimeit (functionToTime);流(计算平均价格为$%1.4f(以%1.3f秒计算),...meanOptionPrice timeTaken);
以0.287秒计算的平均价格为8.7210美元。

为回溯期权定价

在这个例子中,我们使用一个欧式的回溯期权,它的支付是在期权有效期内的最低股票价格和最终股票价格之间的差额。

函数optionPrice = euroLookbackCallOption(S,r,d,v,T,dT)minPrice = S;t < t t = t + dT;dr = (r - d - v*v/2)*dT;pert = v*sqrt(dT)*randn();S = S*exp(dr + pert);如果S结束结束用今天的货币来表示最后的价格。。optionPrice = exp(-r*T) * max(0, S - minPrice);结束

注意,在这种情况下,期权的执行价格是股票的最低价格。因为最终的股票价格总是大于或等于最小值,期权总是被执行,而不是真正的“可选”。

optionPrices = arrayfun(@euroLookbackCallOption,...开始股价,风险自由,股息,波动,...timeToExpiry sampleRate);meanOptionPrice =意味着(optionPrices);测量GPU上的执行时间并显示结果。functionToTime = @() arrayfun(@ eurolookbackcalloption,...开始股价,风险自由,股息,波动,...timeToExpiry sampleRate);timeTaken = gputimeit (functionToTime);流(计算平均价格为$%1.4f(以%1.3f秒计算),...meanOptionPrice timeTaken);
计算平均价格$19.2711在0.286秒。

障碍期权的定价

最后一个例子使用了一个“向上和向外”的障碍选项,如果股票价格达到了这个障碍的水平,这个选项就无效了。如果股票价格保持在障碍水平以下,那么最后的股票价格将用于正常的欧式看涨期权计算。

函数optionPrice = upAndOutCallOption(S,r,d,v,x,b,T,dT)(t < t) && (S < b) t = t + dT;dr = (r - d - v*v/2)*dT;pert = v*sqrt(dT)*randn();S = S*exp(dr + pert);结束如果S < b%以内,所以价格为欧式期权。optionPrice = exp(-r*T) * max(0, S - x);其他的%遇到了障碍,所以取消了期权。optionPrice = 0;结束结束

请注意,我们现在必须提供期权的执行价格和使其失效的障碍价格:

罢工= 95;%期权执行价格($)。障碍= 150;期权的壁垒价格($)。optionPrices = arrayfun(@upAndOutCallOption,...开始股价,风险自由,股息,波动,...罢工,障碍,...timeToExpiry sampleRate);meanOptionPrice =意味着(optionPrices);测量GPU上的执行时间并显示结果。functionToTime = @() arrayfun(@ upandoutcalloption,...开始股价,风险自由,股息,波动,...罢工,障碍,...timeToExpiry sampleRate);timeTaken = gputimeit (functionToTime);流(计算平均价格为$%1.4f(以%1.3f秒计算),...meanOptionPrice timeTaken);
以0.289秒计算的平均价格为6.8166美元。
结束