Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: get every possible combination of weights for a portfolio

I think this problem can be solved using either itertools or cartesian, but I'm fairly new to Python and am struggling to use these:

I have a portfolio of 5 stocks, where each stock can have a weighting of -0.4, -0.2, 0, 0.2 or 0.4, with weightings adding up to 0. How do I create a function that produces a list of every possible combination of weights. e.g. [-0.4, 0.2, 0, 0.2, 0]... etc

Ideally, the function would work for n stocks, as I will eventually want to do the same process for 50 stocks.

edit: To clarify, I'm looking for all combinations of length n (in this case 5), summing to 0. The values can repeat: e.g: [0.2, 0.2, -0.4, 0, 0], [ 0.4, 0, -0.2, -0.2, 0.4], [0,0,0,0.2,-0.2], [0, 0.4, -0.4, 0.2, -0.2] etc. So [0,0,0,0,0] would be a possible combination. The fact that there are 5 possible weightings and 5 stocks is a coincidence (which i should have avoided!), this same question could be with 5 possible weightings and 3 stocks or 7 stocks. Thanks.

like image 861
Chris Waller Avatar asked Jul 27 '16 11:07

Chris Waller


People also ask

How do you find all the possible combinations in Python?

Finding Combinations of Dictionary In Python To calculate the combinations of a dictionary in Python, use the itertools. combinations() method. The combinations() method takes a dictionary as an argument and returns all the possible combinations of the dictionary elements.

What is combination function in Python?

Python – Itertools Combinations() function combinations() provides us with all the possible tuples a sequence or set of numbers or letters used in the iterator and the elements are assumed to be unique on the basis of there positions which are distinct for all elements.

How do you make a number combination in Python?

First import itertools package to implement the permutations method in python. This method takes a list as an input and returns an object list of tuples that contain all permutations in a list form.


2 Answers

Something like this, although it's not really efficient.

from decimal import Decimal
import itertools

# possible optimization: use integers rather than Decimal
weights = [Decimal("-0.4"), Decimal("-0.2"), Decimal(0), Decimal("0.2"), Decimal("0.4")]

def possible_weightings(n = 5, target = 0):
    for all_bar_one in itertools.product(weights, repeat = n - 1):
        final = target - sum(all_bar_one)
        if final in weights:
            yield all_bar_one + (final,)

I repeat from comments, you cannot do this for n = 50. The code yields the right values, but there isn't time in the universe to iterate over all the possible weightings.

This code isn't brilliant. It does some unnecessary work examining cases where, for example, the sum of all but the first two is already greater than 0.8 and so there's no point separately checking all the possibilities for the first of those two.

So, this does n = 5 in nearly no time, but there is some value of n where this code becomes infeasibly slow, and you could get further with better code. You still won't get to 50. I'm too lazy to write that better code, but basically instead of all_bar_one you can make recursive calls to possible_weightings with successively smaller values of n and a value of target equal to the target you were given, minus the sum you have so far. Then prune all the branches you don't need to take, by bailing out early in cases where target is too large (positive or negative) to be reached using only n values.

like image 152
Steve Jessop Avatar answered Oct 17 '22 15:10

Steve Jessop


I understand the values can repeat, but all have to sum to zero, therefore the solution might be:

>>> from itertools import permutations
>>> weights = [-0.4, -0.2, 0, 0.2, 0.4]
>>> result = (com for com in permutations(weights) if sum(com)==0)
>>> for i in result: print(i)

edit: you might use product as @Steve Jassop suggested.

combi = (i for i in itertools.product(weights, repeat= len(weights)) if not sum(i))
for c in combi:
    print(c)
like image 37
Juraj Bezručka Avatar answered Oct 17 '22 15:10

Juraj Bezručka