Часть 1.
Традиционно считается, что задача портфельной оптимизации, или задача Марковица, представляет собой некоторую самостоятельную задачу выбора такого портфеля активов, который обладал бы максимальной доходностью при минимальных рисках.
Прим. В качестве актива могут выступать ценные бумаги (акции), их производные (опционы) или торговые системы.
Решение задачи состоит из двух этапов:
Почему мы используем аналогию портфельной оптимизации с методами машинного обучения — Bag, Boost?! Потому что в действительности (и мы это продемонстрируем) нам абсолютно не важно, насколько хорошо динамику наших временных рядов прогнозируют «слабые» модели – нам важно только то, чтобы ошибки прогнозов наших моделей взаимно компенсировали бы друг друга в некотором интегральном смысле. Иными словами – в случае бустинга – ошибка прогноза линейной композиции была бы минимальной, а в случае портфельной оптимизации – была бы минимальной ошибка прогноза нелинейной композиции (то есть самого портфеля).
Автор — известный в трейдерской среде mehanizator. Создатель сайта для алгоритмических трейдеров long-short.pro
Книга является квинтэссенцией многолетнего опыта автора в области исследований свойств рынка и разработки механических торговых систем.
Являясь практическим руководством к действию, книга глава за главой проводит читателя в мир систематизированной торговли, правил, алгоритма принятия решений и проверки тех или иных гипотез.
Состоит из 4 последовательно связанных глав. Внимание следует уделить всем главам, даже несмотря на то, что кажется что в начале книги автор льет воду. На самом деле воды в книги нет, описательные разделы поведения рыночных участников и свойств рынка необходимы в начале книги, чтобы в последующем читатель смог формировать рабочие гипотезы и, проверив их затем на тестах, выйти на устойчивую алгоримическую (системную) торговлю.
Рекомендую к прочтению всем, кто хочет отойти от импровизации и перейти на системный трейдинг — позволит сэкономить кучу времени и избежать иллюзий простоты этого вида деятельности.
Settings= { Name = "Zigzag5", -- название индикатора delta=2, -- параметр индикатора deltaY=1, -- параметр индикатора linedeltaY=0.75, -- параметр индикатора line= { { Name = "zigzagline3", Type =TYPE_LINE, Width = 2, Color = RGB(0,255, 0) }, { Name = "upline", Type =TYPE_LINE, Width = 2, Color = RGB(255,0, 0) }, { Name = "lowline", Type =TYPE_LINE, Width = 2, Color = RGB(0,0, 255) }, { Name = "declineline", Type =TYPE_LINE, Width = 2, Color = RGB(255,0, 0) }, { Name = "upline2", Type =TYPE_LINE, Width = 1, Color = RGB(255,0, 0) }, { Name = "lowline2", Type =TYPE_LINE, Width = 1, Color = RGB(0,0, 255) }, { Name = "declineline2", Type =TYPE_LINE, Width = 1, Color = RGB(255,0, 0) } } } function getradius(x, y) return math.sqrt(Settings.deltaY*y*y+x*x) end function koef(val) return 1 - 1/(1-1/val) end function Init() vMin = 0 vMax = 0 vMinindex = 0 vMaxindex = 0 voldMinindex = 0 voldMaxindex = 0 upval = 0 lowval = 0 upindex = 1 lowindex = 1 veu = nil vel = nil curfrom = 1 curto = 1 return 7 end function OnCalculate(index) local printz = 0 vsize = Size() ve = nil veu = nil vel = nil curv = nil veu2 = nil vel2 = nil curv2 = nil if index == 1 then vMin = C(index) vMax = C(index) vMinindex = index vMaxindex = index voldMinindex = index voldMaxindex = index ve = C(index) else if voldMaxindex >= voldMinindex then if C(index) > (1 + Settings.delta/100)*vMin then vMin = C(index) vMax = C(index) vMaxindex = index voldMinindex = vMinindex vFrom = voldMaxindex vTo = vMinindex printz = 1 if (C(vMinindex) > C(vsize)) and (upval > koef(getradius(vsize - vMinindex, C(vMinindex) - C(vsize)))) then upval = koef(getradius(vsize - vMinindex, C(vMinindex) - C(vsize))) upindex = vMinindex end if (C(vMinindex) < C(vsize)) and (lowval > koef(getradius(vsize - vMinindex, C(vMinindex) - C(vsize)))) then lowval = koef(getradius(vsize - vMinindex, C(vMinindex) - C(vsize))) lowindex = vMinindex end curfrom = voldMaxindex curto = voldMinindex else if vMin > C(index) then vMin = C(index) vMinindex = index vFrom = voldMaxindex vTo = index printz = 0 curto = index else vFrom = vMinindex vTo = index printz = 0 end curfrom = voldMaxindex end else if voldMaxindex <= voldMinindex then if C(index) < (1 - Settings.delta/100)*vMax then vMax = C(index) vMin = C(index) vMinindex = index voldMaxindex = vMaxindex vFrom = voldMinindex vTo = vMaxindex printz = 1 if (C(vMaxindex) > C(vsize)) and (upval > koef(getradius(vsize - vMaxindex, C(vMaxindex) - C(vsize)))) then upval = koef(getradius(vsize - vMaxindex, C(vMaxindex) - C(vsize))) upindex = vMaxindex end if (C(vMaxindex) < C(vsize)) and (lowval > koef(getradius(vsize - vMaxindex, C(vMaxindex) - C(vsize)))) then lowval = koef(getradius(vsize - vMaxindex, C(vMaxindex) - C(vsize))) lowindex = vMaxindex end curfrom = voldMinindex curto = voldMaxindex else if vMax < C(index) then vMax = C(index) vMaxindex = index vFrom = voldMinindex vTo = index printz = 0 curto = index else vFrom = vMaxindex vTo = index printz = 0 end curfrom = voldMinindex end end end if (printz == 1) or (Size() == index) then for i = vFrom, vTo do k = (C(vTo)- C(vFrom))/(vTo- vFrom) v = i*k + C(vTo) - vTo*k SetValue(i, 1, v) ve = v end if (Size() == index) then ve = C(index) if voldMaxindex >= voldMinindex then vFrom = voldMaxindex vTo = vMinindex end if voldMaxindex <= voldMinindex then vFrom = voldMinindex vTo = vMaxindex end for i = vFrom, vTo do k = (C(vTo)- C(vFrom))/(vTo- vFrom) v = i*k + C(vTo) - vTo*k SetValue(i, 1, v) end -- up level line if upindex ~= nil then if C(upindex) > C(index) then for i = upindex, index do SetValue(i, 2, C(upindex)) SetValue(i, 5, C(upindex)-Settings.linedeltaY*C(vsize)/100) end veu = C(upindex) end end -- low level line if lowindex ~= nil then if C(lowindex) < C(index) then for i = lowindex, index do SetValue(i, 3, C(lowindex)) SetValue(i, 6, C(lowindex)+Settings.linedeltaY*C(vsize)/100) end vel = C(lowindex) end end if voldMaxindex >= voldMinindex then vsign = -1 if curfrom == voldMinindex then vsign = -1 end if curfrom == voldMaxindex then vsign = 1 end -- inclined line if curto- curfrom > 0 then maxcurv = 0 k = (C(curto)- C(curfrom))/(curto- curfrom) for i = curfrom, curto do curv = i*k + C(curto) - curto*k if vsign == -1 then if L(i) < curv then if maxcurv < curv - L(i) then maxcurv = curv - L(i) end end else if H(i) > curv then if maxcurv < H(i) - curv then maxcurv = H(i) - curv end end end end for i = curfrom, index do curv = i*k + C(curto) - curto*k + vsign*maxcurv SetValue(i, 4,curv) curv2 = curv+ vsign*Settings.linedeltaY*C(vsize)/100 SetValue(i, 7,curv2) end end curv = nil end if voldMaxindex <= voldMinindex then vsign = -1 if curfrom == voldMaxindex then vsign = 1 end if curfrom == voldMinindex then vsign = -1 end -- inclined line if curto- curfrom > 0 then maxcurv = 0 k = (C(curto)- C(curfrom))/(curto- curfrom) for i = curfrom, curto do curv = i*k + C(curto) - curto*k if vsign == -1 then if L(i) < curv then if maxcurv < curv - L(i) then maxcurv = curv - L(i) end end else if H(i) > curv then if maxcurv < H(i) - curv then maxcurv = H(i) - curv end end end end for i = curfrom, index do k = (C(curto)- C(curfrom))/(curto- curfrom) curv = i*k + C(curto) - curto*k + vsign*maxcurv SetValue(i, 4,curv) curv2 = curv+ vsign*Settings.linedeltaY*C(vsize)/100 SetValue(i, 7,curv2) end end curv = nil end end end end return ve, veu, vel, curv, veu2, vel2, curv2 end
Всем привет. С вами рубрика «Данные говорят». Да, это первый выпуск в этой рубрике). В этой рубрике мы будем разговаривать с данными. Нет, я не сошел с ума. Данные будут говорить, а я только слушать. А с вами данные тоже разговаривают?
Погнали. Под данными в данном случае имею в виду числа, графики числовых рядов, таблички и аналогичное. В данном конкретном случае речь про числа, графики, таблички по итогам бэктестов стратегии (её болванки, или другими словами корневой идеи).
Если уметь слушать данные, то можно многое услышать – например, например, можно находить баги в коде стратегии, интересные идеи, резервы и т.д. Затягиваешь параметром диапазон значений, а число трейдов растёт? – Ну значит где-то баг. Если вслушиваться в данные – иногда можно идентифицировать не только факт наличие бага, но и его локализацию и характер.
Теперь конкретней про «корреляция графиков зависимости лонга и шорта от значения параметра». Наверно, по формулировке не очень понятно, о чем речь. Тем более, предположу, что так глубоко и в эту сторону копают не только лишь все. Поэтому поясню: допустим, я хочу понять роль параметра А в стратегии, самый простой вариант – не шевеля параметры Б, В, Г и Д, перебирать А с некоторым шагом. Вот мы пошевелили А, не шевеля Б, В, Г, Д. А теперь для каждого прогона посчитали, допустим Profit Factor (возьмем его условно за некий показатель, характеризующий качество стратегии) отдельно для лонговых позиций и отдельно для шортовых. Ну и построили два графика – значение PF в зависимости от А для лонга и значение PF в зависимости от А для шорта. Так вот, иногда/часто эти графики будут прилично коррелировать.