---
Title: Tính phí quyền chọn dựa trên mô hình Black-Scholes
---
# Tính phí quyền chọn dựa trên mô hình Black-Scholes

Gần đây, bỗng nhiên vây quanh mình xuất hiện khá nhiều thông tin liên quan đến mô hình **Black-Scholes** tính phí quyền chọn (cổ phiếu, token, chỉ số,…) rất nổi tiếng và đang được áp dụng rộng rãi trong ngành tài chính.
Mô hình Black–Scholes, hay tên đầy đủ là mô hình **Black–Scholes–Merton** (Fischer Black, Myron Scholes, and Robert C Merton) là một mô hình toán học tính toán sự biến động của thị trường tài chính liên quan đến các tài sản tài chính phái sinh bằng cách đưa ra ước tính lý thuyết về giá của hợp đồng quyền chọn dựa trên các tham số đầu vào như rủi ro thị trường, tính biến động của tài sản tài chính và mức kỳ vọng lợi nhuận. Mô hình này đã được trao giải ***Nobel*** kinh tế năm **1997** cho Myron Scholes và Robert C Merton và được sử dụng rộng rãi trong các chiến lược đầu tư trên toàn cầu.
Công thức Black-Scholes-Merton tính phí quyền chọn cho một tài sản tài chính không bao gồm lợi tức được thể hiện như sau
$$\bbox[yellow]{
C(S_t, K, t, T, r, \sigma) = S_t.N(d_1)-e^{-r(T-t)}.K.N(d_2)
}
$$
Trong đó,
$$
N(d) = \frac{1}{\sqrt{2\pi}}\int_{-\infty}^{d} {e^{-\frac12x^2}}dx
$$
$$
d_1 = \frac{log\frac{S_t}{K}+(T-t)(r+\frac{\sigma^2}{2})}{\sigma\sqrt{T-t}}
$$
$$
d_2 = \frac{log\frac{S_t}{K}+(T-t)(r-\frac{\sigma^2}{2})}{\sigma\sqrt{T-t}}
$$
Trong các công thức trên thì $S_t$ là giá của tài sản tài chính tại thời điểm t. $\sigma$ là hằng số biến động giá của tài sản tài chính (độ lệch chuẩn của lợi nhuận kỳ vọng), $K$ là giá của tài sản tài chính theo hợp đồng quyền chọn, $T$ là ngày đáo hạn của hợp đồng quyền chọn, $r$ là lãi suất phi rủi ro.
Phương trình vi phân của $S_t$ theo mô hình Black-Scholes-Merton (**1973**)
$$
dS_t = rS_tdt + \sigma S_tdZ_t,
$$
Trong đó $Z(t)$ là thành phần ngẫu nhiên của mô hình (theo chuyển động $Brownian$) thể hiện cho tính rủi ro biến động về giá của tài sản tài chính.
Công thức vi phân rời rạc của mô hình BSM được biến đổi thành như sau
$$
S_t = S_{t-\Delta t}exp \left(\left(r-\frac{\sigma^2}{2}\right)\Delta t + \sigma \sqrt{\Delta t}z_t\right).
$$
Biến $z$ chính là giá trị ngẫu nhiên theo phân bố chuẩn. $0 < \Delta t < T$ là bước thời gian đủ nhỏ trong khoảng $(0, T]$, $T$ chính là thời gian kết thúc hợp đồng.
Vậy để tính được $S_t$ thì khó khăn nhất là làm sao tính được $N(d)$.
Như chúng ta đã biết, với một hàm liên tục $f:[a,b] \to \mathbb R$ thì đại lượng
$$
S = \int_{a}^{b} f(x)dx
$$
chính là phần diện tích bôi màu tạo bởi đồ thị của hàm $f$ và trục $x$ như hình bên dưới

Có một vài cách để tính gần đúng tích phân $S$ ở trên. Tuy nhiên, ở đây chúng ta có thể biến đổi thành công thức sau đây
$$
S \approx \frac{b-a}{n}\sum_{i=1}^nf(a+(b-a)U_i),
$$
trong đó, $U_i \sim \mathscr U(0,1)$. Tức là $U_i$ chính là giá trị theo phân bố chuẩn trong khoảng $[0, 1]$
Chúng ta biết rằng, để tính tích phân $S = \int_{-\infty}^{\infty} e^{-x^2}dx$ khá là phức tạp. Để tính gần đúng thì chúng ta có thể tính tích phân gần đúng khá tốt trong khoảng $[-20, 20]$ do giá trị hàm $f$ giảm rất nhanh khi x tăng lên như hình bên dưới

Dưới đây là một đoạn code cài đặt tính phí quyền chọn mua một tài sản tài chính theo mô hình Black-Scholes bằng ngôn ngữ lập trình **Go** có sử dụng mô phỏng **Monte Carlo** để tính gần đúng tích phân của $N(d)$
```go=
package main
import (
"fmt"
"math"
"math/rand"
"time"
)
func main() {
rand.Seed(time.Now().UTC().UnixNano())
// Parameters
S0 := 100.0 // initial value
K := 105.0 // strike price
T := 1.0 // maturity
r := 0.05 //risk free short rate
sigma := 0.2 //volatility
numPoints := 250_000
start := time.Now()
optionPrice := bsmCallValue(S0, K, T, r, sigma, numPoints)
duration := time.Since(start)
fmt.Printf("European Option Value: %.3f\n", optionPrice)
fmt.Println("Execution time: ", duration)
}
func bsmCallValue(S0, K, T, r, sigma float64, n int) float64 {
d1 := math.Log(S0/K) + T*(r+0.5*sigma*sigma)/(sigma*math.Sqrt(T))
d2 := math.Log(S0/K) + T*(r-0.5*sigma*sigma)/(sigma*math.Sqrt(T))
mciD1 := monteCarloIntegrator(gaussian, -20.0, d1, n)
mciD2 := monteCarloIntegrator(gaussian, -20.0, d2, n)
return S0*mciD1 - K*math.Exp(-r*T)*mciD2
}
// MC integrator
func monteCarloIntegrator(f func(float64) float64, a float64, b float64, n int) float64 {
var s float64
for i := 0; i < n; i++ {
ui := rand.Float64()
xi := a + (b-a)*ui
s += f(xi)
}
s = ((b - a) / float64(n)) * s
return s
}
// function to be integrated
func gaussian(x float64) float64 {
return (1 / math.Sqrt(2*math.Pi)) * math.Exp(-0.5*x*x)
}
```
Tổng hợp và lược dịch từ
[The art of solving problems with Monte Carlo simulations](https://ggcarvalho.dev/posts/montecarlo/)
> [name=Ha ĐANG ]