'algorithm to calculate portfolio weights with negative returns?

Summary

Below is the full question (a bit complicated in its full form) here's a super simplified version (which is the heart of what I'm asking). If I told you to give me the weights of 49 and 17, you would take 66 (49+17) and divide each number by 66 (49/66=74% and 17/66=26%). My question is, if I added a negative number -27 to the above numbers, how would you weight them (if I couldn't use a negative weight)?

I somehow need to represent the negative number in the overall weight but the negative weight is throwing my numbers off. 39(49 + 17 + -27), causes 39/39=1.25%, 17/39=44%, and -27/39=-69%. So in the example below, if this were stocks and I gave you $100 how would you know how much to buy?

Detailed question

I'm having a bit of trouble figuring out an algorithm (or the logic how to do this).

Stock       percent of return              Return
Blue        .98                            50       
Red         .85                            20       
Black       .90                           -30      

It's basically providing us with a report saying we want .98% of the return of 50%, 85% of the return from 20% and 90% of the returns from -30 (the total in this case is 39%). I'm unsure how to translate this into an actual portfolio (like how much to buy to get this amount if I do not hold the fund already)?

I'm starting to feel this is not possible, but I'm basically asking if I gave you the above table (name,return and % of return I want to capture) and $100 how can you make that portfolio? If I only gave you one stock that was 50% and said I wanted 100% of its returns you could easily just buy $100 of that single stock.With two stocks you could add the total returns/weights and get the weight but how do you deal with negative returns you want to capture?

I don't think I'm getting this right but here's my logic so far (If this is totally wrong, please ignore and suggest anything you like).

Get list of data
total_return = multiple percent_of_return and return (do this as a recursion for all stocks in the list)
take total of all items in total_return (using absolute numbers..no negatives so above 39 equals 42) and figure out the weight of each from that.
multiply these weights by stock price and divide by total to give weight.

The result of this is (note:the total changed from 39% to 93%):

Blue 0.52688172
red 0.182795699
black 0.290322581

The problem, which I'm really unsure if is converting a negative weight into a absolute (positive) weight. I'm not good with math (and worst with finance) but I'm unsure how to 'buy' a percent of negative returns (the two data points I'm given, but I can enrich it with other data if needed like stock price, etc.). Also, just to make it clear, I do not own these portfolios already so I can't just take these weights against an existing portfolios, I am using the above information as guidance to create a new one (just need to figure out an algo to do that).

Update

I always learn from code so here's my code (in Python) and some test cases (it's horribly ugly as I'm prototyping just to understand the logic of how to do this):

overall_total_value = []
def test(data_return, datacoeff, data_value):
    total_results = 0
    data_total_of_return = {}
    for x in data_return:
        current_value = data_return[x] * (datacoeff[x]*.001)
        data_total_of_return[x] = current_value
        total_results = total_results + current_value

    #abs
    abs_total_value = 0
    for x in data_total_of_return:
        #print x, '=', abs(data_total_of_return[x])
        abs_total_value = abs_total_value + abs(data_total_of_return[x])
    
    print abs_total_value
    weight = {}
    for x in data_total_of_return:
        weight[x] = abs(data_total_of_return[x]/abs_total_value)
    
    total_value = 0
    for x in weight:
        valuer = weight[x] * data_value[x]
        print x, weight[x], '=', valuer
        total_value = total_value + valuer
    
    print 'ABS total % return: ',total_results
    print total_value
    overall_total_value.append(total_value)
    
    print "*"*30
    
    
data_return = {'Blue':50, 'Red':20, 'Black':-30}
data_value = {'Blue':10.4, 'Red':4, 'Black':8}

datacoeff = { "Blue": 78 , "Red": 0 , "Black": 0 , }
test(data_return, datacoeff, data_value)
datacoeff = { "Blue": 48 , "Red": 75 , "Black": 0 , }
test(data_return, datacoeff, data_value)
datacoeff = { "Blue": 46 , "Red": 80 , "Black": 0 , }
test(data_return, datacoeff, data_value)
datacoeff = { "Blue": 38 , "Red": 100 , "Black": 0 , }
test(data_return, datacoeff, data_value)
datacoeff = { "Blue": 62 , "Red": 100 , "Black": 40 , }
test(data_return, datacoeff, data_value)
datacoeff = { "Blue": 100 , "Red": 20 , "Black": 50 , }
test(data_return, datacoeff, data_value)
datacoeff = { "Blue": 98 , "Red": 55 , "Black": 70 , }
test(data_return, datacoeff, data_value)
datacoeff = { "Blue": 90 , "Red": 75 , "Black": 70 , }
test(data_return, datacoeff, data_value)
datacoeff = { "Blue": 100 , "Red": 65 , "Black": 80 , }
test(data_return, datacoeff, data_value)
datacoeff = { "Blue": 98 , "Red": 70 , "Black": 80 , }
test(data_return, datacoeff, data_value)
datacoeff = { "Blue": 96 , "Red": 75 , "Black": 80 , }
test(data_return, datacoeff, data_value)
datacoeff = { "Blue": 94 , "Red": 80 , "Black": 80 , }
test(data_return, datacoeff, data_value)
datacoeff = { "Blue": 92 , "Red": 85 , "Black": 80 , }
test(data_return, datacoeff, data_value)
datacoeff = { "Blue": 90 , "Red": 90 , "Black": 80 , }
test(data_return, datacoeff, data_value)
datacoeff = { "Blue": 88 , "Red": 95 , "Black": 80 , }
test(data_return, datacoeff, data_value)
test(data_return, datacoeff, data_value)
datacoeff = { "Blue": 98 , "Red": 100 , "Black": 100 , }
test(data_return, datacoeff, data_value)


Solution 1:[1]

You are getting this all wrong in my opinion (or there's some confusion in your data). I assume that the return column is something you don't have in advance, otherwise you could engage in arbitrage, which is nonsense. Basic theory: some stocks have positive beta coefficients (they go with the market), others have negative beta coefficients (they go against the market). In the situation you have proposed the first two stocks have (probably) a beta coefficient with the same sign and the remaining one a beta coefficient of the opposite sign. Therefore, since you are trying to reduce your losses it's normal for one of your stocks to have negative returns, as the loss is offset by the gains in the other two stocks.

Let's assume for sake of simplicity that you are trying to invest 100$.

You want to get .98 of the returns of the first stock (whatever they are).

You want to get .85 of the returns of the second stock (whatever they are).

You want to get .90 of the returns of the third stock (whatever they are).

Now let's normalize the desired returns so that they sum to 1 (and by maintaining the proportions!).

For each $ in your portfolio you want to buy:

.98/(.98+.85+.90) = 0.358974358974359$ of the first stock

.85/(.98+.85+.90) = 0.31135531135531136$ of the second stock

.90/(.98+.85+.90) = 0.32967032967032966$ of the third stock

Therefore considering your endowment of 100$ and assuming that you can freely buy portions of stocks you'll invest respectively:

$35.90, $31.14, $32.96

And finally, (and this is not the case!) whenever you find a minus sign in the desired returns (first column) it actually means that you're short selling that stock (i.e. borrowing the underlying asset to sell it in the future at a -hopefully- higher price).

>>> desired_returns = [.98,.85,.9]
>>> real_weights = [i/sum([abs(j) for j in desired_returns]) for i in desired_returns]
>>> real_weights
[0.358974358974359, 0.31135531135531136, 0.32967032967032966]
>>> cash_available=100
>>> labels=['blue','red','green']
>>> for i in range(len(desired_returns)):
...     if desired_returns[i]>=0:
...          print "Buy %s$ of the stock %s" % (cash_available*real_weights[i],labels[i])
...     else:
...           print "Short sell %s$ of the stock %s" % (abs(cash_available*real_weights[i]),labels[i])
Buy 35.8974358974$ of the stock blue
Buy 31.1355311355$ of the stock red
Buy 32.967032967$ of the stock green

Solution 2:[2]

Right now you're trying to calculate this entierly off of the return. If you're able to include current market value as well (i.e. the current (price * size) of the positions if you were to sell them right now) you will achieve the actual weight of each position within your portfolio. From there it's a simple matter of multiplyting this <1 weight by whatever cash you're injecting into the portfolio.

If you have access to the stock price, pull that in and use the following logic.

decimal portfolioAssets;
Dictionary<stock, decimal> stockAssets = new Dictionary<stock, decimal>();
foreach(stock in stocks)
{
    decimal assets = stock.Shares*stockPrice;
    portfolioAssets =+ assets;
    stockAssets.Add(stock, assets);
}

foreach(stock in stocks)
{
decimal weight = stockAssets[stock]/portfolioAssets;
//do something with weight 
}

Solution 3:[3]

Can you just surround your entire formula with ABS(), to return the absolute value, which would eliminate your negative numbers?

Solution 4:[4]

If it's your position that is short then surely the number of shares should be negative ? If you then have a -ve number of shares each with a -ve value you will have a +ve value in your portfolio. In general, though, it's not necessary that +/- signs match up, why can't you hold shares which have lost value and make a -ve contribution to your wealth ?

If you bought 90 shares which lost 30 in value then you have lost 2700 dongs (or whatever your local currency is). Personally I don't have a problem with the idea that the contribution to the total value of a portfolio is, say, -34.54%. However, I agree that it does look a little odd that one of your shares contributes more than 100% to the value of your portfolio. This indicates that perhaps you should follow the advice given in the answer to the question you linked to and ignore, in weighting the values of the holdings in your portfolio, negative values entirely.

What I wouldn't do, in your case, is start ignoring -ve numbers because they leave your results looking untidy. The information contained in the - is essential to valuing your portfolio. Choose derivations of the raw information that suit your purposes, I mean, if you don't like the way the weights come out when calculated as in your question choose a different statistic, one that suits your purposes.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 Icemanind
Solution 4 High Performance Mark