Skip to main content

zipFinam: бэктест и алготорговля на Мосбирже через Финам

zipFinam
Бэктест и алготорговля на Мосбирже через Финам.

zipFinam — открытая Python-библиотека для бэктеста и алготорговли на Московской бирже:
котировки Финама, торговые календари MOEX и исполнение заявок через Finam Trade API.


Стратегия, проверенная на истории, без переписывания запускается на вашем счёте в Финаме.

PyPI Python License Stars

Зачем это нужно · Котировки Финама · MOEX AlgoPack · Торговля на своём счёте · Начало работы · Лицензия

акции и фонды MOEX из Финам Trade API · календари MOEX и FORTS · заявки целыми лотами · капитал стратегии, а не весь счёт · данные MOEX AlgoPack по желанию · движок ziplime


Зачем это нужно

Большинство инструментов для бэктеста сделаны для американского рынка. На Мосбирже с ними начинаются проблемы:

  • Нет данных. Популярные бесплатные источники вроде yfinance российские бумаги толком не покрывают.
  • Свечей мало. OHLCV показывает, куда сходила цена, но не кто её двигал: агрессивный покупатель или пустой стакан, толпа или один крупный игрок.
  • Тестер заглядывает в будущее. Биржевая статистика публикуется с задержкой, иногда пересчитывается задним числом, и наивный бэктест незаметно читает то, чего в тот момент ещё не было.
  • От теста до торговли — вторая разработка. Стратегию, проверенную в одном инструменте, приходится переписывать под API брокера.

zipFinam закрывает все четыре проблемы.


📈 Котировки Финама — вся Мосбиржа одной командой

Бары и справочник инструментов приходят напрямую из Финам Trade API: акции и фонды MOEX, таймфреймы от минуты до квартала. Нужен только токен из личного кабинета Финама.

cd examples
python ingest_finam.py      # справочник инструментов и дневные бары
python run_backtest.py      # бэктест на голубых фишках

Финам подключается к движку как штатный провайдер данных: get_market_data_source("finam") работает так же, как встроенный Yahoo для американского рынка.


🔬 MOEX AlgoPack — то, чего не видно в свечах

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

import zipfinam

flow = await data.history(assets=[sber], fields=["disb", "val"], bar_count=5,
                          data_source="algopack://eq/tradestats")
Таблица Что видит стратегия Рынки
tradestats Кто пересекал спред: объём агрессивных покупок против продаж (disb) акции, фьючерсы, валюта
orderstats Какие заявки выставили и какие сняли: настоящий спрос против декорации акции, фьючерсы, валюта
obstats Спред в б.п., глубина и дисбаланс стакана каждые 5 минут акции, фьючерсы, валюта
hi2 Концентрация потока: покупает толпа или один игрок акции, фьючерсы
futoi Открытый интерес физлиц против юрлиц фьючерсы
alerts Сигналы биржи об аномальной активности акции, фьючерсы, валюта

Без заглядывания в будущее

Это главное отличие от самодельного парсера. Каждая строка AlgoPack становится видна стратегии в момент, когда биржа её опубликовала, а не в момент, к которому она относится:

  • дневной итог виден на следующей сессии, а не в течение своей;
  • hi2 биржа публикует примерно через шесть минут после своей метки времени, и раньше этого стратегия его не увидит;
  • строки, которые биржа пересчитала задним числом (бывает, спустя месяцы), не пропадают из бэктеста до даты пересчёта, а остаются на своём месте.

Сводка за сессию собрана по правилу для каждой колонки: объёмы суммируются, VWAP взвешиваются, снимки стакана усредняются, дисбаланс пересчитывается по итогам дня. Агрегация сверена вручную с реальными данными SBER. Нужны пятиминутки — algopack://eq/tradestats/5min.

Загруженная история кэшируется на диске: инструмент-год tradestats занимает около 3 МБ, и повторный бэктест по тем же годам не скачивает их заново.

Пять готовых стратегий

В examples/algorithms/algopack/ по стратегии на каждую таблицу:

Стратегия Идея
flow_tilt Держать голубые фишки, которые покупают агрессивные деньги
orderstats_conviction Покупать там, где выставленные биды не снимают
obstats_liquidity Держать то, что поддерживает стакан, а не случайный принт ленты
hi2_crowding Идти за бумагами, где покупает кто-то один против рассеянного рынка
futoi_crowd Стоять против толпы физлиц во фьючерсе на доллар/рубль
python run_backtest.py algorithms/algopack/flow_tilt.py

💼 От бэктеста к вашему счёту

Та же стратегия, без изменений, торгует на вашем брокерском счёте в Финаме через Trade API. Укажите данные счёта и запустите пример:

export FINAM_TRADE_TOKEN=...                 # токен счёта, на котором исполняются заявки
export FINAM_ACCOUNT_ID=...                  # номер этого счёта
export FINAM_TRADE_URL=https://api.finam.ru  # заявки уходят на ваш счёт
cd examples && python run_live_finam.py

Исполнение рассчитано на реальные деньги:

  • Стратегии выделяется капитал, а не весь счёт. order_target_percent(0.5) — это половина её бюджета, а не половина брокерского счёта.
  • Лоты. Объём округляется до целых лотов (GAZP — по 10 штук). Если размер лота неизвестен, заявка не отправляется вовсе: наугад ничего не торгуется.
  • Принятая заявка ≠ исполненная. После каждого тика статус заявок запрашивается у брокера, и отклонённая заявка отмечается как ошибка, а не как успех.

Начало работы

pip install "zipfinam[all]"

Создайте .env в рабочей папке:

GRPC_TOKEN=...          # токен Финам Trade API: котировки, справочник, лоты
ALGOPACK_API=...        # ключ MOEX AlgoPack, подписка на https://data.moex.com

Для бэктестов на свечах хватит GRPC_TOKEN. Можно поставить не всё:

Extra Что добавляет
— Данные Финама, календари, адреса algopack://
algopack Клиент MOEX AlgoPack
live Исполнение заявок через Финам

Стратегия — обычный Python:

from ziplime.finance.execution import MarketOrder


async def initialize(context):
    context.stocks = [await context.symbol(s) for s in ("SBER@MISX", "GAZP@MISX")]


async def handle_data(context, data):
    for stock in context.stocks:
        bars = await data.history(assets=[stock], fields=["close"], bar_count=50)
        if len(bars) < 50:
            continue
        closes = bars["close"].to_numpy()
        target = 0.5 if closes[-20:].mean() > closes.mean() else 0.0
        await context.order_target_percent(asset=stock, target=target, style=MarketOrder())

Тикеры пишутся с кодом площадки (SBER@MISX). Имя context.assets занято движком, своим переменным давайте другие имена.

Календарь срочного рынка

Стандартный календарь XMOS заканчивается в 18:45, и фьючерсная стратегия теряет на нём вечернюю сессию. zipFinam добавляет календарь FORTS (09:00–23:50, клиринг 18:50–19:05), а для портфеля из бумаг нескольких бирж подбирает общий: clock_calendar_name(["MISX", "XNYS"]) → 24/5.


Под капотом

zipFinam — надстройка над ziplime, открытым движком бэктестинга и живой торговли от Limex. Движок, метрики и модели исполнения берутся из ziplime, а zipFinam добавляет российский рынок: данные, календари и брокера.

zipfinam/
├── finam/               # Финам: бары, справочник, исполнение (REST и gRPC)
├── algopack/            # MOEX AlgoPack: каталог таблиц, клиент, источник данных
└── venue_calendars.py   # FORTS и календари площадок
examples/                # загрузка, бэктест, живая торговля, стратегии

Тесты работают без сети: pip install -e ".[dev]" && pytest.

Переход с версии 0.x и ограничения
  • Нужен ziplime 2.x. Импорты: from zipfinam import FinamDataSource, FinamAssetDataSource; старый модуль ziplime_grpc_data_source оставлен на время перехода.
  • Готовый assets.sqlite больше не поставляется: справочник загружается из Финама скриптом examples/ingest_finam.py.
  • В стратегиях data.history и data.current вызываются с await, у заявок обязателен style=MarketOrder().
  • Из справочника Финама импортируются акции и фонды; фьючерсы и опционы пропускаются.
  • Торговый день AlgoPack (07:00–23:50) длиннее основной сессии акций (10:00–18:45), поэтому vol и pr_close включают утро и вечер.
  • Адреса algopack:// начинают работать после import zipfinam, сделать его нужно до запуска симуляции.

Лицензия

GNU GPL v3, как у ziplime.

Metadata

Release files for zipfinam 1.26.10

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for zipfinam 1.26.10
File Size Uploaded
zipfinam-1.26.10.tar.gz 144.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for zipfinam 1.26.10
File Interpreter ABI Platform
zipfinam-1.26.10-py3-none-any.whl Python 3 none any Details

Total release size: 293.5 kB

Release files / zipfinam-1.26.10.tar.gz

Download URL zipfinam-1.26.10.tar.gz
Size 144.2 kB
Tags Source
SHA-256 checksum
How to use checksums
c9d88e9c65238759bccd25c981052e52cc10a3303951d855fb7c8b2f0f357f8f
BLAKE2b-256 checksum
How to use checksums
6f6f9f7f8a6b2ebdf3a0484071f5cc0c4068331c625366f8ab23ed23f0eb33da
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.7

Release files / zipfinam-1.26.10-py3-none-any.whl

Download URL zipfinam-1.26.10-py3-none-any.whl
Size 149.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
73a69b4ac2026c8b6ce7d6609e292905d8240f5dcf54d402ba32c0d6576a81f2
BLAKE2b-256 checksum
How to use checksums
b8f3000d0e294a6d04cf65b5b8bad6f3a95dd16aeb266a97a4479b37fff84f61
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.7

Release history Release notifications | RSS feed

This release

1.26.10 This release

2 release files

0.1.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page