#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 Тадаааааа! Теперь есть два параметра.