Simulate 1,000 geometric brownian motions in MATLAB - matlab

I currently have code to simulate a geometric Brown motion, courtesy of http://www-math.bgsu.edu/~zirbel/sde/matlab/index.html.
However, I would like to generate 1,000 simulations and to be to display them in a graph.
The codes I have at the moment to generate a single simulation are as follows:
% geometric_brownian(N,r,alpha,T) simulates a geometric Brownian motion
% on [0,T] using N normally distributed steps and parameters r and alpha
function [X] = geometric_brownian(N,r,alpha,T)
t = (0:1:N)'/N; % t is the column vector [0 1/N 2/N ... 1]
W = [0; cumsum(randn(N,1))]/sqrt(N); % S is running sum of N(0,1/N) variables
t = t*T;
W = W*sqrt(T);
Y = (r-(alpha^2)/2)*t + alpha * W;
X = exp(Y);
plot(t,X); % plot the path
hold on
plot(t,exp(r*t),':');
axis([0 T 0 max(1,exp((r-(alpha^2)/2)*T+2*alpha))])
title([int2str(N) '-step geometric Brownian motion and its mean'])
xlabel(['r = ' num2str(r) ' and alpha = ' num2str(alpha)])
hold off

That code cannot be used directly to simulate 1,000 paths/simulations. Unfortunately, it has not been vectorized. The easiest way to do what you want is to use a for loop:
N = 1e3;
r = 1;
alpha = 0.1;
T = 1;
npaths = 1e3; % Number of simulations
rng(0); % Always set a seed
X = zeros(N+1,npaths); % Preallocate memory
for i = 1:n
X(:,i) = geometric_brownian(N,r,alpha,T);
hold on
end
t = T*(0:1:N).'/N;
plot(t,exp(r*t),'r--');
This is rather slow and inefficient. You will need to modify the function a lot to vectorize it. One thing that would improve performance is if you at least removed the plotting code from inside the function and ran that separately after the loop.
Another alternative might be to use the sde_gbm function in my SDETools toolbox, which is fully-vectorized and much faster:
N = 1e3;
r = 1;
alpha = 0.1;
T = 1;
npaths = 1e3; % Number of simulations
t = T*(0:1:N)/N; % Time vector
y0 = ones(npaths,1); % Vector of initial conditions, must match number of paths
opts = sdeset('RandSeed',0,'SDEType','Ito'); % Set seed
y = sde_gbm(r,alpha,t,y0,opts);
figure;
plot(t,y,'b',t,y0*exp(r*t),'r--');
xlabel('t');
ylabel('y(t)');
title(['Geometric Brownian motion and it's mean: ' int2str(npaths) ...
' paths, r = ' num2str(r) ', \alpha = ' num2str(alpha)]);
In either case, one obtains a plot that looks something like this

To perform 1000 simulations, the straightforward way would be:
Nsims = 1000;
N=10^15; % set to length of individual sim
r = 1;
alpha = 0.1;
T = 1;
t = (0:1:N)'/N;
t = (T*(r-(alpha^2)/2))*t;
W = cat(1,zeros(1,Nsims),cumsum(randn(N,Nsims)));
W = W*(sqrt(T)*alpha/sqrt(N));
Y = repmat(t,1,Nsims) + W;
X = exp(Y);
Plotting is just like before
plot(t,X); % plots ALL 1000 paths
% plot(t,X(:,paths)); % use instead to show only selected paths (e.g. paths =[1 2 3])
hold on
plot(t,exp(r*t),':');
axis([0 T 0 max(1,exp((r-(alpha^2)/2)*T+2*alpha))])
title([int2str(N) '-step geometric Brownian motion and its mean'])
xlabel(['r = ' num2str(r) ' and alpha = ' num2str(alpha)])
hold off
For comparatively short (small) sets of simulations looping over your code or executing the above should do. For heavy duty simulations you may benefit from Horchler's promised speed advantage.

Related

Animating 3D Random Walk Matlab

I am writing a code to simulate random walk in 3D space on Matlab. However, there seems to be a problem with my number of simulations, M. I want to animate multiple simulations on the same graph but I am only get 1 simulation. My input of M instead becomes the number of steps. How can I fix this code? Thank you.
I want it to look like the animation in this video: https://www.youtube.com/watch?v=7A83lXbs6Ik
But after each simulation is complete, another one starts on the same graph but a different color.
The end result should be like this
final
clc;
clearvars;
N = input('Enter the number of steps in a single run: '); % Length of the x-axis and random walk.
M = input('Enter the number of simulation runs to do: '); % The number of random walks.
x_t(1) = 0;
y_t(1) = 0;
z_t(1) = 0;
for m=1:M
for n = 1:N % Looping all values of N into x_t(n).
A = sign(randn); % Generates either +1/-1 depending on the SIGN of RAND.
x_t(n+1) = x_t(n) + A;
A = sign(randn); % Generates either +1/-1 depending on the SIGN of RAND.
y_t(n+1) = y_t(n) + A;
A = sign(randn);
z_t(n+1) = z_t(n) + A;
end
plot3([x_t(1) x_t(n+1)], [y_t(1) y_t(n+1)], [z_t(1) z_t(n+1)], 'g');
hold on
grid on
x_t = x_t(n+1);
y_t = y_t(n+1);
z_t = z_t(n+1);
drawnow;
end
You are plotting in the wrong place:
clc;
clearvars;
N = 100
M = 5
x_t(1) = 0;
y_t(1) = 0;
z_t(1) = 0;
c=lines(M) % save colors so each m has its own
for m=1:M
for n = 1:N % Looping all values of N into x_t(n).
A = sign(randn); % Generates either +1/-1 depending on the SIGN of RAND.
x_t(n+1) = x_t(n) + A;
A = sign(randn); % Generates either +1/-1 depending on the SIGN of RAND.
y_t(n+1) = y_t(n) + A;
A = sign(randn);
z_t(n+1) = z_t(n) + A;
plot3([x_t(n) x_t(n+1)], [y_t(n) y_t(n+1)], [z_t(n) z_t(n+1)],'color',c(m,:));
hold on
grid on
drawnow;
end
end

Looping my algorithm to plot for a different parameter value on the same graph(MATLAB)

I've implemented an algorithm for my physics project which does exactly what I want. The problem that I'm stuck which is not the Physics content itself hence I think it might be somewhat trivial to explain what my code does. I'm mainly stuck with the way MATLAB's plotting works if I was to loop over the same algorithm to produce similar graphs with a slight change of a value of my parameter. Here's my code below:
clear; clc; close all;
% Parameters:
z_nn = 4; % Number of nearest-neighbour in lattice (square = 4).
z_nnn = 4; % Number of next-nearest-neighbours in lattice (square = 4).
Lx = 40; % Number of sites along x-axis.
Ly = 40; % Number of sites along y-axis.
sigma = 1; % Size of a site (defines our units of length).
beta = 1.2; % Inverse temperature beta*epsilon.
mu = -2.53; % Chemical potential mu/epsilon.
mu_2 = -2.67; % Chemical potential mu/epsilon for 2nd line.
J = linspace(1, 11, 11);%J points for the line graph plot
potential = zeros(Ly);
attract = 1.6; %wall attraction constant
k = 1; %wall depth
rho_0 = 0.4; % Initial density.
tol = 1e-12; % Convergence tolerance.
count = 30000; % Upper limit for iterations.
alpha = 0.01; % Mixing parameter.
conv = 1; cnt = 1; % Convergence value and counter.
rho = rho_0*ones(Ly); % Initialise rho to the starting guess(i-th rho_old) in Eq(47)
rho_rhs = zeros(Ly); % Initialise rho_new to zeros.
% Solve equations iteratively:
while conv>=tol && cnt<count
cnt = cnt + 1; % Increment counter.
% Loop over all lattice sites:
for j=1:Ly
%Defining the Lennard-Jones potential
if j<k
potential(j) = 1000000000;
else
potential(j) = -attract*(j-k)^(-3);
end
% Handle the periodic boundaries for x and y:
%left = mod((i-1)-1,Lx) + 1; % i-1, maps 0 to Lx.
%right = mod((i+1)-1,Lx) + 1; % i+1, maps Lx+1 to 1.
if j<k+1 %depth of wall
rho_rhs(j) = 0;
rho(j) = 0;
elseif j<(20+k)
rho_rhs(j) = (1 - rho(j))*exp((beta*((3/2)*rho(j-1) + (3/2)*rho(j+1) + 2*rho(j) + mu) - potential(j)));
else
rho_rhs(j) = rho_rhs(j-1);
end
end
conv = sum(sum((rho - rho_rhs).^2)); % Convergence value is the sum of the differences between new and current solution.
rho = alpha*rho_rhs + (1 - alpha)*rho; % Mix the new and current solutions for next iteration.
end
% disp(['conv = ' num2str(conv_2) ' cnt = ' num2str(cnt)]); % Display final answer.
% figure(2);
% pcolor(rho_2);
figure(1);
plot(J, rho(1:11));
hold on;
% plot(J, rho_2(1,1:11));
hold off;
disp(['conv = ' num2str(conv) ' cnt = ' num2str(cnt)]); % Display final answer.
figure(3);
pcolor(rho);
Running this code should give you a graph like this
Now I want to produce a similar graph but with one of the variable's value changed and plotted on the same graph. My approach that I've tried is below:
clear; clc; close all;
% Parameters:
z_nn = 4; % Number of nearest-neighbour in lattice (square = 4).
z_nnn = 4; % Number of next-nearest-neighbours in lattice (square = 4).
Lx = 40; % Number of sites along x-axis.
Ly = 40; % Number of sites along y-axis.
sigma = 1; % Size of a site (defines our units of length).
beta = 1.2; % Inverse temperature beta*epsilon.
mu = [-2.53,-2.67]; % Chemical potential mu/epsilon.
mu_2 = -2.67; % Chemical potential mu/epsilon for 2nd line.
J = linspace(1, 10, 10);%J points for the line graph plot
potential = zeros(Ly, length(mu));
gamma = zeros(Ly, length(mu));
attract = 1.6; %wall attraction constant
k = 1; %wall depth
rho_0 = 0.4; % Initial density.
tol = 1e-12; % Convergence tolerance.
count = 30000; % Upper limit for iterations.
alpha = 0.01; % Mixing parameter.
conv = 1; cnt = 1; % Convergence value and counter.
rho = rho_0*[Ly,length(mu)]; % Initialise rho to the starting guess(i-th rho_old) in Eq(47)
rho_rhs = zeros(Ly,length(mu)); % Initialise rho_new to zeros.
figure(3);
hold on;
% Solve equations iteratively:
while conv>=tol && cnt<count
cnt = cnt + 1; % Increment counter.
% Loop over all lattice sites:
for j=1:Ly
for i=1:length(mu)
y = 1:Ly;
MU = mu(i).*ones(Ly)
%Defining the Lennard-Jones potential
if j<k
potential(j) = 1000000000;
else
potential(j) = -attract*(j-k).^(-3);
end
% Handle the periodic boundaries for x and y:
%left = mod((i-1)-1,Lx) + 1; % i-1, maps 0 to Lx.
%right = mod((i+1)-1,Lx) + 1; % i+1, maps Lx+1 to 1.
if j<k+1 %depth of wall
rho_rhs(j) = 0;
rho(j) = 0;
elseif j<(20+k)
rho_rhs(j) = (1 - rho(j))*exp((beta*((3/2)*rho(j-1) + (3/2)*rho(j+1) + 2*rho(j) + MU - potential(j)));
else
rho_rhs(j) = rho_rhs(j-1);
end
end
end
conv = sum(sum((rho - rho_rhs).^2)); % Convergence value is the sum of the differences between new and current solution.
rho = alpha*rho_rhs + (1 - alpha)*rho; % Mix the new and current solutions for next iteration.
disp(['conv = ' num2str(conv) ' cnt = ' num2str(cnt)]); % Display final answer.
figure(1);
pcolor(rho);
plot(J, rho(1:10));
end
hold off;
The only variable that I'm changing here is mu. I would like to loop my first code so that I can enter an arbitrary amount of different values of mu and plot them on the same graph. Naturally I had to change all of the lists dimension from (1 to size of Ly) to (#of mu(s) to size of Ly), such that when the first code is being looped, the i-th mu value in that loop is being turned into lists with dimension as long as Ly. So I thought I would do the plotting within the loop and use "hold on" encapsulating the whole loop so that every plot that was generated in each loop won't be erased. But I've been spending hours on trying to figure out the semantics of MATLAB but ultimately I can't figure out what to do. So hopefully I can get some help on this!
hold on only applies to the active figure, it is not a generic property shared among all figures. What is does is changing the value of the current figure NextPlot property, which governs the behavior when adding plots to a figure.
hold on is equivalent to set(gcf,'NextPlot','add');
hold off is equivalent to set(gcf,'NextPlot','replace');
In your code you have:
figure(3); % Makes figure 3 the active figure
hold on; % Sets figure 3 'NextPlot' property to 'add'
% Do some things %
while conv>=tol && cnt<count
% Do many things %
figure(1); % Makes figure 1 the active figure; 'hold on' was not applied to that figure
plot(J, rho(1:10)); % plots rho while erasing the previous plot
end
You should try to add another hold on statement after figure(1)
figure(1);
hold on
plot(J, rho(1:10));

Issue with Discrete Double Fourier Series in MATLAB

The formula for the discrete double Fourier series that I'm attempting to code in MATLAB is:
The coefficient in front of the trigonometric sum (Fourier amplitude) is what I'm trying to extract from the fitting of the data through the double Fourier series seen above. Using my current code, the original function is not reconstructed, therefore my coefficients cannot be correct. I'm not certain if this is of any significance or insight, but the second term for the A coefficients (Akn(1))) is 13 orders of magnitude larger than any other coefficient.
Any suggestions, modifications, or comments about my program would be greatly appreciated.
%data = csvread('digitized_plot_data.csv',1);
%xdata = data(:,1);
%ydata = data(:,2);
%x0 = xdata(1);
lambda = 20; %km
tau = 20; %s
vs = 7.6; %k/s (velocity of CHAMP satellite)
L = 4; %S
% Number of terms to use:
N = 100;
% set up matrices:
M = zeros(length(xdata),1+2*N);
M(:,1) = 1;
for k=1:N
for n=1:N %error using *, inner matrix dimensions must agree...
M(:,2*n) = cos(2*pi/lambda*k*vs*xdata).*cos(2*pi/tau*n*xdata);
M(:,2*n+1) = sin(2*pi/lambda*k*vs*xdata).*sin(2*pi/tau*n*xdata);
end
end
C = M\ydata;
%least squares coefficients:
A0 = C(1);
Akn = C(2:2:end);
Bkn = C(3:2:end);
% reconstruct original function values (verification check):
y = A0;
for k=1:length(Akn)
y = y + Akn(k)*cos(2*pi/lambda*k*vs*xdata).*cos(2*pi/tau*n*xdata) + Bkn(k)*sin(2*pi/lambda*k*vs*xdata).*sin(2*pi/tau*n*xdata);
end
% plotting
hold on
plot(xdata,ydata,'ko')
plot(xdata,yk,'b--')
legend('Data','Least Squares','location','northeast')
xlabel('Centered Time Event [s]'); ylabel('J[\muA/m^2]'); title('Single FAC Event (50 Hz)')

Why is my matlab plot not evolving using finite difference method?

I am trying to use a finite difference method to solve the heat equation for a given function u0. I want to evolve it in time using plots to see each frame change but when I run it all I see is the same frame over and over. I am aware of the error at the ends due to me not giving "u" a first or last index which will cause more overall error in the solution. I am not very good at matlab so I am not sure if I am writing my nested piece correctly.
% set up domain in time and space
t_step = .1;
tspan = [0 :t_step:1000];
L = 10; %length of domain
n = 64;
dx = 2*pi/(n-1); %spacing
x = 0:dx:2*pi;
x = x'; %make x vertical vector
% initial conditions for the function
u0 = sin(2*pi*x/L)+0*cos(3*2*pi*x/L) + 0.2*(cos(5*2*pi*x/L))+0*randn(size(x));
plot(x,u0);title('initial condition');pause;
t = 0;
for m = 1:tspan(end)
u = u0;
t = t + t_step;
for j= 2:n-1
u(j,m) = u0(j-1) - 2*u0(j) + u0(j+1)/dx^2; %u(1) and n left out
end
plot(x,u(:,m))
pause(0.01);
end

Solving ODEs with Matlab, with varying Parameters

Lets say I have a simple logistic equation
dx/dt = 2ax(1 - x/N)
where N is the carrying capacity, a is some growth rate, and both a and N are parameters I'd like to vary.
So what I want to do is to plot a 3D graph of my fixed point and the two parameters.
I understand how to find a fixed point of a single parameter.
Here is my sample code
function xprime = MyLogisticFunction(t,X) %% The ODE
% Parameters
N = 10 % Carrying Capacity
a = 0.5 % Growth Rate
x1prime = 2*a*X(1)*(1 - X(1)/N );
xprime = [x1prime ]';
end
Next my solver
% Initial Number
x0 = 0.4;
%Time Window
tspan=[0 100];
[t,x]=ode45(#MyLogisticFunction,tspan,x0);
clf
x(end,1) % This gives me the fixed point for the parameters above.
So my real question is, how do I put a for loop across two functions, that allows me to vary a and N, so that I can plot out a 3D graph of a and N and my fixed point x*.
I've tried combining both functions into one .m file but it does not seem to work
You need to pass the parameters to your function:
function xprime = MyLogisticFunction(t,X,a,N) %% The ODE
% Parameters (passed as function arguments)
% N = 10 % Carrying Capacity
% a = 0.5 % Growth Rate
x1prime = 2*a*X(1)*(1 - X(1)/N );
xprime = [x1prime ]';
end
and then when you call the ode solver:
% Initial Number
x0 = 0.4;
%Time Window
tspan=[0 100];
a = 0.1:0.1:1; % or whatever
N = 1:10; % or whatever
x_end = zeros(length(a),length(N));
for ii = 1:length(a)
for jj = 1:length(N)
[t,x]=ode45(#(t,X)MyLogisticFunction(t,X,a(ii),N(jj)),tspan,x0);
x_end(ii,jj) = x(end,1);
end
end