Hỏi về VBA nhân array với một số

Liên hệ QC

An dt

Thành viên mới
Tham gia
28/11/21
Bài viết
3
Được thích
0
Chào mọi người,

Em không chuyên về VBA nên có gì sai sót mong mọi người chỉ bảo tường tận chút ít ạ.

Trước tiên em xin giải thích qua về bài tập hy vọng có thể giúp mọi người hình dung dễ hơn: em cần viết code cho cho Binary Option, nghĩa là giả dụ giá tiền ngày hôm nay (ngày 0) là 100, thì ngày mai (ngày 1) sẽ có hai trường hợp xảy ra:
- trường hợp up: giá tiền tăng 10%
- trường hợp down: giá tiền giảm 10%
Như vậy ngày 1, từ 100 sẽ ra hai trường hợp 110 và 90.
Tiếp tục ngày 2, từ 110 lại có hai trường hợp như trên, và từ 90 cũng có hai trường hợp như trên
Cứ tiếp tục như vậy đến ngày n.

Em cần viết code vba tạo bảng thể hiện những trường hợp trên.
Sau khi suy nghĩ thì em có mường tượng code của em sẽ như thế này:
n = 10
u = 0.1
d = 0.1

Dim table(1 To 10, 1 To 10) As Double
Dim i, j As Integer

For i = 1 To 10
For j = 1 To 10
table(i, j) = table(i, j) * ((1 + u) ^ j) * (((1 - d) / (1 + u)) ^ i) 'vì trên cùng 1 dòng, cột sau hơn cột trước u=10%, và trên cùng 1 cột, dòng dưới kém dòng trên (0.9/1.1) %

If i > j Then
table(i, j) = 0 'vì tính toán thông thường sẽ thấy nửa bảng dưới hoàn toàn trống
End If

Next j
Next i

Chạy thử thì nó không báo lỗi nhưng cũng không ra kết quả gì.
Em đoán không thể nhân ma trận bằng "*", em đã thử dùng application.worksheetfunction.mmult nhưng theo em được biết nó để nhân hai ma trận thôi nên cũng không thành công.

Nhờ mọi người giúp đỡ xem nên sửa thế nào hoặc có cách nào khác để lập bảng không ạ. Em xin cảm ơn trước.
 
Chào mọi người,

Em không chuyên về VBA nên có gì sai sót mong mọi người chỉ bảo tường tận chút ít ạ.

Trước tiên em xin giải thích qua về bài tập hy vọng có thể giúp mọi người hình dung dễ hơn: em cần viết code cho cho Binary Option, nghĩa là giả dụ giá tiền ngày hôm nay (ngày 0) là 100, thì ngày mai (ngày 1) sẽ có hai trường hợp xảy ra:
- trường hợp up: giá tiền tăng 10%
- trường hợp down: giá tiền giảm 10%
Như vậy ngày 1, từ 100 sẽ ra hai trường hợp 110 và 90.
Tiếp tục ngày 2, từ 110 lại có hai trường hợp như trên, và từ 90 cũng có hai trường hợp như trên
Cứ tiếp tục như vậy đến ngày n.

Em cần viết code vba tạo bảng thể hiện những trường hợp trên.
Sau khi suy nghĩ thì em có mường tượng code của em sẽ như thế này:


Chạy thử thì nó không báo lỗi nhưng cũng không ra kết quả gì.
Em đoán không thể nhân ma trận bằng "*", em đã thử dùng application.worksheetfunction.mmult nhưng theo em được biết nó để nhân hai ma trận thôi nên cũng không thành công.

Nhờ mọi người giúp đỡ xem nên sửa thế nào hoặc có cách nào khác để lập bảng không ạ. Em xin cảm ơn trước.
table(i,j) = 0 thì nhân với cái gì thì cũng ra = 0, có sai chỗ nào đâu
 
Upvote 0
1. code luộm thuộm:
1.1. luộm thuộm hứ nhất: Code của bạn làm con toán (1 - d) 100 lần và (1 + u) 200 lần. Trong khi nếu bạn gán thẳng từ đầu u = 1.1 và d = 0.9 thì nó khỏi phải tính.
1.2. luộm thuộm thứ hai: code tính nửa dưới của ma trận như thế là rườm rà. Chỉ cần bỏ qua là nó mặc định 0.

2. code sai:
2.1. sai thứ nhất: thuật toán này tính luỹ tiến cấp số nhân nhưng khởi đầu bằng 0 cho nên luôn luôn ra kết qả 0.
2.2. sai thứ hai: thuật toán không đúng với tăng giảm
2.3. sai thứ ba: bạn chưa có cái gì để xác định cái "Bái-nờ-rì Ốp-sần" của bạn. Làm thế nào để biết ngày mai giảm hay tăng?

Const TANG = 1.1#
Const GIAM = 0.9#
...
table(1, 1) = 100
For i = 2 To 10
For j = i To 10 ' nửa dưới không tính, để mặc định 0
table(i, j) = table(i-1, j-1) * IIF( TangHayGiam(i, j), TANG, GIAM)
Next j
Next i
...

Function TangHayGiam(byval i as long, byval j as long) as Boolean
' function tính xem ngày hôm nay tăng hay giảm so với ngày trước
' trả về True nếu tăng, False nếu giảm
...
End Function
 
Lần chỉnh sửa cuối:
Upvote 0
Tăng/ giảm là 2 tùy chọn. Tính n lần thì số lượng kết quả là
2^1 + 2^2 + 2^3 + ... + 2^n
(tổng của n số hạng của 1 cấp số nhân)
 
Upvote 0
Tăng/ giảm là 2 tùy chọn. Tính n lần thì số lượng kết quả là
2^1 + 2^2 + 2^3 + ... + 2^n
(tổng của n số hạng của 1 cấp số nhân)
Tôi không hiểu lắm cách tính của bạn.
Nếu tính theo kiểu dấu mũ thì thuật toán của tôi là:

cummTang = 1#
cummGiam = 1#
For i = 1 To 10
For j = i To 10
If TangHayGiam(i, j) Then
cummTang = cummTang * 1.1#
Else
cummGiam = cummGiam * 0.9#
End If
table(i, j) = 100# * cummTang * cummGiam
Next j
Next i
 
Upvote 0
Tôi không hiểu lắm cách tính của bạn.
Theo tôi hiểu ở bài 1 (mà cũng có thể hiểu sai), thì với mỗi trường hợp sau khi tính sẽ lại có 2 trường hợp
Ví dụ:
n = 0: 1 con ban đầu là 100
n = 1: 2 kết quả là 11090
n = 2: 110 chia 2 trường hợp thành 12199; 90 có 2 trường hợp là 99 và 81, cộng là 4 kết quả
n = 3: Mỗi số đỏ có 2 trường hợp thành 8
...
Nếu n = 3 thì từ 100 ban đầu sẽ có 2 + 4 + 8 = 14 kết quả
 
Upvote 0
Bạn thử đoạn code này xem sao
Mã:
Sub taomang()
Dim arr() As Long
Dim i, j, n As Integer
Dim tang, giam As Double
n = Sheet1.Range("A1") + 1     'So ngay
tang = Sheet1.Range("A3")      'Tang
giam = Sheet1.Range("A4")      'Giam
ReDim arr(1 To n, 1 To 2 ^ (n - 1))
arr(1, 1) = Sheet1.Range("A2").Value 'Gia tri tien ban dau
For i = 2 To n
 For j = 1 To 2 ^ (i - 2)
  arr(i, 2 * j - 1) = arr(i - 1, j) * (1 + tang)
  arr(i, j * 2) = arr(i - 1, j) * (1 - giam)
 Next j
Next i
End Sub
 
Upvote 0
Theo tôi hiểu ở bài 1 (mà cũng có thể hiểu sai), thì với mỗi trường hợp sau khi tính sẽ lại có 2 trường hợp
...
Sau khi xem lại chỗ chú thích trong code của thớt:
Mã:
vì trên cùng 1 dòng, cột sau hơn cột trước u=10%, và trên cùng 1 cột, dòng dưới kém dòng trên (0.9/1.1) %
a(i1 j1) = a(i1, j1-1) * 1.1 ' tăng so với cột trước
a(i2, j2) = a(i2-1, j2) * 0.9 ' giảm so với dòng trước
Như vậy:
a(i, j) = a(i-1, j-1) * 1.1 * 0.9

Cách dễ (lưu ý "dễ" không có nghĩa là "ngắn") nhất để làm bài này là:

a(1, 1) = 100
For j = 2 To 10
a(1, j) = a(1, j-1) * 1.1
Next j
For i = 2 To 10
For j = i To 10
a(i, j) = a(i-1, j) * 0.9
Next j
Next i

...Em đoán không thể nhân ma trận bằng "*", em đã thử dùng application.worksheetfunction.mmult nhưng theo em được biết nó để nhân hai ma trận thôi nên cũng không thành công.
...
Nếu ma trận vuông, và nhân cho một hằng số thì làm được.

b(1 to UBound(a), 1 To UBound(a, 2) As Long
For i = 1 To UBound(b)
b(i, i) = hangSo ' chỉ dựng đường chéo thôi, chỗ còn lại là 0's
Next i
a = Applcation.Mmult(a, b)
 
Upvote 0
Mình nghĩ cái này nó không là ma trận vuông được, vì số giá trị bằng cấp số nhân của ngày (n).
Mã:
For i = 2 To n
 For j = 1 To 2 ^ (i - 2)

 Next j
Next i

0​
1​
2​
3​
100​
110​
121​
133​
90​
99​
109​
99​
109​
81​
89​
109​
89​
89​
73​
 
Lần chỉnh sửa cuối:
Upvote 0
Upvote 0
Mình nghĩ cái này nó không là ma trận vuông được, vì số giá trị bằng cấp số nhân của ngày (n).
Mã:
For i = 2 To n
 For j = 1 To 2 ^ (i - 2)

 Next j
Next i

0​
1​
2​
3​
100​
110​
121​
133​
90​
99​
109​
99​
109​
81​
89​
109​
89​
89​
73​
Dạ cái này là sai sót của em chưa giải thích kỹ, bảng này là kiểu: 110x0,9= 90x1,1= 99 và chỉ ghi đúng 1 giá trị 99 thôi chứ không chia làm hai dòng ạ
Bài đã được tự động gộp:

1. code luộm thuộm:
1.1. luộm thuộm hứ nhất: Code của bạn làm con toán (1 - d) 100 lần và (1 + u) 200 lần. Trong khi nếu bạn gán thẳng từ đầu u = 1.1 và d = 0.9 thì nó khỏi phải tính.
1.2. luộm thuộm thứ hai: code tính nửa dưới của ma trận như thế là rườm rà. Chỉ cần bỏ qua là nó mặc định 0.

2. code sai:
2.1. sai thứ nhất: thuật toán này tính luỹ tiến cấp số nhân nhưng khởi đầu bằng 0 cho nên luôn luôn ra kết qả 0.
2.2. sai thứ hai: thuật toán không đúng với tăng giảm
2.3. sai thứ ba: bạn chưa có cái gì để xác định cái "Bái-nờ-rì Ốp-sần" của bạn. Làm thế nào để biết ngày mai giảm hay tăng?

Const TANG = 1.1#
Const GIAM = 0.9#
...
table(1, 1) = 100
For i = 2 To 10
For j = i To 10 ' nửa dưới không tính, để mặc định 0
table(i, j) = table(i-1, j-1) * IIF( TangHayGiam(i, j), TANG, GIAM)
Next j
Next i
...

Function TangHayGiam(byval i as long, byval j as long) as Boolean
' function tính xem ngày hôm nay tăng hay giảm so với ngày trước
' trả về True nếu tăng, False nếu giảm
...
End Function
Em cảm ơn ạ. Đoạn u với d thì vì cái này cũng là kiểu để inputbox cho nhập số sau ấy ạ, em gán trước giá trị để ví dụ cho dễ nói. Bảng cần ra sẽ có dạng thế này ạ (chỉ là ví dụ thôi và không liên quan đến bài):crr-underlying-price-tree.png
 
Lần chỉnh sửa cuối:
Upvote 0
Bạn thử đoạn code này xem sao
Mã:
Sub taomang()
Dim arr() As Long
Dim i, j, n As Integer
Dim tang, giam As Double
n = Sheet1.Range("A1") + 1     'So ngay
tang = Sheet1.Range("A3")      'Tang
giam = Sheet1.Range("A4")      'Giam
ReDim arr(1 To n, 1 To 2 ^ (n - 1))
arr(1, 1) = Sheet1.Range("A2").Value 'Gia tri tien ban dau
For i = 2 To n
 For j = 1 To 2 ^ (i - 2)
  arr(i, 2 * j - 1) = arr(i - 1, j) * (1 + tang)
  arr(i, j * 2) = arr(i - 1, j) * (1 - giam)
 Next j
Next i
End Sub
em cảm ơn ạ. Em đã thử rồi (đã gán giá trị cho a1:a4) nhưng cũng không hiện ra gì cả :((
 
Upvote 0
...
Em cảm ơn ạ. Đoạn u với d thì vì cái này cũng là kiểu để inputbox cho nhập số sau ấy ạ, em gán trước giá trị để ví dụ cho dễ nói. ...
Bạn không hiểu tôi nói "tính 100 lần" nghĩa là gì rồi.
Tác giả bài #7 cũng không hiểu luôn. Và vì vậy, code ở bài #7 cũng lặp lại con tính giá trị (1 + tang) và (1 - giam) khá nhiều lần.

Bạn có input giá trị u từ đâu đi nữa thì giá trị 1 + u vẫn chỉ cần tính 1 lần.
 
Upvote 0
Web KT
Back
Top Bottom