Alex Maroudas
Alex Maroudas личный блог
23 февраля 2012, 14:55

О влиянии плечей на неопытных трейдеров

неплохая статья Анатолия Уткина,
перепост с http://anatoly-utkin.livejournal.com/7040.html

О влиянии плечей на неопытных трейдеров
23 февраля, 11:51
Для большинства не слишком искушенных трейдеров ценовые движения рынка представляют собой полностью случайное, броуновское движение. Почему это так, я попытался раскрыть здесь: http://www.2stocks.ru/utkin/?p=319. Если бы не было комиссий, то динамика счета такого трейдера также была бы броуновской, и он жил бы долго. При наличии комиссий происходит плавное сползание счета, то есть время на обучение ограничено. Но есть еще одна, очень существенная опасность для счета “броуновского” трейдера–это взятие плечей, и в настоящей статье я бы хотел пояснить существо этой проблемы.
ээДля моделирования ситуации возьмем случай вкладывания постоянной доли капитала. Тогда капитал после очередной сделки, s_next, выражается через капитал до этой сделки, s как s_next=s*(1+f*x/100), где f–доля вложенных средств, x–результат сделки на один лот. В этой простой формуле уже содержится ответ. Во-первых, следующий капитал–это предыдущий УМНОЖИТЬ на что-то. Поэтому если мы умножимся на ноль, то дальше капитал всегда будет нулем. Таким образом, критическим является вопрос о том, на что умножается капитал, то есть о величине (1+f*x/100). Ясно, что x не может быть слишком большим, по крайней мере, оно ограничено размером -100% (для лонга, по крайней мере). Поэтому для любых долей f, меньших единицы, множитель (1+f*x/100) всегда больше нуля, то есть на ноль при отсутствии плеча мы не умножимся никогда. Напротив, при f больших единицы (взятии плеча) существуют такие x, при которых множитель равен нулю. К примеру, при f=5 достаточно x=-20, чтобы капитал занулился. В общем-то, это очевидная вещь, но очевидные вещи надо повторять.
Рассмотрим теперь проблему количественно. Смоделируем динамику капитала трейдера при помощи генератора случайных чисел.  Для этого в формулу s_next=s*(1+f*x/100) будем подставлять в качестве x случайные числа. Здесь достаточно тонким является вопрос о выборе распределения для x. Очевидный, казалось бы, выбор распределения с нулевым средним (например, нормального) не будет правильным, поскольку при этом появится постоянное смещение счета вниз из-за геометрических эффектов. Не вдаваясь в детали, скажу, что правильным распределением будет, например, логнормальное. Запишу сразу конечную формулу для x, которая использовалась: x=exp(sigma*z)-1+M, где sigma–параметр, определяющий волатильность цены инструмента, z–случайная величина, распределенная нормально с нулевым средним и единичным СКО, M–параметр качества трейдера, для “броуновских” трейдеров он равен комиссии, для опытных он положителен.
Перейду к результатам моделирования. Прежде всего, рассмотрим случай отсутствия комиссий и плечей, то есть M=0, f=1. В этом случае счет показывает обычную броуновскую динамику:
401_1.jpg
Отсюда видно, что шансы продержаться неплохи, аж за 10000 сделок ничего особо не происходит (sigma равнялась 1%, что соответствует интрадэйным сделкам). Замечу, что по одной реализации выводы делать не стоит, поэтому в конце я привожу код VBA, по которому каждый может повторить это моделирование. Далее, введем комиссию в размере 0.03%. В общем-то, очевидно, что будет. Счет уменьшится на порядок за число сделок порядка 1/0.03%=около 3000 сделок:
401_2.jpg
Комиссии убивают счет и это путь неплечевых “броуновских” трейдеров. Вывод такой, что у “броуновского” неплечевого трейдера есть около 0.5/комиссия сделок, пока его счет уменьшится в два раза.
Теперь самое интересное–влияние плечей. Выберем в качестве f тройку–это соответствует вложению 300% капитала в каждую сделку. А комиссию занулим–без комиссий! Я привожу достаточно типичную картинку:
401_3.jpg
Это так похоже на работу многих трейдеров (смотри, например, на comon.ru), не правда ли? Рассмотрев множество таких картинок, можно прийти к выводу, что использование плечей СИСТЕМАТИЧЕСКИ убивает счет. То, что было нейтральным при отсутствии плеча (первый рисунок), становится убийственным при его присутствии. Качественные причины этого приведены во втором абзаце статьи. Ну, и наконец, динамика счет при наличии комиссии 0.03% и f=3:
401_4.jpg
Тут, как говорится, без комментариев. 500 сделок–и полсчета нет, 1000 сделок–нет счета полностью.
Выводы:
1) Не умеешь–не торгуй!
2) Если не знаешь, умеешь или нет, торгуй без плечей и пореже–будет больше времени научиться.
3) Единственный способ заработать–это сделать M положительным (то есть, как говорят, торговать с положительным матожиданием).  Но даже при этом большое плечо все равно убьет счет–желающие могут убедиться, поэкспериментировав с кодом.
””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””””
ээНиже прикладываю код VBA. Он выдает эквити в третий столбец того листа Excel, к которому он приложен. Последовательность действий:
1) Открываем новую книгу Excel (пусть она называется book1)
2) Жмем alt+F11–открываем Microsoft Visual Basic
3) Слева  выбираем VBAProject (book1)–Microsoft Excel Objects–Sheet1. Жмем туда правой кнопкой мыши и выбираем View Code
4) В открывшуюся вкладку копируем код.
5) Жмем на сохранить
6) Возвращаемся в excel, жмем alt+F8 и выбираем макрос Sheet1.Leverage. Запускаем его–три первых столбца листа Sheet1 должны заполниться.
7) Строим диаграмму в виде графика по третьему столбцу.
8) Управление параметрами M (comiss в коде), share и sigma–через код VBA. Положительные M соответствуют положительной комиссии и приводят к убыванию счета.
“”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”"”
Option Explicit
Sub Leverage()
Dim i, imax As Integer
Dim s, comiss, sigma, share, x, y As Single
imax = 10000
For i = 2 To imax
x = Rnd()
y = Rnd()
Cells(i, 1) = (-2 * Log(x)) ^ (0.5) * Cos(2 * 3.1415926 * y)
Next i
sigma = 1
sigma = sigma / 100
comiss = 0.03
comiss = comiss / 100
share = 3
For i = 2 To imax
Cells(i, 2) = Exp(sigma * Cells(i, 1)) — 1 — comiss
Next i
s = 1
For i = 2 To imax
s = s * (1 + share * Cells(i, 2))
If s < 0 Then s = 0
Cells(i, 3) = s
Next i
End Sub
81 Комментарий
  • Daytrader
    23 февраля 2012, 15:34
    Плечо — это обычный мультипликатор. Никак на торговлю оно не влияет, выводы высосаны из пальца. Плечо высвобождает лишние финансы из-под залога, что хорошо. Поэтому, больше плечи — лучше.
    • anatolyutkin
      29 июля 2013, 13:30
      Дейтрейдер, Не высосаны. Поиграем в игру. У вас--1000 рублей, у меня--триллион рублей. Вы выбираете некоторую ставку, в случае вашего выигрыша я выплачиваю вам ее, в случае вашего проигрыша-вы выплачиваете мне ставку. Игра такова, что вы выигрываете в среднем в 80% случаев--то есть в четыре раза чаще чем я. Вы можете регулировать ставку.

      Эта игра моделирует систему рынок-трейдер. Вы--очень хороший трейдер, я--рынок.

      В этой игре вы, если будете ставить все, что у вас есть, неизбежно проиграете. Даже с гигантским перевесом в шансах 80/20. Тогда как если будете ставить 1/10 капитала--будете жить за мой счет долго и счастливо. Вот про это и статья.
  • Скальпёр
    23 февраля 2012, 15:57
    огромный плюс! спасибо большое!
    • anatolyutkin
      29 июля 2013, 13:31
      URKA, Пожалуйста :)
  • Мурен(а)
    27 июля 2013, 18:41
    anatolyutkin, ваше творение?
  • Мурен(а)
    27 июля 2013, 18:46
    автору: лучше сохранять картинки на смартлабе, а не просто ссылки на них. когда -нибудь на 2stocks будет переезд на другой адрес и этих картинок мы здесь уже не увидим
    • anatolyutkin
      29 июля 2013, 13:31
      Евгений Александрович-1, Да, мое. Про картинки--согласен. Но работать лень :)
  • ES1667
    27 июля 2013, 18:49
    VBA не Си. Переменные так не декларируются — цедьной строкой. Каждую надо индивидуально.
    • anatolyutkin
      29 июля 2013, 13:31
      ES1667, Приведенный код--рабочий. Проверьте.
      • ES1667
        29 июля 2013, 14:22
        anatolyutkin, зачем мне проверять? Мне глаз хватает :)
        Я не утверждал, что «код нерабочий».
        Да, собственно, весь код :down:

        В этом беда — тупо копипастят не читая и даже не задумываясь — что, куда, зачем… Влазит в экран, не влазит. Лишь бы «плюсикофф, плюсикофф!»
      • ES1667
        29 июля 2013, 14:26
        anatolyutkin, я не обратил внимание, что ты и есть оригинальный автор материала. Если нужны подробные замечания по коду — велкам. Потрачу малость времени :)
        • anatolyutkin
          29 июля 2013, 14:39
          ES1667, Я не программист--так что любые замечания с удовольствием принимаются.
          • ES1667
            29 июля 2013, 15:37
            anatolyutkin, так, если не программист, надо ли оно?

            Ну, самое первое — то, с чего начали — декларация переменных.

            В VBA надо декларировать _каждую_ переменную. В твоей записи:

            Dim i, imax As Integer
            Dim s, comiss, sigma, share, x, y As Single

            явно продекларированы только imax и y. Всем остальным по умолчанию присвоен тип variant.

            Правильной запись будет такой:

            Dim i As Integer, imax As Integer
            Dim s As Single, comiss As Single, sigma As Single, share As Single, x As Single, y As Single

            или, сократив:

            Dim i%, imax%
            Dim s!, comiss!, sigma!, share!, x!, y!

            Чуть позже отпишусь по остальным скользким моментам.
            • anatolyutkin
              29 июля 2013, 16:53
              ES1667, Мне--надо. Я трейдер :)

              По поводу декларирования. Попробовал--да, вы правы. Вот такой код:
              Option Explicit
              Sub a()
              Dim x, y As Single
              MsgBox (TypeName(x))
              End Sub
              выдает x как empty(то есть variant в итоге), а код:

              Option Explicit
              Sub a()
              Dim x as Single, y As Single
              MsgBox (TypeName(x))
              End Sub
              выдает x как Single. Спасибо!
              • ES1667
                29 июля 2013, 17:15
                anatolyutkin, ОК.

                В данном случае это, может, и не принципиально, но коллизий преобразования типов могут вылезти где и когда угодно. Поэтому — декларируем все явно. В этом контексте — респект за тсрользование Option Explicit. Грамотно и полезно.

                Идем далее.

                x = Rnd()
                y = Rnd()

                Мало того, что это делается в цикле (тут свои подводные камни), так еще и без использования Randomize.

                У меня не было времени понять истинное математическое назначение этих рэндомов. Но в данном написании и x, и y будут генериться из ОДНОГО И ТОГО ЖЕ ряда. Я чуть позже вернусь, а ты пока загляни в хэлп VBA по этим функциям — там кратенько описаны нюансы каждой ф-ции.

                If Randomize is not used, the Rnd function (with no arguments) uses the same number as a seed the first time it is called, and thereafter uses the last generated number as a seed value.
                • anatolyutkin
                  29 июля 2013, 18:05
                  ES1667,
                  «В данном случае это, может, и не принципиально, но коллизий преобразования типов могут вылезти где и когда угодно.»
                  Это уж точно. Я к option explicit не так просто пришел :)

                  По Rnd()--а) согласен, и б) я в курсе--данные действительно из одного квазислучайного ряда. Для целей данной заметки сойдет и так--ибо:
                  а) требования к рандому невилики
                  б) заметка все-таки не рассчитана на высокий уровень владения математикой и программированием--так что код самый простейший.
                  Но если по уму, то мне вообще рандом экселевский не нравится. Более хороший ГСЧ--вихрь Мерсенна, есть и куча других. Обсуждалось у меня на блоге: www.2stocks.ru/utkin/?p=113 В комменты тоже загляните--до седьмого, дальше спам.
                  • ES1667
                    29 июля 2013, 18:31
                    anatolyutkin, взгляну обязательно.

                    Про рэндомы — главное что ты в курсе и что это — сознательное допущение, а не неведение. Но! Я не случайно рекомендовал в хелп заглягуть.

                    The Rnd function returns a value less than 1 but greater than or _equal_to_zero_!!!
                    Как тебе? Log(0), а?

                    Идем далее. Не забываем, что я докапываюсь по канону :)

                    Все исходные — синглы, но расчеты ты ведешь, базируясь на значениях ранее расчитанных ячеек. А в них хранятся — даблы. Ты аостоянно то пишешь на лист, то читаешь с него. Медленная и некорректная операция с т.з. что задействован механизм Экселя — расчеты на листе, который может еще и измениться.

                    Вот. Загрубляется значение Cells(i, 2):
                    s = s * (1 + share * Cells(i, 2))
                    If s < 0 Then s = 0
                    Cells(i, 3) = s

                    Опять же — вероятность коллизий. Поэтому — делаем дополнительные переменные для каждого этапа вычисления и потом разом сбрасываем их на лист.

                    Я шары по очереди выкатываю, чтобы не в куче, а постепенно. Я потом выложу окончательный код, как я его вижу.
                  • ES1667
                    29 июля 2013, 21:25
                    anatolyutkin, за ссылку снкс. Посмотрел.
                    А генератор вот сюда переехал
                    www.ntrand.com/
                  • ES1667
                    29 июля 2013, 22:18
                    anatolyutkin, вот уточненный варинат:

                    Sub Leverage_21()

                    Const PIPI As Double = 3.14159265358979

                    Dim dS#, dComiss#, dSigma#, dShare#, _
                        dX#, dY#, dVal#(1 To 3) ' все в даблах
                    Dim i%, iMax%
                    Dim j As Byte
                        
                        iMax = 10000
                        
                        dSigma = 1:      dSigma = dSigma / 100
                        dComiss = 0.03:  dComiss = dComiss / 100
                        dShare = 3
                        dS = 1
                        
                        Randomize ' инициализация Rnd
                        For i = 2 To iMax
                            dX = Rnd(): dY = Rnd()
                            
                            dVal(1) = ((-2 * Log(dX)) ^ (0.5)) * Cos(2 * PIPI * dY)
                            dVal(2) = Exp(dSigma * dVal(1)) — 1 — dComiss
                            dS = -dS * (1 + dShare * dVal(2)) * CInt(dS > 0)
                            dVal(3) = dS ' dS оставлено для понимания
                            
                            For j = 1 To 3
                                Cells(i, j).Value = dVal(j)
                            Next
                            
                            If dS = 0 Then Exit For ' добавил от себя
                        Next
                    End Sub
                    • ES1667
                      29 июля 2013, 22:26
                      ES1667, по уму, так надо вынести генератор в отдельные циклы перед основным:
                      Dim dXX#(), dYY#()
                          ReDim dXX(2 To iMax): ReDim dYY(2 To iMax)
                          
                          Randomize ' инициализация Rnd
                          For i = 2 To iMax
                              dXX(i) = Rnd
                          Next
                          
                          Randomize ' инициализация Rnd
                          For i = 2 To iMax
                              dYY(i) = Rnd
                          Next

                      а в основном цикле убрать генерирование на лету, и подсталять элементы массивов.
                      • ES1667
                        29 июля 2013, 22:28
                        ES1667, в таком варианте dXX(i) и dYY(i)будут из независимо сгенеренных рядов, а не последовательно выбранные из одного ряда.
                        • anatolyutkin
                          29 июля 2013, 23:48
                          ES1667,
                          1) Спасибо большое! Честно говоря, просто приятно :)
                          2) Я, когда роботов пишу, то за каждое замечание типа тех, что вы делаете, плачу деньги. И немалые :) И культура кода нарабатывается путем денежных ударов по башке :)
                          3) По деталям:
                          а) Логарифма нуля бояться не надо. Вероятность того, что x будет нулем, равна нулю. Вообще, это стандартный способ получения нормального распределения из двух равномерных. Подробнее здесь: www.rsdn.ru/forum/alg/1513899.flat --второй коммент (ссылка не особо, просто первое, что попалось в гугле)
                          б) Постоянно пересчитывать из переменной в ячейку листа и обратно--это дурной стиль, согласен. Когда эта статья писалась, я на тиках еще не тестировал, сейчас бы мне такая мысль даже в голову бы не пришла.
                          в) За код спасибо--буду изучать новые приемы. Честно говоря, там есть некоторые вещи, про которые я просто не знал.
                          • ES1667
                            30 июля 2013, 00:34
                            anatolyutkin, рад, что оказался полезен.
                            Чай, и мы в лесу не звери ?)

                            По логарифму… Я не математик, поэтому это утверждение могу только на веру принять. А с точки зрения канонов программирования — лучше предостеречься. х ведь у нас генерится через Rnd, а в мануале написано: Rnd возвращает «greater than or equal to zero» — надо выполнять, поскольку у нас Log(Rnd())

                            И, все-таки, я хотел бы услышать твое авторитетное мнение касательно правильности генерации x и y для обеих частей итогового генератора
                            ((-2 * Log(dX)) ^ (0.5)) * Cos(2 * PIPI * dY)

                            Правильна ли моя посылка, что генераторы каждого должны быть полностью изолированы друг от друга — по последнему моему варианту? Я-то в этом слабо разбираюсь :(
                          • ES1667
                            30 июля 2013, 01:32
                            anatolyutkin,
                            обнfружил ошибку в своем коде!

                            Необходимо заменить

                            dS = -dS * (1 + dShare * dVal(2)) * CInt(dS > 0)

                            на

                            dS = -dS * (1 + dShare * dVal(2))
                            dS = -dS * CInt(dS > 0) ' или If Not (dS > 0) Then dS = 0
                            • anatolyutkin
                              30 июля 2013, 10:29
                              ES1667,
                              «Правильна ли моя посылка, что генераторы каждого должны быть полностью изолированы друг от друга — по последнему моему варианту? Я-то в этом слабо разбираюсь :(»

                              Да, конечно. Строго говоря, равномерно распределенные на [0,1] случайные величины x и y должны быть независимы друг от друга. Вот ссылку нормальную нашел: ru.wikipedia.org/wiki/%D0%9F%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D0%91%D0%BE%D0%BA%D1%81%D0%B0_%E2%80%94_%D0%9C%D1%8E%D0%BB%D0%BB%D0%B5%D1%80%D0%B0

                              Я в свое время когда этот метод генерации нормального распределения осваивал, пришел к выводу, что можно не морочиться особо для грубых целей--и писать как в моем коде. Если же по уму, то надо действовать как вы--изначально рожать два независимых случайных массива. Кроме того, надо отдельно прописать случай, когда x=0 (в этом случае ответ должен быть плюс или минус машинная бесконечность, либо менять x в этом случае на 1E-15).
                              • ES1667
                                30 июля 2013, 12:27
                                anatolyutkin, ага. Понял. Вот тогда окончательный вариант с учетом поправок. Надеюсь нет ни ошибок, ни опечаток. Проверь сам обязательно:)

                                Обрати внимание на жирное — как проводится проверка на ноль. Это тебе на будущее (безотносительно к твоему коду, просто — важный момент) — никогда не проверяй даблы и пр. с плав. точкой на равенство! Нулю, другому даблу и пр. Только на больше-меньше.

                                ------------------------------------------------
                                Sub Leverage_22()

                                Const PIPI As Double = 3.14159265358979
                                Const MIND As Double = 4.94065645841247E-324

                                Dim dS#, dComiss#, dSigma#, dShare#, _
                                    dXX#(), dYY#(), dVal#(1 To 3) ' все в даблах
                                Dim i%, iMax%
                                Dim j As Byte
                                    
                                    dSigma = 1:      dSigma = dSigma / 100
                                    dComiss = 0.03:  dComiss = dComiss / 100
                                    dShare = 3
                                    dS = 1
                                    
                                    iMax = 10000
                                    ReDim dXX(2 To iMax): ReDim dYY(2 To iMax)

                                    Randomize ' инициализация Rnd
                                    For i = 2 To iMax
                                        dXX(i) = Rnd
                                        ' закомментировать ненужное
                                        If Not (dXX(i) > 0) Then dXX(i) = Rnd  ' сгенерить следующее
                                        If Not (dXX(i) > 0) Then dXX(i) = MIND ' взять мин возм double
                                        If Not (dXX(i) > 0) Then dXX(i) = CDbl(«4E-324») ' взять мин возм double
                                    Next

                                    Randomize ' инициализация Rnd
                                    For i = 2 To iMax
                                        dYY(i) = Rnd
                                    Next
                                    
                                    For i = 2 To iMax
                                        dVal(1) = ((-2 * Log(dXX(i))) ^ (0.5)) * Cos(2 * PIPI * dYY(i))
                                        dVal(2) = Exp(dSigma * dVal(1)) — 1 — dComiss
                                        
                                        dS = dS * (1 + dShare * dVal(2))
                                        If Not (dS > 0) Then dS = 0 ' dS = -dS * CInt(dS > 0)
                                        
                                        dVal(3) = dS ' dS оставлено для понимания
                                        
                                        For j = 1 To 3
                                            Cells(i, j).Value = dVal(j)
                                        Next
                                        
                                        'If dS = 0 Then Exit For ' добавил от себя
                                    Next
                                End Sub
                                • anatolyutkin
                                  30 июля 2013, 15:31
                                  ES1667,
                                  Все изучил--код рабочий. Особое спасибо за вот это:
                                  Dim dS#, dComiss#. Ибо переменные надо объявлять правильно--это очень важно.

                                  Вопросы:
                                  1) почему нельзя проверять на равенство floating point?
                                  2) Что делает команда CInt(dS>0). CInt(dS)--преобразует dS в целую. А CInt(dS>0)?
                                  • ES1667
                                    30 июля 2013, 15:50
                                    anatolyutkin,

                                    1. Сравнивать, конечно, можно, но ясно отдавать себе отчет — что ты делаешь и зачем. Это особенности вычислений с плавающей точкой. Можно дисер написать :) Загугли фразу «сравнение double».

                                    2. «dS > 0» дает boolean true или false, а «CInt(dS>0)» преобразует в, соответственно, "-1" или «0». Можно было написать короче, положившись на неявное преобразование типов «dS = -dS * (dS > 0)»

                                    Имеем выигрыш и в записи и в скорости.

                                    Тут надо иметь ввиду, что это справедливо лишь для VBA(VB). Если портировать на C++, к примеру, то там «false == 0» тоже, а вот «true == +1», а не "-1".

                                    И, кстати, в самом Экселе, на листе, нотация именно как в C++ :) Чехарада, то есть…
                                    • ES1667
                                      30 июля 2013, 15:53
                                      ES1667, сравнение на больше-меньше позволяет обойти большинство подводных камней.

                                      Также — никогда не используй VBA-шную ф-цию округления Round() — это не школьное округление! Школьное, как раз, реализовано в ф-ции листа Эксель.
                                      • anatolyutkin
                                        30 июля 2013, 16:31
                                        ES1667, Что не так с Round()? Пишу MsgBox (Round(4.49999999))--выдает 4, пишу MsgBox (Round(4.511111))--выдает 5. Вроде, ровно все? Единственное, для ровно 4.5 Round выдает 4, в отличие от школьного алго, где будет 5. Но это фигня--одна точка ничего не значит.
                                        • ES1667
                                          30 июля 2013, 16:45
                                          anatolyutkin, ты не заморачивайся с этими MsgBox. Люди вот так делают, если из кода:
                                          Debug.Print Round(4.49999999)

                                          А можно прямо из окна дебаггера — Immediate Window — Ctrl+G:
                                          ? Round(4.49999999)

                                          Это явно не документировано, но если до запятой четное — то округляет в меньшую, если нечетное — то в большую:
                                          ? Round(12.5)
                                          12
                                          ? Round(13.5)
                                          14
                                          ? 13.5 — 12.5
                                          1
                                          ? Round(13.5) — Round(12.5)
                                          2

                                          Так что — совсем не фигня. В цепочках вычислений такую муть тебе наведет… На порядки улететь можно… Будешь считать пересеение мувингов :) А, тем более, ты ММ считаешь…

                                          Но, дело хозяйское. Мое дело — предупредить.
                                          • anatolyutkin
                                            30 июля 2013, 17:27
                                            ES1667, Нда, такое округление--это весело! Остается лишь вопрос--а откуда про это узнать можно :)

                                            Ладно, спасибо большое за проведенные уроки. Такие вещи способны сэкономить кучу времени. Если будут программистские вопросы--обращусь. Хотя обычно сам во всем разбираюсь--правда, времени уходит много :)

                                            Я не считаю пересечения мувингов--такие трендовые системы уже плохи для меня. И тем более не считаю ММ--а что там считать то? Там вычисления на уровне два плюс два. К примеру, в обсуждаемой статье как ни верти--плечи и/или комиссы убьют счет--это очевидно вообще без расчетов (см. мой коммент к этой статье от 29.07 13:30)--что и написано в самом начале статьи. Вообще, мой подход к трейдингу изложен здесь: anatoly-utkin.livejournal.com/10280.html и здесь: anatoly-utkin.livejournal.com/14058.html

                                            Общие слова. Любая корректно поставленная задача является грубой. То есть важна сама идея--а детали расчетов не принципиальны (до определенной степени, конечно--тут все расплывчато). В трейдинге (да и вообще в реальном мире) все задачи--грубые. Поэтому если торговая система работает только при периоде мувинга в 157 (это Резвяков небезызвестный рассказывал)--то это плохая система. Также и хороший алгоритм не должен быть особо чувствителен к мелким деталям. Но тут вопрос--что такое мелкие? :)
                                            • ES1667
                                              30 июля 2013, 17:41
                                              anatolyutkin, откуда узнать? Ну, из таких вот диалогов, как наш, например :) Из опыта… Инфы полно — но она вся разбросана.

                                              Но, я тебя просто так не отпущу :) Я твою задачу модернизирвал в несколько ином разрезе. Хотел, чтобы ты взглянул на корректность моих выкладок. Я имею ввиду не выводы по результатам, хоть они и очень интересны, а методику алгоритма на формальную правильность.

                                              Вот, картинка для затравки:



                                              Это 1000 раз прогнанный твой тест, только на реальном контракте CME ES, с реальными комиссами и реальной маржой от депо 50К. По оси Y — шаг, на котором депо становилось меньше залоговой маржи, т.е. невозможность открыть хотя бы одну позу по этому контракту.

                                              Обрати внимание — достаточно много несливных прогонов — потолок 10000.
                                              • ES1667
                                                30 июля 2013, 17:42
                                                ES1667, по нему бы колокол построить… чтобы распределение посмотреть…
                                                • ES1667
                                                  30 июля 2013, 17:50
                                                  ES1667, а округление это ВБА-шное — совершенно правильное, даже название свое имеет. Только нам не походит :)
                                              • anatolyutkin
                                                30 июля 2013, 17:58
                                                ES1667, Да не нужно это все :) Основная модель рынка, отвечающая на все подобные вопросы--это СБ. И ответ для распределений, вероятностей, итд на реальных ликвидных рынках получится такой, какой должен быть для СБ. Имхо, конечно, но это неплохое такое имхо :)

                                                А по поводу картинки--очевидно, что за конечное время (10000 шагов) есть шанс, что счет не сольется. И вы приближенно, методом Монте-Карло, сосчитали вероятность этого--это число несливных прогонов, деленное на общее число прогонов. Можно строить зависимости этой вероятности от времени, комиссов, плечей, итд. Но все это--вещь в себе и не особо нужно (для трейдера, по крайней мере).
                                                • ES1667
                                                  30 июля 2013, 18:11
                                                  anatolyutkin, что здесь значит СБ?
                                                  • ES1667
                                                    30 июля 2013, 18:29
                                                    anatolyutkin, «вы приближенно, методом Монте-Карло, сосчитали вероятность этого--это число несливных прогонов, деленное на общее число прогонов» — Если бы Остап знал, что играет такие мудреные партии, то сильно удивился бы :)

                                                    Я просто прогнал тест из 10000 циклов 1000 раз и на оси Y отложил цикл, на котором депо заканчивалось :)

                                                    А сделал это из того, что, резонно предположив, что я не броуновский трейдер и 50К за 3-4 тыс ходок явно не солью, меня сильно заинтересовал параметр М:
                                                    «M–параметр качества трейдера, для “броуновских” трейдеров он равен комиссии, для опытных он положителен.»

                                                    Твой вариант с равенством его комиссии изучен. Давай двинемся дальше — как его, М, можно модифицировать, чтобы приблизить к реалиям конкретного трейдера?
                                                    • anatolyutkin
                                                      30 июля 2013, 23:10
                                                      ES1667, СБ--случайное блуждание. Каждый следующий шаг не зависит от предыдущего. Я же ссылок кучу дал :)

                                                      «Если бы Остап знал, что играет такие мудреные партии, то сильно удивился бы :)

                                                      Я просто прогнал тест из 10000 циклов 1000 раз и на оси Y отложил цикл, на котором депо заканчивалось :) „

                                                      Я понимаю :) Я просто переформулирую на более глубокий язык то, что вы сделали :)

                                                      В коде для изучения ситуации в зависимости от М надо регулировать comiss. Используемая формула: s = s * (1 + share * Cells(i, 2))--это пересчет капитала на каждом шаге (я кривой изначальный код использую--разберетесь), Cells(i,2)--это случайная величина, являющаяся суммой логнормального распределения (exp(sigma*N)-1, где N--нормально (0,1) распределенная величина) и постоянного смещения comiss (которое есть comiss=комиссия (% от суммы сделки) минус средняя сделка трейдера (%)). Соответственно, единственный параметр в коде, отвечающий за качество работы трейдера--это comiss. Отрицательные comiss соответствуют тому, что трейдер зарабатывает больше, чем тратит на комиссии.
                                                      • ES1667
                                                        30 июля 2013, 23:58
                                                        anatolyutkin, формулу расчета я вкурил прежде, чем высказать свой вердикт о коде :)

                                                        Именно поэтому и спрашиваю. В рамках данной статьи и приведенного кода в предположении, что трейдер — броуновский, М принимается равным комиссии. Если комиссию примем за К, а трейдера за Т, то формула М будет следующей:
                                                        или М = К — Т (для броуна Т = 0, для сознательного Т > 0)
                                                        или М = К / Т (бля броуна Т = 1, для сознательного Т > 1)

                                                        Мне хочется понять — как перейти от броуновских Т к более-менее реальным?
                                                        • ES1667
                                                          31 июля 2013, 00:02
                                                          ES1667, мне нужна реальная, а не абстрактная модель. Комиссы у меня фиксированные, не в процентах, и четко известные. Остается неизвестная Т. Ведь говоря о Т, как о конкретной величине, соответсвтующей броуновскому скиллу трейдера, ту, предполагаю, имел ввиду некоторые ее значения, соответствующие более высокому скиллу?
                                                          • anatolyutkin
                                                            31 июля 2013, 09:34
                                                            ES1667,
                                                            1) Если комиссы фиксированные (в рублях), то их надо вычитать непосредственно из счета. Вот так: s=s(1+share*x)-comiss.
                                                            2) Если комиссы в процентах, то применима моя формула, где М=К-Т.
                                                            3) Еще раз, Т--это средняя сделка трейдера в %. Я ее не могу знать для вас. У меня для разных систем она варьируется от единиц до сотых долей процента.
                                                            4) Из другой оперы. Хочу, чтобы некий код (Account) исполнялся один раз в час в течение недели. Вот код:

                                                            Sub Start_System()

                                                            Dim T, Delta As Date
                                                            Dim i As Integer
                                                            T = Now
                                                            Delta = 0.04166

                                                            Application.OnTime TimeValue(T + 0.0007), «Account»
                                                            For i = 1 To 168
                                                            Application.OnTime TimeValue(T + i * Delta), «Account»
                                                            Next i

                                                            End Sub

                                                            Кривость задания дельты теперь осознаю. Код работает некорректно. Симптомы: первые сутки после запуска работает, а дальше--нет. С чем это может быть связано?
                                                            • ES1667
                                                              31 июля 2013, 10:12
                                                              anatolyutkin, по п.4

                                                              Application.OnTime мне не нравится. Какие-то траблы по ней были и оговорки. Пороюсь в архивах — я там плотно ее прорабатывал. Чуть позже отпишусь.

                                                              А навскидку — не связыывайся ты с явными даблами, не задавай их явно, константой, как ты присвоил дельту и пр. Вкури представление датыа в VBA — целая часть — число дней откуда-то там, дробная — часть суток. Отсюда и пляши.

                                                              0. T опять непродекларирована
                                                              1. Delta = 1 / 24
                                                              2. Ты задаешь сразу все события. Я бы не стал. Скорее всего там есть какие-то ограничения и интерференции. Шедулер-то не бесконечный. Назначай следующее задание из процедуры Account по коректному ее завершению. Другими словами — запусти Account один раз и она по завершении будет сама себя назначать.
                                                              • ES1667
                                                                31 июля 2013, 12:35
                                                                anatolyutkin, по п.4

                                                                Нашел я. Оказалось под руками :) И все вспомнил.
                                                                Я хотел через OnTime прикрутить к собственному календарю событий прикрутить оповещатель. Малой кровью типо обойтись. Хрен там. Плюнул. Код — сплошные костыли. Кривая эта OnTime, как турецкая сабля.

                                                                Ты подключи к проекту библиотеку Access. Там есть прекрасный асинхронный таймер формы. Я тебе класс готовый для работы с ним подкину. Робот у меня с ним работает неделями. Это стопудово проверено.
                                                                • anatolyutkin
                                                                  31 июля 2013, 14:04
                                                                  ES1667, Аксессную dll подключить недолго (правда, найти бы ее еще--так вот сразу в tools--references ее нет). А вот дальше что делать? :)

                                                                  Про дату я в курсе. А 0.04166=1/24 :)
                                                                  • ES1667
                                                                    31 июля 2013, 15:47
                                                                    anatolyutkin,
                                                                    понятно-то — понятно, что 1/24, а вот запись некорректная.
                                                                    ? 1/24
                                                                    4.16666666666667E-02

                                                                    • ES1667
                                                                      31 июля 2013, 16:11
                                                                      anatolyutkin, подожди пока, не ломай мозг с Аксом — там все не так просто :(
                                                                      • ES1667
                                                                        31 июля 2013, 16:57
                                                                        anatolyutkin, с Аксом не связывайся. Давай попробуем с этим OnTime разобраться. Ты так и не ответил — зачем тебе первый таймер через 60.48 сек и 168 щтук через час каждый, все завязанные на одну процедуру?

                                                                        И еще вопросы:
                                                                        — что в этой процедуре?
                                                                        — отТкуда есть еще обращения к OnTime?
                                                                        • anatolyutkin
                                                                          31 июля 2013, 20:38
                                                                          ES1667, Это бухучет сделок. Мне неохота нажимать на кнопки для торговли даже один раз в день--хочу раз в неделю.
                                                                          • anatolyutkin
                                                                            31 июля 2013, 20:39
                                                                            anatolyutkin, 60.48 секунд--это случайность. Люблю повеселиться :)
                                                                            • ES1667
                                                                              31 июля 2013, 20:54
                                                                              anatolyutkin, «60.48 секунд--это случайность. Люблю повеселиться :)»
                                                                              Респект. Всякие шедуллеры как раз надо не по нулям ставить, а со сдвигом — чтобы вероятность пересечения с другими была ниже.
                                                                              • anatolyutkin
                                                                                31 июля 2013, 21:07
                                                                                ES1667, Да, причина веселья именно такая.

                                                                                Предлагаю эту тему закрыть, раз простых решений нам не известно. Я думал, что вы, такой крутой, все сразу скажете :) Поиграюсь с onTime, придумаю, как все наладить. На самом деле я обычно каждый день на рынок поглядываю, так что не в напряг запустить. Оно уж так работает кучу времени--годы :) Кроме того, можно и с сотового зарядить макрос--ибо все давно через виртуалку реализовано.
                                                                          • ES1667
                                                                            31 июля 2013, 21:00
                                                                            anatolyutkin, «Это бухучет сделок»
                                                                            Я не про это :) Я спрашивал — что там такого в коде этой процедуры, что для нее требуется 168 + 1 автономных таймера?

                                                                            Ты не ответил:
                                                                            — откуда есть еще обращения к OnTime?

                                                                            Почему не обойтись одним, перезаряжаемым таймером?
  • anatolyutkin
    29 июля 2013, 13:25
    Ого! В перепост попал. Всем ответил выше.
  • ES1667
    01 августа 2013, 10:10
    anatolyutkin, в контексте «Я пока только готовлю вопросы»
    Прежде всего хочу спросить именно по заголовку статьи — про плечо :)

    В твоих расчетах плечо — константа. В реальности же, при прочих равных, плечо пропорционально уменьшается с ростом депо и наоборот.
    • anatolyutkin
      01 августа 2013, 10:51
      ES1667, Почему? Формула: s=s(1+share*deal_result) описывает случай постоянной доли. То есть в каждую сделку вкладываем share*100 процентов капитала. И от капитала доля и плечо не зависят.
      • ES1667
        01 августа 2013, 11:02
        anatolyutkin, контракт-то остается один. Или я что-то не так понял?

        «x–результат сделки на один лот.»
        • anatolyutkin
          01 августа 2013, 11:14
          ES1667, deal_result--это % результат на вложенное в сделку.

          Вообще говоря, мной применено приближение малого лота. То есть размер лота много меньше размера капитала. В рамках такого приближения мы можем войти точно 23.45% капитала. Условно говоря, у нас 1 мио, а торгуем акцией стоимостью в 1 рубль. Или у нас 100 ярдов, а торгуем RI стоимостью в 100к. Конечно, это приближение, а реально надо учитывать конечную дискретизацию лота (особенно когда капитал уже мал и сравним с размером лота)--но это ничего принципиально не поменяет.
          • anatolyutkin
            01 августа 2013, 11:18
            anatolyutkin, А в реальности я, например, торгую именно постоянную долю. Конечно, я не имею возможности менять лот, скажем, на RI или TRNFP при небольших изменениях капитала--у меня нет 100 ярдов :) Но это все мелкие брызги.
            • ES1667
              01 августа 2013, 11:27
              anatolyutkin, anatolyutkin, дискретность — это другая тема. На данном этапе можно пренебречь.

              Да, если мы торгуем 1 контрактом, то мы задействуем 100% капитала.

              Плечо = Цена_Контракта / Депо

              Растет депо — уменьшается плечо и наоборот. Изменением Цена_Контракта можно пренебречь, в рамках описанной модели (sigma = 1%)
              • ES1667
                01 августа 2013, 11:44
                ES1667, ну, может быть

                Плечо = Цена_Контракта / (Депо — Маржа)
                • anatolyutkin
                  01 августа 2013, 12:39
                  ES1667, Плечо=вкладываемая доля капитала/1. Если вкладывается 100% капитала, то плечо=1, если 200%--то плечо=2, если 50%--то плечо=0.5. При этом вкладываемая доля капитала=цена одной акции(контракта)*количество акций(контрактов)/депо. К примеру, у меня 65к рублей. Я купил 1 лот RI. Полная цена 1 лота RI равна 100к (условно). Тогда плечо=(100к*1 лот)/65к=100/65=1.5. Для двух лотов плечо равно 2*100/65=3. А от ГО плечо вообще не зависит.
                  • ES1667
                    01 августа 2013, 13:20
                    anatolyutkin, ОК. Давай к ГО вернемся позже. Пока не будем учитывать его.

                    Я примерно понимаю твою мысль, но лишь примерно. Прокомментируй, плз:

                    CME, ES (50$ x Indes S&P500). Торгуем одним контрактом.
                    Цена 85'000, депо 50'000, плечо 1.7

                    Если сделка идет в профит +10000 с S&P 1'700 на 1'900
                    Цена 95'000, депо 60'000, плечо 1.58 или
                    Цена 85'000, депо 60'000, плечо 1.42 без учета роста.

                    Если сделка идет в лосс -10000 с S&P 1'700 на 1'500
                    Цена 75'000, депо 40'000, плечо 1.88 или
                    Цена 85'000, депо 40'000, плечо 2.13 без учета падения.

                    Понятно, что внутри дня такого движняка не будет и официальный пересчет будет только на клиринге. Поэтому, при принятой sigma = 1% и установке интрадей можно пренебрегать изменением цены контракта.
                    • anatolyutkin
                      01 августа 2013, 14:21
                      ES1667, Это не моя мысль, это определение плеча :)

                      Вот что у меня: s=s(1+share*x). x--это результат закрытой (купил-продал или вшортил-откупил) сделки. То есть внутрь сделки мы просто не лезем. То есть x--это результаты сделок и прямой связи с графиком инструмента они вообще не имеют.
                      • anatolyutkin
                        01 августа 2013, 14:25
                        anatolyutkin, Пример по ES. Купили по 40000, продали по 50000. Результат этой сделки +25% на вложенное. Капитал до сделки был 100к, купили на 200к. Тогда плечо=2, капитал после сделки равен 100*(1+2*0.25)=150к. Вот и все дела.
                        • anatolyutkin
                          01 августа 2013, 14:32
                          anatolyutkin, Еще одно. Может, термин «результат сделки на вложенное»--не особо удачный. Вот определение результата сделки: результат сделки=(цена выхода-цена входа)/цена входа для лонга и результат сделки=(цена входа-цена выхода)/цена входа для шорта.
                        • ES1667
                          01 августа 2013, 14:59
                          anatolyutkin, актив и ПЛ изменяются неодинаково. Стоимость пункта фиксирована, а не изменяется вместе с ценой актива. Ты это игнорируешь, вот у тебя и получается «просто».

                          Вообще-то, я просил тебя прокомментировать мои выкладки. Будь добр.
                        • ES1667
                          01 августа 2013, 15:11
                          anatolyutkin,
                          вот определение результата сделки: результат сделки=(цена выхода-цена входа)/цена входа для лонга и результат сделки=(цена входа-цена выхода)/цена входа для шорта.
                          Я не знаю, где ты берешь такие «определения» и «формулы». Искренне удивлен… :((

                          PL = (Price_In — Price_Out) * Deal_Side, где
                          Deal_Side = -1 для BUY, LONG и
                          Deal_Side = +1 для SEL, SHORT

                          Знаки — не принципиально, можно поменять, переставив местами слагаемые. Хотя именно такая нотация (покупка с минусом) мною вполне обоснована.
                      • ES1667
                        01 августа 2013, 14:38
                        anatolyutkin, Это не моя мысль, это определение плеча :)
                        Если вкладывается 100% капитала, то плечо=1, если 200%--то плечо=2, если 50%--то плечо=0.5.

                        Я именно так и считаю: «Цена 85'000, депо 50'000, плечо 1.7»
                        85'000 / 50'000 = 1.7

                        Я не прав?
                        • anatolyutkin
                          01 августа 2013, 16:09
                          ES1667, По моему, это все яйца выеденного не стоит. Считать можно как угодно--главное для основного вывода (чрезмерно большое плечо убивает счет)в каком-то виде учитывать рекапитализацию. Хотите переменную стоимость шага цены--да ради бога, учитывайте.

                          То, что считаю я--это на вашем языке надо на каждом клиринге приводить долю в соответствие с капиталом--рекапитализовываться. Это не торговля одним контрактом, ибо один контракт--это не постоянное плечо, а я хочу рассмотреть постоянное.

                          По поводу этого:
                          "
                          PL = (Price_In — Price_Out) * Deal_Side, где
                          Deal_Side = -1 для BUY, LONG и
                          Deal_Side = +1 для SEL, SHORT
                          "
                          Это результат сделки в абсолютных единицах. А мне нужен--результат в процентах. Я же это сто раз уже повторил. Хотите в таком виде--да пожалуйста, считайте так. Если сосчитаете правильно, выводы будут те же.

                          По вашим выкладкам. Я же сказал, что слова клиринг, динамика цены, итд, напрямую к теме не имеют отношения. В расчете есть только процентные результаты сделок--а уж откуда они берутся--это следующий вопрос.

                          Короче. Считайте финансовый результат--и все. Можно точно, можно приближенно. Описываемый эффект настолько груб, что от мелких деталей не зависит. Как именно считать--да не все ли равно. Можно вообще даже слово плечо не употреблять.
                          • ES1667
                            01 августа 2013, 16:40
                            anatolyutkin,
                            «Можно вообще даже слово плечо не употреблять.»

                            Ага. И выбросить его из заголовка обеих статей :)
                            Я чуть позже отвечу подробнее.

Активные форумы
Что сейчас обсуждают

Старый дизайн
Старый
дизайн