使用GPUarrayfun
的蒙特卡罗模拟
这个例子展示了如何使用蒙特卡罗方法在GPU上计算金融期权的价格。
该示例使用了三种简单类型的奇异期权,但您可以用类似的方式为更复杂的期权定价。在本例中,比较在CPU上运行蒙特卡洛模拟和使用蒙特卡洛模拟所花费的时间arrayfun
在GPU上。
股票价格演变
假设价格按照与无风险利率、股息收益率(如果有的话)和市场波动性相关的对数正态分布演化。此外,假设所有这些数量在期权的生命周期内保持固定。这些假设导致了价格的随机微分方程。
,
在哪里 是股价, 是无风险利率, 是股票的年股息收益率, 是价格的波动,和 表示高斯白噪声过程。假设 是对数正态分布的,这个微分方程可以离散得到这个方程。
.
假设持有100美元的股票,用两年的时间窗口来检验一下:
这些股票每年的股息为1%。
无风险政府利率为0.5%。
价格每天抽样,每年250个工作日。
市场波动率为每年20%。
上涨空间= 100;timeToExpiry = 2;股息= 0.01;riskFreeRate = 0.005;sampleRate = 1/250;波动率= 0.20;
为了保证可预测的结果,请设置CPU和GPU随机数生成器的种子。
种子= 1234;rng(种子);gpurng(种子);
模拟股价随时间变化的路径,并绘制结果图。
价格=上涨空间;时间= 0;h = animatedline(标志=“。”);而time < timeToExpiry time = time + sampleRate;drift = (riskFreeRate -股息-波动率*波动率/2)*sampleRate;微扰= * sqrt (sampleRate) * randn波动;价格=价格*exp(漂移+扰动);addpoints (h、时间、价格);结束网格在轴紧包含(“时间(年)”) ylabel (“股票价格(美元)”)
时间CPU和GPU的执行时间
的simulateStockPrice
函数在本例的最后提供,它使用前一节中描述的离散化微分方程模拟股票价格。
准备输入数据,以运行10万个股票价格的蒙特卡罗模拟。
N = 100000;startStockPrices =上涨空间*的(N - 1);
在CPU上进行100,000次模拟。
tic finalStockPricesCPU = 0 (N,1);为i = 1:N finalStockPricesCPU(i) = simulatstockprice (startStockPrices(i),...riskFreeRate、股息、波动,...timeToExpiry sampleRate);结束timeCPU = toc;
因为每次模拟都给出了期权价格的独立估计,所以取平均值作为结果。
流(计算CPU上$%1.4f的平均价格在%1.3f秒内。\n,...意思是(finalStockPricesCPU) timeCPU);
在2.206秒内计算出CPU的平均价格99.0857美元。
为了在GPU上运行仿真,需要在GPU上准备好输入数据gpuArray
对象。
gpuStartStockPrices = gpuArray (startStockPrices);
当你打电话arrayfun
使用GPU阵列和函数句柄作为输入,arrayfun
将指定的函数应用于数组的每个元素。这种行为意味着没有必要遍历每个起始股价。的arrayfun
函数在GPU上将一个基于元素的MATLAB®函数转换为自定义CUDA®内核,这减少了执行操作的开销。
运行simulateStockPrice
函数使用arrayfun
并在GPU上进行10万次模拟gputimeit
.
finalStockPricesGPU = arrayfun (@simulateStockPrice,...gpuStartStockPrices riskFreeRate,股息,波动,...timeToExpiry sampleRate);timeGPU = gputimeit(@() arrayfun(@ simulatestockprice,...gpuStartStockPrices riskFreeRate,股息,波动,...timeToExpiry sampleRate));流(计算GPU上$ 1.4f在%1.3f秒内的平均价格。\n,...意思是(finalStockPricesGPU) timeGPU);
在0.023秒内计算出GPU上99.0442美元的平均价格。
在图形处理器上用直方图绘制蒙特卡洛模拟的结果。
直方图(finalStockPricesGPU, 100);包含(“股票价格(美元)”) ylabel (“频率”网格)在
亚洲期权定价
使用基于期权有效期内股价算术平均值的欧亚期权。的asianCallOption
函数通过在模拟期间累积价格来计算平均价格。对于看涨期权,如果平均价格高于执行价格,则该函数执行期权。支付是平均价格和执行价格之间的差额。使用asianCallOption
,在本例末尾提供,以模拟亚洲看涨期权。
将期权执行价格设为95美元。
罢工= 95;
在CPU和GPU上进行100,000次模拟arrayfun
并展示结果。
tic optionPricesCPU = 0 (N,1);为i=1:N optionPricesCPU(i) = asianCallOption(startStockPrices(i),...riskFreeRate、股息、波动性,罢工,...timeToExpiry sampleRate);结束timeAsianOptionCPU = toc;流(计算CPU上$%1.4f的平均价格在%1.3f秒内。\n,...意思是(optionPricesCPU) timeAsianOptionCPU);
在2.146秒内计算CPU的平均价格为8.6733美元。
optionPricesGPU = arrayfun(@asianCallOption,...gpuStartStockPrices riskFreeRate,股息,波动性,罢工,...timeToExpiry sampleRate);timeAsianOptionGPU = gputimeit(@() arrayfun(@ asiancalloption,...gpuStartStockPrices riskFreeRate,股息,波动性,罢工,...timeToExpiry sampleRate));流(计算GPU上$ 1.4f在%1.3f秒内的平均价格。\n,...意思是(optionPricesGPU) timeAsianOptionGPU);
在0.023秒内计算出GPU上8.7448美元的平均价格。
为回溯选项定价
使用欧式回溯期权,其股息为期权存续期内的最低股价与最终股价之差。期权的执行价格是最低股价。因为最终股价总是大于或等于最小值,期权总是被执行,并不是真正的可选。使用lookbackCallOption
,在本例末尾提供,用于模拟欧式回看调用选项。
在CPU和GPU上进行100,000次模拟arrayfun
并展示结果。
tic optionPricesCPU = 0 (N,1);为i=1:N optionPricesCPU(i) = lookbackCallOption(startStockPrices(i),...riskFreeRate、股息、波动,...timeToExpiry sampleRate);结束timeLookbackOptionCPU = toc;流(计算CPU上$%1.4f的平均价格在%1.3f秒内。\n,...意思是(optionPricesCPU) timeLookbackOptionCPU);
计算平均价格19.2456美元的CPU在2.201秒。
optionPricesGPU = arrayfun (@lookbackCallOption,...gpuStartStockPrices riskFreeRate,股息,波动,...timeToExpiry sampleRate);timeLookbackOptionGPU = gputimeit(@() arrayfun(@ lookbackcalloption,...gpuStartStockPrices riskFreeRate,股息,波动,...timeToExpiry sampleRate));流(计算GPU上$ 1.4f在%1.3f秒内的平均价格。\n,...意思是(optionPricesGPU) timeLookbackOptionGPU);
在0.021秒内计算出GPU上19.3893美元的平均价格。
障碍期权定价
使用涨停障碍期权,如果股价达到障碍水平,该期权将失效。如果股价停留在障碍水平以下,在正常的欧洲看涨期权计算中使用最终股价。使用upAndOutCallOption
函数,该函数在本例的末尾提供,用于模拟一个向上和向上的屏障调用选项。
设置期权的执行价格和期权失效的障碍价格。执行价为95美元,障碍价为150美元。
罢工= 95;障碍= 150;
在CPU和GPU上进行100,000次模拟arrayfun
并展示结果。
tic optionPricesCPU = 0 (N,1);为i=1:N optionPricesCPU(i) = upAndOutCallOption(startStockPrices(i),...riskFreeRate、股息、波动性,罢工,...障碍,timeToExpiry sampleRate);结束timeBarrierOptionCPU = toc;流(计算CPU上$%1.4f的平均价格在%1.3f秒内。\n,...意思是(optionPricesCPU) timeBarrierOptionCPU);
在2.074秒内计算出CPU的平均价格6.8327美元。
optionPricesGPU = arrayfun (@upAndOutCallOption,...gpuStartStockPrices riskFreeRate,股息,波动性,罢工,...障碍,timeToExpiry sampleRate);timeBarrierOptionGPU = gputimeit(@() arrayfun(@ upandoutcalloption,...gpuStartStockPrices riskFreeRate,股息,波动性,罢工,...障碍,timeToExpiry sampleRate));流(计算GPU上$ 1.4f在%1.3f秒内的平均价格。\n,...意思是(optionPricesGPU) timeBarrierOptionGPU);
在0.021秒内计算出GPU上6.7834美元的平均价格。
比较结果
计算每个模拟的CPU执行时间与GPU执行时间的比值。
ratio = [timcpu /timeGPU timeAsianOptionCPU/timeAsianOptionGPU ....timeLookbackOptionCPU / timeLookbackOptionGPU timeBarrierOptionCPU / timeBarrierOptionGPU]
率=1×494.2557 94.6009 104.1725 97.5490
为了可视化结果,绘制每个模拟的执行时间比率。
栏(分类([“股价”“亚洲看涨期权”“Lookback选项”“障碍选择”]),...比率)ylabel (CPU与GPU执行时间之比)
在本例中,在GPU上运行模拟arrayfun
比在CPU上运行模拟要快得多。
当您将本例中描述的技术应用到您自己的代码中时,性能改进将强烈地依赖于您的硬件和您运行的代码。
支持功能
股票价格演化模拟功能
的simulateStockPrice
函数执行蒙特卡罗模拟,以确定最终股票价格。该计算假设价格按照与无风险利率、股息收益率(如果有的话)和市场波动性相关的对数正态分布演进。
的simulateStockPrice
函数以初始股价、无风险利率、股息率、市场波动率、总时间窗和样本利率为输入。
函数finalStockPrice = simulatstockprice(价格,riskFreeRate,股息,波动性,T,dT) T = 0;而t < t t = t + dT;drift = (riskFreeRate -红利-波动率*波动率/2)*dT;微扰= * sqrt (dT) * randn波动;价格=价格。* exp(漂流+微扰);结束finalStockPrice =价格;结束
亚洲呼叫期权功能
的asianCallOption
函数进行蒙特卡罗模拟,以确定亚洲看涨期权价格。该计算假设价格按照与无风险利率、股息收益率(如果有的话)和市场波动性相关的对数正态分布演进。该函数通过累积模拟期间的价格来计算平均价格。对于看涨期权,如果平均价格高于执行价格,则该函数执行期权。支付是平均价格和执行价格之间的差额。
的asianCallOption
函数以初始股价、无风险利率、股息率、市场波动率、执行价格、总时间窗和样本利率为输入。
函数optionPrice = asianCallOption(价格,riskFreeRate,股息,波动率,罢工,T,dT) T = 0;cumulativePrice = 0;而t < t t = t + dT;dr = (riskFreeRate -红利-波动率*波动率/2)*dT;pert = * sqrt (dT) * randn波动;价格=价格*exp(dr + pert);cumulativePrice = cumulativePrice +价格;结束numSteps = (T / dT);meanPrice = cumulativePrice / numSteps;以今天的货币表示最终价格。optionPrice = exp(- riskfreerate *T)*max(0,meanPrice - strike);结束
Lookback选项功能
的lookbackCallOption
函数执行蒙特卡罗模拟,以确定一种欧式回望期权,其股息为期权生命周期内的最低股价与最终股价之差。期权的执行价格是最低股价。因为最终股价总是大于或等于最小值,期权总是被执行,并不是真正的“可选”。
的lookbackCallOption
函数以初始股价、无风险利率、股息率、市场波动率、总时间窗和样本利率为输入。
函数optionPrice = lookbackCallOption(价格,riskFreeRate,股息,波动率,T,dT) T = 0;minPrice =价格;而t < t t = t + dT;dr = (riskFreeRate -红利-波动率*波动率/2)*dT;pert = * sqrt (dT) * randn波动;价格=价格*exp(dr + pert);如果价格< minPrice;结束结束以今天的货币表示最终价格。optionPrice = exp(- riskfreerate *T)*max(0,price - minPrice);结束
障碍选择功能
的upAndOutCallOption
函数执行蒙特卡罗模拟,以确定一个向上和向上的障碍看涨期权价格。如果股价保持在障碍水平以下,该函数在正常的欧洲看涨期权计算中使用最终股价。
的upAndOutCallOption
函数以初始股票价格、无风险利率、股息率、市场波动率、执行价格、障碍价格、总时间窗和样本利率为输入。
函数optionPrice = upAndOutCallOption(价格,riskFreeRate,股息,波动性,罢工,障碍,T,dT) T = 0;而(t < t) &&(价格<障碍)t = t + dT;dr = (riskFreeRate -红利-波动率*波动率/2)*dT;pert = * sqrt (dT) * randn波动;价格=价格*exp(dr + pert);结束如果价格<障碍%在障碍内,价格与欧洲期权相同optionPrice = exp(- riskfreerate *T)*max(0,价格-执行);其他的击中障碍,因此期权被撤回。optionPrice = 0;结束结束
另请参阅
相关的话题
- 测量和改进GPU性能
- 利用arrayfun提高基于元素的MATLAB函数在GPU上的性能
- 定价欧洲和美国的价差期权(金融工具的工具箱)
- 亚洲期权定价(金融工具的工具箱)
- 用不同的股权模型定价欧洲看涨期权(金融工具的工具箱)
- 支持的权益衍生函数(金融工具的工具箱)