Diamond
Diamond личный блог
22 сентября 2021, 21:54

Шаблон торговой системы на Python (backtrader, quantstats)

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

Зачем Python?

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

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

Что потребуется?

— backtrader для логики торговой системы

— quantstats для формирования отчёта

— Jupyter Notebook, если нужно удобнее редактировать код

— Сам Python и установщик пакетов pip

Сам код достаточно простой:

import datetime
import webbrowser
import backtrader as bt
import quantstats as qs
import yfinance as yf

class SmaCross(bt.SignalStrategy):
    params = dict(
    pfast=50, # период быстрой средней, 50 свечей
    pslow=200 # 200 свечей для медленной средней
    )

    def __init__(self):
        sma1, sma2 = bt.ind.SMA(period=self.p.pfast), bt.ind.SMA(period=self.p.pslow) # используем простые скользящие средние
        self.crossover = bt.ind.CrossOver(sma1, sma2)

    def next(self):
        if not self.position:  # если позиция не открыта системой
            if self.crossover > 0:  # если быстрая SMA пересекает медленную вверх
                self.buy()  # открываем длинную позицию

            elif self.crossover < 0:  # во всех остальных случаях закрываем открытую позицию
                self.close()

data = bt.feeds.PandasData(dataname=yf.download('MSFT', '2007-02-02', '2021-09-01', auto_adjust=True)) # в качестве примера берём MSFT, 2008 год тоже торгуем

cerebro = bt.Cerebro()
cerebro.broker.setcash(10000) # начальный депозит 10 000 денег
cerebro.addsizer(bt.sizers.FixedSize,stake = 100) # размер позиции 100 лотов
cerebro.adddata(data)
cerebro.addstrategy(SmaCross)
cerebro.addanalyzer(bt.analyzers.PyFolio, _name='PyFolio') # PyFolio, но quantstats его тоже отрендерит
results = cerebro.run()

strat = results[0]
portfolio_stats = strat.analyzers.getbyname('PyFolio')
returns, positions, transactions, gross_lev = portfolio_stats.get_pf_items()
returns.index = returns.index.tz_convert(None)

qs.reports.html(returns, 'MSFT', output='stats.html', title='SMA Cross') # формируем репорт в quantstats, вместо бенчмарка SPY используем buy&hold MSFT
webbrowser.open('stats.html') # рендерим репорт в html и открываем в новой вкладке


В результате quantstats должен сгенерировать примерно такой отчёт:
Шаблон торговой системы на Python (backtrader, quantstats)

MSFT это трендовый инструмент и система на основе скользящих средних будет иметь положительное матожидание, однако она существенно проиграет Buy & Hold, поскольку средние отстают от рынка. Такая система также 83% времени находится в рынке, но при этом её максимальная просадка составляет 19.45% и это заметно ниже, чем buy & hold, который даёт просадку до 57.94%. Возможно, система могла бы использовать кредитное плечо для повышения доходности.

Диаграммы финансовых результатов явно указывают на необходимость сокращения убытков:
Шаблон торговой системы на Python (backtrader, quantstats)
Данные берутся с 2007 года, но система начинает торговать только в 2009:
Шаблон торговой системы на Python (backtrader, quantstats)

Теперь у нас есть аналог «Hello, world!», только для алготрейдинга и в нём уже есть что улучшить. Можно ещё отрендерить свечной график backtrader со сделками, но Jupyter это не поддерживает:

cerebro.plot(style='candlestick')



29 Комментариев
  • GOLD
    22 сентября 2021, 22:22
    Перед тратой времени и денег на алготрейдинг советую математически доказать себе и своей семье способность алгоритма, созданного на основе обработки известных данных в прошлом, генерировать устойчивую прибыль на неизвестных данных в будущем.
    • Антон Б
      23 сентября 2021, 13:21
      $100, для доказательства достаточно одного примера.
      этот пример продавай в мае и уходи.
      он работает).
      конечно не 100% в год.
      но альфа есть до сих пор.
      и есть причина почему он продолжит работать.

        • Антон Б
          23 сентября 2021, 13:27
          Diamond, да. работает все время.
          и есть экономическая причина почему продолжит в будущем.
          внешняя относительно рынков.

          хотя конечно 100% в год не дает )
          хорошо затыкает рот тем кто говорит что алго не работает в принципе.
          потому что будущее не определено.

          • Дмитрий
            02 октября 2021, 04:27
            Антон Б, это распространённая лажа, а не «причина». Причём она даже именно в тех самых Штатах статистически давно опровергнута как на узком, так и максимально широком наборе бумаг и полувековой стате:

            Сентябрь вон под «гоу эвэй» куда больше подходил и подходит, однако о нём таких баек выдумывать уже не стали.
            • Антон Б
              02 октября 2021, 11:04
              Дмитрий, смотри твой график.
              продавая 1 мая и покупая 1 октября вы прямо в 21 году выкинули 2 убыточных месяца.
              и оставили только прибыльные.

              и при этом говорите что не работает.

              как так?

              цель всех алгоримов отдать риск и взять ревард.
              вот стратегия отдает риск.

              • Дмитрий
                02 октября 2021, 11:13
                Антон Б, у вас глаза есть? Ведь даже в этом году — видно что по обоим таблицам плюс перекрыл минус. А уж в условные «средние» года — тем более.
                Это даже не оспаривая ваше 1 октября, ибо это лишь ваша натяжка постфактум (да ещё лишь этого конкретного одного года). Т.к. в оригинале сентябрь в перерыв отнюдь не включается.
                • Антон Б
                  02 октября 2021, 11:18
                  Дмитрий, плюс перекрыл минус… наверно.
                  но цель отдать риск и взять ревард.
                  а не бороться с минусом и принимать риски.

                  даже тот же етф на sp500 имеет просадку историческую 51%
                  что очень много.
                  по этому его приходится разбавлять облигациями чуть не на 50%.
                  облигациями которые в среднем НЕ ПОКРЫВАЮТ инфляцию.

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

                  + вы 5 месяцев не в риске.
                  и цена этих денег тоже 0.
                  потому что вы можете собрать из них синтетику и покрыть инфляцию.
                  (почти)

                  ну и так далее.

                  это работающий пример.
                  который работает.
                  но 100% годовых не приносит.

                  свою функцию ПРИМЕРА — тыкать носом тем кто говорит что алго не работает потому что будущее не определено он выполняет.

                  • Дмитрий
                    02 октября 2021, 12:43
                    Антон Б, «свою функцию ПРИМЕРА — тыкать носом тем кто говорит что алго не работает потому что будущее не определено он выполняет.»
                    В том и дело, что как раз НЕ выполняет. Совокупный плюс за оригинальные 4 мес(ибо в оригинале как раз май+лето) с лихвой  перекрывает историческую среднегодовую инфляцию в долларе(она чуть более 2% годовых) за этот же срок. Что показывает, что регулярный ежегодный 4х месячный выход из акций был нецелесообразен, несмотря на опис. вами волу. Взятую, как я понял, лишь от одного 2008го.
                    Вообще, перед тем как соберетесь таки кого-то высокомерно «тыкать носом», хотя бы сами разберитесь с вопросом, а то тыкать начнут уже вас 😉
                    Удачи!
                    • Антон Б
                      03 октября 2021, 09:46
                      Дмитрий, прикольно.
                      для того чтобы ткнуть носом нужен 1 Любой! пример.
                      (для доказательства существования нужно любой пример на выбор того кто доказывает существование)

                      я его привел.
                      это не такой пример как думал Дмитрий — значит он не подходит?
                      («продавай в мае и уходит » я нигде не сказал когда приходить, вы придумали это за меня.)
                      Показывать что алго работает: берите и получайте доход.
                      Уменьшайте риски.
                      (а уменьшить риск важнее чем получить больше доход)
                      Вот вам базовый пример.
                      Вызывает у людей буквально ненависть!.

                      зато торговать руками как зомби!
                      буквально как зомби.

                      это то что нужно? ).
                      • Дмитрий
                        03 октября 2021, 13:05
                        Антон Б, какая ненависть, вы о чем?
                        Даже отдельный май ПЛЮСОВОЙ — что прекрасно видно из обоих таблиц. Это притом, что за эти полвека в США было аж 3 мощнейших кризиса на фонде. Куда как тяжелее всяких короновирусов.
                        А про руки вообще не ко мне. Я исключительно фундаменталист, да ещё и долгосрочник, живущий от дохода с инвестпортфеля. Над сливами типичного трейдунья могу лишь недоумевать, а уж никак не самозабвенно «торговать руками».
                • Антон Б
                  02 октября 2021, 11:23
                  Дмитрий, в оригинале, и в вашем графике сентябрь исключается.
                  просто вокруг прибыльных идей много лжи.
                  никому не интересно чтобы прибыльные и простые идеи попадали в общество.
  • Rostislav Kudryashov
    22 сентября 2021, 22:25
    У меня уйма торговых систем, сказочно прибыльных, если не учитывать комиссию и проскальзывание.
    А если учитывать, то на длинной истории торгов возникают неприемлемо большие интервалы без прибыли. И от таких систем мне не нужны никакие сигналы ни на какие девайсы.
    Для таких результатов вполне хватает программы WealthLab со скриптами на C#.
    • Свой Мужик
      22 сентября 2021, 23:08
      Rostislav Kudryashov, зато этих ботов можно потом продавать )
  • ✔  ⓈⒺⓇⒼⒾⓄ:Ⓩ
    23 сентября 2021, 00:23
    какие скользящие??!!! а просто смотреть, что и сколько покупают большие дядьки, и повторять??..
  • ezomm
    23 сентября 2021, 00:54
    В шорт нужны средние с меньшим периодом и участием в сделке. В индюке Ишимоку есть простой сигнальщик  ref(C,+9) . Вообще Ишимоку готовая система. Там берется середина цены временного диапазона и она выдвигается из прошлого в настоящее(облако).У Билла В. на этом же принципе аллигаторы.
  • Michael
    23 сентября 2021, 07:12
    Зачем изобретать велосипед, если есть движок TSLab?
    • Антон Б
      23 сентября 2021, 13:22
      Michael, там все не так просто.
      в конце вы получаете алго который стоит вам примерно 100к в год лицензии.
      чтобы просто работать.

      один коннектор стоит примерно 50к в год.
      к одному брокеру.

      а брокеров как минимум 2.
      потому что нужно два — для рискменеджмента.

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


      • Кирилл Гудков
        23 сентября 2021, 14:45
        Антон Б, а от каких рисков страхует одновременная роботорговля с 2-х брокеров? Эти риски стоят всего сопутствующего геммора?
      • Michael
        24 сентября 2021, 01:30
        Антон Б, не путайте бекстетинг и разработку стратегии с ее автоматической проторговкой. Если вы разрабатываете логику на Python — то вам все равно нужно вкорячивать коннекторы к брокеру. Речь о том, что для разработки стратегии и тестировании алгоритмов типа «скользящих средних» необязательно лезть в кодинг — все это уже бесплатно доступно в TSLab + хорошая визуализация сделок на графике.

        Коннекторы — отдельный вопрос. 


        • Антон Б
          24 сентября 2021, 07:50
          Michael, OSA там есть коннекторы в открытом коде.
          и не только том.
          C#
          пишу )
          а вот идеи тестирую на pine и python

          потому что пишется тест быстрее в разы.
  • CloseToAlgoTrading
    23 сентября 2021, 10:45
    за кванстат спасибо ) 
  • akumidv
    23 сентября 2021, 15:15
    В Backtrader не предусмотрена возможность гипероптимизации параметров, т.е. прогнать по всей области параметров каким-то интсрументом из машинного обучения простым способом не получится. Можно сделать оберткув над инициализацией, но это очень медленно. У меня получалось доя двух МА на обычном ПК где-то 50 циклов на небольшой истории в секунду. Но стратегии сложнее гораздо медленней — на 15 минутках за пару лет по 2-3 секунды на цикл. Если параметров в оптимизаци. От 5-10 по 10 значений в каждом — то BT просто не подойдет. А медленно из-за самой архитектуры — здесь ООП и классы и очень много действий на каждый шаг вне pandas. Соответствеено и задержки.
  • Ferrum
    08 декабря 2021, 20:49
    Спасибо за пост! Запили плиз пост про тестирование стратегий на TV и ограничения.
  • Виталий
    03 марта 2023, 21:23
    Ошибка при запуске:

    [*********************100%***********************] 1 of 1 completed
    Traceback (most recent call last):
    File «C:\Users\cloud\PycharmProjects\MyTradeBot\MyBot.py», line 40, in <module>
    qs.reports.html(returns, 'MSFT', output='stats.html', title='SMA Cross') # формируем репорт в quantstats, вместо бенчмарка SPY используем buy&hold MSFT
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File «C:\Users\cloud\PycharmProjects\MyTradeBot\venv\Lib\site-packages\quantstats\reports.py», line 87, in html
    benchmark = _utils._prepare_benchmark(benchmark, returns.index, rf)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File «C:\Users\cloud\PycharmProjects\MyTradeBot\venv\Lib\site-packages\quantstats\utils.py», line 269, in _prepare_benchmark
    benchmark = benchmark_prices.reindex(new_index, method='bfill') \
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File «C:\Users\cloud\PycharmProjects\MyTradeBot\venv\Lib\site-packages\pandas\core\series.py», line 5094, in reindex
    return super().reindex(**kwargs)
    ^^^^^^^^^^^^^^^^^^^^^^^^^
    File «C:\Users\cloud\PycharmProjects\MyTradeBot\venv\Lib\site-packages\pandas\core\generic.py», line 5289, in reindex
    return self._reindex_axes(
    ^^^^^^^^^^^^^^^^^^^
    File «C:\Users\cloud\PycharmProjects\MyTradeBot\venv\Lib\site-packages\pandas\core\generic.py», line 5304, in _reindex_axes
    new_index, indexer = ax.reindex(
    ^^^^^^^^^^^
    File «C:\Users\cloud\PycharmProjects\MyTradeBot\venv\Lib\site-packages\pandas\core\indexes\base.py», line 4412, in reindex
    indexer = self.get_indexer(
    ^^^^^^^^^^^^^^^^^
    File «C:\Users\cloud\PycharmProjects\MyTradeBot\venv\Lib\site-packages\pandas\core\indexes\base.py», line 3912, in get_indexer
    return self._get_indexer_non_comparable(target, method=method, unique=True)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File «C:\Users\cloud\PycharmProjects\MyTradeBot\venv\Lib\site-packages\pandas\core\indexes\base.py», line 6182, in _get_indexer_non_comparable
    raise TypeError(f«Cannot compare dtypes {self.dtype} and {other.dtype}»)
    TypeError: Cannot compare dtypes datetime64[ns, America/New_York] and datetime64[ns]

    Process finished with exit code 1

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

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