After reading carefully the previous question Random numbers that add to 100: Matlab
I am trying to solve a similar but slightly more complicated problem.
I would like to create an array of n elements that sums with 1, however I want to add a restriction that the minimum gain (or if you like the number of significant digits) for each element is fixed.
For example, if I need 10 numbers that add up to 1 without any restrictions, the following works fine:
num_stocks=10; num_simulations=100000; temp = [zeros(num_simulations,1),sort(rand(num_simulations,num_stocks-1),2),ones(num_simulations,1)]; weights = diff(temp,[],2);
I foolishly thought that by scaling this, I can add a restriction as follows
num_stocks=10; min_increment=0.001; num_simulations=100000; scaling=1/min_increment; temp2 = [zeros(num_simulations,1),sort(round(rand(num_simulations,num_stocks-1)*scaling)/scaling,2),ones(num_simulations,1)]; weights2 = diff(temp2,[],2);
However, although this works for small values ββof n and small values ββof the increment, if, for example, n = 1000, and the increment is 0.1%, then with a large number of tests the first and last numbers have an average value that is consistently lower than 0.1% .
I am sure there is a logical explanation / solution for this, but I tore my hair to try to find it, and wondered if someone would be so kind as to point me in the right direction. To put a problem in context, create random stock portfolios (hence the sum of up to 1).
Thanks in advance
Thanks for the answers so far, just to clarify (as I think my initial question may have been poorly worded), these are weights with a fixed increment of 0.1%, so 0%, 0.1%, 0.2 % etc.
I tried using integers first
num_stocks=1000; min_increment=0.001; num_simulations=100000; scaling=1/min_increment; temp = [zeros(num_simulations,1),sort(randi([0 scaling],num_simulations,num_stocks-1),2),ones(num_simulations,1)*scaling]; weights = (diff(temp,[],2)/scaling); test=mean(weights);
but it was worse, the average value for the first and last weights is much lower than 0.1% .....
Modify to reflect Floris' excellent answer and clarify
The source code I used to solve this problem (before finding this forum) was
function x = monkey_weights_original(simulations,stocks) stockmatrix=1:stocks; base_weight=1/stocks; r=randi(stocks,stocks,simulations); x=histc(r,stockmatrix)*base_weight; end
This works very fast, which is important, considering that I want to run just 10,000,000 simulations, 10,000 simulations per 1,000 shares take just over 2 seconds with one core, and I run all the code on an 8-core computer using the parallel toolbar .
It also gives exactly the distribution that I was looking for in terms of funds, and I think it is also likely to get a portfolio that is 100% in 1 share, since it is intended for a portfolio that is 0.1% in each (although I'm glad you got it fixed).
My problem is that although it works for 1000 shares and increases by 0.1%, and I think that it works for 100 shares and an increase of 1%, since the number of shares decreases, then each choice becomes a very large percentage (as a last resort with 2 shares you will always get a 50/50 portfolio).
Essentially, I think this solution is similar to the binomial solution proposed by Floris (but more limited)
However, my question arose because I would like to make my approach more flexible and be able to say 3 shares and a 1% gain that my current code will not handle correctly, therefore, how I came across the original StackOverflow question
Floris's recursive approach will come up with the right answer, but speed will be a serious problem, given the scale of the problem.
An example of an original study is here.
http://www.huffingtonpost.com/2013/04/05/monkeys-stocks-study_n_3021285.html
I am currently working on expanding it with more flexibility regarding the weight of the portfolio and the number of shares in the index, but it seems that my programming and the ability of probability theory are the limiting factor .......