Эта статья была вдохновлена наблюдениями за некоторыми распространенными предостережениями и ловушками после того, как я попытался применить технологии машинного обучения к торговым проблемам во время исследования данных на квантовой платформе изобретателей.
Если вы еще не читали мою предыдущую статью, мы рекомендуем вам прочитать мою руководство по автоматизированной среде исследования данных, созданной на квантовой платформе изобретателей, и систематические методы разработки стратегии торговли.
Вот его адрес:https://www.fmz.com/digest-topic/4187иhttps://www.fmz.com/digest-topic/4169 这两篇文章.
Этот учебник предназначен для любителей, инженеров и ученых данных всех уровней навыков. Независимо от того, являетесь ли вы крупным бизнесменом или маленьким программистом, единственные навыки, которые вам понадобятся, - это базовое знание языка программирования Python и достаточное знание командной строки (для того, чтобы настроить проект в области науки о данных).
发明者量化平台FMZ.COM除了提供优质的各大主流交易所的数据源,还提供一套丰富的API接口以帮助我们在完成数据的分析后进行自动化交易。这套接口包括查询账户信息,查询各个主流交易所的高,开,低,收价格,成交量,各种常用技术分析指标等实用工具,特别是对于实际交易过程中连接各大主流交易所的公共API接口,提供了强大的技术支持。
Все эти характеристики, упомянутые выше, упакованы в систему, похожую на Docker, и мы должны просто купить или арендовать свою собственную облачную службу, чтобы завершить развертывание этой системы.
В официальном названии платформы количественного измерения изобретателей система Docker называется системой хостеров.
Для того, чтобы узнать, как развернуть хостеров и ботов, обратитесь к моей предыдущей статье:https://www.fmz.com/bbs-topic/4140
Читатели, которые хотят купить хост для развертывания собственных облачных серверов, могут ознакомиться с этой статьей:https://www.fmz.com/bbs-topic/2848
После успешного развертывания хороших облачных сервисов и систем хостеров, следующим шагом будет установка самого большого храма Python: Anaconda.
Для реализации всех необходимых программных условий ("зависимость библиотеки, управление версиями и т. д.) самый простой способ - использовать Anaconda.
Поскольку мы устанавливаем Anaconda на облачных сервисах, мы рекомендуем установить на облачных серверах версию Anaconda с командной строкой для Linux-систем.
О том, как установить Anaconda, читайте в официальном руководстве:https://www.anaconda.com/distribution/
Если вы опытный программист Python и не чувствуете необходимости использовать Anaconda, это совершенно нормально. Я бы предположил, что вам не нужна помощь при установке необходимых зависимостей, вы можете просто перейти к этому разделу.
Окончательный результат стратегии торговли должен отвечать на следующие вопросы:
Направление: определить, дешевы ли активы, дороги ли или справедливы.
开仓条件:如果资产价格便宜或者昂贵,你应该做多或者做空.
Бронирование: если цена актива разумна, и мы имеем позиции в этом активе (предыдущие покупки или продажи), следует ли вам бронировать
Ценовой диапазон: цена (или диапазон) для проведения открытых торгов
Количество: количество средств, с которыми торгуется (например, количество цифровых валют или количество рук на товарные фьючерсы)
Машинное обучение может быть использовано для ответа на каждый из этих вопросов, но для остальной части статьи мы сосредоточимся на ответе на первом вопросе - направлении торговли.
Существуют два типа методов построения стратегии, один - на основе модели; другой - на основе добычи данных.
В моделируемой стратегии мы начинаем с модели низкой эффективности рынка, где мы строим математические выражения (например, цены, доходы) и проверяем их эффективность на более длительных временных циклах. Эта модель обычно является упрощенной версией действительно сложной модели, которая требует проверки ее смысла и стабильности на более длительных циклах.
С другой стороны, мы сначала ищем ценовые модели и пытаемся использовать алгоритмы в методах извлечения данных. Причины, вызывающие эти модели, не имеют значения, поскольку только определенные модели будут продолжать повторяться в будущем. Это слепой метод анализа, который требует тщательной проверки, чтобы идентифицировать истинные модели из случайных моделей.
Очевидно, что машинное обучение легко применимо к методам добычи данных. Давайте посмотрим, как использовать машинное обучение для создания торговых сигналов с помощью добычи данных.
Примеры кода используют рецензирующие инструменты и автоматизированные API-интерфейсы для транзакций, основанные на квантовой платформе изобретателей. После того, как вы полностью развернете хост и установите Anaconda, вам нужно просто установить необходимую нам аналитическую базу данных и известную модель машинного обучения scikit-learn.
pip install -U scikit-learn
Перед тем, как мы начнем, стандартная система задач машинного обучения показывает следующий рисунок:
Система задач машинного обучения
Характеристики, которые мы собираемся создать, должны иметь некоторую предсказательную способность (X), мы хотим предсказать целевые переменные (Y), и использовать исторические данные для обучения ML-моделей, которые могут предсказывать Y как можно ближе к фактическому значению. Наконец, мы используем эту модель для предсказания новых неизвестных данных Y. Это приводит нас к первому шагу:
То есть, в нашей структуре выше, что такое Y?
Что вы хотите предсказать?
Хотите ли вы предсказать будущие цены, будущую рентабельность/Pnl, сигналы покупки/продажи, оптимизировать распределение портфеля и пытаться эффективно выполнять сделки?
Предположим, что мы пытаемся предсказать цену на следующем временном счете. В этом случае Y ((t) = цена ((t + 1)). Теперь мы можем завершить нашу структуру с историческими данными.
Обратите внимание, что Y (t) известна только в ретроспекции, но когда мы используем нашу модель, мы не будем знать цену t в то время t (t + 1). Мы используем нашу модель для прогнозирования Y (предсказанное, t) и сравниваем его с фактическим значением только в то время t + 1; это означает, что вы не можете использовать Y в качестве характеристики в модели прогнозирования.
Как только мы знаем цель Y, мы также можем решить, как оценить наши прогнозы. Это очень важно для различения различных моделей данных, с которыми мы будем пробовать. В зависимости от проблемы, которую мы решаем, выберите показатель, который измеряет эффективность нашей модели. Например, если мы прогнозируем цену, мы можем использовать погрешность уравнительного корня в качестве показателя.
ML Framework для прогнозирования будущих цен
Для демонстрации мы создадим прогнозирующую модель, которая будет предсказывать будущее ожидаемое значение базового показателя предполагаемого инвестиционного показателя, в котором:
basis = Price of Stock — Price of Future
basis(t)=S(t)−F(t)
Y(t) = future expected value of basis = Average(basis(t+1),basis(t+2),basis(t+3),basis(t+4),basis(t+5))
Поскольку это проблема регрессии, мы будем оценивать модель на RMSE (отклонение от корня); мы также будем использовать Total Pnl в качестве критерия оценки.
Примечание: для знаний по математике RMSE, пожалуйста, обратитесь к соответствующей информации в Википедии
Сбор и очистка данных, которые помогут вам решить проблему
Если мы прогнозируем цены, вы можете использовать данные о ценах на инвестиционные индексы, объемах сделок на инвестиционные индексы, аналогичные данные на соответствующие инвестиционные индексы, показатели инвестиционных индексов на рынке в целом, цены на другие соответствующие активы и т. д.
Вам необходимо установить для этого права доступа к данным, убедиться, что ваши данные точны и не ошибаются, и решить проблемы с потерянными данными ("очень распространенные проблемы"), а также убедиться, что ваши данные непредвзяты и полностью представляют все рыночные условия ("например, одинаковое количество сценариев прибыли и убытка"), чтобы избежать отклонений в модели.
Если вы используете квантовую платформу изобретателяFMZ.COMМы можем получить доступ к бесплатным глобальным данным от Google, Yahoo, NSE и Quandl; глубокие данные о внутренних товарных фьючерсах, таких как CTP и EOS; данные о основных цифровых валютных биржах, таких как Binance, OKEX, Huobi и BitMex.
Для упрощения демонстрации мы использовали следующие данные в качестве кубиков MQK для виртуальных инвестиционных показателей, а также очень удобный инструмент количественного измерения Auquan Curve Toolbox.https://github.com/Auquan/auquan-toolbox-python
# Load the data
from backtester.dataSource.quant_quest_data_source import QuantQuestDataSource
cachedFolderName = '/Users/chandinijain/Auquan/qq2solver-data/historicalData/'
dataSetId = 'trainingData1'
instrumentIds = ['MQK']
ds = QuantQuestDataSource(cachedFolderName=cachedFolderName,
dataSetId=dataSetId,
instrumentIds=instrumentIds)
def loadData(ds):
data = None
for key in ds.getBookDataByFeature().keys():
if data is None:
data = pd.DataFrame(np.nan, index = ds.getBookDataByFeature()[key].index, columns=[])
data[key] = ds.getBookDataByFeature()[key]
data['Stock Price'] = ds.getBookDataByFeature()['stockTopBidPrice'] + ds.getBookDataByFeature()['stockTopAskPrice'] / 2.0
data['Future Price'] = ds.getBookDataByFeature()['futureTopBidPrice'] + ds.getBookDataByFeature()['futureTopAskPrice'] / 2.0
data['Y(Target)'] = ds.getBookDataByFeature()['basis'].shift(-5)
del data['benchmark_score']
del data['FairValue']
return data
data = loadData(ds)
С помощью вышеперечисленного кода Auquan's Toolbox загрузила и загрузила данные в словарь набора данных. Теперь нам нужно подготовить данные в любом из наших предпочтительных форматов. Функция ds.getBookDataByFeature (((((((((((((((((((((((((((((((((((((((((((((((())))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))
Это очень важный шаг!Перед тем, как мы продолжим, мы должны разделить данные на тренировочные наборы для тренировки вашей модели; тестовые наборы для оценки производительности модели.
Разделять данные на тренировочные и тестовые наборы
Поскольку данные обучения используются для оценки параметров модели, ваша модель может перенастраиваться на эти данные обучения, и данные обучения могут вводить в заблуждение производительность модели. Если вы не сохраняете какие-либо отдельные тестовые данные и не используете все данные для обучения, вы не будете знать, насколько хорошо или плохо ваша модель выполняет новые невидимые данные. Это одна из основных причин, по которой обученные модели ML терпят неудачу с реальными данными: люди тренируют все доступные данные и взволнованы обученными показателями данных, но модель не может делать никаких значимых предсказаний с неподготовленными данными в реальном времени.
Разделять данные на тренировочные, проверяющие и тестирующие наборы
Этот подход имеет проблемы. Если мы повторяем тренировочные данные, оцениваем производительность тестовых данных и оптимизируем нашу модель до тех пор, пока мы не будем удовлетворены производительностью, мы подразумеваем, что тестовые данные являются частью тренировочных данных. В конечном итоге наша модель может хорошо работать с этой группой тренировочных и тестовых данных, но не может гарантировать, что она будет хорошо предсказывать новые данные.
Чтобы решить эту проблему, мы можем создать отдельный набор данных проверки. Теперь вы можете тренировать данные, оценивать производительность данных проверки, оптимизировать их, пока не будете удовлетворены производительностью, и, наконец, тестировать тестовые данные. Таким образом, тестовые данные не будут загрязнены, и мы не будем использовать любую информацию из тестовых данных для улучшения нашей модели.
Помните, что после проверки производительности тестовых данных не стоит возвращаться назад и пытаться оптимизировать модель. Если вы обнаружите, что ваша модель не дает хороших результатов, полностью отбросьте модель и начните сначала. Рекомендуется разделить 60% тренировочных данных, 20% проверенных данных и 20% тестовых данных.
Для нашей задачи у нас есть три доступных набора данных, мы будем использовать один как тренировочный набор, второй как проверяющий набор, и третий как наш тестовый набор.
# Training Data
dataSetId = 'trainingData1'
ds_training = QuantQuestDataSource(cachedFolderName=cachedFolderName,
dataSetId=dataSetId,
instrumentIds=instrumentIds)
training_data = loadData(ds_training)
# Validation Data
dataSetId = 'trainingData2'
ds_validation = QuantQuestDataSource(cachedFolderName=cachedFolderName,
dataSetId=dataSetId,
instrumentIds=instrumentIds)
validation_data = loadData(ds_validation)
# Test Data
dataSetId = 'trainingData3'
ds_test = QuantQuestDataSource(cachedFolderName=cachedFolderName,
dataSetId=dataSetId,
instrumentIds=instrumentIds)
out_of_sample_test_data = loadData(ds_test)
Для каждого из них мы добавляем целевую переменную Y, которая определяется как среднее значение следующих пяти базисных значений.
def prepareData(data, period):
data['Y(Target)'] = data['basis'].rolling(period).mean().shift(-period)
if 'FairValue' in data.columns:
del data['FairValue']
data.dropna(inplace=True)
period = 5
prepareData(training_data, period)
prepareData(validation_data, period)
prepareData(out_of_sample_test_data, period)
Анализировать поведение данных и создавать характеристики, которые могут быть предсказуемыми
Сейчас начинается настоящая инженерия; золотой закон выбора характеристик заключается в том, что предсказательная способность в основном исходит от характеристик, а не от модели. Вы обнаружите, что выбор характеристик оказывает гораздо большее влияние на производительность, чем выбор модели.
Не выбирайте на произвол судьбы большое количество характеристик, пока не изучены отношения с целевыми переменными.
Мало или никакое отношение к целевым переменным может привести к чрезмерному приспособлению
Характеристики, которые вы выбираете, могут быть очень взаимосвязаны, и в этом случае меньшее количество характеристик может объяснить цели.
Обычно я создаю несколько интуитивно значимых характеристик, чтобы увидеть, как целевые переменные связаны с этими характеристиками, и как они связаны между собой, чтобы решить, какие из них использовать.
Вы также можете попробовать сортировать кандидаты по максимальному информационному коэффициенту (MIC), выполнять анализ основных компонентов (PCA) и другие методы.
ML-модели часто хорошо работают в области стандартизации. Однако, при обработке данных временных последовательностей нормализация является сложной задачей, поскольку будущий диапазон данных неизвестен. Ваши данные могут выходить за рамки стандартизации, что приводит к ошибкам модели.
Увеличение: характеристики, разделяемые стандартным отклонением или четырёхзначным диапазоном
Жители: исторический средний вычитаем из текущего
Унификация: два ретроспективных периода выше ((x - mean) / stdev
Регулярная унификация: стандартизация данных в диапазоне от -1 до +1 в ретроспективном периоде ((x-min) / ((max-min) и переопределение центра
Обратите внимание, что поскольку мы используем исторические непрерывные средние, стандартные отклонения, максимальные или минимальные значения за ретроспективный период, то приведение стандартизированных значений к характеристикам будет означать различные фактические значения в разное время. Например, если текущее значение характеристики 5 и среднее значение 30 последовательных циклов - 4,5, то после пребывания оно будет преобразовано в 0,5. После этого, если среднее значение 30 последовательных циклов станет 3, то значение 3,5 станет 0,5. Это может быть причиной ошибок модели.
Для первой итерации в нашей проблеме мы создали большое количество характеристик с использованием смешанных параметров.
def difference(dataDf, period):
return dataDf.sub(dataDf.shift(period), fill_value=0)
def ewm(dataDf, halflife):
return dataDf.ewm(halflife=halflife, ignore_na=False,
min_periods=0, adjust=True).mean()
def rsi(data, period):
data_upside = data.sub(data.shift(1), fill_value=0)
data_downside = data_upside.copy()
data_downside[data_upside > 0] = 0
data_upside[data_upside < 0] = 0
avg_upside = data_upside.rolling(period).mean()
avg_downside = - data_downside.rolling(period).mean()
rsi = 100 - (100 * avg_downside / (avg_downside + avg_upside))
rsi[avg_downside == 0] = 100
rsi[(avg_downside == 0) & (avg_upside == 0)] = 0
return rsi
def create_features(data):
basis_X = pd.DataFrame(index = data.index, columns = [])
basis_X['mom3'] = difference(data['basis'],4)
basis_X['mom5'] = difference(data['basis'],6)
basis_X['mom10'] = difference(data['basis'],11)
basis_X['rsi15'] = rsi(data['basis'],15)
basis_X['rsi10'] = rsi(data['basis'],10)
basis_X['emabasis3'] = ewm(data['basis'],3)
basis_X['emabasis5'] = ewm(data['basis'],5)
basis_X['emabasis7'] = ewm(data['basis'],7)
basis_X['emabasis10'] = ewm(data['basis'],10)
basis_X['basis'] = data['basis']
basis_X['vwapbasis'] = data['stockVWAP']-data['futureVWAP']
basis_X['swidth'] = data['stockTopAskPrice'] -
data['stockTopBidPrice']
basis_X['fwidth'] = data['futureTopAskPrice'] -
data['futureTopBidPrice']
basis_X['btopask'] = data['stockTopAskPrice'] -
data['futureTopAskPrice']
basis_X['btopbid'] = data['stockTopBidPrice'] -
data['futureTopBidPrice']
basis_X['totalaskvol'] = data['stockTotalAskVol'] -
data['futureTotalAskVol']
basis_X['totalbidvol'] = data['stockTotalBidVol'] -
data['futureTotalBidVol']
basis_X['emabasisdi7'] = basis_X['emabasis7'] -
basis_X['emabasis5'] +
basis_X['emabasis3']
basis_X = basis_X.fillna(0)
basis_y = data['Y(Target)']
basis_y.dropna(inplace=True)
print("Any null data in y: %s, X: %s"
%(basis_y.isnull().values.any(),
basis_X.isnull().values.any()))
print("Length y: %s, X: %s"
%(len(basis_y.index), len(basis_X.index)))
return basis_X, basis_y
basis_X_train, basis_y_train = create_features(training_data)
basis_X_test, basis_y_test = create_features(validation_data)
Выбор соответствующей статистической/ML модели в зависимости от выбранного вопроса
Выбор модели зависит от того, как будет построена проблема. Вы решаете проблему наблюдения (каждая точка X в характеристической матрице отображается в целевой переменной Y) или проблему неконтролируемого обучения (без данного отображения, модель пытается изучать неизвестные модели)? Вы решаете проблему регрессии (предсказывание фактической цены в будущем времени) или проблему классификации (предсказывание только направления цены в будущем времени) (увеличение/уменьшение).
Обучение под наблюдением или без наблюдения
Возвращение or классификация
Некоторые из распространенных алгоритмов обучения, которые могут помочь вам:
Линейная регрессия ((параметры, регрессия)
Logistic regression (параметры, классификация)
K-близкий (KNN) алгоритм (на основе примеров, регрессия)
SVM, SVR (параметры, классификация и регрессия)
Дерево решения
Лес для решения
Я рекомендую начинать с простой модели, такой как линейная или логическая регрессия, и строить более сложную модель оттуда по мере необходимости. Я также рекомендую вам читать математику, лежащую в основе модели, а не использовать ее как черный ящик.
Обучите и оптимизируйте свою модель с помощью обучения и проверки наборов данных
Теперь вы готовы к окончательному построению модели. На этом этапе вы действительно просто повторяете модель и параметры модели. Вы тренируете свою модель на данных обучения, измеряете ее производительность на данных проверки, а затем возвращаетесь, оптимизируете, перетренируете и оцениваете.
Только после того, как у вас есть модель, которая вам нравится, и затем переходите к следующему шагу.
Давайте начнем с простой линейной регрессии.
from sklearn import linear_model
from sklearn.metrics import mean_squared_error, r2_score
def linear_regression(basis_X_train, basis_y_train,
basis_X_test,basis_y_test):
regr = linear_model.LinearRegression()
# Train the model using the training sets
regr.fit(basis_X_train, basis_y_train)
# Make predictions using the testing set
basis_y_pred = regr.predict(basis_X_test)
# The coefficients
print('Coefficients: \n', regr.coef_)
# The mean squared error
print("Mean squared error: %.2f"
% mean_squared_error(basis_y_test, basis_y_pred))
# Explained variance score: 1 is perfect prediction
print('Variance score: %.2f' % r2_score(basis_y_test,
basis_y_pred))
# Plot outputs
plt.scatter(basis_y_pred, basis_y_test, color='black')
plt.plot(basis_y_test, basis_y_test, color='blue', linewidth=3)
plt.xlabel('Y(actual)')
plt.ylabel('Y(Predicted)')
plt.show()
return regr, basis_y_pred
_, basis_y_pred = linear_regression(basis_X_train, basis_y_train,
basis_X_test,basis_y_test)
Линейная регрессия без унификации
('Coefficients: \n', array([ -1.0929e+08, 4.1621e+07, 1.4755e+07, 5.6988e+06, -5.656e+01, -6.18e-04, -8.2541e-05,4.3606e-02, -3.0647e-02, 1.8826e+07, 8.3561e-02, 3.723e-03, -6.2637e-03, 1.8826e+07, 1.8826e+07, 6.4277e-02, 5.7254e-02, 3.3435e-03, 1.6376e-02, -7.3588e-03, -8.1531e-04, -3.9095e-02, 3.1418e-02, 3.3321e-03, -1.3262e-06, -1.3433e+07, 3.5821e+07, 2.6764e+07, -8.0394e+06, -2.2388e+06, -1.7096e+07]))
Mean squared error: 0.02
Variance score: 0.96
Посмотрите на модельные коэффициенты. Мы не можем сравнивать их или сказать, какие из них имеют значение, поскольку они принадлежат к разным масштабам. Давайте попробуем объединить их, чтобы они соответствовали одинаковым пропорциям, а также навязать некоторую стабильность.
def normalize(basis_X, basis_y, period):
basis_X_norm = (basis_X - basis_X.rolling(period).mean())/
basis_X.rolling(period).std()
basis_X_norm.dropna(inplace=True)
basis_y_norm = (basis_y -
basis_X['basis'].rolling(period).mean())/
basis_X['basis'].rolling(period).std()
basis_y_norm = basis_y_norm[basis_X_norm.index]
return basis_X_norm, basis_y_norm
norm_period = 375
basis_X_norm_test, basis_y_norm_test = normalize(basis_X_test,basis_y_test, norm_period)
basis_X_norm_train, basis_y_norm_train = normalize(basis_X_train, basis_y_train, norm_period)
regr_norm, basis_y_pred = linear_regression(basis_X_norm_train, basis_y_norm_train, basis_X_norm_test, basis_y_norm_test)
basis_y_pred = basis_y_pred * basis_X_test['basis'].rolling(period).std()[basis_y_norm_test.index] + basis_X_test['basis'].rolling(period).mean()[basis_y_norm_test.index]
Линейный регресс унификации
Mean squared error: 0.05
Variance score: 0.90
Эта модель не улучшает предыдущую модель, но и не ухудшает её. Теперь мы можем фактически сравнивать коэффициенты, чтобы увидеть, какие коэффициенты действительно важны.
Давайте посмотрим на коэффициенты.
for i in range(len(basis_X_train.columns)):
print('%.4f, %s'%(regr_norm.coef_[i], basis_X_train.columns[i]))
Результаты:
19.8727, emabasis4
-9.2015, emabasis5
8.8981, emabasis7
-5.5692, emabasis10
-0.0036, rsi15
-0.0146, rsi10
0.0196, mom10
-0.0035, mom5
-7.9138, basis
0.0062, swidth
0.0117, fwidth
2.0883, btopask
2.0311, btopbid
0.0974, bavgask
0.0611, bavgbid
0.0007, topaskvolratio
0.0113, topbidvolratio
-0.0220, totalaskvolratio
0.0231, totalbidvolratio
Мы можем ясно видеть, что некоторые характеристики имеют более высокие коэффициенты по сравнению с другими характеристиками и могут быть более сильными предсказателями.
Давайте посмотрим на взаимосвязь между различными характеристиками.
import seaborn
c = basis_X_train.corr()
plt.figure(figsize=(10,10))
seaborn.heatmap(c, cmap='RdYlGn_r', mask = (np.abs(c) <= 0.8))
plt.show()
Соотношение между характеристиками
Тёмно-красные зоны обозначают высокоактивные переменные. Давайте снова создадим/изменим некоторые характеристики и попробуем улучшить нашу модель.
例如,我可以轻松地丢弃像emabasisdi7这样的特征,这些特征只是其他特征的线性组合.
def create_features_again(data):
basis_X = pd.DataFrame(index = data.index, columns = [])
basis_X['mom10'] = difference(data['basis'],11)
basis_X['emabasis2'] = ewm(data['basis'],2)
basis_X['emabasis5'] = ewm(data['basis'],5)
basis_X['emabasis10'] = ewm(data['basis'],10)
basis_X['basis'] = data['basis']
basis_X['totalaskvolratio'] = (data['stockTotalAskVol']
- data['futureTotalAskVol'])/
100000
basis_X['totalbidvolratio'] = (data['stockTotalBidVol']
- data['futureTotalBidVol'])/
100000
basis_X = basis_X.fillna(0)
basis_y = data['Y(Target)']
basis_y.dropna(inplace=True)
return basis_X, basis_y
basis_X_test, basis_y_test = create_features_again(validation_data)
basis_X_train, basis_y_train = create_features_again(training_data)
_, basis_y_pred = linear_regression(basis_X_train, basis_y_train, basis_X_test,basis_y_test)
basis_y_regr = basis_y_pred.copy()
('Coefficients: ', array([ 0.03246139,
0.49780982, -0.22367172, 0.20275786, 0.50758852,
-0.21510795, 0.17153884]))
Mean squared error: 0.02
Variance score: 0.96
Посмотрите, наши характеристики модели не изменились, нам просто нужны некоторые характеристики, чтобы объяснить нашу целевую переменную. Я рекомендую вам попробовать больше этих характеристик, попробовать новые комбинации и т. Д., Чтобы увидеть, что может улучшить нашу модель.
我们还可以尝试更复杂的模型,看看模型的变化是否可以提高性能.
from sklearn import neighbors
n_neighbors = 5
model = neighbors.KNeighborsRegressor(n_neighbors, weights='distance')
model.fit(basis_X_train, basis_y_train)
basis_y_pred = model.predict(basis_X_test)
basis_y_knn = basis_y_pred.copy()
from sklearn.svm import SVR
model = SVR(kernel='rbf', C=1e3, gamma=0.1)
model.fit(basis_X_train, basis_y_train)
basis_y_pred = model.predict(basis_X_test)
basis_y_svr = basis_y_pred.copy()
model=ensemble.ExtraTreesRegressor()
model.fit(basis_X_train, basis_y_train)
basis_y_pred = model.predict(basis_X_test)
basis_y_trees = basis_y_pred.copy()
Проверка эффективности фактических данных образца
Продуктивность повторного тестирования на тестируемом наборе данных (не тронутых)
Это критический момент. Мы начали работать над нашей конечной оптимизационной моделью с последнего шага в тестировании данных, и мы отложили ее в сторону с самого начала.
Это дает вам реальные ожидания того, как ваша модель будет выполняться с новыми и невидимыми данными, когда вы начнете торговать в реальном времени. Поэтому необходимо убедиться, что у вас есть чистый набор данных, который не используется для обучения или проверки модели.
Если вам не нравятся результаты повторных измерений тестовых данных, пожалуйста, отбросьте модель и начните сначала. Не возвращайтесь, чтобы переоптимизировать свою модель, это приведет к чрезмерному соответствию! (Кроме того, рекомендуется создать новый тестовый набор данных, поскольку этот набор данных теперь загрязнен; когда мы отбросили модель, мы уже имели представление о содержании данного набора данных).
Здесь мы будем использовать инструментарий Auquan.
import backtester
from backtester.features.feature import Feature
from backtester.trading_system import TradingSystem
from backtester.sample_scripts.fair_value_params import FairValueTradingParams
class Problem1Solver():
def getTrainingDataSet(self):
return "trainingData1"
def getSymbolsToTrade(self):
return ['MQK']
def getCustomFeatures(self):
return {'my_custom_feature': MyCustomFeature}
def getFeatureConfigDicts(self):
expma5dic = {'featureKey': 'emabasis5',
'featureId': 'exponential_moving_average',
'params': {'period': 5,
'featureName': 'basis'}}
expma10dic = {'featureKey': 'emabasis10',
'featureId': 'exponential_moving_average',
'params': {'period': 10,
'featureName': 'basis'}}
expma2dic = {'featureKey': 'emabasis3',
'featureId': 'exponential_moving_average',
'params': {'period': 3,
'featureName': 'basis'}}
mom10dic = {'featureKey': 'mom10',
'featureId': 'difference',
'params': {'period': 11,
'featureName': 'basis'}}
return [expma5dic,expma2dic,expma10dic,mom10dic]
def getFairValue(self, updateNum, time, instrumentManager):
# holder for all the instrument features
lbInstF = instrumentManager.getlookbackInstrumentFeatures()
mom10 = lbInstF.getFeatureDf('mom10').iloc[-1]
emabasis2 = lbInstF.getFeatureDf('emabasis2').iloc[-1]
emabasis5 = lbInstF.getFeatureDf('emabasis5').iloc[-1]
emabasis10 = lbInstF.getFeatureDf('emabasis10').iloc[-1]
basis = lbInstF.getFeatureDf('basis').iloc[-1]
totalaskvol = lbInstF.getFeatureDf('stockTotalAskVol').iloc[-1] - lbInstF.getFeatureDf('futureTotalAskVol').iloc[-1]
totalbidvol = lbInstF.getFeatureDf('stockTotalBidVol').iloc[-1] - lbInstF.getFeatureDf('futureTotalBidVol').iloc[-1]
coeff = [ 0.03249183, 0.49675487, -0.22289464, 0.2025182, 0.5080227, -0.21557005, 0.17128488]
newdf['MQK'] = coeff[0] * mom10['MQK'] + coeff[1] * emabasis2['MQK'] +\
coeff[2] * emabasis5['MQK'] + coeff[3] * emabasis10['MQK'] +\
coeff[4] * basis['MQK'] + coeff[5] * totalaskvol['MQK']+\
coeff[6] * totalbidvol['MQK']
newdf.fillna(emabasis5,inplace=True)
return newdf
problem1Solver = Problem1Solver()
tsParams = FairValueTradingParams(problem1Solver)
tradingSystem = TradingSystem(tsParams)
tradingSystem.startTrading(onlyAnalyze=False,
shouldPlot=True,
makeInstrumentCsvs=False)
Результаты рецензирования, Pnl в долларах (Pnl не учитывает затраты на транзакции и другие расходы)
Проверка сверки, коллективное обучение, багирование и расширение
В дополнение к сбору большего количества данных, созданию лучших функций или тестированию большего количества моделей, есть несколько вещей, которые вы можете попробовать улучшить.
1. Проверка на прокат
Проверка сверки
Рыночные условия редко остаются неизменными. Предположим, что у вас есть данные за год, и вы тренируетесь с данными с января по август, и вы тестируете свою модель с данными с сентября по декабрь, и вы, возможно, в конечном итоге тренируетесь против очень конкретного набора рыночных условий. Может быть, в первом полугодии не было рыночных колебаний, некоторые экстремальные новости привели к резкому росту рынка в сентябре, и ваша модель не смогла бы изучить эту модель и принесла бы вам мусорные прогнозы.
Возможно, лучше попробовать прогрессивную прокатную проверку: с января по февраль, с марта, с апреля по май, с июня и так далее.
2. Коллективное обучение
Коллективное обучение
Некоторые модели могут хорошо работать при прогнозировании некоторых сценариев, в то время как модели могут быть чрезмерно слишком хорошо при прогнозировании других сценариев или в некоторых случаях; один из способов уменьшить ошибки и чрезмерное соответствие - использовать наборы различных моделей; ваш прогноз будет средним из тех, которые прогнозируют многие модели, и ошибки различных моделей могут быть компенсированы или уменьшены; некоторые из распространенных методов сбора - Багирование и Повышение;
Запаковка
Повышение
Для краткой справки я перейду через эти методы, но вы можете найти больше информации в Интернете.
Давайте попробуем сборный подход к нашей проблеме.
basis_y_pred_ensemble = (basis_y_trees + basis_y_svr +
basis_y_knn + basis_y_regr)/4
Mean squared error: 0.02
Variance score: 0.95
Решайте свои проблемы
Сбор надежных данных и очистка данных
Разделять данные на тренировочные, проверяющие и тестирующие наборы
Создание и анализ характеристик
Выбор подходящей модели обучения в зависимости от поведения
Используйте данные обучения, чтобы обучить свою модель и сделать прогноз.
Проверить и оптимизировать производительность на своде подтверждений
Проверка конечной производительности тестов
Но это не все, у вас есть только надежная модель прогнозирования. Помните, что мы действительно хотим в нашей стратегии?
Разработка сигналов на основе прогнозных моделей для определения направления торговли
Разработка конкретных стратегий для выявления открытых позиций
Исполнительная система для идентификации позиций и цен
Все это нужно для того, чтобы использовать изобретательскую квантовую платформу.FMZ.COMНа платформе Inventor Quantify есть множество совершенных альтернативных стратегий, которые, в сочетании с методом машинного обучения, позволят вам создать свои собственные стратегии. Стратегия Square расположена в:https://www.fmz.com/square
Важные сведения о стоимости сделки:你的模型会告诉你所选资产何时是做多或做空。然而,它没有考虑费用/交易成本/可用交易量/止损等。交易成本通常会使有利可图的交易成为亏损。例如,预期价格上涨0.05美元的资产是买入,但如果你必须支付0.10美元进行此交易,你将最终获得净亏损$0.05。在你考虑经纪人佣金,交换费和点差后,我们上面看起来很棒的盈利图实际上是这样的:
В результате обратного измерения после оплаты и отклонения Pnl в долларах
В последующих статьях мы подробно обсудим эти вопросы.
И наконец, давайте посмотрим на некоторые из распространенных ловушек.
Постарайтесь избегать чрезмерного приспособления!
Не перетренируйте после каждой точки данных: это распространенная ошибка, которую люди делают в разработке машинного обучения. Если ваша модель нуждается в перетренировке после каждой точки данных, то это может быть не очень хорошая модель. То есть, она нуждается в регулярной перетренировке и должна выполняться только с разумной частотой (например, если вы делаете предсказания в течение дня, перетренируйтесь в конце недели).
Избегайте отклонений, особенно прогрессивных: это еще одна причина, по которой модель не работает, убедитесь, что вы не используете любую информацию о будущем. В большинстве случаев это означает, что не используйте целевую переменную Y в качестве характеристики в модели. Во время ретроспективного тестирования вы можете использовать ее, но она не будет использоваться при фактическом запуске модели, что сделает вашу модель непригодной для использования.
Осторожность в отклонениях в добыче данных: поскольку мы пытаемся провести ряд моделей с нашими данными, чтобы определить их соответствие, если нет особых причин, убедитесь, что вы выполняете строгие тесты, чтобы отделить случайные модели от реальных моделей, которые могут возникнуть. Например, линейная регрессия хорошо объясняет тенденцию к росту, и она, скорее всего, будет лишь частью более крупного случайного движения!
Это очень важно, и я считаю необходимым повторить это.
Слишком большое соответствие - это самая опасная ловушка в стратегии торговли.
Сложный алгоритм может отлично справляться с ретроспекцией, но терпеть неудачу с новыми, невидимыми данными, которые не показывают никаких тенденций в данных и не дают никаких реальных прогнозов. Он хорошо подходит для данных, которые он видит.
Сделайте свою систему как можно проще. Если вы обнаружите, что вам требуется много сложных функций для интерпретации данных, вы можете быть слишком насыщенными.
Разделяйте ваши доступные данные на тренировочные и тестовые данные, и всегда проверяйте производительность реальных образцов данных, прежде чем использовать их для реальной торговли.
Однозначно.Спасибо, папа.
congcong009Отличные статьи, идеи и резюме для начинающих практиков
лалаладемаксия- Это неправда.