Примечание: эта статья указывает на устаревшую версию Quantiacs. Пожалуйста, ознакомьтесь с более свежими материалами о новой версии Quantiacs: начать работу, простой алгоритм биткойнов, пример машинного обучения и оптимизатор.
В предыдущих статьях мы показали, как реализовать простые торговые стратегии в Quantiacs. Здесь мы описываем реализацию алгоритма, использующего методы машинного обучения.
Набор инструментов Python Quantiacs позволяет использовать методы машинного обучения для написания торговых алгоритмов. Мы описываем пример, основанный на keras, и используем модель долгосрочной краткосрочной памяти (LSTM) для прогнозирования временных рядов.
Все системные файлы Quantiacs должны содержать определение настроек:
def mySettings(): settings = {} settings['markets'] = ['F_ES'] settings['slippage'] = 0.05 settings['budget'] = 1000000 settings['lookback'] = 504 settings['beginInSample'] = '20140101' settings['endInSample'] = '20170101' return settings
Эти настройки определяют один актив для торговли, фьючерс на индекс E-Mini S&P 500, устанавливают проскальзывание равным 5% дневного диапазона актива, фиксируют начальный капитал на уровне 1 млн долларов США, определяют период ретроспективного анализа в 504 дня и установите начальный и конечный дни симуляции.
Кроме того, мы определяем вспомогательную функцию, которая создает и обучает сеть LSTM. Первым делом импортируем необходимые модули:
import numpy as np from keras.models import Sequential from keras.layers import Dense from keras.layers import LSTM import tensorflow as tf
Далее мы определяем функцию:
def createAndTrain(DATE, CLOSE, settings): lst_dates = DATE.tolist() lst_dates = lst_dates[1:] price_data = CLOSE[1:, :] average = np.average(price_data) std_dev = np.std(price_data) price_data = (price_data - average) / std_dev return_data = (CLOSE[1:, :] - CLOSE[:- 1, :]) / CLOSE[:- 1, :] # define training set and target: trainX = np.reshape(price_data, (price_data.shape[0], 1, price_data.shape[1])) trainY = return_data # create and fit the LSTM network: model = Sequential() model.add(LSTM(4, input_dim=1)) model.add(Dense(1)) model.compile(loss='mean_squared_error', optimizer='adam') model.fit(trainX, trainY, epochs=100, batch_size=1, verbose=0) settings['mean'] = average settings['std'] = std_dev settings['model'] = model return
Функция выполняет контролируемое обучение, определяя обучающий набор, в котором функции являются нормализованными ценами ЗАКРЫТИЯ активов. Нормализация происходит путем вычитания из CLOSE среднего значения и деления на стандартное отклонение. Целевая переменная представлена относительной доходностью активов.
Затем он создает сеть LSTM и согласовывает ее с обучающим набором. Функция расширяет настройки торговой системы, определяя три новых объекта:
settings['mean'] = average settings['std'] = std_dev settings['model'] = model
которые используются торговой системой.
Торговая логика определяется функцией торговой системы:
def myTradingSystem(DATE, CLOSE, exposure, equity, settings): lookBack = settings['lookback'] if 'model' not in settings: createAndTrain(DATE[:lookBack - 2], CLOSE[:lookBack - 2], settings) model = settings['model'] average = settings['mean'] std_dev = settings['std'] testX = (CLOSE[lookBack-1:] - average) / std_dev testX = np.reshape(testX, (testX.shape[0], 1, testX.shape[1])) testY = model.predict(testX) newDelta = testY[0] nMarkets = CLOSE.shape[1] pos = np.ones((1, nMarkets)) if newDelta >= 0: pos[0] = 1 else: pos[0] = -1 return pos, settings
Торговая система вызывает вспомогательную функцию, которая строит модель, используя срез данных, а затем применяет модель для прогнозирования относительной доходности. Если прогнозируемая доходность положительна, система открывает длинную позицию, в противном случае - короткую.
Основной вызов функции:
if __name__ == '__main__': from quantiacsToolbox import runts inter_op_parallelism_threads = 1 tf.random.set_seed(1) results = runts(__file__)
Та же логика определения вспомогательной функции для выполнения промежуточных операций может использоваться для более простых методов, таких как выполнение линейной регрессии.
Если вас интересует статистика и машинное обучение, и вы хотите проверить свои идеи на мировых финансовых рынках, отправьте свой код до конца 2020 года и примите участие в конкурсе Q14 на Quantiacs!
Полная стратегия
import numpy as np from keras.models import Sequential from keras.layers import Dense from keras.layers import LSTM import tensorflow as tf def createAndTrain(DATE, CLOSE, settings): lst_dates = DATE.tolist() lst_dates = lst_dates[1:] price_data = CLOSE[1:, :] average = np.average(price_data) std_dev = np.std(price_data) price_data = (price_data - average) / std_dev return_data = (CLOSE[1:, :] - CLOSE[:- 1, :]) / CLOSE[:- 1, :] # define training set and target: trainX = np.reshape(price_data, (price_data.shape[0], 1, price_data.shape[1])) trainY = return_data # create and fit the LSTM network: model = Sequential() model.add(LSTM(4, input_dim=1)) model.add(Dense(1)) model.compile(loss='mean_squared_error', optimizer='adam') model.fit(trainX, trainY, epochs=100, batch_size=1, verbose=0) settings['mean'] = average settings['std'] = std_dev settings['model'] = model return def myTradingSystem(DATE, CLOSE, exposure, equity, settings): lookBack = settings['lookback'] if 'model' not in settings: createAndTrain(DATE[:lookBack - 2], CLOSE[:lookBack - 2], settings) model = settings['model'] average = settings['mean'] std_dev = settings['std'] testX = (CLOSE[lookBack-1:] - average) / std_dev testX = np.reshape(testX, (testX.shape[0], 1, testX.shape[1])) testY = model.predict(testX) newDelta = testY[0] nMarkets = CLOSE.shape[1] pos = np.ones((1, nMarkets)) if newDelta >= 0: pos[0] = 1 else: pos[0] = -1 return pos, settings def mySettings(): settings = {} settings['markets'] = ['F_ES'] settings['slippage'] = 0.05 settings['budget'] = 1000000 settings['lookback'] = 504 settings['beginInSample'] = '20140101' settings['endInSample'] = '20170101' return settings if __name__ == '__main__': from quantiacsToolbox import runts inter_op_parallelism_threads = 1 tf.random.set_seed(1) results = runts(__file__)