Привет, это моя первая статья о среде, и спасибо, что решили ее прочитать. Меня зовут Виктор, и я энтузиаст в мире машинного обучения и глубокого обучения. Весь код, использованный в статье, будет находиться в репозитории гитхаб. Подробно описывать не буду, приведу только основные сокращения кода с небольшими комментариями, чтобы он был быстрее и понятнее. Так как код лучше.
Статья носит исключительно ознакомительный характер и категорически не способствует применению в реальной торговле!
Сегодня мы рассмотрим, как применять двунаправленный LSTM для прогнозирования направления цены закрытия следующего дня акций Microsoft (MSFT).
Я предпочитаю использовать env-файл anaconda и yml со всеми зависимостями. Вы можете найти этот файл в репозитории.
Сначала нам нужно загрузить данные из файла csv и нормализовать цену открытия и закрытия с помощью MinMaxScaler.
Хотелось бы посмотреть, как выглядит разница между логарифмами цен закрытия. Мы не будем использовать эти данные в этой статье, но они могут быть очень полезны при классификации прогнозных данных для более чистых сигналов.
давайте посмотрим на наш тестовый сплит:
Накапливайте каждые 50 дневных баров и функцию подготовки данных с помощью вычислителя ema.
Следующим шагом делаем модель. Я предпочитаю разбивать данные разной природы и объединять на последних этапах
Параметры для наших моделей
len = 50 test_size = 0.2 neurons = 100 epochs = 10 batch_size = 32 loss = 'mse' dropout = 0.2 optimizer = 'adam'
Постепенно получайте данные для обучения и тестирования и тренируйте нашу модель
_train, x_test, x_open_train, x_open_test, y_train, y_test, x_tech_train, x_tech_test = prepare_data(df.values, target_col, len, test_size) print(x_train.shape) # (3988, 50, 5) print(x_test.shape) # (996, 50, 5) print(x_open_train.shape) # (3988, 1) print(x_open_test.shape) # (996, 1) print(x_tech_train.shape) # (3988, 5) print(x_tech_test.shape) # (996, 5) y_train = np.array(y_train).reshape(1, -1).squeeze() y_test = np.array(y_test).reshape(1, -1).squeeze() print(y_train.shape) # (3988,) print(y_test.shape) # (996,)
Обучение…
model = build_lstm_model(x_train, x_tech_train, x_open_train, output_size=1, neurons=neurons, dropout=dropout, loss=loss, optimizer=optimizer) history = model.fit(x=[x_train, x_tech_train, x_open_train], y=y_train, epochs=epochs, batch_size=batch_size, verbose=1, shuffle=True, validation_split=0.05) Train on 3788 samples, validate on 200 samples Epoch 1/10 3788/3788 [==============================] - 26s 7ms/step - loss: 0.0145 - val_loss: 6.3099e-04 Epoch 2/10 3788/3788 [==============================] - 23s 6ms/step - loss: 4.3845e-04 - val_loss: 1.8132e-04 Epoch 3/10 3788/3788 [==============================] - 23s 6ms/step - loss: 3.4634e-04 - val_loss: 1.5705e-04 Epoch 4/10 3788/3788 [==============================] - 27s 7ms/step - loss: 2.8954e-04 - val_loss: 1.1994e-04 Epoch 5/10 3788/3788 [==============================] - 29s 8ms/step - loss: 2.4499e-04 - val_loss: 1.1416e-04 Epoch 6/10 3788/3788 [==============================] - 37s 10ms/step - loss: 2.2312e-04 - val_loss: 1.0454e-04 Epoch 7/10 3788/3788 [==============================] - 26s 7ms/step - loss: 1.9670e-04 - val_loss: 1.3416e-04 Epoch 8/10 3788/3788 [==============================] - 25s 7ms/step - loss: 1.9615e-04 - val_loss: 1.2558e-04 Epoch 9/10 3788/3788 [==============================] - 28s 7ms/step - loss: 1.8774e-04 - val_loss: 8.5019e-05 Epoch 10/10 3788/3788 [==============================] - 25s 7ms/step - loss: 1.8120e-04 - val_loss: 8.2655e-05
Рассчитать ошибку
preds = model.predict([x_test, x_tech_test, x_open_test]).squeeze() mean_absolute_error(preds, y_test) 0.011188932196784048
позволяет увидеть реальную цену закрытия с прогнозируемыми ценами
close_real_normallized = close_price_scaller.inverse_transform(y_test.reshape(-1, 1)) close_pred_normallized = close_price_scaller.inverse_transform(preds.reshape(-1, 1)) fig, ax = plt.subplots(1, figsize=(70, 15)) ax.plot(close_real_normallized, label='actual', linewidth=2) ax.plot(close_pred_normallized, label='prediction', linewidth=2) ax.set_ylabel('price', fontsize=14) ax.set_title('title', fontsize=16) ax.legend(loc='best', fontsize=16);
давай пофантазируем немного
Теперь мы можем посчитать, сколько денег принесет нам наша модель.
pred_bi_direct =[0] for index in range(1, len(close_pred_normallized)): prev_pred = close_pred_normallized[index-1] pred = close_pred_normallized[index] delta_pred = prev_pred - pred pred_bi_direct.append(1 if delta_pred < 0 else -1) balance_story = calculate_profit()
Ой ... Но давайте посмотрим на это под другим углом. На этом графике есть система, в ней нет хаоса. Итак, давайте немного обманем
pred_bi_direct =[0] for index in range(1, len(close_pred_normallized)): prev_pred = close_pred_normallized[index-1] pred = close_pred_normallized[index] delta_pred = prev_pred - pred pred_bi_direct.append(-1 if delta_pred < 0 else -1) balance_story = calculate_profit()
Конечно, этот расчет очень приблизительный, он не учитывает комиссию брокера и другие расходы. Но я полагаю, что если вы добавите прогнозные данные и их классифицируете, это может дать интересные более четкие результаты.
Бонус, еще одна акция:
Спасибо, что дочитали эту статью до конца. Очень надеюсь, что он оказался для вас интересным и полезным. Если у вас возникнут вопросы, вы можете связаться со мной:
телеграмма: @Oladushkin
Вы можете найти другие мои эксперименты: kaggle