Search code examples
algorithmfinance

randomly create a portfolio of a given size


There are 100 different stocks in total to choose from. Each stock has a price, p_i, I want to create random portfolios for simulation purposes. The total value of the portfolio needs to be $1,000,000 (give or take $100) and the number of different shares in the portfolio can be random too (for example the portfolio could be long in 20 stocks). I'm struggling to create "a good" algorithm to do this.

It's not really a knapsack problem because nothing needs to be optimized. It is kind of like a random sample but not quite. So I'm wondering what algorithm I could use to solve this problem. Any ideas?


Solution

    • Choose N number of stocks from the total universe of stocks
    • Generate N random floats, X_1, ..., X_N, between 0 and 1
    • Let T = the sum of the numbers = X_1 + ... + X_N. If T equals 0, repeat step 1.
    • Normalize the numbers: X_1 = X_1 / T, ... X_N = X_N / T. Notice the sum X_1 + ... + X_N now equals 1.
    • Let W = the value of the total portfolio (e.g. W = 1000000)
    • Invest X_i * W dollars in the ith stock
    • The number of shares bought of the ith stock is therefore S_i = X_i * W / p_i

    In Python,

    import numpy as np
    import pandas as pd
    pd.options.display.float_format = '{:.2f}'.format
    
    N = 100
    W = 10**6
    portfolio_size = np.random.randint(1, N+1)
    df = pd.DataFrame({'price': np.random.uniform(1, 100, size=(N,))})
    df = df.iloc[np.random.choice(N, portfolio_size, replace=False)]
    while True:
        df['value'] = np.random.random(portfolio_size)
        T = df['value'].sum()
        if T != 0: break
    df['value'] *= W/T
    df['shares'] = df['value']/df['price']
    df.index.name='stock num'
    print(df)
    print('Total value of portfolio: {}'.format(df['value'].sum()))
    

    yields something like

               price     value  shares
    stock num                         
    0          34.52  65296.14 1891.72
    24          6.82  13008.12 1906.35
    83         15.56 100550.05 6463.14
    12         60.35  30366.58  503.17
    77         76.75 100814.58 1313.49
    36         96.50  85649.01  887.53
    51         26.28  96860.06 3685.21
    9          43.22  31757.96  734.87
    56         67.33  19889.57  295.40
    66         79.99  30343.49  379.34
    21          1.45   1718.19 1187.56
    30         34.48  33604.31  974.65
    52         80.15  64579.28  805.71
    55         41.02  10226.60  249.29
    40          8.49  25755.19 3032.82
    20         89.46 102164.38 1142.06
    5          45.94  42620.16  927.71
    73         96.17   6021.88   62.62
    58         60.00  24133.96  402.21
    45         40.59 114640.49 2824.31
    Total value of portfolio: 1000000.0