Info

This question is closed. Reopen it to edit or answer.

How can we optimize this code using vectorization?

1 view (last 30 days)
Akash
Akash on 6 Nov 2014
Closed: MATLAB Answer Bot on 20 Aug 2021
% initialize temporary array to store cumulative return factors
cumRetFact = zeros(13);
cumRetFact(13) = 1; % the index starts one year and one month ago
% build index forward using returns from the input variable 'returns'
for index = 12:-1:1
cumRetFact(index) = cumRetFact(index + 1,1) * (1 + (returns{index ,2})/100);
end
For the purpose of performance optimization, it is better to replace the above "for loop" with the following piece of code:
cumRetFact(1:12,2) = cumRetFact(2:13,1).*((cell2mat(returns(1:12,2))/100)+1)
If not, how can we optimize the above "for loop" by using vectorization?

Answers (1)

Geoff Hayes
Geoff Hayes on 6 Nov 2014
Akash - if I understand your above code correctly, you may be able to use the cumprod function which can return the returns the cumulative product of an array starting at the beginning of the first element. For example (from the given link), if
A = [1 2 3 4 5]';
cumprod(A)
ans =
1
2
6
24
120
Suppose then that we extract the second column from your returns cell array, dividing each element by 100 and adding 1, as
A = 1 + cell2mat(returns(1:12,2))/100;
This means that your above loop becomes
for index = 12:-1:1
cumRetFact(index) = cumRetFact(index + 1,1) * A(index);
end
If we consider each index, this means that (the below isn't MATLAB code)
cumRetFact(13) = 1
cumRetFact(12) = cumRetFact(13)*A(12) = 1*A(12)
cumRetFact(11) = cumRetFact(12)*A(11) = 1*A(12)*A(11)
cumRetFact(10) = cumRetFact(11)*A(10) = 1*A(12)*A(11)*A(10)
.
.
cumRetFact(1) = cumRetFact(2)*A(1) = 1*A(12)*A(11)*A(10)*..*A(2)*A(1)
This seems to suggest that you can use cumprod in order to update cumRetFact as
cumRetFact = zeros(13,1);
cumRetFact(13) = 1;
A = 1 + cell2mat(returns(1:12,2))/100;
cumRetFact(12:-1:1) = cumRetFact(13)*cumprod(flipud(A));
Note that we are updating cumRetFact in the order 12:-1:1 (instead of the usual 1:12) just to keep it more similar to your for loop. That means that we have to flip our column A in the up and down direction (so reverse the elements) using flipud.
For example,
returns = cell(12,2);
for k=1:12
returns{k,2} = randi(255,1,1);
end;
The above initialized returns to
returns =
[] [178]
[] [ 81]
[] [243]
[] [ 9]
[] [112]
[] [ 98]
[] [196]
[] [203]
[] [ 48]
[] [125]
[] [114]
[] [165]
We then extract the second column as
A = 1 + cell2mat(returns(1:12,2))/100;
so that A is
A =
2.78
1.81
3.43
1.09
2.12
1.98
2.96
3.03
1.48
2.25
2.14
2.65
THis means that cumRetFact can be initialized to
cumRetFact = zeros(13,1);
cumRetFact(13) = 1;
cumRetFact(12:-1:1) = cumRetFact(13)*cumprod(flipud(A));
and so
cumRetFact =
13375
4811
2658
774.94
710.95
335.35
169.37
57.22
18.884
12.76
5.671
2.65
1

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!