如何检测数字模式中的热点趋势?

4
这更多是一个算法问题,比如说你有一个模式,像4 6 2 4 9 5 23 54 33,最后三个数字形成了一串连续增长的趋势。我想知道如何在程序上(或数学上)检测出来。
目前,我考虑使用滑动窗口的方式扫描数据,比如过去3个数字的平均值作为基准,如果新的值(23)远高于这个平均值,我们标记可能开始了一段连续的趋势。后续的数字也不应该偏离得太远,以便继续认为这段连续的趋势还在继续。
这种方法是否高效?已经存在解决此类问题的算法吗?

算法的结果有任何要求吗?例如,热门趋势需要最少的数字数量是多少?你的想法是:如果给你这样一串数字 1 1 1 10 9 8 7 6 5 4 3 2 1 1 1... 它不会识别结尾,你会怎么做? - deviantfan
两个或三个算是热门。因此,上述序列将把10、9视为连续的。 - Maksim Kneller
2
你能否给出一个更精确的定义,来描述你认为的“热门”状态? - example
3个回答

4

好的。我已经尝试过了,但在开始之前,我必须说这不是基于任何算法(至少:我没有知ingly地基于现有算法),它存在一些缺陷(它不考虑负数/零),可能还有许多边缘情况需要解决。

为了找到两个数字之间的距离以确定它们是否相似,我发现了这个简单的公式

百分比差异=(L-S)/ S

其中L代表“最大值”,S代表“最小值”。

首先,对于1到40之间的50个值的5个随机序列的输出:

7 14 34 13 4 1 3 34 10 29 25 32 28 39 14 32 37 30 21 27 28 27 26 25 27 34 15 36 3 29 32 35 8 32 20 5 30 4 17 16 27 35 7 34 7 37 14 31 38 23 
Possible hot streak (treshold 0,95): 27 - 28 - 27
Possible hot streak (treshold 0,95): 28 - 27 - 26
Possible hot streak (treshold 0,95): 27 - 26 - 25

9 16 17 3 11 19 28 10 25 10 25 6 31 21 37 29 24 35 20 9 2 34 14 6 1 33 21 31 19 30 20 23 38 19 21 16 19 6 21 1 17 20 18 7 30 22 4 26 37 17 
Possible hot streak (treshold 0,8): 17 - 20 - 18

14 18 12 30 22 15 3 12 3 18 38 36 31 35 30 3 8 13 39 21 11 19 14 19 31 22 16 7 15 19 29 34 33 2 16 3 12 8 37 6 14 7 4 4 2 21 29 22 17 27 
Possible hot streak (treshold 0,8): 38 - 36 - 31
Possible hot streak (treshold 0,8): 36 - 31 - 35
Possible hot streak (treshold 0,8): 31 - 35 - 30
Possible hot streak (treshold 0,8): 29 - 34 - 33

14 31 26 16 6 35 5 32 38 39 38 35 36 24 29 4 3 29 20 28 31 39 15 34 8 4 15 11 18 11 32 34 30 28 5 38 9 17 35 21 37 19 9 37 8 18 11 20 14 37 
Possible hot streak (treshold 0,95): 38 - 39 - 38

18 39 3 29 36 14 17 32 9 3 20 33 15 28 8 5 6 9 19 30 35 25 34 38 30 13 30 17 27 29 33 35 36 20 33 33 31 2 31 30 21 16 9 33 2 5 4 21 30 3 
Possible hot streak (treshold 0,9): 33 - 35 - 36
Possible hot streak (treshold 0,9): 33 - 33 - 31

我采用的想法非常简单:给定一个项目列表,迭代它,从当前索引开始分组前3个,并查看它们是否在可接受的阈值范围内。如果是,则继续,直到找到当前阈值内的所有组合。如果没有符合设定阈值的组合,则将阈值减去0.05(即:更加宽松),并重新开始。

需要注意的是,该算法基本上是在序列中搜索规范化的值组。您可以通过在运行算法后计算被认为是热门连胜的3个值的总和,并获取该阈值中值的最大和来改进此算法。这应该给您最高的连胜。

因此,这个算法的作用是找到连胜,你所要做的就是找到热门连胜(这很琐碎)。

还有一些方面可以改进,只需采取周围值较低的序列,但这将取决于您想要将算法带到多远。

采用这种方法的好处之一是它已经部分实现了这一点(由于用于确定两个数字之间差异的公式,您会注意到序列通常在总数据集的较高部分)。

值3和2将返回0.5的百分比差,而值30和29将是0.03,因此后者将更快地被算法捕捉到。在这方面,您已经自动收集了热浪,但它没有考虑周围的值以获得更高的精度。

代码:

void Main()
{
    for(int i = 0; i < 5; i++){
        var list = GetList();
        DisplayList(list);
        GetHotStreaks(list);
    }
}

private static Random rand = new Random();

private List<int> GetList(){
    var list = new List<int>();

    for(int i = 0; i < 50; i++){
        list.Add(rand.Next(1, 40));
    }
    return list;
}

private void DisplayList(List<int> list){
    for(int i = 0; i < list.Count; i++){
        Console.Write(list[i] + " ");
    }
    Console.WriteLine();
}

private void GetHotStreaks(List<int> list){
    double treshold = 0.95;
    bool found = false;

    while(treshold > 0.0){
        for(int i = 0; i < list.Count - 2; i++){
            if(AreWithinRange(list[i], list[i + 1], list[i + 2], treshold)){
                Console.WriteLine (string.Format("Possible hot streak (treshold {0}): {1} - {2} - {3}", treshold, list[i], list[i + 1], list[i + 2]));
                found = true;
            }
        }

        if(found){
            Console.WriteLine ();
            return;
        }

        treshold -= 0.05;
    }   
}

private bool AreWithinRange(int val1, int val2, int val3, double treshold){
    return AreWithinRange(val1, val2, treshold) && AreWithinRange(val2, val3, treshold);
}

// http://www.oracle.com/webfolder/technetwork/data-quality/edqhelp/Content/processor_library/matching/comparisons/percent_difference.htm
private bool AreWithinRange(int val1, int val2, double treshold){
    double max = Math.Max(val1, val2);
    double min = Math.Min(val1, val2);
    double pd = (max - min) / min;

    //Console.WriteLine ("Values: val1: {0}\t val2: {1}\t PD: {2}\t T: {3}", val1, val2, pd, treshold);
    return pd <= 1 - treshold;
}

0

我认为你应该看一下FIR滤波器,特别是离散时间FIR滤波器。

基本上它们是你的算法的一个广义版本(如果我理解正确的话)。

你需要更严格地定义何时被认为是的连胜(如果你将其视为定性属性)。FIR滤波器在信号处理中已经相当成熟,并且(如果使用正确的参数)基本上会输出与当前连胜的热度相等的分数。

这假设您不对连胜长度施加任何严格限制,但您希望得到依赖于连胜长度的分数。

FIR还可以检测被打断的连胜,我不确定这是否符合您的用例要求。

我认为如果连胜没有那么突然开始,那么你的算法可能会有问题,因此标记连胜开始的阈值可能不会超过。


0

你的问题有点像股票交易员在寻找价格(通常还有成交量)意外上涨的股票时所寻找的。

移动平均线 简单移动平均线只是对过去n个数字进行平均。相比之下,指数移动平均线更加重视最近的数字而不是最初的数字。

我建议使用EMA与SMA的比率,比如比率大于2表示热潮来临。

也可以使用较短、移动速度较快的移动平均线与较长、移动速度较慢的移动平均线进行比较。当快速线穿过慢速线时,你可能会开始寻找热潮。

振荡器 振荡器可以告诉你价格是否处于其范围的顶部或底部。

我建议使用相对强度指数超过70表示热潮来临。


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