Сколько можно торговать? Объем, комиссии и проскальзывание

Урок 10 курса по арбитражу. Объединим комиссии и обход стакана, посчитаем прибыль в зависимости от объема сделки и найдем объем с максимальной прибылью. Короткий код на Python с числами для ручной проверки.

Урок 10 курса "Собери своего арбитражного бота". В уроке 9 вы научились обходить стакан заявок. Сегодня добавим комиссии и зададим вопрос, на который должен ответить каждый бот: сколько монет торговать?

Две силы тянут в разные стороны

Торговля большим числом монет дает два эффекта.

  • Чем больше монет, тем больше прибыль от разницы цен, если она есть.
  • Чем больше монет, тем глубже вы заходите в стакан, где цены хуже. Это проскальзывание.

При небольшом объеме выигрывает разница цен. При большом - проскальзывание. Где-то между ними есть объем с максимальной прибылью. Если убыток возникает даже на самом маленьком объеме, сделки нет.

Сверху добавляются комиссии. Комиссия - это процент от суммы сделки. Допустим, на обеих биржах комиссия равна 0.1 процента (0.001). При покупке вы платите цену плюс 0.1 процента. При продаже получаете цену минус 0.1 процента.

Считаем прибыль для одного объема вручную

Возьмем стаканы из урока 9:

  • Биржа A, asks: 2 монеты по 100.00, затем 3 по 100.20. Здесь покупаем.
  • Биржа B, bids: 1 монета по 100.30, затем 5 по 99.90. Здесь продаем.

Торгуем 1 монетой.

  • Покупка 1 на A: 100.00. С комиссией: 100.00 × 1.001 = 100.10.
  • Продажа 1 на B: 100.30. С комиссией: 100.30 × 0.999 = 100.1997.
  • Прибыль: 100.1997 − 100.10 = 0.0997.

Торгуем 1.5 монеты.

  • Покупка 1.5 на A: весь объем с первого уровня, 1.5 × 100.00 = 150.00. С комиссией: 150.15.
  • Продажа 1.5 на B: 1 × 100.30 + 0.5 × 99.90 = 150.25. С комиссией: 150.0998.
  • Прибыль: 150.0998 − 150.15 = −0.0502. Получился убыток.

Половина монеты со второго уровня B продается по 99.90, то есть дешевле цены покупки. Лишние полмонеты превратили прибыль в убыток.

Прибыль в зависимости от объема

Прямой способ найти лучший объем - проверить много вариантов и выбрать самый выгодный. Так работает код ниже. Для одной пары можно проверить несколько сотен значений. Бот, который проверяет тысячи пар при каждом обновлении цены, использует правило предельной прибыли из следующего раздела и останавливается раньше.

Запишем прибыль как функцию: передаем объем и получаем заработанную сумму. Код использует walk из урока 9.

def walk(levels, amount):
    money, left = 0.0, amount
    for price, size in levels:
        take = min(size, left)
        money += take * price
        left -= take
        if left <= 0:
            break
    return money, amount - left

asks_A = [(100.00, 2), (100.20, 3)]
bids_B = [(100.30, 1), (99.90, 5)]
FEE = 0.001

def profit(q):
    paid, got_a = walk(asks_A, q)
    received, got_b = walk(bids_B, q)
    if got_a < q or got_b < q:          # в стакане недостаточно объема для такого размера
        return None
    return received * (1 - FEE) - paid * (1 + FEE)

for q in [0.5, 1, 1.5, 2, 3, 4, 5]:
    p = profit(q)
    print(q, None if p is None else round(p, 4))

best = max((q / 10 for q in range(1, 51)), key=lambda q: profit(q) if profit(q) is not None else -1e9)
print("best size", best, "profit", round(profit(best), 4))

Результат:

0.5 0.0498
1 0.0997
1.5 -0.0502
2 -0.2002
3 -0.7003
4 -1.2004
5 -1.7005
best size 1.0 0.0997

Прибыль растет до объема 1 монета (это размер верхнего уровня B), а когда продажа доходит до 99.90, начинает падать. Лучший объем - 1 монета с прибылью 0.0997. Это около 0.1 процента от 100, а комиссия обычного трейдера примерно такая же. Поэтому арбитраж на ликвидных рынках - игра с небольшой маржой.

Правило, которое объясняет эту картину

При обходе стакана каждая следующая монета имеет свою цену - цену уровня, с которого она взята. Дополнительную прибыль от следующей монеты назовем предельной прибылью: сколько она принесет при продаже на B минус стоимость покупки на A, с учетом комиссий. Пока предельная прибыль положительна, добавление монеты выгодно. Когда она становится отрицательной, остановитесь. Лучший объем находится там, где предельная прибыль пересекает ноль.

Проверим на примере. Первая монета: B приносит 100.30 × 0.999 = 100.1997, A берет 100.00 × 1.001 = 100.10. Предельная прибыль +0.0997. Вторая монета: B приносит 99.90 × 0.999 = 99.8001, A берет 100.10. Предельная прибыль −0.2999. Останавливаемся на одной монете.

Значит, не нужно проверять каждый объем. Обходите оба стакана одновременно, по одной монете или одному уровню, и остановитесь, когда предельная прибыль перестанет быть положительной. В настоящем боте сравнение лучших цен из урока 4 служит быстрой первой проверкой, а этот обход - второй, точной.

Другие ограничения объема

Даже лучший по стакану объем может оказаться слишком большим или маленьким:

  • Баланс. Нельзя купить больше, чем позволяет ваш остаток в котируемой валюте.
  • Правила биржи. Для каждой пары есть минимальный размер ордера и шаг (нельзя торговать 0.0000001 монеты).
  • Ваш лимит риска. Бот с бюджетом 10 долларов не торгует на 1000 долларов.

Итоговый объем - наименьшее из значений: min(best size by book, balance, risk limit), округленное вниз до шага биржи. Если результат меньше биржевого минимума, пропустите сделку.

Попросите ИИ-агента написать и проверить код

Расплывчатый запрос:

Рассчитай лучший объем сделки.

Запрос с числами для проверки:

Напиши size.py. Используй walk из book.py. Добавь profit(asks, bids, q, fee), возвращающую прибыль после комиссий для объема q или None, если в любом стакане недостаточно объема. Проверка: asks [(100.00, 2), (100.20, 3)], bids [(100.30, 1), (99.90, 5)], fee 0.001. При q = 1 прибыль должна быть 0.0997, при q = 1.5 прибыль должна быть -0.0502, при q = 6 результат должен быть None. Затем добавь best_size(asks, bids, fee, step), которая проверяет объемы, кратные step, и возвращает лучший. При step 0.1 результат должен быть 1.0. Не используй случайные числа.

Пересчитайте вручную первые два значения, как в этом уроке. Если агент выдает другую прибыль при 1.5, попросите показать обход обоих стаканов.

Ваше упражнение

  1. Запустите код и сравните результат с таблицей выше.
  2. Измените комиссию на 0, затем на 0.003. Что происходит с лучшим объемом и прибылью? При какой комиссии сделка перестает приносить прибыль? (Подсказка: для одной монеты прибыль равна 0.30 − 200.3 × комиссия, она становится нулевой примерно при комиссии 0.15 процента.)
  3. Добавьте на B третий уровень bid (99.95, 3) после первого. Вручную посчитайте прибыль для 2 монет, затем проверьте кодом.
  4. Измените walk, чтобы она также возвращала среднюю цену, и выведите средние цены покупки и продажи при лучшем объеме.

Что дальше

Теперь бот по цифрам на экране знает, что и в каком объеме торговать. Но к моменту прихода ордера цифры уже устарели, ордера исполняются частично, а второй этап сделки может сорваться. Урок 11 проверит реальность: что может пойти не так между планом и деньгами.