金融工程与并行计算:第二章 仿真法在财务工程的使用 Part 3

第四节 资产过程的描述与离散化

现代财务模型大都以连续交易作为分析的架构,亦即,交易是连续进行,两次交易间的时间间隔为无限小,因此称之为连续时间财务。然而,当我们要进行模拟时,却是必须将之离散化。这是因为在实际进行模拟时,我们只能以有限的步数,仿真期末资产可能的价格。也因此,每次模拟的时间跨距(Time Interval)是有限的,而非无限小。这种以有限间隔的仿真实作,取代模型中间隔无限小的假设,称之为离散化(Discretization),实务最常使用的是尤拉法(Euler Schemes)。另外尚有两个较为精细的方法,分别是Milstein Schemes与二阶法(Second-Order Method),然而由于效率上的考虑,实务上使用的机会不大。

 

一、尤拉法

以传统的Black-Scholes模型为例,

…………………………………………………………..(2.4.1)

最简单的离散化为尤拉法的离散化,

因此,可得下面的迭代模拟方程式。

…………………………………………(2.4.2)

 

(2.4.1)式可以改写如下,

……………………………………………………………….…(2.4.3)

(2.4.3)式的随机微分方程式,在给定期初资产价格S0下,可以求得期末价格ST的移转方程式如下,

…………………………………………....…(2.4.4)

由于,(2.4.4)式是公式解,因此不论时间跨距长短,都可以直接用来仿真期末价格。实务上,十万次的模拟是一般的要求。

(2.4.2)式的差分方程式,在给定期初资产价格S1下,可以求得期末价格S2的移转方程式如下,

……………………………………………(2.4.5)

通常,我们以一天走一步的方式来进行模拟。因此,如果到期时间为一年,则一条仿真的路径要走365步。十万条的路径应该是可以接受的模拟量。

 

二、Milstein法

 

三、二阶法

 

第五节 C#单资产风险中立的模拟

在CPUBSProcess方案中,STBSProcess项目,我们以Black-Scholes资产价格程序为仿真的对象,

然而,实际在进行模拟时,我们采用(2.4.5)式一天一步的方式来模拟,

模拟的期限为一年,为了配合一些市场上交易契约的条件,我们假定需要一个月进行一次的比价。

假定起始日为2014/7/1,我们首先计算未来十二个比价的日期,与2014/7/1相减,算出每一比价日期要走的步数。因此我们要记录2014/8/1,2014/9/1,2014/10/1,2014/11/1,2014/12/1,2015/1/1,2015/2/1,2015/3/1,2015/4/1,2015/5/1,2015/6/1,2015/7/1等日的汇率价格。下面程序使用两个循环来控制模拟的进行,外循环控制仿真的路径,一共512*256条路径。内回圈控制每一步的进行,一共365步,同时把12个比价日的汇率纪录下来。

 

一、风险中立订价理论:鞅性方法

令Rt为一证券之t期之报酬率, rt为无风险报酬率,RP表风险溢酬,令E[RP]=α。则一证券之报酬率包含无风险报酬率与风险溢酬两个成分。

…………………………............................…………...(2.5.1)

如果我们用Rt作为该证券之折现率,则此证券之t期市场价格可由下式求得,

……………………………………………...............................(2.5.2)

然而,由于Rt本身可能无法事前确定,因此我们不能直接使用(2.5.2)式计算证券t期之市场价格。

令t期无风险债券Bt =1,则Bt+1 =1+rt。令Xt = St / Bt,如果我们经过某种方式处理,得到Et[Xt+1]= Xt。由于rt可由市场上直接观察得到,因此Xt本身的计算没有困难。

Et[Xt+1|Xt ] = Xt,此性质称为鞅性(Martingale),又称之为一公平赌局(Fair Game)。如果我们将Xt视为t期末之财富,则t+1期末之财富的期望值Et[Xt+1|Xt ],等于t期末之财富。因此,t+1期的赌局是一个公平的赌局,参与者由此赌局赚得的财富期望值为零。

近代财务理论使用机率测度转换的方法,以零息债券价格为计价单位,得到鞅性的良好性质。由此性质,得到衍生商品定价的一般理论,这也提供我们使用仿真方法计算选择权价格理论基础。使我们回避掉估计证券风险溢酬的难题。下面说明模拟法实作的细节,至于有关鞅性定价理论的细节,有兴趣的读者可参考Neftci(2002)的说明。

 

二、实作的方法

考虑欧式选择权,依据风险中立定价法,到期日为T,目前时间为t=0,我们可以下式估算期初选择权价值,

…………………….…………………….............................(2.5.3)

若利率为固定不变,可简化为

……………………..……………….............................………(2.5.4)

模拟M次,求平均数可得估计值

…………………………………………………............................…(2.5.5)

依据风险中立定价法,股价过程为

若目前价格为S0,未来T的价格为ST,则Ln(ST)为一常态分配,其平均数与标准偏差分别为

…………….………..............................………….….(2.5.6)

Ln(ST/S0) 为服从下述之常态分配

…………….………………….................................(2.5.7)

估计值的误差为

…………………….…………….………...........................…….(2.5.8)

其中

……………………….....................................….(2.5.9)

 

三、Black-Scholes解析解公式

在Black-Scholes股票选择权的公式中,他们基于无套利的条件,使用了风险中立的评价与(2.4.1)的股价随机程序。其步骤为

1.假设股价的预期收益为无风险资产的收益率r。

2.计算选择权在到期日时预期的偿付。

3.以无风险资产的收益率折现该偿付。

藉由上述的分析,Black和Scholes利用偏微分方程式,推导出了不支付股利股票的欧式买、卖权公式。买权和卖权价格公式分别为

………………………………………….........................(2.5.10)

…………...………………………..........................…(2.5.11)

其中

………………………..………………..........................(2.5.12)

............................…………..……………..(2.5.13)

S = 目前股价,

K = 执行价格,

r = 融资利率为即期利率,

T = 距到期日的时间,

 = 股价之波动性,

N(x)函数为标准常态变量之累积机率函数。

 


#001 namespace STBSProcess

#002 {

#003     public partial class Form1 : Form

#004     {

#005         public Form1()

#006        {

#007            InitializeComponent();

#008        }

#009         private voidbutton2_Click(object sender, EventArgs e)

#010        {

#011            Application.Exit();

#012        }

#013         const intBlocksPerGrid = 256;

#014         const intThreadsPerBlock = 512;

#015         static int NPath =ThreadsPerBlock * BlocksPerGrid; //131,072 Paths

#016         static int MStep =13;

#017         static DateTime RefDate;

#018         static List<DateTime> FixingDate;

#019         static int[]h_StepGrid;

#020         double[,] S = new double[NPath, MStep];

#021         double[] Value = new double[NPath];

#022         private voidbutton3_Click(object sender, EventArgs e)

#023        {

#024            double Asset = 100.0;

#025            double Strike = 100.0;

#026            double TTM = 1.0;

#027            double Sigma = 0.3;

#028            double Rate = 0.04;

#029            double Yield = 0.02;

#030            double dt = 1.0 / 365.0;

#031            // Analytic Benchmark

#032            double d1 = (Math.Log(Asset / Strike)

#033                + (Rate - Yield + 0.5 * Sigma * Sigma) * TTM)

#034                / (Sigma * Math.Sqrt(TTM));

#035            double d2 = d1 - Sigma * Math.Sqrt(TTM);

#036            double CValue = Asset * Math.Exp(-Yield* TTM) * DStat.NormDist(d1)

#037                - Strike * Math.Exp(-Rate * TTM) * DStat.NormDist(d2);

#038            double PValue = Strike * Math.Exp(-Rate* TTM) * DStat.NormDist(-d2)

#039                - Asset * Math.Exp(-Yield * TTM) * DStat.NormDist(-d1);

#040             //Random Rnd =new Random(1234);

#041            MersenneTwister Rnd = newMersenneTwister(1234);

#042            Stopwatch SW = new Stopwatch();

#043            RefDate = new DateTime(2014, 7, 1);

#044            FixingDate = new List<DateTime>();

#045            //MStep depend on the remaining FixingDayNumber, Including RefDate

#046            // 0, 1, 2,..., 12, 0 for RefDate

#047            for (inti = 0; i < MStep; i++)

#048            {

#049                FixingDate.Add(RefDate.AddMonths(i));

#050            }

#051            h_StepGrid = new int[MStep];

#052            for (inti = 0; i < MStep; i++)

#053            {

#054                TimeSpan TS = FixingDate[i].Subtract(RefDate);

#055                h_StepGrid[i] = (int)TS.TotalDays;

#056            }

#057            double s1, n1;

#058

#059            SW.Start();

#060            for (inti = 0; i < NPath; i++)

#061            {

#062                s1 = Asset;

#063                int diff = 0;

#064                S[i, 0] = s1;

#065                for (intj = 0; j < (MStep - 1); j++)

#066                {

#067                     diff = h_StepGrid[j + 1] -h_StepGrid[j];

#068                     for(int k = 0; k < diff; k++)

#069                     {

#070                         n1 =DStat.N_Inv(Rnd.NextDouble());

#071                         s1 = s1 *Math.Exp(((Rate-Yield) - (Sigma*Sigma)/2.0) * dt

#072                             + (Sigma *Math.Sqrt(dt) * n1));

#073                     }

#074                     S[i, j + 1] = s1;

#075                }

#076                Value[i] = Math.Max(s1 - Strike, 0);

#077            }

#078            double sum = 0.0;

#079            for (inti = 0; i < NPath; i++)

#080            {

#081                sum = sum + Value[i];

#082            }

#083            sum = (sum / NPath) * Math.Exp(-(Rate - Yield) * TTM);

#084            SW.Stop();

#085

#086            double gap = sum - CValue;

#087            double ratio = (gap / CValue) * 100.0;

#088            textBox1.Text = SW.ElapsedMilliseconds.ToString();

#089            textBox2.Text = CValue.ToString();

#090            textBox3.Text = sum.ToString();

#091            textBox4.Text = gap.ToString();

#092            textBox5.Text = ratio.ToString();

#093             listBox1.Items.Clear();

#094            for (intj = 0; j < MStep; j++)

#095            {

#096                listBox1.Items.Add(S[0, j].ToString());

#097            }

#098        }

#099     }

#100 }

程序行表2.5


 

执行结果如上图,运算时间约5.8秒,模拟值为12.8400,与解析解的理论值12.5677,误差值为0.2723,误差百分比约2.2%上下。我们也把前十个仿真路径的值,作图输出,可以看到整个路径上标的资产价格的变化。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值