Машинное обучение в трейдинге: теория, модели, практика и алготорговля - страница 261
Вы упускаете торговые возможности:
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Регистрация
Вход
Вы принимаете политику сайта и условия использования
Если у вас нет учетной записи, зарегистрируйтесь
И какие результаты в прогнозировании? посмею спросить.
Вот подготовленная табличка для обучения моделей.
Цены конвертнуты в дельты по колонкам; убрал колонки без изменений или с NA.
В каждую строку впихнул по 3 лага для каждой колонки (текущая строка минус предыдущая; предыдущая минус пред-предыдущая; пред-предыдущая минус пред-пред-пердыдущая)
Цель - рост/падение значения на следующей строке (следующая строка минус текущая, округлённая в +-1, или 0 если без изменений; всего 3 класса). У всех целей префикс "target_"
*Для предсказания какой-то цели нельзя использовать другие цели, а то будет заглядывание в будущее. Все колонки что имеют префикс "target_" - нельзя использовать как предиктор или инпут.
Проблемка.
Поделил csv файл на две части по строкам, в отношении 10:1 на тренировочные данные и фронттест. Обучил модель для target_SiH7.bid (из таблицы выше), получил точность классификации 62% на тренировочных, и 74% на новых данных. Обрадовался, но перепроверил, оказалось что класс 0 очень несбалансирован по отношению к другим, и как раз по количеству имеет 60% и 74%. То есть модель научилась хорошо детектить 0, а на классы -1 и 1 забила.
Нужна другая оценка. Для двух несбалансированных классов отлично подходит такая метрика - https://en.wikipedia.org/wiki/Cohen's_kappa, но в нашем случае есть три несбалансированных класса, а не два, есть ли аналог Каппа для 3?
Если Вы меня спрашивали, то однозначно ответить наверно не смогу, очень много того что прогнозируется и всё по разному. Но в среднем где то 60-65%
Интересно, а можете описать поподробней..
Просто я сейчас занимаюсь в совсем другой области прогнозирования и не могу себе позволить распыляться потому я не могу вместе с вами делать эксперименты на этой маркет дате, но читать и наблюдать мне очень интересно, пишите больше пожалуйста...
оказалось что класс 0 очень несбалансирован по отношению к другим, и как раз по количеству имеет 60% и 74%. То есть модель научилась хорошо детектить 0, а на классы -1 и 1 забила.
У меня была такая же проблема когда я random forest тренировал на развороты, разворотов естественно было намного меньше чем не разворотов. Чем больше делал деревьев тем больше МО забивало на классы разворота и больше концентрировалось на классе не разворот.
В caret есть несколько методов для балансировки классов , но все они банальные типа - либо дублируем тот класс которого меньше чтобы выровнять чтобы сумма наблюдений во всех классах стала одинаковой, либо наоборот удаляем лишние наблюдения из того класса в котором наблюдений больше
Ни один из методов не показал себя как то выгодней чем вообще без балансировки (но это исключительно в моем случаи)
Интересно, а можете описать поподробней..
Просто я сейчас занимаюсь в совсем другой области прогнозирования и не могу себе позволить распыляться потому я не могу вместе с вами делать эксперименты на этой маркет дате, но читать и наблюдать мне очень интересно, пишите больше пожалуйста...
У меня была такая же проблема когда я random forest тренировал на развороты, разворотов естественно было намного меньше чем не разворотов. Чем больше делал деревьев тем больше МО забивало на классы разворота и больше концентрировалось на классе не разворот.
В caret есть несколько методов для балансировки классов , но все они банальные типа - либо дублируем тот класс которого меньше чтобы выровнять чтобы сумма наблюдений во всех классах стала одинаковой, либо наоборот удаляем лишние наблюдения из того класса в котором наблюдений больше
Ни один из методов не показал себя как то выгодней чем вообще без балансировки (но это исключительно в моем случаи)
Всё обсуждаемо. Я предложил фортс фьючи, к примеру Si, RI, BR и тп. самые ликвидные в общем. В качестве результата предлагаю сигнал (-1,0,1)(шорт,кэш,лонг), сигнал однозначное чем вероятность и не искажен MM как заявки. Постапроботка, признаки и таргеты дело хозяйское, или заказывайте.
После некоторых размышлений пришел к выводу что нужно добавить как минимум ещё стакан{price:vol,…||…, price:vol }, как есть, один последний за секунду, для каждого прогнозируемого инструмента, тогда дельта не нужна и бид, аск тоже, это ИМХО обязательно, если с лентой за секунду раздельные объёмы и смещение ОИ ,более менее информативно, то для стакана одна дельта очень мало, нужно как минимум видеть разные “плиты” распределение и тп. и вроде всё, как для начала хватит. Добавьте стакан и выкладывайте тренировочный датасет за пару дней, будем играться. :)
В конце концов остановился на метрике Scott's Pi https://en.wikipedia.org/wiki/Scott's_Pi
Вот мои результаты с этой оценкой, обучал модель на первых 91% строк, и потом делал фронттест на последних оставшихся данных (отношение backtest : fronttest = 10:1)
колонки "class_0_rate" в табличке - отношение класса 0 к классам -1и1, чтоб можно было отсеять в экселе те результаты где это значение слишком велико.
Последние две колонки - метрика Scott's Pi для тренировки и теста, значение будет от -1 до 1; где 0=результат рандомен и меодель бесполезна, а 1 = всё отлично. Отрицательный результат - не очень хорошо, обратная корреляция, можно попробовать инвертировать результат предсказания. Обратная корреляция иногда вполне прокатывает с двумя классами, когда торгуешь в полную противоположность предсказанию. Но вот с тремя классами "противоположность" как-то сложно найти, каждому классу соответсвуют два противположных, крч отрицательная оценка в этом случае это тоже плохо.
Крч нужно выбирать ту валюту где bid (или ask) предсказания имеют похожие и большие значения оценки на backtest и fronttest, например xagusd. Хотя оценка 0.18 по шкале от 0 до 1 это мало. Да и предсказывать на один тик вперёд в реальной торговле тоже плохо. В общем результат есть, но неприменим :)
код R для Scott's Pi
if(length(act) != length(pred)){
stop("different length")
}
n_observ <- length(act)
all_levels <- unique(c(act,pred))
n_levels <- length(all_levels)
marginal_matrix <- matrix(NA, ncol=n_levels, nrow=n_levels)
colnames(marginal_matrix) <- all_levels
rownames(marginal_matrix) <- all_levels
for(i in 1:n_levels){
for(j in 1:n_levels){
marginal_matrix[i,j] <- sum((act==all_levels[i]) & (pred==all_levels[j]))
}
}
diagSum <- 0
for(i in 1:n_levels){
diagSum <- diagSum + marginal_matrix[i,i]
}
diagSum <- diagSum / n_observ
marginalSum <- 0
for(i in 1:n_levels){
marginalSum <- marginalSum + ((sum(marginal_matrix[i,]) + sum(marginal_matrix[,i]))/n_observ/2)^2
}
p <- marginalSum
return((diagSum - p)/(1-p))
}
В конце концов остановился на метрике Scott's Pi https://en.wikipedia.org/wiki/Scott's_Pi
Вот мои результаты с этой оценкой, обучал модель на первых 91% строк, и потом делал фронттест на последних оставшихся данных (отношение backtest : fronttest = 10:1)
колонки "class_0_rate" в табличке - отношение класса 0 к классам -1и1, чтоб можно было отсеять в экселе те результаты где это значение слишком велико.
Последние две колонки - метрика Scott's Pi для тренировки и теста, значение будет от -1 до 1; где 0=результат рандомен и меодель бесполезна, а 1 = всё отлично. Отрицательный результат - не очень хорошо, обратная корреляция, можно попробовать инвертировать результат предсказания. Обратная корреляция иногда вполне прокатывает с двумя классами, когда торгуешь в полную противоположность предсказанию. Но вот с тремя классами "противоположность" как-то сложно найти, каждому классу соответсвуют два противположных, крч отрицательная оценка в этом случае это тоже плохо.
Крч нужно выбирать ту валюту где bid (или ask) предсказания имеют похожие и большие значения оценки на backtest и fronttest, например xagusd. Хотя оценка 0.18 по шкале от 0 до 1 это мало. Да и предсказывать на один тик вперёд в реальной торговле тоже плохо. В общем результат есть, но неприменим :)
код R для Scott's Pi
if(length(act) != length(pred)){
stop("different length")
}
n_observ <- length(act)
all_levels <- unique(c(act,pred))
n_levels <- length(all_levels)
marginal_matrix <- matrix(NA, ncol=n_levels, nrow=n_levels)
colnames(marginal_matrix) <- all_levels
rownames(marginal_matrix) <- all_levels
for(i in 1:n_levels){
for(j in 1:n_levels){
marginal_matrix[i,j] <- sum((act==all_levels[i]) & (pred==all_levels[j]))
}
}
diagSum <- 0
for(i in 1:n_levels){
diagSum <- diagSum + marginal_matrix[i,i]
}
diagSum <- diagSum / n_observ
marginalSum <- 0
for(i in 1:n_levels){
marginalSum <- marginalSum + ((sum(marginal_matrix[i,]) + sum(marginal_matrix[,i]))/n_observ/2)^2
}
p <- marginalSum
return((diagSum - p)/(1-p))
}