Как генерировать веса с помощью constraint sum {x_i} = 1 для более чем двух активов в сетчатой сетке?

#python #algorithm #numpy

#python #алгоритм #numpy

Вопрос:

Я хотел бы сгенерировать веса активов для более чем двух активов в сетчатой сетке, чтобы сумма была равна единице. Например, я могу использовать пространство строк numpy с двумя активами, но не уверен, как это сделать с более чем 2 активами:

 import numpy as np

# get 3 weight configurations for 2 assets, that sum up to one
[np.array([w, 1-w]) for w in np.linspace(0, 1, 3)]
>[array([0., 1.]), 
  array([0.5, 0.5]), 
  array([1., 0.])]

# get 4 weight configurations for 2 assets, that sum up to one
[np.array([w, 1-w]) for w in np.linspace(0, 1, 4)]
>[array([0., 1.]),
  array([0.33333333, 0.66666667]),
  array([0.66666667, 0.33333333]),
  array([1., 0.])]

# get 5 weight configurations for 2 assets, that sum up to one
[np.array([w, 1-w]) for w in np.linspace(0, 1, 5)]
> [array([0., 1.]),
   array([0.25, 0.75]),
   array([0.5, 0.5]),
   array([0.75, 0.25]),
   array([1., 0.])]
 

ОБНОВЛЕНИЕ: под сетчатой сеткой я подразумеваю, что веса не являются случайными, а соответствуют шаблону сетки сетки, например, для 3 активов это были бы возможные конфигурации. Конечно, степень детализации зависит от количества конфигураций веса, запрошенных в num аргументе такой функции (эквивалентно numpy#linspace):

 [1, 0, 0]
[0, 1, 0]
[0, 0, 1]
[0.333333, 0.333333, 0.333333]
[0.333333, 0.666666, 0]
[0.666666, 0.333333, 0]
[0, 0.333333, 0.666666]
[0, 0.666666, 0.333333]
[0.333333, 0, 0.666666]
[0.666666, 0, 0.333333]
 

Комментарии:

1. можете ли вы определить «равноудаленный»?

2. @Marat спасибо, что изучили этот вопрос 🙂 действительно, обновляя вопрос.

3. Трудно понять вопрос, даже с приведенным примером. Если каждый триплет представляет точку в трехмерном пространстве, то данные точки не равноудалены от какого-либо центра и не являются их попарно удаленными константами.

4. @Stef, спасибо, вы действительно правы, равноудаленное — не лучшее описание, я изменю его на сетчатый шаблон.

5. проблема здесь в том, что не каждое количество точек будет генерировать допустимое размещение шаблона сетки. Например, в трехмерном пространстве это возможно только для n (n 1) / 2 точек, где n — количество шагов вдоль одной из осей. 10 баллов в примере 4*5 / 2

Ответ №1:

Вот решение, которое соответствует вашим примерам.

Используя целочисленное разделение!

 from sympy.utilities.iterables import partitions
from more_itertools import distinct_permutations
# if you don't want to install more_itertools:
#     set(itertools.permutations( ... ))
#     is equivalent but less efficient than
#     more_itertools.distinct_permutations( ... )
from collections import Counter  # not really needed; just for .elements()

def weights(dim, grid):
    for p in partitions(grid, m=dim):
        p[0] = dim - sum(p.values())
        yield from (distinct_permutations(x / grid for x in Counter(p).elements()))

print( list(weights(2, 2)) )
# [(0.0, 1.0), (1.0, 0.0), (0.5, 0.5)]

print( list(weights(2, 4)) )
# [(0.0, 1.0), (1.0, 0.0), (0.25, 0.75), (0.75, 0.25), (0.5, 0.5)]

print( list(weights(2, 3)) )
# [(0.0, 1.0), (1.0, 0.0), (0.333, 0.667), (0.667, 0.333)]

print( list(weights(3, 2)) )
# [(0.0, 0.0, 1.0), (0.0, 1.0, 0.0), (1.0, 0.0, 0.0), (0.0, 0.5, 0.5), (0.5, 0.0, 0.5), (0.5, 0.5, 0.0)]

for x,y,z in weights(3, 3):
    print('{:0.2f},{:0.2f},{:0.2f}'.format(x,y,z))
# 0.00,0.00,1.00
# 0.00,1.00,0.00
# 1.00,0.00,0.00
# 0.00,0.33,0.67
# 0.00,0.67,0.33
# 0.33,0.00,0.67
# 0.33,0.67,0.00
# 0.67,0.00,0.33
# 0.67,0.33,0.00
# 0.33,0.33,0.33
 

Соответствующая документация:

Комментарии:

1. Действительно, извините, мой плохой, выглядит хорошо 🙂 Я все еще не вижу, откуда берутся дубликаты…

2. @SkyWalker Я написал это из-за всей путаницы с «равноудаленным». Теперь это намного понятнее. Кроме того, ваш пример очень хорош. Я удалю это утверждение из начала моего ответа.

3. @SkyWalker: Ах! Смотрите! Итак, я что-то неправильно понял!!

4. @SkyWalker К счастью, это легко исправить. Обратите внимание, как partitions принимает два параметра; Я использовал то же n самое для обоих. Мы можем использовать другое значение. Хм.

5. @SkyWalker Тадаааааа! Теперь есть два параметра.