|
|
Line 1: |
Line 1: |
− | =1.0
| |
| | | |
− |
| |
− | This is how MATLAB looks on my machine although it may be arranged slightly differently on yours. However the 4 main elements A to D will always be there and I will briefly explain them
| |
− |
| |
− | = Preliminaries =
| |
− |
| |
− | Very often in your life you have to repeat the same operation many times (move your right and left legs while walking/running) or behave differently depending on external conditions (there is or there is no bus on a bus stop). Quite often these two are combined together. Say, if there is a bus on a bus stop, then you run trying to catch it, otherwise walk or stop and enjoy the usual Manchester weather. The same is true for programming. Quite often you want to repeat the same operation many times, or you want to change the way you treat your data depending on some conditions. We start with conditional statements. They execute different pieces of code depending whether <source enclose=none>condition</source> is true or false. There are several ways you can formulate it. The shortest
| |
− |
| |
− | <source>if condition
| |
− | statement1;
| |
− | statement2;
| |
− | ...
| |
− | end
| |
− | </source>
| |
− | , executes <source enclose=none>statement1;statement2,...</source> only if <source enclose=none>condition</source> is satisfied. <source enclose=none>condition</source> can be anything that generate non-zero or 0 (True or False), say <source enclose=none>i>0</source>, <source enclose=none>size(y,1)\sim=40</source>, or <source enclose=none>5-i</source>. The last condition is True always but for <source enclose=none>i=5</source>. A slightly longer version
| |
− |
| |
− | <source> if condition
| |
− | statement1;
| |
− | statement2;
| |
− | ...
| |
− | else
| |
− | statement1a;
| |
− | statement2a;
| |
− | ...
| |
− | end
| |
− | </source>
| |
− | runs <source enclose=none>statement1;statement2;...</source>, if <source enclose=none>condition</source> is true and <source enclose=none>statement1a;statement2a;...</source> otherwise. In the most general case it looks like
| |
− |
| |
− | <source> if condition1
| |
− | statement1;
| |
− | statement2;
| |
− | ...
| |
− | elseif condition2
| |
− | statement1a;
| |
− | statement2a;
| |
− | ...
| |
− | ...
| |
− | ...
| |
− | elseif conditionN
| |
− | statement1b;
| |
− | statement2b;
| |
− | ...
| |
− | else
| |
− | statement1c;
| |
− | statement2c;
| |
− | ...
| |
− | end</source>
| |
− | In this case, however, you have to ensure that <source enclose=none>condition1, condition2, …, conditionN</source> are mutually disjoint. As an example, you might think about different actions depending on your final grade. Say, condition1: <source enclose=none>grade<30</source>; condition 2: <source enclose=none>(grade>=30)&&(grade<40)</source>; condition 3: <source enclose=none>(grade>=40)&&(grade<50)</source>; etc.
| |
− |
| |
− | MATLAB has two statements that creates a loop. First, it is unconditional loop:
| |
− |
| |
− | <source>for CounterVariable=[range of values]
| |
− | statement1;
| |
− | statement2;
| |
− | ...
| |
− | end</source>
| |
− | It repeats at most as many times as many elements it has in the <source enclose=none>[range of values]</source>. If range of values is empty, this loop does not run. Say, if you define a range <source enclose=none>10:1</source>, MATLAB creates an empty range. Thus, this loop will not be executed. If you define a range <source enclose=none>1:3:10</source>, MATLAB creates a range of four values <source enclose=none>[1 4 7 10]</source>, and the loop runs four times. During the first iteration, <source enclose=none>CounterVariable=1</source>, during the second <source enclose=none>CounterVariable=4</source>, etc. After the end of the loop <source enclose=none>CounterVariable=10</source>. Please note, this is very unwise to modify the counter inside the loop. All modifications will disappear after the next iteration. Please also note, that the values in the range could be anything, including filenames or matrices from a cell vector. There are two commands that can modify an execution of the loop. <source enclose=none>continue</source> breaks the current ''iteration'' of the loop. Once it is observed, the loop continues skipping current iteration. <source enclose=none>break</source> stops the execution of the loop and your program continues after this point. These commands are used inside <source enclose=none>if</source> statements. Say, <source enclose=none>if CounterVariable == 10 continue;end</source> skips the loop iteration for <source enclose=none>CounterVariable = 10</source>.
| |
− |
| |
− | Second, it is a conditional loop
| |
− |
| |
− | <source>while condition
| |
− | statement1;
| |
− | statement2;
| |
− | ...
| |
− | end </source>
| |
− | This version of loop executes statements as long as <source enclose=none>condition</source> is true. If <source enclose=none>condition</source> is always true, your loop runs forever.
| |
− |
| |
− | == <source enclose=none>for ... end</source> loop ==
| |
− |
| |
− | A standard application for <source enclose=none>for ... end</source> loop is a reconstruction of AR(p) series once AR(p) coefficients and a vector of error terms in known. <math>y_t=\phi_0+\sum_{i=1}^p \phi_i y_{t-i}+e_t.</math> For simplicity, we assume that <math>p=1</math>. Also, to be able to compute <math>y_1</math>, we need to provide <math>y_0</math>. Since we don’t know <math>y_0</math>,the best guess for <math>y_0</math> is <math>E(y_0)</math>. For stationary AR(1) process, that is for the case <math>|\phi_1|<1</math>, <math>E(y_0)=\phi_0/(1-\phi_1)</math>. Thus, knowing <math>y_0</math> and <math>e_t</math> for <math>t=1,\ldots,T</math>, we can reconstruct <math>y_t,\ t=1\ldots,T</math>:
| |
− |
| |
− | <math>\begin{aligned}
| |
− | y_1=&\phi_0+\phi_1 y_0+e_1\\
| |
− | y_2=&\phi_0+\phi_1 y_1+e_2\\
| |
− | &\ldots\\
| |
− | y_t=&\phi_0+\phi_1 y_{t-1}+e_t\\
| |
− | &\ldots\\
| |
− | y_T=&\phi_0+\phi_1 y_{T-1}+e_T\end{aligned}</math>
| |
− |
| |
− | Definitely, if you are patient enough and <math>T</math> is not very large, you can create your m file with <math>T</math> lines in it. However, once <math>T</math> is unknown, this approach would not work. Fortunately, there is a better alternative for this type of operations. All these computations can be summarized using the following algorithm:
| |
− |
| |
− | # Find a length of a vector of error terms <source enclose=none>e</source>: <source enclose=none>T=size(e,1)</source>
| |
− | # Initialize a vector <source enclose=none>y</source> of the same length as vector <source enclose=none>e</source>: <source enclose=none>y=zeros(T,1)</source>
| |
− | # Compute <source enclose=none>y(1)=phi0+phi1*(phi0/(1-phi1))+e(1)</source>. Please remember, we assume that <math>y_0=E(y)=\phi_0/(1-\phi_1)</math>
| |
− | # Compute <source enclose=none>y(i)=phi0+phi1*y(i-1)+e(i)</source> for <math>i=2</math>
| |
− | # Repeat line 4 for <math>i=3,...,T</math>
| |
− |
| |
− | Assuming vector <source enclose=none>e</source> is known in advance, the MATLAB code is
| |
− |
| |
− | <source> T=size(e,1);
| |
− | y=zeros(T,1);
| |
− | y0=phi0/(1-phi1);
| |
− | y(1)=phi0+phi1*y0+e(1);
| |
− | for i=2:T
| |
− | y(i)=phi0+phi1*y(i-1)+e(i);
| |
− | end</source>
| |
− | However, if <source enclose=none>phi1=1</source>, <math>E(y_t)</math> is not constant. In this situation the formula we use in the code does not work and will create either a series <source enclose=none>y</source> of <math>\pm\infty</math>, if <source enclose=none>phi0 \ne 0</source> or a series of not a numbers <source enclose=none>NaN</source>, if <source enclose=none>phi0=0</source><ref>There are two special numerical values in MATLAB. One is infinity <source enclose=none>Inf</source>, and another is not a number <source enclose=none>NaN</source>. A value of a variable becomes <source enclose=none>Inf</source> if the number is too big in absolute value (<math>\approx \pm 2e308</math>). Also, infinity is generated once you have expressions like <math>x/0</math>, where <math>x\ne0</math>. After that, infinity can only change a sign or become not a number. Not a number appears when there is an uncertainty of a kind of <math>0/0</math>, <math>\infty-\infty</math> and such. Any algebraic operations with <source enclose=none>NaN</source> result <source enclose=none>NaN</source>
| |
− | </ref>.
| |
− |
| |
− | == <source enclose=none>if else end</source> or <source enclose=none>if end</source> ==
| |
− |
| |
− | To avoid these inconveniences, we have to consider separately two cases:
| |
− |
| |
− | # AR(1) process is stationary, i.e. <math>|\phi_1|<1</math>
| |
− | # AR(1) process is nonstationary, i.e. <math>|\phi_1|\ge 1</math>
| |
− |
| |
− | For the latter, we have to acknowledge the fact that <math>E(y_t)=\mu_t</math>, i.e. unconditional expectation is a function of time. In this case we have to set <math>E(y_0)</math> to some value. A standard assumption for non-stationary series is to assume that <math>E(y_0)=0</math>.
| |
− |
| |
− | The algorithm in this case would look like:
| |
− |
| |
− | # Find a length of a vector of error terms <source enclose=none>e</source>: <source enclose=none>T=size(e,1)</source>
| |
− | # Initialize a vector <source enclose=none>y</source> of the same length as vector <source enclose=none>e</source>: <source enclose=none>y=zeros(T,1)</source>
| |
− | # Check whether <source enclose=none>abs(phi1)<1</source>. If this statement is true, then <source enclose=none>y0=phi0/(1-phi1)</source>. Else, <source enclose=none>y0=0</source>. Please remember, we set <math>y_0=E(y_0)</math>.
| |
− | # Compute <source enclose=none>y(1)=phi0+phi1*y0+e(1)</source>.
| |
− | # Compute <source enclose=none>y(i)=phi0+phi1*y(i-1)+e(i)</source> for <math>i=2</math>
| |
− | # Repeat line 4 for <math>i=3,...,T</math>
| |
− |
| |
− | Assuming vector <source enclose=none>e</source> is known in advance, the MATLAB code is
| |
− |
| |
− | <source> T=size(e,1);
| |
− | y=zeros(T,1);
| |
− | if abs(phi1)<1
| |
− | y0=phi0/(1-phi1);
| |
− | else
| |
− | y0=0;
| |
− | end
| |
− | y(1)=phi0+phi1*y0+e(1)
| |
− | for i=2:T
| |
− | y(i)=phi0+phi1*y(i-1)+e(i);
| |
− | end</source>
| |
− | If you don’t like word else, you can skip it:
| |
− |
| |
− | <source> T=size(e,1);
| |
− | y=zeros(T,1);
| |
− | y0=0;
| |
− | if abs(phi1)<1
| |
− | y0=phi0/(1-phi1);
| |
− | end
| |
− | y(1)=phi0+phi1*y0+e(1)
| |
− | for i=2:T
| |
− | y(i)=phi0+phi1*y(i-1)+e(i);
| |
− | end</source>
| |
− | == <source enclose=none>while end</source> loop ==
| |
− |
| |
− | An alternative way of running the same code is to use a conditional loop (purely for demonstration purposes). Usually conditional loop is used when the number of iterations is not known in advance.
| |
− |
| |
− | # Find a length of a vector of error terms <source enclose=none>e</source>: <source enclose=none>T=size(e,1)</source>
| |
− | # Initialize a vector <source enclose=none>y</source> of the same length as vector <source enclose=none>e</source>: <source enclose=none>y=zeros(T,1)</source>
| |
− | # Check whether <source enclose=none>abs(phi1)<1</source>. If this statement is true, then <source enclose=none>y0=phi0/(1-phi1)</source>. Else, <source enclose=none>y0=0</source>. Please remember, we set <math>y_0=E(y_0)</math>.
| |
− | # Compute <source enclose=none>y(1)=phi0+phi1*y0+e(1)</source>.
| |
− | # Compute <source enclose=none>y(i)=phi0+phi1*y(i-1)+e(i)</source> for <math>i=2</math>
| |
− | # Increase i by 1, i.e. <math>i=i+1</math> (please note, in programming this is not a stupid statement,
| |
− | # Repeat line 4 while <math>i<=T</math>
| |
− |
| |
− | Assuming vector <source enclose=none>e</source> is known in advance, the MATLAB code is
| |
− |
| |
− | <source> T=size(e,1);
| |
− | y=zeros(T,1);
| |
− | if abs(phi1)<1
| |
− | y0=phi0/(1-phi1);
| |
− | else
| |
− | y0=0;
| |
− | end
| |
− | y(1)=phi0+phi1*y0+e(1)
| |
− | i=2;
| |
− | while i<=T
| |
− | y(i)=phi0+phi1*y(i-1)+e(i);
| |
− | i=i+1;
| |
− | end</source>
| |
− | == Imperfect substitutes of the above ==
| |
− |
| |
− | MATLAB has two powerful tools that make programmer’s life much easier and utilization of loops/if less frequent. In addition, quite often it makes the code run faster. In particular,
| |
− |
| |
− | # Logical expressions work not only on scalars, but also on vectors, matrices and, in general, on n-dimensional arrays.
| |
− | # Subvectors/submatrices can be extracted using logical 0-1 arrays.
| |
− |
| |
− | === Irrelevant but useful example ===
| |
− |
| |
− | typing <source enclose=none>a=1:5</source> in MATLAB command window create a <math>1\times5</math> row-vector <source enclose=none>a</source> with values <math>[1\ 2\ 3\ 4\ 5]</math>. Logical expression <source enclose=none>ind=(a>3.5)</source> will create a so called logical vector <source enclose=none>ind</source> with values <math>[0\ 0\ 0\ 1\ 1]</math>, i.e. it is 1 if the according element is greater than 3.5 and 0 otherwise. Now, typing <source enclose=none>b=a(ind)</source> will generate a <math>2\times1</math> subvector <source enclose=none>b</source> with values <math>[4\ 5]</math>. You can also create some vectors or matrices with specific values changed: a command <source enclose=none>a(ind)=a(ind)*2</source> replace the last two values of the original vector <source enclose=none>a</source>. As a result, the vector <source enclose=none>a</source> becomes <math>[1 \ 2\ 3\ 8\ 10]</math>.
| |
− |
| |
− | === Slightly less irrelevant example ===
| |
− |
| |
− | In some occasions you would like to modify a matrix of interest. Say, in some surveys “no answer” is coded as 999. Once you import the whole dataset in <source enclose=none>X</source>, you might want to replace these with, say, NaN. It can be done for the whole matrix of interest: <source enclose=none>X(X==999)=NaN</source>.
| |
− |
| |
− | === Relevant example ===
| |
− |
| |
− | To demonstrate these capabilities in a more relevant environment, let’s run a very simple example. Assume that we have <math>T\times1</math> vector of returns <source enclose=none>r</source> and want to
| |
− |
| |
− | # Compute number of positive, negative and zero returns
| |
− | # Compute means of positive and negative returns
| |
− |
| |
− | The algorithm for this is quite straightforward:
| |
− |
| |
− | # Find out a length of vector <source enclose=none>r</source>, T
| |
− | # Initiate three counter variables, <source enclose=none>Tplus=0, Tzero=0, Tminus=0</source>, and vectors <source enclose=none>rplus=zeros(T,1), rminus=zeros(T,1)</source> (since we don’t know how many negative and positive returns we will observe
| |
− | # Check whether r(i) is greater, smaller or equal to 0 for i=1
| |
− | # If <source enclose=none>r(i)>0</source>, add 1 to Tplus, set <source enclose=none>rplus(Tplus)=r(i)</source>;
| |
− | # Else if <source enclose=none>r(i)<0</source> add 1 to Tminus, set <source enclose=none>rminus(Tminus)=r(i)</source>;
| |
− | # Else add 1 to Tzero
| |
− | # Repeat 3-6 for <math>i=2,\ldots,T</math>
| |
− | # Remove excessive zeros from <source enclose=none>rplus</source> and <source enclose=none>rminus</source>: <source enclose=none>rplus=rplus(1:Tplus);</source><br />
| |
− | <source enclose=none>rminus=rminus(1:Tminus);</source>
| |
− | # Compute means of rminus and rplus. Number of positive, negative and zero returns are stored in <source enclose=none>Tplus,Tminus,Tzero</source>
| |
− |
| |
− | MATLAB translation:
| |
− |
| |
− | <source>T=size(r,1);
| |
− | Tplus=0;Tminus=0;Tzero=0;
| |
− | rplus=zeros(T,1);rminus=zeros(T,1);
| |
− | for i=1:T
| |
− | if r(i)>0
| |
− | Tplus=Tplus+1;%increasing Tplus by one if return is positive
| |
− | rplus(Tplus)=r(i);%storing positive return in the proper subvector
| |
− | elseif r(i)<0
| |
− | Tminus=Tminus+1;%increasing Tminus by one if return is negative
| |
− | rminus(Tminus)=r(i);%storing negative return in the proper subvector
| |
− | else
| |
− | Tzero=Tzero+1;%increasing Tzero by one if return is neither positive nor negative
| |
− | end
| |
− | end
| |
− | rplus=rplus(1:Tplus);%removing excessive zeros from a subvector of positive returns
| |
− | rminus=rminus(1:Tminus);%removing excessive zeros from a subvector of negative returns
| |
− | meanplus=mean(rplus);%computing mean of positive returns
| |
− | meanminus=sum(rminus)/Tminus;%computing mean of negative returns</source>
| |
− | Using MATLAB capabilities mentioned in this section, the algorithm can be reduced to:
| |
− |
| |
− | # Construct a vector <source enclose=none>indplus</source> that has 1 for positive returns and 0 for negative returns
| |
− | # Construct a vector <source enclose=none>indminus</source> that has 1 for negative returns and 0 for positive returns
| |
− | # Assign to <source enclose=none>Tplus</source> a sum of elements of <source enclose=none>indplus</source>. This is a number of positive returns
| |
− | # Assign to <source enclose=none>Tminus</source> a sum of elements of <source enclose=none>indminus</source>. This is a number of negative returns
| |
− | # Compute <source enclose=none>Tzero</source> which is <source enclose=none>T-Tplus-Tminus</source>
| |
− | # Construct a vector of positive returns <source enclose=none>rplus=r(indplus)</source> and compute its mean
| |
− | # Construct a vector of negative returns <source enclose=none>rminus=r(indminus)</source> and compute its mean
| |
− |
| |
− | MATLAB implementation:
| |
− |
| |
− | <source> T=size(r,1);
| |
− | indplus = r>0;%constructing an indicator vector with 1s if r(i)>0, 0 otherwise
| |
− | indminus = r<0;%constructing an indicator vector with 1s if r(i)<0, 0 otherwise
| |
− | Tplus=sum(indplus);%computing a number of positive returns
| |
− | Tminus=sum(indminus);%computing a number of negative returns
| |
− | Tzero=T-Tplus-Tminus;%computing a number of zero returns
| |
− | rplus=r(indplus);%constructing a vector of positive returns
| |
− | rminus=r(indminus);%constructing a vector of negative returns
| |
− | meanplus=sum(rplus)/Tplus; %computing mean of positive returns
| |
− | meanminus=mean(rminus); %computing mean of negative returns</source>
| |
− | Or, a slightly shorter version of the same thing
| |
− |
| |
− | <source> T=size(r,1);
| |
− | rplus = r(r>0);%constructing a vector of positive returns
| |
− | rminus = r(r<0);%%constructing a vector of negative returns
| |
− | Tplus=size(rplus,1);%computing a number of positive returns
| |
− | Tminus=size(indminus,l);%computing a number of negative returns
| |
− | Tzero=T-Tplus-Tminus;%computing a number of zero returns
| |
− | meanplus=sum(rplus)/Tplus; %computing mean of positive returns
| |
− | meanminus=mean(rminus); %computing mean of negative returns</source>
| |
− | This way you write a code that is shorter, less prone to errors and easier to read (at least after some practice).
| |
− |
| |
− | <references />
| |