Избранное трейдера Денис Жарков
Всего лишь неделю нужно для того, чтобы каждый из вас смог сам научиться программировать сверточные нейронные сети, которые торгуют не хуже этой*:
Основное отличие машинного обучения от традиционного программирования состоит в том, что в задачах классического программирования вы знаете некие правила и жестко программируете их в поведении программы; в задачах машинного обучения вы не знаете по каким конкретно правилам должна работать программа и позволяете моделям машинного обучения самим найти их. Если вы хотите создать торгового робота, обычно, вы сами ищете некоторые правила (например, пересечение скользяшек, MACD>80 при убывающей луне — покупаю 2 лота) и жестко задаете такое поведения в роботе, тестируете и, возможно, оптимизируете некоторые параметры, но почему бы не поручить само придумывание правил машине? Методы машинного обучения, в теории, могут сами выбрать индикаторы, разработать правила входа, выхода и оптимальный размер позиций. Да чего уж… они могут сами придумать индикаторы, паттерны, которые могут быть гораздо лучше чем то, что придумали до этого люди. Ведь так и случилось в сфере обработки изображений, нейронные сети научились выделять значимые признаки из изображений гораздо лучше, чем алгоритмы, придуманные людьми. Компьютер обыгрывает людей в шахматы — игру, знания для которой люди накапливали ни одну сотню лет. Станет ли алготрейдинг следующей сферой, где будет господствовать нейронные сети или какой другой метод машинного обучения?
Так как насчет практического применения ML? Как вообще это выглядит?!
А выглядит это так, что 80% времени data scientist тратит на работу с данными, чтобы потом загнав их в модельку мобильно получить прогноз. Вообще, предполагалось что такой мощный инструмент как нейросети сможет работать с сырыми данными, то есть загонишь в нейросеть обычную котировку, а дальше могучие нейроны похимичат, сгенерируют кучу фичей и найдут нужную их комбинацию (на самом деле никаких фичей нейросети на создают, но можно представить). Ну вот например такое явление как большой ГЭП, важный показатель? Еще какой! В сырых данных он содержится, то есть можно помечтать что если мы создадим очень сложную нейросеть, то она сможет вытащить это значение самостоятельно. Что такое ГЭП нейросеть конечно не знает, но путем манипуляций с весами она найдет, что когда меняется циферка в дате то образовавшийся большой разрыв в цене имеет большое влияние для хорошей аппроксимации.
Мечты, мечты. Пока все что я видел в результате скармливания нейросети сырах данных-это слезы, боль и убожество. В общем мы пойдет другим путем. Мы не будет скармливать модели сырятину и мусор, мы постараемся кормить его качественно чтобы удои увеличивались и все такое.
Есть такое понятие как в ML как feature engenering. Наверно единственное более менее креативное что остается человеку в этом бездушном мире машинного обучения. А уж коли мы ведем речь о RF, то сам бог велел заняться этим, RF знаете ли не нейросети, там даже теоретически сырятина в данных не приветствуется. Вот этим мы и займемся.
Откуда же нам взять эти фичи и главное как? Тут каждому воля вольная. Например можно сдув пыль с WealthLab использовать старичка как генератора фичей. Кто не знает в него вшито около полусотни известных индексов и еще столько же, но с неизвестным кодом. А еще можно запрограммировать свои фичи. По своему «знанию и разумению», своих «знаний и разумений» я накопил много, но почти все они из разряда «все эти технические индикаторы не стоят ничего». Зато кое что из своего показали свою небезнадежность. В общем на первый случай я сгенерировал около 17 своих фичей, затем ранжировал их для каждой стоки, итого 34 фичи. Стоки брал из числа 20 самых ликвидных отечественных фишек с 2010 года по март 2018, что дало 50 тысяч дневных наблюдений. Прямо сказать не густо, но что есть. Тем более речь идет о демонстрации силушки RF.
Вот набор моих фичей:
Week 49303 non-null int64 GEP 49303 non-null float64 Min10 49303 non-null float64 Cl/High 49303 non-null float64 Cl/Low 49303 non-null float64 Cl/w_High 49303 non-null float64 Cl/w_Low 49303 non-null float64 wdif 49303 non-null float64 dif 49303 non-null float64 Vol20/Vol200 49303 non-null float64 tHigh% 49303 non-null float64 tLow% 49303 non-null float64 tHigh%-tLow% 49303 non-null float64 Cl/SMA21 49303 non-null float64 Cl/SMA5 49303 non-null float64 SMA5-SMA21 49303 non-null float64 Cl/(minSMA) 49303 non-null float64 Cl/(maxSMA) 49303 non-null float64 l_Min10 49303 non-null int64 s_Min10 49303 non-null int64 l_gep 49303 non-null int64 s_gep 49303 non-null int64 l_cl/high 49303 non-null int64 s_cl/high 49303 non-null int64 l_cl/low 49303 non-null int64 s_cl/low 49303 non-null int64 l_wdif 49303 non-null int64 s_wdif 49303 non-null int64 l_SMA5-SMA21 49303 non-null int64 S_SMA5-SMA21 49303 non-null int64 L_Cl/(maxSMA) 49303 non-null int64 S_Cl/(maxSMA) 49303 non-null int64 L-tHigh%-tLow% 49303 non-null int64 S_tHigh%-tLow% 49303 non-null int64
Как учили «знающие» люди – торгуй график, на графике видны все действия игроков. Вот я и торговал график. И, если в моменте я был практически миллионером, то на дистанции утрачивал почти все преимущество. Что не так? Торгуя график, я полагался только на свои зрительные ощущения, а это влекло за собой досадные ошибки.
Поэтому я решил разобраться, а что я, собственно, торгую. Попытался сделать так, чтобы моей торговой системой мог управлять человек, который понятие не имел о трейдинге. Для этого пришлось препарировать бары и извлечь из них полезную, на мой взгляд, информацию, чтобы выявить закономерности. А уже эти закономерности представить в виде алгоритма, понятного всем.
Торговал я в то время фьючерсными контрактами на часовом и пятиминутном тайм-фреймах. Для примера, давайте разберем фьючерс на акции Сбербанка — часовик. Я заметил, что на рынке время от времени, возникают моменты, когда происходит жор. В это время игроки покупают актив прямо по рынку, по любой цене – лишь бы купить. Кто-то говорит, что это крупный игрок разгоняет цену, но я, больше, чем уверен, что крупный игрок так рынок не разгоняет, а делает это через новости. А жор – это пир спекулянтов, которые узнали о чем-то самыми последними.
На американском рынке торгуется более 18000 эмитентов. Когда матёрым русским инвесторам задают вопрос почему они смотрят только на наш рынок, то обычно получают следующий ответ:
Там слишком много компаний. Чтобы их изучить, уйдут столетия.
Не поспоришь. У меня на беглый анализ одного годового отчета уходит не меньше часа. А тут их надо отсматривать тысячами. И делать какие-то выводы. Где взять столько времени?
Я задал себе вопрос, а можно ли сузить этот круг до нескольких десятков компаний? И как это сделать?
Как оказалось, рецепты есть. Вам понадобятся:
Одними из самых простых, и, в тоже время, эффективных рабочих стратегий на рынке, является торговля внутренних и внешних баров. Найти и идентифицировать внутренний и внешний бар на графике цены очень просто. В этом посте, я постараюсь развернуто дать ответ, как можно выстраивать свою стратегию торговли по этим паттернам.
Начну с определений. Во-первых, стоит заметить, что не важно, в каком виде отображается ваш график цены. В статье я буду использовать график в виде баров, но все нижесказанное будет применимо и к свечному графику. Т.к., для того, чтобы определить внутренний бар на графике или внешний, достаточно сравнить диапазон текущего бара с предыдущим.
Ну что ж, ближе к делу. В классической теории технического анализа, внутренние и внешние бары относят к разворотным формациям, которые находятся на экстремумах графика цены. Если вы слепо будете следовать этой концепции, то потерпите фиаско. Я торгую пробои внутренних и внешних баров, не уделяя особого значения, в какой точке движения они находятся. И это получается наиболее эффективно.
Settings={ Name="MNKHL", period=200, delta=0, line= { { Name = "cur1", Type =TYPE_LINE, Width = 1, Color = RGB(0,0, 0) }, { Name = "cur2", Type =TYPE_LINE, Width = 1, Color = RGB(0,255, 0) }, { Name = "cur3", Type =TYPE_LINE, Width = 1, Color = RGB(255,0, 0) }, { Name = "cur4", Type =TYPE_LINE, Width = 1, Color = RGB(255,0, 0) }, { Name = "cur5", Type =TYPE_LINE, Width = 1, Color = RGB(0,255, 0) } } } --[[ описание свойств: period - период, за каротрый делается расчет delta - смещение назад назначение: построение тенденции использовался: метод наименьших квадратов (аппроксимация линией) --]] function Init() return 5 end function OnCalculate(index) sz = Size() n = Settings.period d = Settings.delta if (index ~= sz) then return nil, nil, nil, nil, nil else y = nil if index-n-d > 0 then a1 = 0 a2 = 0 a3 = 0 a4 = 0 for i=index-n+1-d, index-d do a1 = a1+i*C(i) a2 = a2+i a3 = a3+C(i) a4 = a4+i*i end if((n*a4 - a2*a2) ~= 0) then a = (n*a1 - a2*a3)/(n*a4 - a2*a2) b = (a3 - a*a2)/n j = index-n+1-d mh1 = H(j) ml1 = L(j) mh2 = H(j) ml2 = L(j) dmh1 = 0 dml1 = 0 dmh2 = 0 dml2 = 0 for j=index-n+1-d, index-d do y = a*j + b SetValue(j, 1, y) if H(j) < y and y - H(j) > dmh1 then mh1 = H(j) dmh1 = y - H(j) end if L(j) < y and y - L(j) > dml1 then ml1 = L(j) dml1 = y - L(j) end if H(j) > y and H(j) - y > dmh2 then mh2 = H(j) dmh2 = H(j) - y end if L(j) > y and L(j) - y > dml2 then ml2 = L(j) dml2 = L(j) - y end end for j=index-n+1-d, index-d do y = a*j + b SetValue(j, 2, y-dmh1) SetValue(j, 3, y-dml1) SetValue(j, 4, y+dmh2) SetValue(j, 5, y+dml2) end end end return y end end