9

这个问题是这个问题的延续

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

到目前为止我:

在Andrew Burnett-Thompson 博士的帮助下,使用中心五点法尝试区分平滑的价格集,如此处所述

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

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

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

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

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

谁有更好的方法?

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

在此处输入图像描述 在此处输入图像描述

4

4 回答 4

4

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

于 2012-01-11T11:31:51.253 回答
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]

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

于 2012-01-11T15:20:44.937 回答
1

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

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

private double getCx(StockPrices stockPrices, LocalDate executionDate, int x, double m) { return 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;
}
于 2016-05-03T07:07:31.207 回答
0

另一种方法基于这里的一些想法。对于系列中的每个点,查看(窗口)之前和之后的 n 个点。如果当前点的值在窗口中最高,则将其设为峰值转折点(如果最低,则将其设为低谷)。排除序列中的第一个和最后一个 n 点。

对月度数据进行实验,得到以下 n=6 的数据。 在此处输入图像描述

于 2019-09-06T17:03:08.557 回答