Горячие клавиши

← и →: предыдущая и следующая глава

S или /: поиск по книге

?: показать эту подсказку

Esc: закрыть подсказку или поиск

Если вы пришли с tinkoff-investments

Справка для тех, у кого бот уже написан на SDK tinkoff-investments (gRPC API Т-Банка, T-Invest API) и кто переносит его на brokapi. Цель: показать, что в каком месте меняется, чтобы перенос не превратился в двойную заявку. Левая колонка описывает API Т-Банка, на котором стоит SDK, названия методов сверяйте с версией своего SDK.

Идея одна: brokapi берет на себя то, что в SDK делал ваш код (сверка, лимиты, перевод единиц), и взамен требует порядка, который в SDK был по желанию. Поэтому перенос - это не замена вызовов один к одному.

Таблица соответствий

ТемаВ SDKВ brokapi
Количество в заявкелоты: quantity=2 значит два лоташтуки: qty=params.lot_size * 2. Не кратное лоту, дробное, нулевое - Rejected с кодом invalid_qty до отправки
Как назвать инструментfigi (устаревает) или instrument_id (uid), строкойawait client.instrument("SBER") возвращает InstrumentId (ключ SBER@TQBR и uid внутри). Везде передается он, а не строка. У Т-Банка instrument делает один запрос к справочнику
Номер заявкиorder_id: строка, ключ идемпотентности, вы его придумываетеcid: brokapi.new_cid(), UUID, в журнал на диск до place. Повтор того же cid библиотека не отправит: Rejected с кодом duplicate_place
Потоки событийотдельный поток на рыночные данные, на сделки, на статусы заявок, на портфель, каждый со своей подпискойодин поток client.events: async for envelope in client.events. В конверте source и типизированный payload (стакан, OrderSnapshot, Execution, Reconnected…). Подписки - subscribe_*
Сверка после старта и обрывасвоя, как вы напишетеобязательный reconcile(журнал) до первой торговой команды, иначе NotReconciled. После обрыва потока своих заявок (Reconnected), Overflow и ошибки Degraded торговля закрыта до новой сверки. Подписка на статусы - до reconcile
Цена и деньгиQuotation(units, nano) и MoneyValue(currency, units, nano), переводы своими функциямиDecimal везде. float отвергается (TypeError). Цена округляется до шага функцией round_to_step
Стоп-заявкиpost_stop_order, get_stop_orders, cancel_stop_order, количество в лотахplace_stop(kind=, qty=, stop_price=, limit_price=, expiry=), active_stop_orders(), cancel_stop(...), количество в штуках. Событий о срабатывании нет: узнавать только опросом. После рестарта cid стопа Т-Банк не возвращает, снимать надо по broker_id (Стоп-заявки, Python)
Ошибкиисключение с кодом gRPC и номером Т-Банка, разбор на васиерархия по исходу: Rejected (точно не сделано, поле code), Unknown (мог сделать, не повторять, спросить order_state(cid)), RateLimited (подождать retry_after), Transport (сеть, для чтения можно повторить), Config (настройка). Автоповтора команд нет и не будет (Ошибки)
Лимиты запросовсчитаете сами, ждете ответа об ошибкеодин счетчик на пользователя Т-Банка (BrokerLimiter), команда без квоты не уходит: RateLimited. Несколько клиентов одного брокера делят счетчик через limiter=
Счетaccount_id в каждом вызовеклиент привязан к одному счету (account_id= в connect). Несколько счетов - несколько клиентов с общим limiter= (Несколько брокеров и счетов)
Песочницасвой клиент или адрес песочницы, счет открываете OpenSandboxAccountconnect("tbank", sandbox=True), счет песочницы по-прежнему открываете сами (Т-Банк, где взять токен)
Длинная история свечейпостраничные запросы, лимит периода на васcandle_pages и load_candles режут период на окна по лимитам брокера (История свечей). Один candles на длинный период - Rejected
Синхронный клиентесть синхронный и асинхронныйтолько asyncio

Что и как переносить

Два преобразования, без которых не обходится ни один перенос. Лоты в штуки: старый код ставил quantity=lots, новому нужны единицы инструмента. Quotation в Decimal: пригодится для данных, которые вы хранили в файлах (в самом brokapi цены уже Decimal).

async def place_lots(
    client: brokapi.Client, ticker: str, lots: int, price: Decimal, side: brokapi.Side = brokapi.Side.BUY
) -> uuid.UUID:
    """The order of the old code was `quantity=lots`. Here the quantity is in units of the instrument: lots times the lot size."""
    instrument = await client.instrument(ticker)  # an InstrumentId (the uid inside), not a figi string
    params = await client.trading_params(instrument)
    cid = brokapi.new_cid()  # the old `order_id`: made by the bot, in its journal before the call
    await client.place(cid=cid, instrument=instrument, side=side, qty=params.lot_size * lots, price=price)
    return cid
def quotation_to_decimal(units: int, nano: int) -> Decimal:
    """`Quotation(units, nano)` and the `units` and `nano` of `MoneyValue` of the old code, for the data you keep in files.

    Exact: no float on the way. Negative prices have both parts negative, as in the API of the broker."""
    return Decimal(units) + Decimal(nano) / Decimal(1_000_000_000)

Порядок переноса, который не оставляет дыр:

  1. Подключите клиента к песочнице и прогоните старую логику через connect("tbank", sandbox=True). Первая ступень вообще без токена: Быстрый старт.
  2. Замените номер заявки: order_id -> cid из журнала, записанного до вызова. Это главное отличие, на нем держится безопасность повторов.
  3. Добавьте подписку на статусы и reconcile в начале работы. Бот, у которого в журнале есть живые cid, передает их в reconcile.
  4. Разберите исходы place по таблице из торгового бота: Unknown и Transport на команде не повторяются.
  5. Если у бота есть стопы, добавьте проверку на старте: Бот со стопом: старт и рестарт.
  6. Перед боевым счетом - Перед боевым счетом и Аварийная остановка бота.

Если вы пришли с QUIK

brokapi не подключается к QUIK и не заменяет терминал: он говорит с API брокера напрямую (БКС, Т-Банк, Финам, АЛОР, Bybit), и ни терминал, ни запущенный на машине QUIK не нужны. Скрипты QUIK (Lua, QUIK# и им подобные) живут внутри терминала и реагируют на его события (OnOrder, OnTrade, OnTransReply) и таблицы, заявка там - транзакция с номером TRANS_ID. В brokapi то же самое делают поток client.events (статусы заявок и сделки), portfolio() с позициями и cid, который бот придумывает сам и пишет в журнал до place. Переносится логика стратегии, а слой связи с терминалом заменяется целиком. Что изменится по порядку работы, описано в таблице выше: сверка до торговли, единицы в штуках, Decimal вместо float.

Листать можно клавишами Влево и Вправо.

brokapi by RunInfra