0

感谢您的回答,我之前没有使用过 StackOverflow,所以我对答案的数量和速度感到惊讶——太棒了。

我还没有正确地完成答案,但认为我应该在问题规范中添加一些信息。见下图。

我无法在此发布图片,因为我没有足够的积分,但您可以在http://journal.acquitane.com/2010-01-20/image003.jpg看到图片

这张图片可能更准确地描述了我想要实现的目标。因此,您可以在页面上的水平线上看到图表上的价格点。现在,您可以在每条线的 0.5% 范围内得到一个聚类,这被认为是一件好事,也是我想自动识别这些聚类的原因。您可以在图表上看到 S2 和 MR1、R2 和 WPP1 有一个集群。

所以我每天都会产生这些价格点,然后我可以手动识别那些在 0.5% 以内的价格点。- 但这个问题的目的是如何用 python 例程来做。

我再次复制了带有标签的列表(见下文)。请注意,标价点与图像中的价格点不匹配,因为它们来自两个不同的日子。

[YR3,175.24,8] [SR3,147.85,6] [YR2,144.13,8] [SR2,130.44,6] [YR1,127.79,8] [QR3,127.42,5] [SR1,120.94,6] [ QR2,120.22,5] [MR3,118.10,3] [WR3,116.73,2] [DR3,116.23,1] [WR2,115.93,2] [QR1,115.83,5] [MR2,115.56,3] [DR2 ,115.53,1] [WR1,114.79,2] [DR1,114.59,1] [WPP,113.99,2] [DPP,113.89,1] [MR1,113.50,3] [DS1,112.95,1] [WS1, 112.85,2] [DS2,112.25,1] [WS2,112.05,2] [DS3,111.31,1] [MPP,110.97,3] [WS3,110.91,2] [50MA,110.87,4] [MS1,108.91 ,3] [QPP,108.64,5] [MS2,106.37,3] [MS3,104.31,3] [QS1,104.25,5] [SPP,103.53,6] [200MA,99.42,7] [QS2,97.05, 5] [YPP,96.68,8] [SS1,94.03,6] [QS3,92.66,5] [YS1,80.34,8] [SS2,76.62,6] [SS3,67.12,6] [YS2,49.23,8 ] [YS3,32.89,8]

我确实在原始列表中犯了一个错误,因为 C 组是错误的,不应该包括在内。感谢您指出了这一点。

0.5% 也不是固定的,这个值会每天都在变化,但我只是用 0.5% 作为一个例子来说明问题。

再次感谢。标记

PS。我现在会开始检查答案。

你好:

我需要对股价进行一些操纵。我刚刚开始使用 Python,(但我认为我在用任何语言实现它都会遇到麻烦)。我正在寻找一些关于如何在 python 中很好地实现这一点的想法。

谢谢马克

问题:我有一个列表列表(FloorLevels(见下文)),其中子列表有两个项目(股票价格,重量)。我想将股价在彼此相差 0.5% 以内时分组。一个团体的实力将由其总重量决定。例如:

Group-A
115.93,2
115.83,5
115.56,3
115.53,1
-------------
TotalWeight:12
-------------
Group-B
113.50,3
112.95,1
112.85,2
-------------
TotalWeight:6
-------------    

FloorLevels[   
[175.24,8]
[147.85,6]
[144.13,8]
[130.44,6]
[127.79,8]
[127.42,5]
[120.94,6]
[120.22,5]
[118.10,3]
[116.73,2]
[116.23,1]
[115.93,2]
[115.83,5]
[115.56,3]
[115.53,1]
[114.79,2]
[114.59,1]
[113.99,2]
[113.89,1]
[113.50,3]
[112.95,1]
[112.85,2]
[112.25,1]
[112.05,2]
[111.31,1]
[110.97,3]
[110.91,2]
[110.87,4]
[108.91,3]
[108.64,5]
[106.37,3]
[104.31,3]
[104.25,5]
[103.53,6]
[99.42,7]
[97.05,5]
[96.68,8]
[94.03,6]
[92.66,5]
[80.34,8]
[76.62,6]
[67.12,6]
[49.23,8]
[32.89,8]
]
4

7 回答 7

3

我建议重复使用k-means 聚类——我们简称为 KMC。kKMC 是一种简单而强大的聚类算法……但它需要“被告知”你的目标是多少个聚类。您事先并不知道(如果我理解正确的话)-您只需要最小的k,即没有两个“聚集在一起”的项目X%彼此分开。所以,从k相等开始1——所有东西都聚集在一起,不需要聚类;-)——检查集群的直径(集群的“直径”,从几何学术语的使用来看,是任何两个之间的最大距离集群的成员)。

如果直径为> X%,则设置k += 1,以簇数执行 KMC k,并重复检查,迭代。

在伪代码中:

def markCluster(items, threshold):
    k = 1
    clusters = [items]
    maxdist = diameter(items)
    while maxdist > threshold:
        k += 1
        clusters = Kmc(items, k)
        maxdist = max(diameter(c) for c in clusters)
    return clusters

当然,假设我们有合适diameterKmcPython 函数。

这听起来像你想要的那种东西吗?如果是这样,那么我们可以继续向您展示如何编写diameterKmc(在纯 Python 中,如果您要处理的数量相对有限items,否则可能通过利用强大的第三方附加框架,例如numpy)——但它是如果你真的想要一些完全不同的东西,那么不值得去这么麻烦,从哪里来检查!-)

于 2010-01-25T05:38:57.700 回答
2

如果对于, * 1.05 >=和/ 1.05 <=中的每只股票,股票s属于一个组,对吗?GtGstst

我们如何将股票添加到每个组中?如果我们有股票 95、100、101 和 105,我们以 100 开始一个组,然后添加 101,我们将得到 {100、101、105}。如果我们在 100 之后做 95,我们最终会得到 {100, 95}。

我们只需要考虑所有可能的排列吗?如果是这样,您的算法将效率低下。

于 2010-01-25T04:47:48.357 回答
2

您需要更详细地说明您的问题。“当股价在 0.5% 以内时将它们分组”是什么意思?

可能性:

(1) 小组中的每个成员与小组其他成员的差距在 0.5% 以内

(2)对列表进行排序,在差距大于0.5%的地方进行拆分

请注意,116.23 在 115.93 的 0.5% 范围内 -- abs((116.23 / 115.93 - 1) * 100) < 0.5-- 但您已将一个数字放入 A 组,并将一个数字放入 C 组。

简单的例子:a, b, c = (0.996, 1, 1.004)... 注意 a 和 b 适合,b 和 c 适合,但 a 和 c 不适合。您希望它们如何分组,为什么?输入列表中的顺序是否相关?

可能性(1)产生 ab,c 或 a,bc ... 请打破平局规则
可能性(2)产生 abc(没有大的差距,所以只有一组)

于 2010-01-25T05:09:09.887 回答
1

您将无法将它们分类为硬“组”。如果您有价格 (1.0,1.05, 1.1),那么第一个和第二个应该在同一个组中,第二个和第三个应该在同一个组中,但不是第一个和第三个。

一种快速而肮脏的方式来做一些你可能会觉得有用的事情:

def make_group_function(tolerance = 0.05):
    from math import log10, floor
    # I forget why this works. 
    tolerance_factor = -1.0/(-log10(1.0 + tolerance))
    # well ... since you might ask
    # we want: log(x)*tf - log(x*(1+t))*tf = -1, 
    # so every 5% change has a different group. The minus is just so groups 
    # are ascending .. it looks a bit nicer.
    #
    # tf = -1/(log(x)-log(x*(1+t)))
    # tf = -1/(log(x/(x*(1+t))))
    # tf = -1/(log(1/(1*(1+t)))) # solved .. but let's just be more clever
    # tf = -1/(0-log(1*(1+t)))
    # tf = -1/(-log((1+t))
    def group_function(value):
        # don't just use int - it rounds up below zero, and down above zero
        return int(floor(log10(value)*tolerance_factor))
    return group_function

用法:

group_function = make_group_function()
import random
groups = {}
for i in range(50):
    v = random.random()*500+1000
    group = group_function(v)
    if group in groups:
        groups[group].append(v)
    else:
        groups[group] = [v]

for group in sorted(groups):
    print 'Group',group
    for v in sorted(groups[group]):
        print v
    print
于 2010-01-25T05:35:06.020 回答
0

对于给定的一组股票价格,可能有不止一种方法可以对彼此相差 0.5% 以内的股票进行分组。如果没有一些额外的规则来对价格进行分组,就无法确定答案会满足您的真正需求。

于 2010-01-25T05:20:20.780 回答
0

除了选择适合的值的正确方法之外,这是一个问题,在这个问题中加入一点面向对象可以使它更容易处理。

我在这里创建了两个类,具有最少的理想行为,但这可以使分类变得更容易——你在 Group 类中得到一个点来使用它。

我可以看到下面的代码是不正确的,从某种意义上说,组包含的限制会随着新成员的添加而变化——即使分离标准保持不变,您也可以重写 get_groups 方法以使用多通道方法。这应该不难——但是代码太长了,在这里没有帮助,我认为这段代码足以让你继续前进:

from copy import copy

class Group(object):
    def __init__(self,data=None, name=""):
        if data:
            self.data = data
        else:
            self.data = []
        self.name = name

    def get_mean_stock(self):
        return sum(item[0] for item in self.data) / len(self.data)

    def fits(self, item):
        if 0.995 < abs(item[0]) / self.get_mean_stock() < 1.005:
            return True
        return False

    def get_weight(self):
        return sum(item[1] for item in self.data)

    def __repr__(self):
        return "Group-%s\n%s\n---\nTotalWeight: %d\n\n" % (
            self.name,
            "\n".join("%.02f, %d" % tuple(item) for item in self.data ),
            self.get_weight())


class StockGrouper(object):
    def __init__(self, data=None):
        if data:
            self.floor_levels = data
        else:
            self.floor_levels = []

    def get_groups(self):
        groups = []
        floor_levels = copy(self.floor_levels)
        name_ord = ord("A") - 1
        while floor_levels:
            seed = floor_levels.pop(0)
            name_ord += 1
            group = Group([seed], chr(name_ord))
            groups.append(group)
            to_remove = []
            for i, item in enumerate(floor_levels):
                if group.fits(item):
                    group.data.append(item)
                    to_remove.append(i)
            for i in reversed(to_remove):
                floor_levels.pop(i)
        return groups

测试:

floor_levels = [  [stock. weight] ,... <paste the data above> ]
s = StockGrouper(floor_levels)
s.get_groups()
于 2010-01-25T13:19:34.540 回答
0

对于分组元素,您可以使用 itertools.groupby() 吗?随着数据的排序,很多分组工作已经完成,然后您可以测试迭代中的当前值是否与上一个值相差 <0.5%,并让 itertools.groupby() 分解为每次您的函数返回 false 时创建新组。

于 2010-01-25T16:45:44.850 回答