这个问题是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点最小值/最大值)
答案 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)