как определить поворотные моменты в данных о ценах акций - PullRequest
8 голосов
/ 11 января 2012

Этот вопрос является продолжением этого .

Моя цель - найти поворотные моменты в данных о ценах на акции.

Пока что я:

Попытка дифференцирования сглаженного набора цен с помощью Др. Эндрю Бернетт-Томпсон с использованием центрированного пятиточечного метода, как объяснено здесь .

Я использую EMA20 тиковых данных для сглаживания набора данных.

Для каждой точки на графике я получаю 1-ю производную (dy / dx). Я создаю второй график для поворотных точек. Каждый раз, когда dy / dx находится между [-some_small_value] и [+ some_small_value] - я добавляю точку к этой диаграмме.

Проблемы: У меня нет реальных поворотных моментов, я понимаю что-то близкое. Я получаю слишком много или слишком мало очков - в зависимости от [some_small_value]

Я попробовал второй способ добавления точки, когда dy / dx превращается из отрицательной в положительную, что также создает слишком много точек, возможно, потому, что я использую EMA данных тиков (а не цены закрытия 1 минуты)

Третий метод - разделить набор данных на куски из n точек и найти минимальные и максимальные точки. Это работает нормально (не идеально), но отстает.

У кого-нибудь есть лучший метод?

Я приложил 2 изображения вывода (1-я производная и n точек мин / макс)

enter image description here enter image description here

Ответы [ 3 ]

4 голосов
/ 11 января 2012

Вы можете принять во внимание второй производный, что означает, что вы должны дополнительно (к вашему первому производному) оценить (y_{i-1} + y_{i+1} - 2y_i) / (dx)². Если это выше определенного порога, у вас есть максимум, если он ниже, у вас есть минимум, иначе вы можете отменить его. Это должно отбрасывать много точек, которые вы продолжаете использовать, используя метод нахождения экстремумов (y' = 0), поскольку это условие также справедливо для седловых точек.

1 голос
/ 03 мая 2016

Это работает Patrick87, спасибо. Ниже приведены Java-функции для реализации того же:

Предположим, у StockPrices есть карта контрольной даты и значения StockPrice (цена, средняя где x = 5)

private double getCx (StockPrices stockPrices, LocalDate executeDate, int x, double m) { return Math.abs (getFx (stockPrices, executeDate) - getGx (stockPrices, executeDate)) - m * getHx (stockPrices, executeDate, 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;
}
1 голос
/ 11 января 2012

Это просто идея, своего рода идея под другим углом, и, возможно, очень плохая идея, но, поскольку дифференциация не работает, что-то вроде этого может быть мыслью.

Сначала необходимо определить минимальный значимый интервал по оси X. На вашей фигуре, если вы считаете, что это слишком мало, вы получите ложные срабатывания от ударов. Концептуально это похоже на идею сглаживания ваших данных. Назовите этот интервал дх.

Далее, используя скользящее окно размера dx, сгенерируйте кривую скользящего среднего, соответствующую вашей кривой. Есть много разных способов сделать это (удалить статистические выбросы или использовать больше или меньше точек в окне). Назовите эту кривую g (x), а исходную кривую f (x). Кроме того, создайте кривую h (x), которая дает некоторую меру изменчивости данных в скользящем окне, которое вы используете для вычисления g (x) (стандартное отклонение должно работать нормально, если вы используете несколько точек из интервала).

Теперь начнем вычислять кривые вида c_m (x) = | f (x) - g (x) | - м * ч (х). Вы можете начать с m = 1. Любые точки x, для которых c_m (x) положительна, являются кандидатами в локальные мин / макс. В зависимости от того, сколько хитов вы получите, вы можете начать увеличивать или уменьшать m. Вы можете сделать это аналогично поиску в binarys: если вы хотите больше точек, сделайте 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. Построим g (x), взяв простое среднее значение точек вокруг 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]

Похоже, это сработало довольно хорошо. Не стесняйтесь делиться мыслями. Обратите внимание, что это может быть более или менее эквивалентно дифференцированию, учитывая теорему о среднем значении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...