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

发布于 2024-12-25 21:19:20 字数 897 浏览 4 评论 0原文

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

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

到目前为止,我:

Dr. 的帮助下,尝试区分平滑后的价格设置。 Andrew Burnett-Thompson 使用中心五点法,如此处所述。

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

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

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

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

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

有人有更好的方法吗?

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

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

This question is a continuation of this one.

My goal is to find the turning points in stock price data.

So far I:

Tried differentiating the smoothed price set, with the help of Dr. Andrew Burnett-Thompson using the centered five-point method, as explained here.

I use the EMA20 of tick data for smoothing the data set.

For each point on the chart I get the 1st derivative (dy/dx).
I create a second chart for the turning points.
Each time the dy/dx is between [-some_small_value] and [+some_small_value] - I add a point to this chart.

The problems are:
I don't get the real turning points, I get something close.
I get too much or too little points - depening on [some_small_value]

I tried a second method of adding a point when dy/dx turns from negative to positive, which also creates too many points, maybe because I use EMA of tick data (and not of 1 minute closing price)

A third method is to divide the data set into slices of n points, and to find the minimum and maximum points. This works fine (not ideal), but it's lagging.

Anyone has a better method?

I attached 2 pictures of the output (1st derivative and n points min/max)

enter image description here
enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

兔姬 2025-01-01 21:19:20

您可以考虑二阶导数,这意味着您还应该(对于一阶导数)计算 (y_{i-1} + y_{i+1} - 2y_i) / (dx)²。如果高于某个阈值,则有一个最大值;如果低于某个阈值,则有一个最小值,否则可以丢弃它。这应该会丢弃您继续使用查找极值方法 (y' = 0) 的许多点,因为此条件对于鞍点也有效。

You could take the second derivative into account, meaning you should additionally (to your first derivative) evaluate (y_{i-1} + y_{i+1} - 2y_i) / (dx)². If this is above a certain threshold you have a maximum, if it is below you have a minimum and else you can discard it. This should throw out a lot of points that you keep using your method of finding extrema (y' = 0), because this condition is also valid for saddle points.

我一向站在原地 2025-01-01 21:19:20

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

对月度数据进行实验,得到以下结果(n=6)。 输入图片此处描述

Another approach based on some of the ideas here. For each point in the series, look at n points before and after (the window). If the value of the current point is the highest in the window, make it a peak turning point (if it lowest, make it a trough). Exclude the first and final n points in the series.

Experimented with monthly data and got the following with n=6. enter image description here

定格我的天空 2025-01-01 21:19:20

这只是一个想法,一个从不同角度来看的想法,而且可能是一个非常糟糕的想法,但由于差异化不起作用,所以类似的事情可能是一个想法。

首先,您需要确定最小有意义的 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]

实际上,这似乎工作得相当好。请随意分享想法。请注意,根据均值定理,这可能或多或少相当于微分。

Here's just an idea, sort of an idea from a different angle, and possibly a very bad idea, but since differentiation isn't working, something like this might be a thought.

First, you need to determine a minimum meaningful X-axis interval. In your figure, if you take this to be too small, you will get false positives from the bumps. This is conceptually similar to the idea of smoothing your data. Call this interval dx.

Next, using a sliding window of size dx, generate a moving average curve corresponding to your curve. There are lots of different ways you could think about doing this (to remove statistical outliers, or to use more or fewer points in the window). Call this curve g(x), and your original curve f(x). Additionally, make a curve h(x) which gives some measure of the variability of data in the sliding window which you use to compute g(x) (standard deviation should work fine if you're using a few points from the interval).

Now, begin computing curves of the form c_m(x) = |f(x) - g(x)| - m * h(x). You can start with m = 1. Any points x for which c_m(x) is positive are candidates for a local min/max. Depending on how many hits you get, you can begin increasing or decreasing m. You can do this in a way similar to binarys search: if you want more points, make m = (min + m) / 2, and if you want fewer points, make m = (max + m) / 2 (adjusting min and max accordingly).

So here's an example of what I'm suggesting. Let's say we have the following series:

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

We choose dx = 5. We construct g(x) by taking a simple average of the points around 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]

With m = 1 we get:

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]

This seems to have worked fairly well, actually. Feel free to share thoughts. Note that this might be more or less the equivalent of differentiation, given the mean value theorem.

风向决定发型 2025-01-01 21:19:20

帕特里克87 可以了,谢谢。以下是实现相同功能的 java 函数:

假设 StockPrices 有一个关键日期和值的映射 StockPrice (price,average where x = 5)

private double getCx(StockPrices stockPrices, LocalDateexecutionDate, 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;
}

That's works Patrick87, Thanks. Following are java function to implement the same:

Assume StockPrices has a map of key date and value StockPrice (price, average where 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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文