I will preface this post with the obvious fact that I'm not very experienced in MATLAB and this post may be somewhat confusing. Any help is appreciated!
I need to store data inside two parameters but unsure on how to do it. The number of "x" values is known but it is a user inputted value, so it's not something that can be hard coded. Same as the "y" values. Here's a simplified example of what I think I need (numbers are hard coded here for the sake of the example).
Then, the final figure should have multiple plots on it. Each "x" variable is its own "output" that needs to be plotted. In the end I need "x" number of plots with "z" and "y" being the (X,Y) coordinates for each "x" plot, respectively.
EDIT: Updated example code.
list = [.0025, .005, .0075];
x = input('How many? ');
y = linspace(2.4*10^9, 5.0*10^9, 1000);
z = zeros(x, length(y));
for i = x
time = list(i)/(3*10^8);
for j = y
z(i,j) = (time * j);
end
end
for i = x
plot(z(i,j));
end
I get the following error:
Requested 3x2400000000 (53.6GB) array exceeds maximum array size preference. Creation of arrays greater
than this limit may take a long time and cause MATLAB to become unresponsive. See array size limit or
preference panel for more information.
The example that I provided could be totally wrong but I hope I have explained enough for someone to provide feedback.
Create the z-Array beforehand to your needs: https://uk.mathworks.com/help/matlab/ref/zeros.html
Then you can fill it with z[x,y] = x+y
HTH
Related
I have to construct the following function in MATLAB and am having trouble.
Consider the function s(t) defined for t in [0,4) by
{ sin(pi*t/2) , for t in [0,1)
s(t) = { -(t-2)^3 , for t in [1,3)*
{ sin(pi*t/2) , for t in [3,4)
(i) Generate a column vector s consisting of 512 uniform
samples of this function over the interval [0,4). (This
is best done by concatenating three vectors.)
I know it has to be something of the form.
N = 512;
s = sin(5*t/N).' ;
But I need s to be the piecewise function, can someone provide assistance with this?
If I understand correctly, you're trying to create 3 vectors which calculate the specific function outputs for all t, then take slices of each and concatenate them depending on the actual value of t. This is inefficient as you're initialising 3 times as many vectors as you actually want (memory), and also making 3 times as many calculations (CPU), most of which will just be thrown away. To top it off, it'll be a bit tricky to use concatenate if your t is ever not as you expect (i.e. monotonically increasing). It might be an unlikely situation, but better to be general.
Here are two alternatives, the first is imho the nice Matlab way, the second is the more conventional way (you might be more used to that if you're coming from C++ or something, I was for a long time).
function example()
t = linspace(0,4,513); % generate your time-trajectory
t = t(1:end-1); % exclude final value which is 4
tic
traj1 = myFunc(t);
toc
tic
traj2 = classicStyle(t);
toc
end
function trajectory = myFunc(t)
trajectory = zeros(size(t)); % since you know the size of your output, generate it at the beginning. More efficient than dynamically growing this.
% you could put an assert for t>0 and t<3, otherwise you could end up with 0s wherever t is outside your expected range
% find the indices for each piecewise segment you care about
idx1 = find(t<1);
idx2 = find(t>=1 & t<3);
idx3 = find(t>=3 & t<4);
% now calculate each entry apprioriately
trajectory(idx1) = sin(pi.*t(idx1)./2);
trajectory(idx2) = -(t(idx2)-2).^3;
trajectory(idx3) = sin(pi.*t(idx3)./2);
end
function trajectory = classicStyle(t)
trajectory = zeros(size(t));
% conventional way: loop over each t, and differentiate with if-else
% works, but a lot more code and ugly
for i=1:numel(t)
if t(i)<1
trajectory(i) = sin(pi*t(i)/2);
elseif t(i)>=1 & t(i)<3
trajectory(i) = -(t(i)-2)^3;
elseif t(i)>=3 & t(i)<4
trajectory(i) = sin(pi*t(i)/2);
else
error('t is beyond bounds!')
end
end
end
Note that when I tried it, the 'conventional way' is sometimes faster for the sampling size you're working on, although the first way (myFunc) is definitely faster as you scale up really a lot. In anycase I recommend the first approach, as it is much easier to read.
The function is supposed to return a value. However, when I type:
val(1d4)
it returns
ans =
[]
However, if I copied line by line, and set all parameters (V eps_today etc.), and run in the command window, it works fine...Have no clue where the problem is. Thanks:)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%This function calculates the value function of both small and big%
%investment %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function negval=val(k_next)
global V eps_today k_today eps_gv k_gv z_today delta xi
theta=0.5327; beta=0.95; rho=0.7675; sigma_eta=0.7704;
%identify the grid point that falls just below
klo=max(sum(k_next>k_gv),1);
%above
khi=klo+1;
%Linear Interpolation, effectively only on the dimension of k
if klo<size(k_gv,2)
V_temp=V(:,klo)+(k_next-k_gv(klo))/(k_gv(khi)-k_gv(klo))*(V(:,khi)-V(:,klo));
else
%when k_next> maximum point of k_gv
V_temp=V(:,size(k_gv,2));
end
EV=mean(V_temp,1);
negval=-(exp(z_today+eps_today)*k_today^theta-xi*k_today-(k_next-(1-delta)*k_today)+beta*EV);
end
I tried to replicate your problem but I couldn't. If I do not set the global variables Matlab shouts and refuses to proceed through the function. Setting some of them to empty values was the same (did not try them all). If I do set the globals then the function always gives me a value.
But I strongly suspect it has something to do with the globals anyway (can you show the code where they are initialized?). As I mentioned in the comment I would get rid of them, the code could look like this
Main programme
%set parameters
Pars.beta = beta=0.95;
Pars.theta = 0.5327;
Pars.rho=0.7675;
Pars.sigma_eta=0.7704;
Pars.delta = ...;
Pars.xi = ...;
%set grid
eps_gv = ...
k_gv = ...
ne = length(eps_gv);
nk = length(k_gv);
V = zeros(ne,nk);
k_next = ...;
value = val(k_next,V,eps_gv,k_gv,Pars);
Val function
negval = function val(k_next,V,eps_gv,k_gv,Pars)
theta=Pars.theta; beta=Pars.beta; rho=Pars.rho; etc.
You don't even need eps_today and k_today as these should be the values on the grid (ie eps_gv and k_gv). I don't know what z_today is but there should either be a grid for z or z_today should be a parameter, in which case it should be in Pars. Of course if you use eps_gv and k_gv instead of eps_today and k_today the negval = ... line needs to be modified to take account of them being arrays not scalars.
One last comment, there is a bug on the EV=mean(V_temp,1); line. The mean function calculates the average of (the columns of) V. To calculate the expected value you need to do a weighted average where you weight each row of V by the probability of eps being eps_gv(1) (ie sum(V(i,:)*prob_eps(i)), sum going over i) . What you did works only if all shocks have equal probability. Pointing out since I am not sure you are aware of that.
I'm trying to take 5 years of data from a netcdf file for a variable and create an annual cycle. So take all 5 Jans and average them, take all 5 Febs and average them, etc, and plot on a line graph. I'm just starting the code (I want to get this to work before I move on) and am getting the following error message of: In an assignment A(:) = B, the number of elements in A and B must be the same.
My question is, is there a better way to do this?
Thanks for your help in advance. I'm a newbie, so I know this may be a simple question.
ncid = netcdf.open('example.nc','NC_NOWRITE');
PS1 = netcdf.getVar(ncid,netcdf.inqVarID(ncid, 'ps'), 'single');
for i = 1:12
MonthlyPS1(i) = PS1(month==i);
end
That should dump data into bins for each month, where I can later calculate the average.
If PS1 is a 5-by-12 array of real numbers, then:
MonthlyPS1 = mean(PS1);
If PS1 is a 12-by-5 array of real numbers, then:
MonthlyPS1 = mean(PS1, 2);
If PS1 is a 60-by-1 array of real numbers, then:
MonthlyPS1 = mean(reshape(PS1, 12, 5), 2);
If PS1 is not an array of real numbers, you need to explain what PS1 is, as requested by CST-Link. Also, it is not clear what the variable month is.
I will try to write a solution, but I'm no sure it is what you need (there's a certain amount of guessing related to my answer).
Also I will not write it in Matlab-idiomatic code, but rather explicit loops and calculations; like this you may see easier if it's what you want or not:
% allocate space for monthly mean values
PS1_mean = zeros(size(PS1,1), size(PS1,2), 12)
for d = 1:size(PS1,3)
% calculate the month for date d
m = mod(d, 12);
if m == 0
m = 12;
end;
% cumulate the data
PS1_mean(:, :, m) = PS1_mean(:, :, m) + PS1(:, :, d);
end;
% calculate the mean value
% (this might be tricky for incomplete years)
n_years = fix(size(PS1,3) / 12);
PS1_mean = PS1_mean / n_years;
To plot a "slice" of data for e.g. March, you may try:
mesh(PS1_mean(:,:,3));
Again, I hope that's what you're looking for.
I have a matrix time-series data for 8 variables with about 2500 points (~10 years of mon-fri) and would like to calculate the mean, variance, skewness and kurtosis on a 'moving average' basis.
Lets say frames = [100 252 504 756] - I would like calculate the four functions above on over each of the (time-)frames, on a daily basis - so the return for day 300 in the case with 100 day-frame, would be [mean variance skewness kurtosis] from the period day201-day300 (100 days in total)... and so on.
I know this means I would get an array output, and the the first frame number of days would be NaNs, but I can't figure out the required indexing to get this done...
This is an interesting question because I think the optimal solution is different for the mean than it is for the other sample statistics.
I've provided a simulation example below that you can work through.
First, choose some arbitrary parameters and simulate some data:
%#Set some arbitrary parameters
T = 100; N = 5;
WindowLength = 10;
%#Simulate some data
X = randn(T, N);
For the mean, use filter to obtain a moving average:
MeanMA = filter(ones(1, WindowLength) / WindowLength, 1, X);
MeanMA(1:WindowLength-1, :) = nan;
I had originally thought to solve this problem using conv as follows:
MeanMA = nan(T, N);
for n = 1:N
MeanMA(WindowLength:T, n) = conv(X(:, n), ones(WindowLength, 1), 'valid');
end
MeanMA = (1/WindowLength) * MeanMA;
But as #PhilGoddard pointed out in the comments, the filter approach avoids the need for the loop.
Also note that I've chosen to make the dates in the output matrix correspond to the dates in X so in later work you can use the same subscripts for both. Thus, the first WindowLength-1 observations in MeanMA will be nan.
For the variance, I can't see how to use either filter or conv or even a running sum to make things more efficient, so instead I perform the calculation manually at each iteration:
VarianceMA = nan(T, N);
for t = WindowLength:T
VarianceMA(t, :) = var(X(t-WindowLength+1:t, :));
end
We could speed things up slightly by exploiting the fact that we have already calculated the mean moving average. Simply replace the within loop line in the above with:
VarianceMA(t, :) = (1/(WindowLength-1)) * sum((bsxfun(#minus, X(t-WindowLength+1:t, :), MeanMA(t, :))).^2);
However, I doubt this will make much difference.
If anyone else can see a clever way to use filter or conv to get the moving window variance I'd be very interested to see it.
I leave the case of skewness and kurtosis to the OP, since they are essentially just the same as the variance example, but with the appropriate function.
A final point: if you were converting the above into a general function, you could pass in an anonymous function as one of the arguments, then you would have a moving average routine that works for arbitrary choice of transformations.
Final, final point: For a sequence of window lengths, simply loop over the entire code block for each window length.
I have managed to produce a solution, which only uses basic functions within MATLAB and can also be expanded to include other functions, (for finance: e.g. a moving Sharpe Ratio, or a moving Sortino Ratio). The code below shows this and contains hopefully sufficient commentary.
I am using a time series of Hedge Fund data, with ca. 10 years worth of daily returns (which were checked to be stationary - not shown in the code). Unfortunately I haven't got the corresponding dates in the example so the x-axis in the plots would be 'no. of days'.
% start by importing the data you need - here it is a selection out of an
% excel spreadsheet
returnsHF = xlsread('HFRXIndices_Final.xlsx','EquityHedgeMarketNeutral','D1:D2742');
% two years to be used for the moving average. (250 business days in one year)
window = 500;
% create zero-matrices to fill with the MA values at each point in time.
mean_avg = zeros(length(returnsHF)-window,1);
st_dev = zeros(length(returnsHF)-window,1);
skew = zeros(length(returnsHF)-window,1);
kurt = zeros(length(returnsHF)-window,1);
% Now work through the time-series with each of the functions (one can add
% any other functions required), assinging the values to the zero-matrices
for count = window:length(returnsHF)
% This is the most tricky part of the script, the indexing in this section
% The TwoYearReturn is what is shifted along one period at a time with the
% for-loop.
TwoYearReturn = returnsHF(count-window+1:count);
mean_avg(count-window+1) = mean(TwoYearReturn);
st_dev(count-window+1) = std(TwoYearReturn);
skew(count-window+1) = skewness(TwoYearReturn);
kurt(count-window +1) = kurtosis(TwoYearReturn);
end
% Plot the MAs
subplot(4,1,1), plot(mean_avg)
title('2yr mean')
subplot(4,1,2), plot(st_dev)
title('2yr stdv')
subplot(4,1,3), plot(skew)
title('2yr skewness')
subplot(4,1,4), plot(kurt)
title('2yr kurtosis')
I have a homework problem, I think I did it correctly but need to make sure 100%. Can anyone check for me, before I hand it in?
Thank you.
Question:
Plot the function given by f (x) = 2 sin(2x) − 3 cos(x/2) over the in-
terval [0, 2π] using steps of length .001 (How?). Use the commands max and min to estimate the maximum and minimum points. Include the maximum and minimum points as tick marks on the x-axis and the maximum and minimum values as tick marks on the y-axis.
My code:
x=linspace(0,2*pi,6280);
f=#(x)...
2.*sin(2.*x)-3.*cos(x./2);
%f = #(x)2.*sin(2.*x)-3.*cos(x./2)
g=#(x)...
-1*(2.*sin(2.*x)-3.*cos(x./2));
%g = #(x)-1*(2.*sin(2.*x)-3.*cos(x./2))
[x3,y5]=fminbnd(g,0,2*pi);
%x3 = 4.0968
%y3 = -3.2647
[x2,y4]=fminbnd(f,0,2*pi);
%x2 =2.1864
%y2 = -3.2647
y2=max(f(x));
y3=min(f(x));
plot(x,f(x));
set(gca,'XTick',[x2 x3]);
set(gca,'YTick',[y2 y3]);
(*after I paste this code here, it appeared not as nice as I had it in my program, don't know why)
To create a vector with certain step do
x=0:0.001:2*pi;
Why do you have g(x) function and why are you using fminbind? Use MIN and MAX, return index of those values and find related x values.
[ymin, minindex] = min(f(x));
xmin = x(minindex);
For general case if you have multiple min/max values, index will contain only the first occurrence. Instead you can do:
minindex = find(y==ymin);
Or for real values to avoid precision error:
minindex = find(abs(y-ymin)<=eps);
Also your last statement returns error Values must be monotonically increasing. To avoid it sort your tick values.
set(gca,'XTick',sort([xmin xmax]));
set(gca,'YTick',sort([ymin ymax]));