如何识别股票价格数据的转折点

时间:2012-01-11 11:20:33

标签: algorithm math differential-equations

这个问题是this one的延续。

我的目标是找到股票价格数据的转折点。

到目前为止我:

尝试使用居中的五点方法在Dr. Andrew Burnett-Thompson的帮助下区分平滑的价格集,如here所述。

我使用刻度数据的EMA20来平滑数据集。

对于图表上的每个点,我得到一阶导数(dy / dx)。 我为转折点创建了第二张图表。 每次dy / dx介于[-some_small_value]和[+ some_small_value]之间时 - 我都会在此图表中添加一个点。

问题是:   我没有得到真正的转折点,我得到了一些接近的东西。   我得分太多或太少 - 取决于[some_small_value]

我尝试了第二种方法,当dy / dx从负变为正时添加一个点,这也会创建太多点,可能是因为我使用了刻度数据的EMA(而不是1分钟的收盘价)

第三种方法是将数据集分成n个点的切片,并找到最小和最大点。这工作正常(不理想),但它是滞后的。

任何人都有更好的方法吗?

我附上了2张输出图片(一阶导数和n点最小值/最大值)

enter image description here enter image description here

4 个答案:

答案 0 :(得分:4)

您可以考虑二阶导数,这意味着您应该另外(对于您的一阶导数)评估(y_{i-1} + y_{i+1} - 2y_i) / (dx)²。如果这超过某个阈值,你有一个最大值,如果它低于你有一个最小值,否则你可以丢弃它。这应该抛出你使用查找极值(y' = 0)的方法的许多要点,因为这个条件对于鞍点也是有效的。

答案 1 :(得分:1)

这只是一个想法,从一个不同的角度出发,可能是一个非常糟糕的想法,但由于差异化不起作用,这样的事情可能是一个想法。

首先,您需要确定最小有意义的X轴间隔。在你的图中,如果你认为它太小,你会从颠簸中得到误报。这在概念上类似于平滑数据的想法。将此时间间隔称为dx。

接下来,使用大小为dx的滑动窗口,生成与曲线对应的移动平均曲线。有很多不同的方法可以考虑这样做(删除统计异常值,或在窗口中使用更多或更少的点)。将此曲线称为g(x),并将原始曲线称为f(x)。另外,制作一个曲线h(x),它可以用来计算滑动窗口中数据的可变性,用于计算g(x)(如果你使用间隔中的几个点,标准偏差应该可以正常工作)。

现在,开始计算c_m(x)= | f(x) - g(x)|形式的曲线 - m * h(x)。您可以从m = 1开始。任何c_m(x)为正的点x都是本地最小值/最大值的候选值。根据您获得的点击次数,您可以开始增加或减少m。您可以通过类似于二进制搜索的方式执行此操作:如果您想要更多的点,请使m =(min + m)/ 2,如果您想要更少的点,请使m =(max + m)/ 2(调整min和相应地最大)。

所以这是我所建议的一个例子。假设我们有以下系列:

f(x) = [  1,   2,   4,   3,   2,   3,   6,   7,   8,   7, 
          5,   4,   3,   2,   2,   3,   2,   3,   5,   8,   9]

我们选择dx = 5.我们通过采用x周围点的简单平均值来构造g(x):

g(x) = [2.3, 2.5, 2.4, 2.8, 3.6, 4.2, 5.2, 6.2, 6.6, 6.2, 
        5.4, 4.2, 3.2, 2.8, 2.4, 2.4, 3.0, 4.2, 5.4, 6.3, 7.3]

h(x) = [1.2, 1.1, 1.0, 0.7, 1.4, 2.4, 2.3, 1.7, 1.0, 1.5,
        1.9, 1.7, 1.2, 0.7, 0.5, 0.6, 1.1, 2.1, 2.7, 2.4, 1.7]

当m = 1时,我们得到:

c(x) = [0.1, xxx, 0.6, xxx, 0.2, xxx, xxx, xxx, 0.4, xxx,
        xxx, xxx, xxx, 0.1, xxx, 0.0, xxx, xxx, xxx, xxx, 0.0]

实际上,这似乎运作得相当好。随意分享想法。请注意,考虑到平均值定理,这可能或多或少等同于区分。

答案 2 :(得分:1)

这是有效的Patrick87,谢谢。以下是java函数实现相同:

假设StockPrices有一个关键日期和价值StockPrice的地图(价格,平均值,其中x = 5)

private double getCx(StockPrices stockPrices,LocalDate executionDate,int x,double m){         返回Math.abs(getFx(stockPrices,executionDate) - getGx(stockPrices,executionDate)) - m * getHx(stockPrices,executionDate,x);     }

private double getGx(StockPrices stockPrices, LocalDate executionDate) {
    return stockPrices.getAvg(executionDate, 5);
}

private double getFx(StockPrices stockPrices, LocalDate executionDate) {
    return stockPrices.getPrice(executionDate);
}

public double getHx(StockPrices stockPrice, LocalDate localDate, int x) {
    //standard deviation
    return Math.sqrt(getVariance(stockPrice, localDate, x));
}

private double getVariance(StockPrices stockPrice, LocalDate localDate, int x) {
    double sum = 0;
    int count = 0;
    for (int i = - (x / 2); i <= (x / 2) ; i++) {
        LocalDate date = localDate.with(BusinessDay.add(localDate, i, stockPrice.getPriceMap(), 2));
        double avg = stockPrice.getAvg(date, 5);
        double price = stockPrice.getPrice(date);
        if (price != 0.0) {
            sum += Math.pow((price - avg), 2);
            count++;
        }
    }
    return sum / count;
}

答案 3 :(得分:0)

基于此处某些思想的另一种方法。对于序列中的每个点,请查看窗口前后的n个点。如果当前点的值在窗口中最高,则使其成为峰值拐点(如果最低,则使其成为低谷)。排除系列中的第一个和最后一个n点。

使用月度数据进行了实验,得出以下结果,n = 6。 enter image description here