字體:小 中 大 |
|
|
|
| 2018/07/03 12:26:10瀏覽664|回應0|推薦0 | |
|
第四節 資產過程的描述與離散化
現代財務模型大都以連續交易作為分析的架構,亦即,交易是連續進行,兩次交易間的時間間隔為無限小,因此稱之為連續時間財務。然而,當我們要進行模擬時,卻是必須將之離散化。這是因為在實際進行模擬時,我們只能以有限的步數,模擬期末資產可能的價格。也因此,每次模擬的時間跨距(Time Interval)是有限的,而非無限小。這種以有限間隔的模擬實作,取代模型中間隔無限小的假設,稱之為離散化(Discretization),實務最常使用的是尤拉法(Euler Schemes)。另外尚有兩個較為精細的方法,分別是Milstein Schemes與二階法(Second-Order Method),然而由於效率上的考量,實務上使用的機會不大。
一、尤拉法 以傳統的Black-Scholes模型為例,
最簡單的離散化為尤拉法的離散化,
因此,可得下面的迭代模擬方程式。
(2.4.1)式可以改寫如下,
(2.4.3)式的隨機微分方程式,在給定期初資產價格S0下,可以求得期末價格ST的移轉方程式如下,
由於,(2.4.4)式是公式解,因此不論時間跨距長短,都可以直接用來模擬期末價格。實務上,十萬次的模擬是一般的要求。 (2.4.2)式的差分方程式,在給定期初資產價格S1下,可以求得期末價格S2的移轉方程式如下,
通常,我們以一天走一步的方式來進行模擬。因此,如果到期時間為一年,則一條模擬的路徑要走365步。十萬條的路徑應該是可以接受的模擬量。
二、Milstein法
三、二階法
第五節 C#單資產風險中立的模擬 在CPUProcess方案中,STBSProcess專案,我們以Black-Scholes資產價格程序為模擬的對象,
然而,實際在進行模擬時,我們採用(2.4.5)式一天一步的方式來模擬, 模擬的期限為一年,為了配合一些市場上交易契約的條件,我們假定需要一個月進行一次的比價。 假定起始日為2014/7/1,我們首先計算未來十二個比價的日期,與2014/7/1相減,算出每一比價日期要走的步數。
一、風險中立訂價理論:鞅性方法 令Rt為一證券之t期之報酬率, rt為無風險報酬率,RP表風險溢酬,令E[RP]=α。則一證券之報酬率包含無風險報酬率與風險溢酬兩個成分。
如果我們用Rt作為該證券之折現率,則此證券之t期市場價格可由下式求得,
然而,由於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,我們可以下式估算期初選擇權價值,
若利率為固定不變,可簡化為
模擬M次,求平均數可得估計值
依據風險中立定價法,股價過程為
若目前價格為S0,未來T的價格為ST,則Ln(ST)為一常態分配,其平均數與標準差分別為
Ln(ST/S0) 為服從下述之常態分配
估計值的誤差為
其中
三、Black-Scholes解析解公式 在Black-Scholes股票選擇權的公式中,他們基於無套利的條件,使用了風險中立的評價與(2.4.1)的股價隨機程序。其步驟為 1.假設股價的預期收益為無風險資產的收益率r。 2.計算選擇權在到期日時預期的償付。 3.以無風險資產的收益率折現該償付。 藉由上述的分析,Black和Scholes利用偏微分方程式,推導出了不支付股利股票的歐式買、賣權公式。買權和賣權價格公式分別為
其中
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 void button2_Click(object sender, EventArgs e) #010 { #011 Application.Exit(); #012 } #013 const int BlocksPerGrid = 256; #014 const int ThreadsPerBlock = 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 void button3_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 = new MersenneTwister(1234); #042 Stopwatch SW = new Stopwatch(); #043 RefDate = new DateTime(2014, 7, 1); #044 FixingDate = new List<DateTime>(); #045 //MStep depend on the remaining FixingDay Number, Including RefDate #046 // 0, 1, 2,..., 12, 0 for RefDate #047 for (int i = 0; i < MStep; i++) #048 { #049 FixingDate.Add(RefDate.AddMonths(i)); #050 } #051 h_StepGrid = new int[MStep]; #052 for (int i = 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 (int i = 0; i < NPath; i++) #061 { #062 s1 = Asset; #063 int diff = 0; #064 S[i, 0] = s1; #065 for (int j = 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 (int i = 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 (int j = 0; j < MStep; j++) #095 { #096 listBox1.Items.Add(S[0, j].ToString()); #097 } #098 } #099 } #100 } 程式列表2.5
執行結果如上圖,運算時間約7.2秒,模擬值為12.8400,與解析解的理論值12.5677,誤差值為0.2723,誤差百分比約2.2%上下。我們也把前十個模擬路徑的值,作圖輸出,可以看到整個路徑上標的資產價格的變化。 |
|
| ( 創作|其他 ) |




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






…………………………………(2.4.2)
………………………………………………………….…(2.4.3)
……………………………....…(2.4.4)
……………………………………(2.4.5)

…………............................…………...(2.5.1)
……………………………...............................(2.5.2)
…………………….............................(2.5.3)
.……………….............................………(2.5.4)
………………………………............................…(2.5.5)

............................………….….(2.5.6)
……….................................(2.5.7)
.…………….………...........................…….(2.5.8)
................................….(2.5.9)
…………………….........................(2.5.10)
…………..........................…(2.5.11)
..………………..........................(2.5.12)
.........…………..……………..(2.5.13)
= 







