рекомендации

суббота, 8 февраля 2020 г.

Прогнозирование котировок акций в Python

Перевод. Оригинал: Stock Prediction in Python

Попытка предсказать движение фондового рынка - заманчивая перспектива для исследователей данных, мотивирующихся не столько стремлением к материальной выгоде, сколько решением сложной задачи. Мы видим ежедневные взлеты и падения рынка и представляем, что должны быть паттерны, которые мы или наши модели, могут изучить, чтобы побить всех тех дей-трейдеров дня из бизнес школ. Естественно, когда я начал использовать аддитивные модели для прогнозирования временных рядов, мне пришлось протестировать этот метод на испытательном полигоне фондового рынка с симулированными котировками. Неизбежно, я присоединился ко многим другим, которые пытались обыграть рынок изо дня в день и потерпели неудачу. Однако, в процессе, я изучил тонкости Python, включая объектно-ориентированное программирование, манипулирование данными, моделирование и визуализацию.
Я также узнал, почему мы должны избегать ежедневной игры на фондовом рынке (все, что я могу сказать, нужно играть в длинную игру)!



Один день против 30 лет: на что бы вы предпочли поставить деньги?

Когда мы не достигаем немедленного успеха - в любой задаче, а не только в науке о данных - у нас есть три варианта:

1. Настроить результаты, чтобы они выглядели так, как будто мы добились успеха
2. Скрыть результаты, чтобы никто ничего не заметил
3. Показать все наши результаты и методы, чтобы другие (и мы сами) могли научиться делать что-то лучше

В то время как третий вариант является лучшим выбором на индивидуальном и общественном уровне, для его реализации требуется наибольшее мужество. Я могу выборочно выбирать диапазоны, когда моя модель приносит солидную прибыль, или я могу выбросить ее и притвориться, что никогда не тратил на это долгие часы. Это кажется довольно наивным! Мы продвигаемся, постоянно терпя неудачи и учась на ошибках, а не только продвигая наш успех. Более того, код Python, написанный для сложной задачи, не является кодом Python, написанным напрасно!

В этом посте описаны возможности прогнозирования Stocker, инструмента «анализа акций», который я разработал в Python. В предыдущей статье я показал, как использовать Stocker для анализа, и полный код доступен на GitHub для всех, кто хочет использовать его самостоятельно или внести свой вклад в проект.

Stocker

Stocker - это инструмент Python для исследования курсов ценных бумаг. Как только у нас установлены необходимые библиотеки (ознакомьтесь с документацией), мы можем запустить Jupyter Notebook в той же папке, что и скрипт, и импортировать класс Stocker:

from stocker import Stocker

Класс теперь доступен в нашей сессии. Мы создаем объект класса Stocker, передавая ему любой допустимый тикер (выводится жирным шрифтом):

amazon = Stocker('AMZN')

AMZN Stocker Initialized. Data covers 1997-05-16 to 2018-01-18.

Точно так же у нас есть 20 лет ежедневных данных об акциях Amazon для изучения! Stocker построен на основе финансовой библиотеки Quandl и содержит более 3000 акций. Мы можем сделать простой график истории акций, используя метод plot_stock:

amazon.plot_stock()

Maximum Adj. Close = 1305.20 on 2018-01-12.
Minimum Adj. Close = 1.40 on 1997-05-22.
Current Adj. Close = 1293.32.




Аналитические возможности Stocker можно использовать для нахождения общих тенденций и моделей в данных, но мы сосредоточимся на прогнозировании будущей цены. Прогнозы в Stocker делаются с использованием аддитивной модели, которая рассматривает временные ряды как комбинацию общего тренда вместе с сезонностями в разных временных масштабах, таких как ежедневный, еженедельный и ежемесячный. Stocker использует пакет prophet, разработанный Facebook для аддитивного моделирования. Создание модели и прогнозирование можно выполнить с помощью Stocker в одну строку:

# прогноз дневных цен
model, model_data = amazon.create_prophet_model(days=90)

Predicted Price on 2018-04-18 = $1336.98



Обратите внимание, что зеленая линия прогноза содержит доверительный интервал. Это отражает неопределенность модели в прогнозе. В этом случае ширина доверительного интервала устанавливается равной 80%, что означает, что мы ожидаем, что этот диапазон будет содержать фактические значения 80% общего времени. Доверительный интервал увеличивается во времени, потому что оценка имеет все большую неопределенность. Каждый раз, когда мы делаем прогноз, мы должны включать доверительный интервал. Хотя большинство людей стремятся получить простой ответ о будущем, наш прогноз должен отражать, что мы живем в неопределенном мире!

Любой может делать прогнозы по акциям: просто выберите число, и это будет ваша оценка (я могу ошибаться, но я почти уверен, что это делают все люди с Уолл-стрит). Чтобы доверять нашей модели, мы должны оценить ее на предмет точности. В Stocker существует ряд методов оценки точности модели.

Оценка прогнозов

Чтобы рассчитать точность, нам нужен тестовый набор и обучающий набор. Нам нужно знать ответы - фактическую цену акций - для тестового набора, поэтому мы будем использовать данные за прошлый год (в нашем случае 2017). При обучении мы не позволяем нашей модели видеть ответы на тестовом наборе, поэтому мы используем данные за три года до периода тестирования (2014–2016 гг.). Основная идея обучения с учителем заключается в том, что модель изучает паттерны и взаимосвязи в данных из обучающего набора, а затем может правильно воспроизводить их для тестовых данных.

Нам нужно дать количественную оценку нашей точности, поэтому мы используем прогнозы для тестового набора и фактические значения, рассчитываем метрики, включая среднюю ошибку в долларах на тестовом и обучающем наборах, процент времени, когда мы правильно предсказали направление изменения цены, и процент времени, когда фактическая цена попала в прогнозируемый 80% доверительный интервал. Все эти вычисления автоматически выполняются Stocker с хорошей визуализацией:

amazon.evaluate_prediction()

Prediction Range: 2017-01-18 to 2018-01-18.

Predicted price on 2018-01-17 = $814.77.
Actual price on    2018-01-17 = $1295.00.

Average Absolute Error on Training Data = $18.21.
Average Absolute Error on Testing  Data = $183.86.

When the model predicted an increase, the price increased 57.66% of the time.
When the model predicted a  decrease, the price decreased  44.64% of the time.

The actual value was within the 80% confidence interval 20.00% of the time.



Это ужасная статистика! С таким же успехом мы могли бы бросить монетку. Если бы мы использовали это для инвестирования, нам, вероятно, было бы лучше купить что-нибудь более разумное, например, лотерейные билеты. Однако пока не отказывайтесь от модели. Обычно мы ожидаем, что первая модель будет довольно плохой, потому что мы используем настройки по умолчанию (называемые гиперпараметрами). Если наши первоначальные попытки не увенчались успехом, мы можем повернуть эти ручки, чтобы сделать модель лучше. Существует ряд различных настроек, которые нужно отрегулировать в модели Prophet, причем наиболее важна априорная шкала изменения, которая контролирует вес, который модель придает смещению в тренде данных.

Выбор приоритета точек изменения

Точки изменения показывают, где временной ряд переходит от роста к падению или от постепенного роста к все более быстрому (или наоборот). Они имеют место в местах с наибольшим изменением скорости временных рядов. Приоритет таких точек представляет значимость, которая уделяется точкам изменения в модели. Это используется для контроля переобучения (также известное как смещение против компромисса).

Более высокий приоритет создает модель с большим весом в точках изменения и более гибкой подгонкой. Это может привести к переобучению, потому что модель будет тесно привязана к данным обучения и не сможет обобщать новые данные. Понижение приоритета уменьшает гибкость модели, что может вызвать противоположную проблему: недостаточное обучение. Это происходит, когда наша модель недостаточно внимательно следит за обучающими данными и не может изучить базовые паттерны. Выяснение правильных настроек для достижения правильного баланса - это больше вопрос техники, чем теории, и здесь мы должны полагаться на эмпирические результаты. Класс Stocker содержит два разных способа выбора подходящего приоритета: визуально и количественно. Мы можем начать с графического метода:

# приоритеты точек изменения - это список точек изменения для оценки
amazon.changepoint_prior_analysis(changepoint_priors=[0.001, 0.05, 0.1, 0.2])



Здесь мы обучаемся данным за три года, а затем показываем прогнозы на шесть месяцев. Мы не определяем количество прогнозов здесь, потому что мы просто пытаемся понять роль приоритета точки изменения. Этот график отлично иллюстрирует переобучение! Самый низкий приоритет, синяя линия, не очень внимательно следит за обучающими данными (черные точки). Он как бы делает свое дело и выбирает маршрут через общую окрестность данных. Напротив, высший приоритет, желтая линия, как можно ближе придерживается обучающих наблюдений. Значение по умолчанию для точки изменения - 0,05, которое находится где-то посередине между двумя крайностями.

Обратите внимание также на разницу в неопределенности (заштрихованные интервалы) для приоритета. Наименьшее значение имеет наибольшую неопределенность обучающих данных, но наименьшую неопределенность тестовых данных. Напротив, самый высокий приоритет имеет наименьшую неопределенность в данных обучения, но наибольшую неопределенность в данных испытаний. Чем выше приоритет, тем увереннее алгоритм на обучающих данных, поскольку он внимательно следит за каждым наблюдением. Однако, когда дело доходит до тестовых данных, модель теряется без каких-либо точек данных для ее привязки. Поскольку курсы акций имеют небольшую изменчивость, мы, вероятно, захотим иметь более гибкую модель, чем модель по умолчанию, чтобы она могла охватить как можно больше паттернов.

Теперь, когда у нас есть представление о влиянии приоритета, мы можем численно оценить различные значения, используя обучающий и тестовый наборы:

amazon.changepoint_prior_validation(start_date='2016-01-04', end_date='2017-01-03', changepoint_priors=[0.001, 0.05, 0.1, 0.2])

Validation Range 2016-01-04 to 2017-01-03.

cps  train_err  train_range    test_err  test_range
0.001  44.507495   152.673436  149.443609  153.341861
0.050  11.207666    35.840138  151.735924  141.033870
0.100  10.717128    34.537544  153.260198  166.390896
0.200   9.653979    31.735506  129.227310  342.205583

Здесь мы должны быть осторожны, чтобы наши данные валидации не совпадали с нашими тестовыми данными. Если бы это было так, мы бы создали лучшую модель для тестовых данных, но тогда мы просто переобучили бы тестовые данные, и наша модель не смогла бы перейти на реальные данные. В целом, как это обычно делается в науке о данных, мы используем три различных набора данных: обучающий набор (2013–2015), набор валидации (2016) и тестовый набор (2017).

Мы оценили четыре приоритета с четырьмя показателями: ошибка обучения, диапазон обучения (доверительный интервал), ошибка тестирования и диапазон тестирования (доверительный интервал) со всеми значениями в долларах. Как мы видели на графике, чем выше приоритет, тем ниже ошибка обучения и тем ниже погрешность обучающих данных. Мы также видим, что более высокий приоритет уменьшает нашу ошибку тестирования, подкрепляя нашу интуицию тем, что тесное соответствие с данными является хорошей идеей для акций. В обмен на большую точность в тестовом наборе мы получаем больший диапазон неопределенности в тестовых данных с увеличением приоритета.

Валидация приоритета Stocker также отображает два графика, иллюстрирующие эти моменты:




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

# проверяем больший приоритет в одном и том же диапазоне проверки
amazon.changepoint_prior_validation(start_date='2016-01-04', end_date='2017-01-03', changepoint_priors=[0.15, 0.2, 0.25,0.4, 0.5, 0.6])



Ошибка тестового набора сводится к минимуму при приоритете 0,5. Мы установим атрибут changepoint prior объекта Stocker соответствующим образом.

amazon.changepoint_prior_scale = 0.5

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

Оценка уточненной модели

Теперь, когда наша модель оптимизирована, мы можем снова оценить ее:

amazon.evaluate_prediction()

Prediction Range: 2017-01-18 to 2018-01-18.

Predicted price on 2018-01-17 = $1164.10.
Actual price on    2018-01-17 = $1295.00.

Average Absolute Error on Training Data = $10.22.
Average Absolute Error on Testing  Data = $101.19.

When the model predicted an increase, the price increased 57.99% of the time.
When the model predicted a  decrease, the price decreased  46.25% of the time.

The actual value was within the 80% confidence interval 95.20% of the time.



Это выглядит лучше! Это показывает важность оптимизации модели. Использование значений по умолчанию дает разумное первое предположение, но мы должны быть уверены, что используем правильные «настройки» модели, точно так же, как мы пытаемся оптимизировать звучание стереозвука путем регулировки баланса и затухания.

Игра на фондовом рынке

Прогнозирование - интересное упражнение, но самое интересное - посмотреть, насколько хорошо эти прогнозы будут реализованы на реальном рынке. Используя метод valu_prediction, мы можем «играть» на фондовом рынке, используя нашу модель в течение периода оценки. Мы будем использовать стратегию, основанную на нашей модели, которую мы затем сможем сравнить с простой стратегией покупки и удержания акций в течение всего периода.

Правила нашей стратегии просты:

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

Мы играем каждый день в течение всего периода оценки, который в нашем случае равен 2017 году. Чтобы играть, добавьте количество акций к вызову метода. Stocker расскажет нам, как сработает стратегия, в цифрах и графиках:

# Going big 
amazon.evaluate_prediction(nshares=1000)

Вы играли на фондовом рынке с акциями AMZN с 2017-01-18 по 2018-01-18 с 1000 акциями.

When the model predicted an increase, the price increased 57.99% of the time.
When the model predicted a  decrease, the price decreased  46.25% of the time.

The total profit using the Prophet model = $299580.00.
The Buy and Hold strategy profit =         $487520.00.

Thanks for playing the stock market!



Это дает нам ценный урок: купи и держи! Несмотря на то, что мы бы заработали значительную сумму, играя в нашу стратегию, лучше было бы просто инвестировать в долгосрочной перспективе.

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

Всегда играйте не на реальном счете!




Я знал, что наша модель может сделать это! Тем не менее, наша модель выиграла у рынка только тогда, когда мы имели возможность задним числом выбрать тестовый период.

Прогнозы на будущее

Теперь, когда мы удовлетворены тем, что у нас есть достойная модель, мы можем делать прогнозы, используя метод gnast_future ().

amazon.predict_future(days=10)
amazon.predict_future(days=100)




Модель Amazon в целом оптимистична, как и большинство «профессионалов». Кроме того, неопределенность возрастает по мере того, как мы делаем оценки, как и ожидалось. В действительности, если бы мы использовали эту модель для активной торговли, мы бы обучали новую модель каждый день и делали прогнозы максимум на один день в будущем.

Хотя мы не сможем разбогатеть на инструменте Stocker, выгода заключается в разработке, а не в конечных результатах! На самом деле мы не можем знать, сможем ли мы решить проблему, пока не попробуем, но лучше попробовать и потерпеть неудачу, чем никогда не пытаться вообще! Для тех, кто заинтересован в проверке кода или использовании Stocker, он доступен на GitHub.

Комментариев нет:

Отправка комментария