Chr*_*ler 6 python list cartesian-product python-itertools
我认为这个问题可以使用itertools或者笛卡尔来解决,但我对Python很新,我正在努力使用它们:
我有5个股票的投资组合,其中每个股票的权重可以是-0.4,-0.2,0,0.2或0.4,权重加起来为0.我如何创建一个函数来生成每个可能组合的列表权重.例如[-0.4,0.2,0,0.2,0] ......等
理想情况下,该功能适用于n种股票,因为我最终希望对50种股票进行相同的处理.
编辑:为了澄清,我正在寻找长度为n的所有组合(在这种情况下为5),求和为0. 值可以重复:例如:[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]等.[0,0,0,0,0]将是一个可能的组合.有5个可能的权重和5个股票的事实是巧合(我应该避免!),同样的问题可能是5个可能的权重和3个股票或7个股票.谢谢.
类似这样的事情,虽然效率并不高。
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,)
Run Code Online (Sandbox Code Playgroud)
我从评论中重复一遍,你不能这样做n = 50。代码会产生正确的值,但没有时间迭代所有可能的权重。
这段代码并不出色。它做了一些不必要的工作来检查情况,例如,除了前两个之外的所有情况的总和已经大于 0.8,因此没有必要单独检查这两个中第一个的所有可能性。
因此,这n = 5几乎很快就能完成,但是n这段代码变得异常缓慢是有一定价值的,并且您可以使用更好的代码走得更远。你仍然不会达到 50。我懒得编写更好的代码,但基本上all_bar_one你可以使用possible_weightings连续较小的值和等于给定目标的n值减去总和进行递归调用target到目前为止你已经做到了。然后修剪所有不需要的分支,在target仅使用值无法达到太大(正或负)的情况下尽早退出n。