Что значит исключить проскальзывание цены и как это реализовать
Что проверяют
Понимаете ли, что между показанной пользователю ценой и моментом исполнения проходит время, и умеете ли закрывать этот разрыв кодом, а не рассуждениями о рынке. Вопрос прикладной: такие сервисы пишут на Go ради конкурентности, и именно конкурентность здесь всё и ломает.
Как отвечать
Проскальзывание это разница между ценой, на которую рассчитывал клиент, и ценой фактического исполнения. Убрать её полностью нельзя, задача в том, чтобы сделать её контролируемой: либо исполнить по обещанной цене, либо отказать, но не провести сделку втихую по худшей.
Рабочая схема на бэкенде:
- котировка выдаётся объектом с идентификатором, ценой, сроком жизни и подписью, клиент присылает её обратно вместе с заявкой;
- сервер сам проверяет срок и подпись, цене из тела запроса не верит никогда;
- заявка несёт допуск: предельную цену или максимальное отклонение; вышли за него, отказ с понятным кодом;
- сверка допуска, резервирование средств и создание сделки идут в одной транзакции с блокировкой строки или сравнением версии, иначе две горутины прочитают одно состояние и запишут по очереди;
- повтор по таймауту обязан быть идемпотентным: ключ от клиента, уникальный индекс в базе, на повтор тот же ответ.
По самому Go добавьте конкретику: context с дедлайном на всём пути заявки, отказ вместо ожидания при истёкшей котировке, мьютекс на инструмент или шардирование по символу вместо одной глобальной блокировки.
Где спотыкаются
Считают, что лимитная заявка сама решает задачу. Она ограничивает цену, но не гарантирует исполнение: заявка может остаться неисполненной или исполниться частично, и эти состояния надо обрабатывать. А стоп-заявка по рынку проскальзывание наоборот увеличивает.
Второе: проверяют допуск на клиенте. Цена, пришедшая из браузера или мобильного приложения, это пожелание, решение принимает сервер.
Третье: надеются на повторы. Ретрай без идемпотентного ключа даёт вторую сделку по новой цене, то есть ровно тот убыток, от которого защищались.