Repeated option pricing with Sobol Sequence (Matlab) - matlab

Trying to calculate the variance of a European option using repeated trial (instead of 1 trial). I want to compare the variance using the standard randn function and the sobolset. I'm not quite sure how to draw repeated samples from the latter.
Generating from randn is easy:
num_steps = 100;
num_paths = 10;
z = rand(num_steps, mum_paths); % 100 paths, for 10 trials
Once I have this, I can loop through all the 10 columns of the z matrix, and can also repeat the experiment many times, as the randn function will provide a new random variable set everytime.
for exp_num = 1: 20
for col = 1: 10
price_vec = z(:, col);
end
end
I'm not quite sure how to do this with the sobolset. I understand I can create a matrix of dimensions to start with (say 100* 10). I can loop through as above through all the columns for the first experiment. However, when I try the next experiment (#2), the loop starts from the beginning and all the numbers are the same. Meaning I don't get any variation in my pricing. It seems I will need to find a way to randomize the column selection at the start of every experiment number. Is there a better way to do this??
data1 = sobolset(1000, 'Skip', 1000, 'Leap', 100)
data2 = net(test1, 10)
for exp_num = 1: 20
% how do I change the start of the column selection here, so that the next data3 is different from %the one in the previous exp_num?
for col = 1:10
data3(:, col) = data(2:, col)
% perform calculations
end
end
I hope this is making sense....
Thanks for the help!
Update: 8/21
I tried the following:
num_runs = 100
num_samples = 1000
for j = 1: num_runs
for i = 1 : num_samples
sobol_set = sobolset(num_samples,'Skip',j*50,'Leap',1e2);
sobol_set = net(sobol_set, 5);
sobol_seq = sobol_set(:, i)';
z_uncorr = norminv(sobol_seq, 0, 1)
% do pricing with z_uncorr through some function F
end
end
After generating 100 prices (through some function F, mentioned above), I find that the variance of the 100 prices is higher than that I get from the standard pseudo random numbers. This should not be the case. I think I'm still not sampling correctly from the sobolset. Any advice would be appreciated.

Related

How to repeat random walk simulation and record end results in MatLab?

Hi I am working on my first random walk program. I was just able to figure out the random walk program itself. It is a simple 1d random walk, with 1000 steps. Here is what my code looks like so far:
stepslim = 1000;
rnew(1) = 0
r=0;
%Now we will set up the for loop
for isteps = 2:1:stepslim;
if rand <= 0.5 %The if-else statement will tell the walker
step = -1; %which direction it steps in
else
step = +1;
end
rnew(isteps) = rnew(isteps-1) + step; %This adds the new step
end
plot(rnew); %This will plot our random walk
This works just fine, and now I need to attempt a few more tasks:
Run this simulation X times to generate an ensemble. Record/store the final location of the walker at the end of each simulation in the ensemble.
Generate a histogram for the ending position of the walker for each simulation in the ensemble ▪ Adjust the bin-width to “make sense” of your results.
Repeat and plot results for X = [1000, 2000, 10000, 20000, 100000, 1000000]
I am not sure how to repeat the simulation and record the ending values into an ensemble. I would appreciate some help in accomplishing these tasks
Your method for generating the random walks is very, very, very slow... if you want to change your approach, I would suggest you yo use the following code instead:
steps = 1000;
rw = cumsum(-1 + 2 * round(rand(steps,1)),1);
Starting from that point, here is how you could run your simulation x times, record each result and retrieve the last step of every simulation:
iters = 10;
steps = 1000;
rws = NaN(steps,iters);
for i = 1:iters
rws(:,i) = cumsum(-1 + 2 * round(rand(steps,1)),1);
end
% retrieve the last step
last_steps = rws(end,:);
In order to plot an histogram of the last steps, you could use the histogram function which should be flexible enough to print something coherent enough with your data:
histogram(last_steps);
To use different step sizes, just enclose everything inside another for loop in which you cycle on every step size that you define within an array:
X = [1000, 2000, 10000, 20000, 100000, 1000000];
for j = 1:numel(X)
% previous code with variable "steps" replaced by X(j)
end

Dice simulation with matlab

I am new on this forum. First of all, I find it very interesting to have such a website were everyone can get help in different domains. Thank you very much.
So I have a problem: I was supposed to resolve the following problem:
Simulate with rand ntrials of rolling a dice.
if rand() in [0, 1/6] then 1 was thrown;
if rand() in (1/6, 2/6] then 2 was thrown
...
if rand() in (5/6, 1] then 6 was thrown.
Generate with hist an histogramm of the results of ntrials.
This is what I did:
ntrials = 100;
X = abs(rand(1,ntrials)*6) + 1;
hist(floo(X))
Now there is a second exercise that I must do:
two dice are thrown and S is the sum of the 2 dice
Compute the probability that S respectively accept one of the value 2,3,4,5.....12.
Write a Matlab function twoTimesDice that the theoritical result through a simulation of the throw of 2 dice like in the first exercise.
That is what I tryed:
function twoTimesDice
x1 = abs(rand(1,11))*6 + 1;
s1 = floor(x1); % probably result of the first dice
x2 = abs(rand(1,11))*6 +1;
s2 = floor(x2) % probably result of de second dice
S = s1 +s2;
hist(S);
end
Can you tell me please if I did it well?
Generating a dice roll between 1 and 6 can be done by randi().
So first, use randi() instead of floor() and abs():
X = randi(6,1,ntrials)
which will give you an array of length ntrials with random integers ranging from 1 to 6. (you need the 1 there or it will return a square matrix of size ntrials by ntrials). randi documentation
In the function my personal preference would be to request the number of trials as input.
Your function then becomes:
function twoTimesDice(ntrials)
s1 = randi(6,1,ntrials); % result of the first dice
s2 = randi(6,1,ntrials); % result of the second dice
S = s1 +s2;
hist(S);
end
For a normalised histogram, you can replace hist(S) by:
numOfBins = 11;
[histFreq, histXout] = hist(S, numOfBins);
figure;
bar(histXout, histFreq/sum(histFreq)*100);
xlabel('Value');ylabel('Percentage');
(As described in this question)
For the first part, I would use floor instead of abs,
X = floor(rand(1, ntrials)*6) + 1;
as it returns the values you are looking for, or as Daniel commented, use
randi(6)
which returns an integer.
Then you can just run
hist(X,6)
For the second part, I believe they are asking for two dice rolls, each being 1-6, and not one 2-12.
x = floor(rand(1)*6) + 1;
The distribution will look different. Roll those twice, add the result, that is your twoTimesDice function.
Roll that ntrials times, then do a histogram of that (as you already do).
I am not sure how random rand() really is though.

Writing a matlab program for combinations of large numbers

Because for combinations of large numbers at times matlab replies NaN, the assignment is to write a program to compute combinations of 200 objects taken 90 at a time. Once this works we are to make it into a function y = comb(n,k).
This is what I have so far based on an example we were given of the probability that 2 people in a class have the same birthday.
This is the example:
nMax = 70; %maximum number of people in classroom
nArray = 1:nMax;
prevPnot = 1; %initialize probability
for iN = 1:nMax
Pnot = prevPnot*(365-iN+1)/365; %probability that no birthdays are the same
P(iN) = 1-Pnot; %probability that at least two birthdays are the same
prevPnot = Pnot;
end
plot(nArray, P, '.-')
xlabel('nb. of people')
ylabel('prob. that at least two have same birthday')
grid on
At this point I'm having trouble because I'm more familiar with java. This is what I have so far, and it isn't coming out at all.
k = 90;
n = 200;
nArray = 1:k;
prevPnot = 1;
for counter = 1:k
Pnot = (n-counter+1)/(prevPnot*(n-k-counter+1);
P(iN) = Pnot;
prevPnot = Pnot;
end
The point of the loop I wrote is to separate out each term
i.e. n/k*(n-k), times (n-counter)/(k-counter)*(n-k-counter), and so forth.
I'm also not entirely sure how to save a loop as a function in matlab.
To compute the number of combinations of n objects taken k at a time, you can use gammaln to compute the logarithm of the factorials in order to avoid overflow:
result = exp(gammaln(n+1)-gammaln(k+1)-gammaln(n-k+1));
Another approach is to remove terms that will cancel and then compute the result:
result = prod((n-k+1:n)./(1:k));

How can I rearrange a list of numbers so that every N numbers is nonrepeating?

So I have a list of 190 numbers ranging from 1:19 (each number is repeated 10 times) that I need to sample 10 at a time. Within each sample of 10, I don't want the numbers to repeat, I tried incorporating a while loop, but computation time was way too long. So far I'm at the point where I can generate the numbers and see if there are repetitions within each subset. Any ideas?
N=[];
for i=1:10
N=[N randperm(19)];
end
B=[];
for j=1:10
if length(unique(N(j*10-9:j*10)))<10
B=[B 1];
end
end
sum(B)
Below is an updated version of the code. this might be a little more clear in showing what I want. (19 targets taken 10 at a time without repetition until all 19 targets have been repeated 10 times)
nTargs = 19;
pairs = nchoosek(1:nTargs, 10);
nPairs = size(pairs, 1);
order = randperm(nPairs);
values=randsample(order,19);
targs=pairs(values,:);
Alltargs=false;
while ~Alltargs
targs=pairs(randsample(order,19),:);
B=[];
for i=1:19
G=length(find(targs==i))==10;
B=[B G];
end
if sum(B)==19
Alltargs=true;
end
end
Here are some very simple steps to do this, basically you just shuffle the vector once, and then you grab the last 10 unique values:
v = repmat(1:19,1,10);
v = v(randperm(numel(v)));
[a idx]=unique(v);
result = unique(v);
v(idx)=[];
The algorithm should be fairly efficient, if you want to do the next 10, just run the last part again and combine the results into a totalResult
You want to sample the numbers 1:19 randomly in blocks of 10 without repetitions. The Matlab function 'randsample' has an optional 'replacement' argument which you can set to 'false' if you do not want repetitions. For example:
N = [];
replacement = false;
for i = 1:19
N = [N randsample(19,10,replacement)];
end
This generates a 19 x 10 matrix of random integers in the range [1,..,19] without repetitions within each column.
Edit: Here is a solution that addresses the requirement that each of the integers [1,..,19] occurs exactly 10 times, in addition to no repetition within each column / sample:
nRange = 19; nRep = 10;
valueRep = true; % true while there are repetitions
nLoops = 0; % count the number of iterations
while valueRep
l = zeros(1,nRep);
v = [];
for m = 1:nRep
v = [v, randperm(nRange,nRange)];
end
m1 = reshape(v,nRep,nRange);
for n = 1:nRep
l(n) = length(unique(m1(:,n)));
end
if all(l == nRep)
valueRep = false;
end
nLoops = nLoops + 1;
end
result = m1;
For the parameters in the question it takes about 300 iterations to find a result.
I think you should approach this constructively.
It's easy to initially find a 19 groups that fulfill your conditions just by rearranging the series 1:19: series1 = repmat(1:19,1,10); and rearranged= reshape(series1,10,19)
then shuffle the values
I would select two random columns copy them and switch the values at two random positions
then make a test if it fulfills your condition - like: test = #(x) numel(unique(x))==10 - if yes replace your columns
just keep shuffling till your time runs out or you are happy
of course you might come up with more efficient shuffling or testing
I was given another solution through the MATLAB forum that works pretty well (Credit to Niklas Nylen over on the MATLAB forum). Computation time is pretty low too. It basically shuffles the numbers until there are no repetitions within every 10 values. Thanks all for your help.
y = repmat(1:19,1,10);
% Run enough iterations to get the output random enough, I selected 100000
for ii = 1:100000
% Select random index
index = randi(length(y)-1);
% Check if it is allowed to switch places
if y(index)~=y(min(index+10, length(y))) && y(index+1)~=y(max(1,index-9))
% Make the switch
yTmp = y(index);
y(index)=y(index+1);
y(index+1)=yTmp;
end
end

??? Index exceeds matrix dimensions PSD Proplem

Hey guys I am trying to find the Power Spectral Density of a .wav signal i recorded which is essentially a sine immersed in noise. The function that i have written is supposed to take records all of 1024 points in length and use it to find the Gxx of the signal by finding Gxx per record and then adding them and dividing them by the number of records better explained in the algorithm below:
a. Step through the wav file and extract the first record length (e.g. 1 to 1024 points). (Note that the record length is your new “N”, hence the frequency spacing changes in accordance with this, NOT the total length of the wav file).
b. Perform the normal PSD function on this record.
c. Store this vector.
d. Extract the next 1024 points in the wav file (e.g. 1025:2048) and perform PSD on this record.
e. Add this to the previously stored record and continue through steps c to e until you reach the end of your wav file or the total number of records you want. (Remember that total records*record length must be less than the total length of the wavfile!)
f. Divide the PSD by the number of averages (or number of records).
This is your averaged PSD
The function I created is as follows:
%Function to plot PSD
function[f1, GxxAv] = HW3_A_Fn_811003472_RCT(x,fs,NumRec)
Gxx = 0;
GxxAv = 0;
N = 1024;
df = fs/N;
f1 = 0:df:fs/2;
dt = 1/fs;
T = N*dt;
q = 0;
e = 1;
for i = 1:NumRec;
for r = (1+q):(N*e);
L = x(1+q:N*e);
M = length(L);
Xm = fft(L).*dt;
aXm = abs(Xm);
Gxx(1)=(1/T).*(aXm(1).*aXm(1));
for k = 2:(M/2);
Gxx(k) = (2/T) *(aXm(k).*(aXm(k)));
%Gxx = Gxx + Gxx1(k);
end
Gxx((M/2)+1)= (1/T)*(aXm((M/2)+1)).*(aXm((M/2)+1));
q = q+1024;
e = e+1;
%Gxx = Gxx + Gxx1((M/2)+1);
end
GxxAv = GxxAv + Gxx;
%Gxx = Gxx + Gxx1;
end
GxxAv = GxxAv/NumRec;
And the code I used to call this function is as follows:
[x,fs] = wavread('F:\Final\sem1Y3\Acoustics\sinenoise5s.wav');
[f1,GxxAv] = HW3_A_Fn_811003472_RCT(x,fs,100); %where 100 is the number of records to generated
plot(f1,GxxAv)
xlabel ('Frequency / Hz', 'fontsize', 18)
ylabel ('Amplitude Squared per Frequency / WU^2/Hz', 'fontsize', 18)
title ('Plot of the single sided PSD, using Averaging', 'fontsize', 18)
grid on
When Trying to plot this graph the following error was observed:
??? Index exceeds matrix dimensions.
Error in ==> HW3_A_Fn_811003472_RCT at 19
L = x(1+q:N*e);
Error in ==> HW3_A_3_811003472_RCT at 3
[f1,GxxAv] = HW3_A_Fn_811003472_RCT(x,fs,100); %where 100 is the number of records to generated
I am not sure how to fix it and i have tried many different methods but still i get this error. I am not too familiar with Matlab but all I really want to do for line 19 is to go like:
x(1:1024), x(1025:2048), x(2049:3072), x(3072:4096)...etc to 100 records
Any ideas??? Thanks
This is obviously homework, so I am not gonna do your work for you. But there quite some things wrong with your code. Start by fixing all of those first:
Use more appropriate function names, homework123 is not a good name to describe what the function does.
Use more appropriate variable names. More standard in this context would be nfft instead of N and n_average instead of NumRec. I don't care about the exact thing you use, but it should describe exactly what the variable does.
Your error message clearly hints that you are trying to index x in some illegal way. Start with making a loop that just prints the right indices (1..1024, 1025..2048, ...) and make sure it follows your instruction E. Only when this works as expected add the rest of the code.
you use a triple-nested for-loop. You only need a single for-loop or while-loop to solve this problem.