物品排名算法

11

我有一个包含6500个物品的清单,想要进行交易或投资(不是真钱,而是某个游戏)。每个物品有5个数字,将用于在其他物品中排序。

每天交易物品的总数量:这个数字越高,越好。

物品在过去5天内的唐奇安通道:这个数字越高,越好。

价格的中位数价差:这个数字越低,越好。

物品的20日移动平均价差:这个数字越低,越好。

物品的5日移动平均价差:这个数字越高,越好。

所有5个数字的权重相同,换句话说,它们都应该以同等的价值影响最终的数字。

目前,我只是将每个物品的5个数字相乘,但它并没有按我希望的方式对物品进行排名。我只想将所有5个数字组合成一个加权数字,以便我可以用它来对所有6500个物品进行排名,但我不确定如何正确或数学地实现它。

注意:每天交易物品的总数量和唐奇安通道的数字要比价差高得多,而价差更像是百分比类型的数字。这可能是为什么将它们全部相乘没有起作用的原因;每天交易物品的总数量和唐奇安通道在最终数字中起着更重要的作用。


1
你能加入一个具体的例子吗?通常情况下,您会希望对输入数据中的数字进行归一化处理,然后将它们简单地相加,这样就可以产生一个可靠的排名。 - madmik3
例如,每天交易量为400。唐奇安通道为30000。中位数价差为0.30。20日均线的价差为0.85,5日均线的价差为1.2。将它们相加会引起与将它们相乘相同的问题。 - Krzysztof Czelusniak
如果你想做一些关于机器学习的事情(就像templatetypedef怀疑的那样),我可以给你一些链接和建议;但是,如果你不需要的话,我会省去这些麻烦。请澄清一下。 - foo
不,你要么需要它,要么不需要 - 这取决于你所面临的问题是否有用。机器学习适用于与直接算法无法解决的不同类型的问题。 - foo
1
那个“特定的游戏”是不是指EVE Online呢? :) - foo
显示剩余2条评论
5个回答

15

人们无法回答这个问题的原因是我们没有办法比较两个不同的“属性”。如果只有两个属性,比如交易量和中位数价格差,(2000万,50%)是否比(100,1%)更糟糕或更好?只有您可以决定。

将所有内容转换为相同大小的数字可能会有所帮助,这就是所谓的“标准化”。一个好的方法是Prasad提到的z分数。这是一个统计概念,用于查看数量的变化。您需要对数字的统计分布进行一些假设才能使用它。

像价差这样的东西可能是正态分布-形状类似于正态分布。对于这些内容,如Prasad所说,取z(spread) = (spread-mean(spreads))/standardDeviation(spreads)

像交易量这样的东西可能是幂律分布。对于这些内容,在计算平均值和标准差之前,您可能需要取log()。即z分数为z(qty) = (log(qty)-mean(log(quantities)))/sd(log(quantities))

然后只需将每个属性的z分数相加即可。

要针对每个属性执行此操作,您需要对其分布有一定的了解。您可以猜测,但最好的方法是绘制图表并查看。您可能还想在对数刻度上绘制图表。请参见wikipedia的长列表


通过这个答案,我对如何思考数字规范化的理解比之前一年学到的更多了。 - orangepips
嗯,我应该为所有5个类别绘制数据图,然后将这些图与维基百科上的分布列表进行比较吗?但是我不确定如何绘制它。我可以将数据放在y轴上,那么我应该将特定项目放在x轴上吗?如果我这样做,我猜我应该按属性对应值从低到高对x轴上的项目进行排序? - Krzysztof Czelusniak
你需要创建一个直方图(类似于条形图)。最简单的方法是使用Excel(或Open Office等)。请参见http://www.ncsu.edu/labwrite/res/gt/gt-bar-home.html#ith - Nick Fortescue

5

您可以将每个属性向量x(长度为N = 6500)替换为向量Z(x)z-score,其中

Z(x) = (x - mean(x))/sd(x).

这将使它们转换为相同的“比例”,然后您可以将Z分数(具有相等权重)相加以获得最终得分,并通过此总分对N=6500个项目进行排名。如果您在问题中找到了其他属性向量,该向量将是“好”的指标(例如证券的10天回报率?),那么您可以拟合此预测属性与这些z-scored变量的回归模型,以确定最佳的非均匀权重。


3

每个项目的初始得分为0。对于这5个数字中的每一个,将列表按照该数字进行排序,并将每个项目在该排序中的排名加到其得分中。然后,只需按组合分数对项目进行排序即可。


同意,这将是最简单的方法,并且可以满足OP的要求。 - Prasad Chalasani
这是我原本计划要做的。然而,数据范围差异很大。例如,交易数量可以从2到4000万不等。4000万远高于接下来的结果,约为2000万,而后者也明显高于下一个项目。按照每天交易顺序排名只会使4000万的项目比2000万的项目多一个排名位置,尽管二者相差约2000万。如果我找不到更好的解决方案,这就是我要做的事情。 - Krzysztof Czelusniak
所以,毕竟你确实需要规范化。 - foo

2
您通常会将数据条目归一化到它们各自的范围。由于它们没有固定的范围,因此您将不得不使用滑动范围-或者更简单地说,将它们归一化为日常范围。
对于每天,获取给定类型的所有条目,获取它们中的最高值和最低值,确定它们之间的差异。让Bottom=最低值,Range=最高值和最低值之间的差异。然后您计算每个条目(value-Bottom)/Range,这将导致在0.0和1.0之间的某些内容。这些是您可以继续使用的数字。
伪代码(括号替换为缩进以使其更易于阅读):
double maxvalues[5]; 
double minvalues[5];
// init arrays with any item
for(i=0; i<5; i++)
   maxvalues[i] = items[0][i]; 
   minvalues[i] = items[0][i]; 
// find minimum and maximum values
foreach (items as item)
   for(i=0; i<5; i++)
       if (minvalues[i] > item[i])
           minvalues[i] = item[i];
       if (maxvalues[i] < item[i])
           maxvalues[i] = item[i];

// now scale them - in this case, to the range of 0 to 1.
double scaledItems[sizeof(items)][5]; 
double t;
foreach(i=0; i<5; i++)
   double delta = maxvalues[i] - minvalues[i];
   foreach(j=sizeof(items)-1; j>=0; --j)
      scaledItems[j][i] = (items[j][i] - minvalues[i]) / delta; 
      // linear normalization

有一个类似的需求。如果使用好的库(STL、boost或其他实现平台上的库),代码会更加优雅,而且规范化应该在单独的函数中实现,这样你就可以根据需要将其替换为其他变量,如log()。


我所说的将5个数字组合成加权数字,是指最终数字将是加权的,因为这5个因素都会对它产生同等影响。我有一个固定范围,如果你所说的范围是最高数字和最低数字的话。然而,该范围从1(不是100万,只是1)到4000万。大部分范围在100到400之间。这40万会不会使结果失衡? - Krzysztof Czelusniak
好的,已修改帖子。我所说的固定范围是指在所有可能值中它们从未超过的范围。这就是为什么我谈到了归一化。线性归一化可以减少五个条目之间的差异。如果某些数据的分布如此(分布在不同量级上),您可能希望通过使用类似于对数缩放的东西来改进它。无法从您写的内容中得知。 - foo
我同意@foo的观点,进行日志或其他缩放会有所帮助。 - Prasad Chalasani

0

每日交易物品总量:这个数字越高,越好。(a)

过去5天内该物品的唐奇安通道:这个数字越高,越好。(b)

价格中位数的差价:这个数字越低,越好。(c)

该物品20日移动平均线的差价:这个数字越低,越好。(d)

该物品5日移动平均线的差价:这个数字越高,越好。(e)

a + b - c - d + e = "得分" (得分越高,越好)


这个忽略了(a)和(b)比传播范围要大得多,会使这两个因素主导结果。 - Teepeemm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接