zipFinam
Бэктест и алготорговля на Мосбирже через Финам.
zipFinam — открытая Python-библиотека для бэктеста и алготорговли на Московской бирже:
котировки Финама, торговые календари MOEX и исполнение заявок через Finam Trade API.
Стратегия, проверенная на истории, без переписывания запускается на вашем счёте в Финаме.
Зачем это нужно · Котировки Финама · 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)
| File | Size | Uploaded | |
|---|---|---|---|
| zipfinam-1.26.10.tar.gz | 144.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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
|