Xem mẫu
- Giải bài toán Markowitz: Tối ưu hóa danh mục đầu tư chứng khoán bằng
VBA for Excel
Tác giả: Nguyễn Văn Thắng
Harry Markowitz đã mô hình hóa quá trình lựa chọn danh mục đầu tư (nhờ
đó đoạt giải Nobel kinh tế năm 1990) dưới dạng một bài toán quy hoạch phi
tuyến (bài toán Markowitz). Mục tiêu của bài toán Markowitz là tìm các tỉ
trọng của các chứng khoán trong danh mục đầu tư sao cho giảm tới mức tối
thiểu phương sai (rủi ro) của danh mục mà đạt được một mức thu nhập đã
định. Giải liên tiếp bài toán với các mức thu nhập mục tiêu người ta xác định
được một tập hợp các danh mục đầu tư có hiệu quả. Từ đây nhà đầu tư sẽ lựa
chọn một danh mục nằm trong tập hợp này dựa trên quan điểm của mình về
việc đánh đổi giữa thu nhập và rủi ro.
Tìm
Với hệ ràng buộc
- Trong đó:
Phương sai thu nhập của danh mục
đầu tư
Tỉ trọng của chứng khoán thứ i
trong danh mục đầu tư gồm n chứng
khoán; do thị trường chứng khoán
nước ta chưa cho phép bán khống.
(Nếu cho phép bán khống thì bài
Xi
toán được giải bằng phương pháp
Lagrange và rủi ro của danh mục tối
ưu còn giảm nhiều hơn, bài toán
Markowitz kinh điển không có điều
kiện này)
- Thu nhập kỳ vọng của chứng khoán
ri
thứ i
Thu nhập dự tính của toàn bộ danh
mục đầu tư
Tôi đã viết một chương trình nhỏ bằng VBA for Excel để giải bài toán
Markowitz. Qua tạp chí TGVT giới thiệu để các bạn cùng xem xét và sửa đổi
chương trình hiệu quả hơn.
THUẬT TOÁN
Phương pháp giải: Tham khảo phương pháp “Gradien” và “đơn hình” trong
giáo trình “Tối ưu hóa” – Nhà xuất bản khoa học kỹ thuật của PGS.TS Bùi
Minh Trí.
Bước 1 : Tìm phương án đầu tiên xo
Bước 2 : Tính các đạo hàm riêng của f(x) tại xo
Bước 3 : Khởi tạo vector ma trận cho bài toán đơn hình
Bước 4 : Sử dụng thuật toán đơn hình hai pha để giải bài toán đơn hình để
tìm hướng di chuyển xk
Bước 5 : Kiểm tra điều kiện tối ưu của bài toán Markowitz
- Bước 6 : Nếu chưa tìm thấy lời giải, tính nhân tố l, tính xk+1, đặt xo=xk+1
rồi quay trở lại bước 2.
CHƯƠNG TRÌNH
Chương trình gồm 20
hàm viết bằng VBA for
Excel được tóm tắt trong
bảng bên dưới. Bạn đọc
có thể tải file “Solution
for Markowitz.xls” tại
website của TGVT để
xem chi tiết mã nguồn
(mở Tools\Macro\Visual
Basic Editor để xem). (dữ liệu trích từ trang web http://www.saga.vn/
Taichinh/Quihoach/Mohinhhoa_Dubao/5673.saga)
HƯỚNG DẪN SỬ
DỤNG
Dữ liệu
Giả sử chúng ta xem xét việc thiết lập danh mục đầu tư từ 5 mã chứng khoán
và có bảng dữ liệu về thu nhập từ tháng 12/2004 đến 7/2007 tại sheet Dulieu
vùng B2:F33 như sau:
- Để thuận lợi cho việc tính toán ta định nghĩa các vùng dữ liệu bằng chọn
Insert\Name\Define như sau:
AGF=dulieu!$B2$B33; GIL=dulieu!$C2$C33; GMD=dulieu!$D2$D33;
NKD=dulieu!$E2$E33; REE =dulieu!$F2$F33
Thiết lập các tham số
Tham số được thiết lập tại sheet thamso, như sau:
Hàm/thủ tục Chức năng Tham số
• Hàm lấy dữ • “Var” bảng dữ liệu
liệu, tính phương về ma trận phương
án khởi tạo, tạo sai;
lập vector • ”R” bảng dữ liệu về
1. Function Sol(Var Gradien của vector thu nhập kỳ
As Range, R As f(xo), gọi hàm vọng của các chứng
Range, RConst As “donhinh” để tìm khoán,
Double, idx As xk; tìm lamda l, • “Rconst” thu nhập
Integer) As Double tính toán xk+1. mục tiêu của danh
• Trả về tỷ trọng mục,
tối ưu của chứng • “idx” số thứ tự của
khoán thứ “idx” chứng khoán cần tính
trong danh mục tỷ trọng
- • R() vector thu nhập
• Thủ tục lập
kỳ vọng của các
phương án đầu
2. Sub FirstSol(R() As chứng khoán
tiên của bài toán
Double, X() As • X() vector trả về
Markowit
Double, RConst As của phương án
(phương án này
Double) • Rconst thu nhập
chỉ bao gồm 2
mục tiêu của chứng
chứng khoán)
khoán
• X() vector phương
án đang xét Xo
• Thủ tục tính các
3. Sub SetGradien(X() • Var() (mảng 2
đạo hàm riêng
As Double, Var() As chiều) ma trận hiệp
của hàm f(x) rồi
Double, Gra() As phương sai các
gán vào mảng
Double) chứng khoán
Gra()
• Gra() vector
gradien của hàm f(x)
4. Function • Hàm trả về • X() vector phương
Lamda(X() As nhân tố lamda l án đang xét Xo
Double, DX() As để từ đó chuyển • DX() là vector hiệu
Double, Var() As sang một phương của phương án Xk và
Double) As Double án phân bổ chứng Xo
- khoán mới tốt • Var() ma trận hiệp
hơn phương sai các
chứng khoán
• X() vector phương
án đang xét Xo
5. Sub SetXnew(X() • Lamda là nhân tố
• Thủ tục trả về
As Double, Lamda As lamda l
phương án tốt
Double, DX() As • DX() là vector hiệu
hơn vào mảng
Double, X_new() As của phương án Xk và
X_new()
Double) Xo
• X_new() phương án
tốt hơn trả về
• Hàm giải bài • A() mảng hai chiều
6. Function toán quy hoạch ứng với ma trận tham
donhinh(a() As tuyến tính theo số của bài toán đơn
Double, b() As thuật toán đơn hình
Double, C() As hình 2 pha • B() mảng 1 chiều
Double, X() As • Trở về True nếu ứng với vector ràng
Double) As Boolean giải được bài toán buộc
Phương án tối ưu • C() mảng 1 chiều
được trả về mảng ứng với vetor của
- X() hàm mục tiêu
• X() phương án cực
biên trả về
• Thủ tục lập
7. Sub • Base() mảng chỉ tới
phương án cực
SetXVector(X() As các cột cơ sở của
biên của bài toán
Double, base() As bảng đơn hình
quy hoạch tuyến
Integer, simplex() As • Simplex() mảng 2
tính rồi gán vào
Double) chiều ứng bảng đơn
mảng X()
hình của bài toán quy
hoạch tuyến tính
• Hàm tính các • Delta() vector các
8. Function Delta của bài Delta của bảng đơn
TestDelta(Delta() As toán đơn hình rồi hình đang xét
Double, X() As gán vào mảng • X() phương án cực
Double, base() As Delta() biên đang xét
Integer, C_matrix() As • Kiểm tra điều base() mảng chỉ tới
Double, simplex() As kiện tối ưu của các cột cơ sở của
Double, nv As bài toán đơn hình bảng đơn hình
Integer) As Integer • Kiểm tra sự • C_matrix() vector
không giải được của hàm mục tiêu của
của bài toán đơn bài toán đơn hình
- hình • Simplex() là bảng
• Chỉ ra hướng để đơn hình
chuyển đổi bảng • nv là giá trị mà
đơn hình tốt hơn Base(nv) chỉ tới
bằng cách trả về chính là biến phải
số thứ tự của đưa khỏi cơ sở của
Delta lớn nhất( bảng đơn hình)
chính là biến cần
phải đưa vào cơ
sở của bảng đơn
hình) và đặt giá
trị cho biến nv
(giá trị mà
Base(nv) chỉ tới
là biến phải đưa
khỏi cơ sở của
bảng đơn hình)
9. Sub • Thủ tục biến đổi • base() mảng chỉ tới
ChangeSimplex(base() bảng đơn hình các cột cơ sở của
As Integer, simplex() nhằm tìm ra bảng đơn hình
As Double, V_in As phương án cực • Simplex() là bảng
Integer, nv As Integer) biên tốt hơn đơn hình
• V_in là biến mới
- được đưa vào cơ sở
• Nv là chỉ số mà
Base(nv) trỏ tới phải
ra khỏi cơ sở
• Hàm trả về chỉ
10. Function Min(arr() số của phần tử
• arr() mảng 1 chiều
As Double) As Integer dương nhỏ nhất
trong mảng
• Hàm trả về chỉ
11. Function
số của phần tử
Max(arr() As Double) • arr() mảng 1 chiều
lớn nhất trong
As Integer
mảng
• Hàm trả về chỉ
12. Function
số của phần tử
Min2(arr() As Double) • arr() mảng 1 chiều
nhỏ nhất trong
As Integer
mảng
13. Function • Hàm trả về tích
• X() mảng 1 chiều
SumProduct(X() As vô hướng của 2
• Y() mảng 1 chiều
Double, Y() As vector
- Double) As Double
14. Function
• Hàm trả về tích • X() mảng 1 chiều
SumSuper(X() As
vô hướng của 1 • Y() ma trận
Double, Y() As
vector và 1 dòng • M chỉ số dòng của
Double, m As Integer)
của 1 ma trận ma trận được nhân
As Double
• Thủ tục trả về
15. Sub SetDX(DX()
hiệu của hai
As Double, X_cu() As
vector X_cu() và
Double, X_moi() As
X_moi() vào
Double)
vector DX()
16. Sub SetEqual(X() • Thủ tục đặt
As Double, Y() As vector X() bằng
Double với vector Y()
• Thủ tục gán giá • B() vector ràng
17. Sub SetB(b() As buộc của bài toán
trị cho vector b()
Double, n As Integer, đơn hình
của bài toán đơn
RConst As Double) • N chính bằng số
hình
chứng khoán
- • Rconst thu nhập
mục tiêu của danh
mục chứng khoán
• A() ma trận tham số
của bài toán đơn hình
• Thủ tục gán giá
18. Sub SetA(a() As • N chính bằng số
trị cho mảng 2
Double, n As Integer, chứng khoán
chiều a() của bài
R() As Double • R() vector thu nhập
toán đơn hình
kỳ vọng của các
chứng khoán
• C() vector mục tiêu
19. Function SetC(C() • Thủ tục gán giá của bài toán đơn hình
As Double, n As trị cho vector c() • N chính bằng số
Integer, G() As của bài toán đơn chứng khoán
Double) hình • G() vector gradien
của hàm f(x)
20. Public Function • Var_matrix là bảng
• Hàm trả về ma trận phương
Varience(Var_matrix
phương sai của sai/hiệp phương sai
As Range, W_matrix
danh mục đầu tư • W_matrix phương
As Range) As Double
án phân bổ các chứng
- khoán
• Vùng từ B3:F3 là các tham số về thu nhập kỳ vọng (trung bình) chứng
khoán
Tại ô B3 công thức =AVERAGE(AGF)
Tại ô C3 công thức =AVERAGE(GIL)
Tại ô D3 công thức =AVERAGE(GMD)
Tại ô E3 công thức =AVERAGE(NKD)
Tại ô F3 công thức=AVERAGE(REE)
- • Vùng từ B4:F4 là các tham số về độ lệch chuẩn về thu nhập của chứng
khoán
Tại ô B4 công thức =SQRT(VAR(AGF))
Tại ô C4 công thức = SQRT(VAR(GIL))
Tại ô D4 công thức = SQRT(VAR(GMD))
Tại ô E4 công thức = SQRT(VAR(NKD))
Tại ô F4 công thức= SQRT(VAR(REE))
• Vùng từ B9:F13 là ma trận phương sai/hiệp phương sai của thu nhập của
các chứng khoán
Tại ô B9 là phương sai của chứng khoán AGF; công thức =VAR(AGF)
Tại ô C10 phương sai của chứng khoán GIL; công thức =VAR(GIL)
Tại ô D11 phương sai của chứng khoán GMD; công thức =VAR(GMD)
Tại ô E12 phương sai của chứng khoán NKD; công thức =VAR(NKD)
Tại ô F13 phương sai của chứng khoán REE; công thức =VAR(REE)
Tại ô B10 là hiệp phương sai của chứng khoán AGF và GIL; công thức
=COVAR(AGF;GIL)
Tại ô C9 là hiệp phương sai của chứng khoán GIL và AGF; công thức
=COVAR(AGF;GIL)
- Tại ô B11 là hiệp phương sai của chứng khoán AGF và GMD; công thức
=COVAR(AGF;GMD)
Tương tự như vậy ta điền hết công thức vào các ô còn trống
• Ta tiếp tục định nghĩa các vùng dữ liệu sau cho tiện việc tính toán (bằng
Insert\Name\Define)
Thunhap=thamso!$B$3:$F$3;phuongsai= thamso!$B$9:$F$13
Xử lý bài toán
• Vùng từ D3:H23 là các tính toán xử lý của chúng ta về tỷ trọng phân bổ
chứng khoán, ví dụ:
- Tại ô D4 công thức =sol(phuongsai;thunhap;A4;1)
Tại ô E4 công thức =sol(phuongsai;thunhap;A4;2)
Tại ô F4 công thức =sol(phuongsai;thunhap;A4;3)
Tại ô G4 công thức =sol(phuongsai;thunhap;A4;4)
Tại ô F4 công thức =sol(phuongsai;thunhap;A4;5)
Tương tự ô G22 công thức =sol(phuongsai;thunhap;A22;4)
• Vùng B3:B23 là tính toán về phương sai của danh mục, ví dụ:
tại ô B2 có công thức =varience(phuongsai;D2:F2)
tại ô B22 có công thức =varience(phuongsai;D22:F22)
• Vùng C3:C23 là tính toán về độ lệch chuẩn của danh mục:
tại ô C2 công thức=SQRT(B2)
tại ô C22 công thức=SQRT(B22)
Thông qua kết quả tính toán ta thấy ngay được hiệu của việc đa dạng hóa
danh mục đầu tư, ví dụ danh mục đầu tư Y ở vùng D13:F13
(AGF=26,7%;GIL=17,4%;GMD=21,2%;NKD=11,4%;REE=23,3%) có thu
nhập là 7% và độ lệch chuẩn là 15,04%; danh mục này hiệu quả hơn danh
mục Z gồm 100% chứng khoán GMD có thu nhập 7% và độ lệch chuẩn
24,2%. Có thể nói danh mục Y chi phối danh mục Z. Các danh mục đầu tư bị
- chi phối bởi các danh mục đầu tư khác gọi là “các danh mục đầu tư kém hiệu
quả”. Tập hợp hiệu quả là một phần của danh mục đầu tư khả dĩ có độ lệch
chuẩn tối thiểu sau khi cắt bỏ các danh mục đầu tư kém hiệu quả. Để làm rõ
hơn điều này ta chọn vùng A3:C23 để vẽ biểu đồ có dạng, như sau:
Ta thấy ngay danh mục đầu tư nằm trên đoạn BC chính là đường danh mục
đầu tư hiệu quả. Đây là các danh mục tốt nhất bởi vì không thể tìm được một
danh mục nào khác tốt hơn về thu nhập mà lại không phải hy sinh về rủi ro
(độ lệch) và ngược lại không thể tìm một danh mục nào khác có rủi ro ít hơn
mà không phải hy sinh về thu nhập. Các danh mục đầu tư nằm phía dưới
đoạn BC là không hiệu quả vì cùng một mức rủi ro nhưng lại có thu nhập
thấp hơn. Nhà đầu tư thông minh sẽ lựa chọn một danh mục nào đó nằm trên
đường BC dựa trên quan điểm của anh ta về việc đánh đổi giữa thu nhập và
rủi ro.
nguon tai.lieu . vn