Всем доброго времени суток!


Меня зовут Илья и сегодня я хочу вам немного рассказать о своем хобби — криптовалютном алго-трейдинге. Скоро будет год, как меня настигла мысль написать торгового робота, который бы минимизировал человеческий фактор торговли (торгующие люди наверняка знают, что такое каждые пять минут обновлять баланс и зачастую делать какие-то поспешные, и потому неверные, торговые решения). Потому было решено переложить все на робота, удалить приложения по просмотру курсов с телефона и начать спать спокойно. Потратив много времени на написание чего-то более или менее работающего, хочу дать читателю маленькое overview, с чего стоит начинать на этом веселом (и нервном) поприще, как алготрейдинг. Этот гайд не является призывом начинать торговлю, не содержит советов по инвестированию, преследуются исключительно образовательные цели.


Как вы можете видеть из заголовка, тот робот, которого мы с вами напишем, будет работать на бирже BitMEX. Выбор объясняется очень просто — там есть плечи вплоть до 100. И наш робот будет работать с маржой.


Стой стой, что такое маржа?

Для тех, кто не понял о чем я говорю. Маржинальная торговля это торговля с кредитным плечом. [1] Что такое кредитное плечо?


Кредитное плечо — это отношение Вашего депозита к лоту, с которым Вы работаете. Т.е. имея на депозите 100$, Вы можете совершить сделку с лотом в 10 000, и тогда оно будет равно 1 к 100. Если же Вы выставите лот в 5 000, то кредитное плечо будет 1 к 50 и т.д. [2]


Итак, я надеюсь, что у читающего это есть базовые знания о торговле на бирже, к примеру, что такое OHLCV свечи (a.k.a. японские свечки), что бывают разные временные промежутки их представления и т.д.


Ну что, приступим к нашему маленькому приключения в страну алгоритмической маржинальной торговли?


Я любитель top-down коммуникации и поэтому я для начала расскажу, что я собираюсь сделать, а потом мы приступим к реализации. Глобально есть две важные вещи, которые надо сделать для запуска робота: разработать стратегию принятия решения (при каких условиях покупать) и разработать логику поверх принятого решения (сколько и как покупать).


Стратегия принятия решение (мозг) в нашем случае будет состоять из индикатора MACD (англ. Moving Average Convergence/Divergence — схождение/расхождение скользящих средних). Индикатор используют для проверки силы и направления тренда, а также определения разворотных точек. Строится на основе скользящих средних. Существует две модификации индикатора MACD: линейный MACD и MACD-гистограмма. [3] Мы воспользуемся реализацией MACD-гистограммы из библиотеки TA-lib и на основе этого индикатора будем принимать решение о покупке или продаже.


Пример MACD из Википедии

Логика поверх решения нашего индикатора будет простой: если индикатор сказал покупать, то мы купим, если продавать, то мы продадим. Торговать будем фиксированным количеством денег с фиксированным плечом.


Первое с чего мы начнем, это установка нужных библиотек. Для начала нам нужен клиент биржи, его берем тут. Мозг нашего робота будет основываться на техническом анализе, поэтому надо поставить библиотеку TA-lib. Ну и стандартный набор — numpy, pandas.


После установки всех нужных библиотек предлагаю читателю зарегистрироваться на https://testnet.bitmex.com — это копия биржи BitMEX, но там вы торгуете не реальным деньгами, а виртуальными. Очень удобно использовать для отладки роботов перед запуском на реальной бирже. После регистрации создаем себе ключи и создаем клиент биржи:


client = bitmex.bitmex(
    test=True,
    api_key="YOUR_KEY",
    api_secret="YOUR_SECRET"
)

Обратите внимание на параметр test. Он выставлен в true, что означает, что мы будем торговать на тестовой бирже. Этот пост не будет про использование API биржи, все возникающие вопросы по нему вы можете перенаправить в API explorer, благо он у них очень удобный.


Следующим шагом нам надо получить данных для использования их на MACD индикаторе. Мы получим 100 свечей с разрешением в 1 час.


ohlcv_candles = pd.DataFrame(client.Trade.Trade_getBucketed(
            binSize=self.timeframe,
            symbol='XBTUSD',
            count=100,
            reverse=True
        ).result()[0])

Теперь у нас есть датафрейм со свечками, давайте применим индикатор.


macd, signal, hist = talib.MACD(ohlcv_candles.close.values, 
                                              fastperiod = 8, 
                                              slowperiod = 28, 
                                              signalperiod = 9)

Почему параметры такие?

Я выбрал такие параметры немного поигравшись со стратегией и ее бэктестом на Trading View. Вот примеры картинок с точками входа/выхода стратегии на графике и сколько денег она заработала. Но учтите, это стратегия тестировалась без плеча.




Итак, получив индикатор, давайте поймем, как на его основе принимать решение. Ну тут все просто. Когда гистограмма пересекает нулевое значение снизу вверх, то это является сигналом к покупке, и наоборот.


#sell
if hist[-2] > 0 and hist[-1] < 0:
    return -1
#buy
if hist[-2] < 0 and hist[-1] > 0:
    return 1
#do nothing
else:
    return 0

Все очень просто и понятно. Давайте оформим это в один класс, который назовем стратегией.


class Strategy():
    def __init__(self, client, timeframe='5m'):
        self.client = client
        self.timeframe = timeframe

    def predict(self):
        ohlcv_candles = pd.DataFrame(self.client.Trade.Trade_getBucketed(
            binSize=self.timeframe,
            symbol='XBTUSD',
            count=100,
            reverse=True
        ).result()[0])

        macd, signal, hist = talib.MACD(ohlcv_candles.close.values, 
                                                      fastperiod = 8, 
                                                      slowperiod = 28, 
                                                      signalperiod = 9)

        #sell
        if hist[-2] > 0 and hist[-1] < 0:
            return -1
        #buy
        if hist[-2] < 0 and hist[-1] > 0:
            return 1
        #do nothing
        else:
            return 0

Теперь давайте напишем исполнителя наших решений. Логика простая — стратегия сказала нам покупать, значит мы покупаем. Приведу код торговца сразу, в нем ничего сложного нет:


class Trader():
    def __init__(self, client, strategy, money_to_trade=100, leverage=5):
        self.client = client
        self.strategy = strategy

        self.money_to_trade = money_to_trade
        self.leverage = leverage

    def execute_trade(self):
        prediction = self.strategy.predict()
        print(f"Last prediction: {prediction}")

        try:
            if prediction == -1:
                response = self.client.Order.Order_new(
                    symbol="XBTUSD",
                    side="Sell",
                    orderQty=self.money_to_trade * self.leverage,
                ).result()
            if prediction == 1:
                response = self.client.Order.Order_new(
                    symbol="XBTUSD",
                    side="Buy",
                    orderQty=self.money_to_trade * self.leverage,
                ).result()
        except Exception as e:
            print("Something goes wrong!")
            print(str(e))

        return

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


  1. Возвращается комиссия за выставление ордера
  2. Не нужно запариваться с отдельным исполнителем цены, который в общем случае должен защищать от падений биржи, передвигать выставленный ордер в случае задержки исполнения, и т.д. и т.п.

Теперь логика принятия решения у нас есть, логика исполнения решений у нас есть, осталось это все дело скомпоновать. Нам нужно запускать процесс торговли раз в выбранный нами временной период, в данном случае это был 1 час. Я сделаю это с костылем во имя быстроты написания, но лучше это делать, к примеру, через cron.


time_to_wait_new_trade = 60*60 #sec

strategy = Strategy(client, timeframe='1h')
trader = Trader(client, strategy)

while True:
    if round(time.time()) % time_to_wait_new_trade == 0:
        trader.execute_trade()
        time.sleep(10)

Ну вот, теперь это дело можно оформить в один скрипт и смело запускать, но только на тестовой бирже! На реальной бирже этого делать не советую, ибо можно потерять деньги. Данный скрипт своей целью ставил показать, что начать легко, и сделал более умный мозг у данной модели вы запросто сможете зарабатывать некоторые суммы.


Jupyter тетрадку с кодом я выложил в свой репозиторий, если кому-то интересно просмотреть — you are welcome!


  1. https://ru.wikipedia.org/wiki/Маржинальная_торговля
  2. https://www.fxclub.org/faq/chto-takoe-kreditnoe-plecho/"
  3. https://ru.wikipedia.org/wiki/Индикатор_MACD

Комментарии (36)


  1. Sabubu
    12.05.2018 01:25

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

      except Exception:
                print("Something goes wrong!")


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

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


    1. ilyakrotov Автор
      12.05.2018 10:07

      Я согласен с вами, исправил.


  1. amaksr
    12.05.2018 04:25

    Я правильно понял, что net profit в размере 1.84% эта система у вас заработала за 552 сделки, что составляет около 2-3 месяцев торгов? И 1.84% это после вычета комиссии, или до?


    1. ilyakrotov Автор
      12.05.2018 15:38

      Это данные с бэктеста на Trading View. Я могу предложить вам зайти и проверить эти данные самому на стратегии MACD Strategy, используя тикер XBTUSD (BITCOIN / US DOLLAR PERPETUAL INVERSE SWAP CONTRACT XBTUSD). Этот бэктест нельзя назвать полным отражением написаной стратегии, ибо там нет плеча, но зато есть пирамидинг.


      1. amaksr
        12.05.2018 19:28
        +1

        1.84% за 552 сделки и так то немного. Но если из 1.84% вычесть комиссию 0.1%, то результатом этой стратегии окажется глубокий минус.
        С другой стороны, тот факт, что 1.84% = 1840 дол предполагает, что для торговли доступно 100000 дол, и это видимо уже с плечом.
        Стоит также упомянуть, что при торговле с плечом х100 на той бирже, если вы что-то купили, и рынок неожиданно тикнул вниз на 0.4% (с учетом комиссий), то ваши позиции принудительно закрываются, и вся стратегия на этом закончится.
        В общем техническая реализация торговли это, конечно, интересно, но гораздо интереснее было бы узнать о параметрах какой-нибудь реально рабочей стратегии. Но ктож ее раскроет? Стратегия будет рабочей только до того момента, пока о ней остальные не узнали.


      1. dshap
        13.05.2018 00:00

        Индикаторы, плечо и Мортингейл — три столпа любого начинающего аглотрейдера :)


  1. ady1981
    12.05.2018 13:30
    +1

    Коллега, приветствую :). Я написал торгового робота для биржи Bittrex и могу поделится своим опытом:

    1) самое главное, что нужно понимать: значение цены — это не чисто случайная величина, а смесь: неслучайная_составляющая + случайная_составляющая.
    Отсюда следует, что брать любое среднее можно только от случайных величин => для усреднения данных нужно:
    (а) либо выделять данные, в которых изменением неслучайной компоненты можно пренебречь,
    (б) либо уметь оценивать неслучайную компоненту и предварительно вычитать ее из данных.
    2) Неслучайная компонента — гораздо сложнее случайной. Как правило для учета неслучайной компоненты нужны оценки человека-аналитика (так называемые, «оценки по мнению»).
    3) В оценку скользящего среднего я не веру. На мой взгляд, в этой оценке случайная и неслучайная компоненты смешиваются вместе и это приводит только к искажению данных. Плюс в этой оценке участвуют какие-то волшебные числа, которые ниоткуда не следуют. Я верю в стандартное распределение, которые еще никто отменить не смог :).
    4) Нужно понимать, на чем робот может вообще зарабатывать / уменьшать потери:
    4.1) На случайных колебаний в условиях без тренда (с учетом вероятности появления новых трендов): определяем среднюю цену, покупаем актив ниже этой цены и продаем актив выше этой цены;
    4.2) На тренде вверх: покупаем в начале тренда и продаем в конце тренда;
    4.3) На тренде вниз: продаем актив, если он есть.


  1. vis_inet
    12.05.2018 13:48

    4.2) На тренде вверх: покупаем в начале тренда и продаем в конце тренда;
    4.3) На тренде вниз: продаем актив, если он есть.

    Как вы понимаете, что тренд есть?


    1. ady1981
      12.05.2018 14:12

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


      1. Zar13st
        12.05.2018 15:41

        Что-то я сомневаюсь, что это приносит прибыль. Ну кроме того случая когда купили биток по 100$ и продали по 15к$.

        Всё жду когда хоть кто-то похвастается плюсовым графиком, а пока подобные статьи выглядят как алгоритм для доступа к джойнказино =)


        1. ilyakrotov Автор
          12.05.2018 15:44

          Я согласенс вашим скептицизмом, предложенная мною стратегия не является сверхприбыльной, она является лишь примером использования библиотеки talib, бекстеста с trading view и написания кода по исполнению какой-то стратегии. Но если основываться на прошлых данных, такая стратегия в долгосрочной перспективе имеет право на жизнь и может зарабатывать a.k.a выдавать плюсовой график :)


          1. Zar13st
            12.05.2018 16:46

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


            1. mspain
              12.05.2018 17:47

              А что уникального было в 2017г с битком? Вся история битка это памп+дамп+затишье. И каждый раз цена растет в итоге


              1. Zar13st
                12.05.2018 19:27

                Я в команде программист, трейдеры сказали, что бэктест битка за 2017 плохая идея


            1. ady1981
              12.05.2018 21:33

              В ценах битка в 2017 году есть закономерности, которые будут работать и в 2018 и позже.
              Будут ли эти данные полностью определять цену битка в 2018 году?
              Нет не будут.


              1. Zar13st
                12.05.2018 22:09

                Ну о том, что бы выбросить данные за 2017 речи и не шло. Я хотел сказать, что прогнать стратегию на данных за 2017 увидеть там красивые цифры и ожидать что в 2018 будет так же наивно.


                1. mspain
                  13.05.2018 06:30

                  Биток растет не раз в год, так что возможно затишье в пару лет и больше, но потом что будет не так как в 2017?


  1. MistaTwista
    12.05.2018 14:45

    для упрощения себе жизни, ордера здесь исполняются не по выставленной заранее цене, а по рыночной

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


    1. tirinox
      12.05.2018 15:20

      Хотелось бы, чтобы вы поподробнее рассказали о проблемах, которые грозят появиться.


      1. turbanoff
        13.05.2018 00:12

        Проблема, разумеется, одна — неожиданная цена fill. Когда вы посылаете market order биржа филит его по цене на момент приёма биржей. Эта цена может отличаться от цены, которую ожидал ваш бот.


      1. MistaTwista
        13.05.2018 14:22

        Акцентирую внимание на самом важном (в дополнение к сказанному turbanoff), цена может ЗНАЧИТЕЛЬНО отличаться от ожидаемой вами. Поэтому, когда имеете дело с биржей – всегда ставьте лимитированные заявки. Если есть хоть одна причина по которой нужно пользоваться ценой по рынку – надеюсь меня поправят :)


  1. ilyakrotov Автор
    12.05.2018 15:33

    Я почти согласен с этим, лимитные ордера это единственный возможный вариант в долгосрочной перспективе, особенно учитывая то, что на BitMEX есть ордера с антикомиссией (что очень приятно).

    Но все же если алгоритм работает на больших таймфреймах, то закупка по маркету, то есть погрешность порядка единиц/нескольких десятков долларов, не сильно влияет на перфоманс алгоритма.


  1. nikolz
    12.05.2018 16:45

    добрый день, всем!
    Хочу добавить пару ложек дегтя…
    1) Как правило прибыльные стратегии получаются на истории, а в реале они убыточные.
    Причин для этого много. Часто это связано с тем, что свечи, которыми отображают сделки и по которым строят индикаторы тоже являются индикаторами.
    Более того, свечи относятся к индикаторам заглядывающим в будущее.
    Т е закрытие свечи на графике всегда отображается «задним» числом.
    Поэтому, если есть желание как-то приблизить результат тестов к реальности,
    то при тестировании на истории сигнал надо формировать на закрытии свечи,
    а сделку совершать на открытии следующей.
    2) Алгоритм на основе пересечения двух скользящих средних — это самый примитивный алгоритм, который в реале не работает. Если обратиться к цифрой обработке сигналов то можно понять что это алгоритм подобен полосовому фильтру с фиксированной настройкой. Он будет давать выигрыш (выделять сигнал) лишь при совпадении частоты его настройки с колебаниями рынка и сильном отношении сигнал/шум.
    А это будет лишь иногда и то если повезет.
    В остальных случаях алгоритм будет давать либо шумовые сигналы, либо явно убыточные, так как игра на бирже — это игра с отрицательным мат ожиданием.
    Этот алгоритм подобен фразе в букваре «Мама мыла раму»
    Его обычно рассказывают во всех букварях по трейдингу,
    чтобы Буратинам было понятно,
    что делать прибыльных торговых роботов ну очень просто.


  1. SADKO
    12.05.2018 16:58

    Куда ты гонишь телят, Макар?
    Там же минное поле,
    И кругом растяжки!


    Ну серьёзно, по корну у него макдак с моржом по рынку торгуют :-)
    Уже это выдаёт не любителя, но профессионального зазывалу поля чудес, я молчу про мелкие детали за которыми как правило прячется совсем не маленький дьявол…

    Вы посмотрите не размеры этих часовых свечек, посчитайте вероятность словить маржинкол в течении ближайшего часа… Поразмышляйте над лагами машек и их производных, в частности макдака, может быть действительно, с таким лагом раз в час запускаться не грех вовсе…

    Для тах кто совсем не в теме, вот пример, масонский немного, но считайте его выдержкой из евангелия от Макиавелли :-)
    Когда строят дом, сначала делают фундамент, потом каркас стены итд…
    … но у наш строитель пытается прикрутить спутниковую антенну (конектор к конкретной бирже) на крышу которой нет, по этому решает не скорую руку сделать домик из соломы, установив в проём железную дверь как у настоящих банкиров…

    Халявы в этой жизни нет, и если кто то вам её даёт, это не с проста.
    С начала нужно сделать нормальное хранилище и визуализацию, потом платформу для тестирования, и на ней уже что-то правильно тестировать, правильно, а коннектор дело вообще самое последнее…
    Этот пост по сути промо лохотрона «миллионерша раскрывает секрет казино» бесплатно, вот тебе пример кода и рабочая стратегия, а плечё тебе поможет заработать ещё больше :-)


  1. Zar13st
    12.05.2018 17:26

    На работе думали на тему алготрейдинга на крипте и решили сосредоточить наши немногочисленные силы на традиционных инструментах. Посему вопрос: получается ли у кого-то?


    1. vis_inet
      12.05.2018 19:04

      А как получается на традиционных инструментах?


      1. Zar13st
        12.05.2018 19:34

        Бот написан, идей полно, но истину еще не нашли.


        1. devsolution
          13.05.2018 10:26

          Они никогда и не будет найдена. Да и вообще, что есть истина, если задуматься


  1. dshap
    13.05.2018 00:11

    А чем биток вам не традиционный инструмент? Возьмите GBTC или CBOE:XBT


  1. ittakir
    13.05.2018 07:37

    Интересно, почему всех алготрейдеров тянет в этот Биткоин?
    Как инструмент торговли он весьма опасен, волатильность 5-10% в день — легко! Абсолютная непрозрачность рынка, любой анонимус-миллиардер может двигать курсом, любая незначительная новость может обрушить курс.
    Есть же фьючерсы на нефть, евродоллар, SP500. Они, как мне кажется, более трендовые, меньше подвержены случайным выбросам в несколько процентов. Комиссии при торговле фьючерсами очень небольшие, плечи есть. Но не такие страшные как 1:100 на биткоине. Вы только вдумайтесь 1:100 на биткоине, который за день 10% ходит. То есть за день можно 10 раз обнулить свой счет, если программа зависла или интернет пропал.


    1. Zar13st
      13.05.2018 08:42

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


    1. Slav2
      13.05.2018 11:47

      ittakir, на биткоинах и доход высокий. 0.5% в сутки при торговле без плеча получить более чем реально. Допустим вы неправильно вошли в рынок и биткоин упал на 20% по отношению к доллару сразу после покупки. Если у вас правильно работающий алгоритм вы уже через месяц вышли в ноль (по долларам) и заработали 20% по биткоинам. Обычно криптотрейдеры считают доход в биткоинах и не торгуют против доллара накапливая биткоины. Волатильность на криптовалютных парах ниже. Зачастую если биткоин растет, то и альты начинают расти и наоборот. Есть 2 критических момента: выгоднее купить биткоин на входе в рынок и выгоднее продать если надо вывести средства. Это можно сделать всего несколько дней в месяц.

      Думаю будет не лишним дать ссылку на хороший гайд по торговле на BitMex. Автор опытный торговец, ведет свою группу в телеграмм: telegra.ph/Gajd-po-torgovle-na-Bitmex-05-12


      1. ittakir
        13.05.2018 13:26

        0.5% в сутки можно делать на любом инструменте без плечей из вышеперечисленных, включая обычные акции. Я бы вообще не ставил задачу максимизации дохода. Главное, это получать доход стабильно и безопасно, а деньги на большой депозит всегда можно найти.
        Ваш пример про -20% мне не очень понятен. Если ваш алгоритм допустил падение счета на 20%, где гарантия что он отыграется через месяц? Что мешает ему в этих сделках еще несколько раз не сделать по -20%?


        1. Slav2
          13.05.2018 20:39

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

          По поводу прибыли и убытка, 0.5% это 1.005^365=610% в год. Если такой результат получается на акциях, то я наверно зря игнорирую эту возможность. Хорошим результатом при торговле вручную на криптовалютах считается 20% в месяц.


  1. Slav2
    13.05.2018 10:26

    nikolz: Как раз таки наоборот, матожидание торговли на бирже это положительная величина. Представьте себе волновую электростанцию. Колебания выполняют работу, которая преобразуется в энергию и для нас это нормально. На бирже также колебательный процесс, но колебания не волн, а стоимости. Было бы странно, если бы эти колебания нельзя было бы превратить в прибыль. Технически осуществить это не просто. Против менее продвинутых ботов играют более продвинутые боты. А также люди с тугими кошельками, которые периодически устраивают встряску. Когда цена скачет 2-3% за пару минут, MACD на часовике не сможет торговать в плюс.

    Под торговлей в плюс я понимаю получение прибыли на протяжении нескольких месяцев. Срок менее месяца не дает полноценной картины работы бота. К примеру мой относительно несложный бот торговал в плюс в биткоинах на паре ETH_BTC за полтора месяца до начала февраля. Торговал на полониксе. С февраля начались одни убытки, а все потому что график стал падающий. Шортить (продавать несуществующий актив с дальнейшей покупкой по более низкой цене) бот не умеет и его пришлось остановить.

    SADKO: Как вы словите маржинкол если торгуете без плеча? На крипте торговаться с плечем и не требуется, там и без этого колебания цены больше чем требуется. Но в целом вы правы. Начинать надо с записи и анализа стаканов заказов. Любой индикатор основывающийся на анализе свечек дает картину с запозданием, да и сами свечки вносят элемент неопределенности. Например цена закрытия это что, цена последней продажи или покупки? Для криптовалютных бирж есть разница, которая может доходить до 0.1-0.5% в зависимости от комиссии биржи.

    Zar13st: Получается. А почему у вас не вышло, или вы еще не пытались?


  1. planarik
    13.05.2018 12:12

    Криптовалюты
    Кредитное плечо

    Ясно-понятно.