Чому стоп-ордер не спрацьовує в мобільному застосунку
Стоп-ордер не спрацював у найневдаліший момент — позиція залишається відкритою довше, ніж планував трейдер, і закривається вже за іншою ціною.
Причина зазвичай не в стратегії, а в ланцюжку «екран застосунку — канал зв’язку — торгова система»: умовна заявка виконується на боці біржі, але її розміщення ініціює телефон, і будь-який збій у цьому ланцюжку обертається втраченою заявкою.
Класичний випадок — втрата заявки під час розриву зв’язку. Користувач натиснув «купити», інтерфейс показав підтвердження, а запит до торгового ядра не дійшов: під час перемикання між мережами відповідь губиться, і застосунок домафльовує успіх за локальним станом.
Друга часта історія — помилка розміщення заявки в застосунку, коли ціна та обсяг підставляються зі застарілого знімка стакана, і стоп іде з ціною, якої на ринку вже немає.
Неспрацьована умовна заявка з’являється й після перезапуску застосунку. Якщо підтверджений ідентифікатор заявки не збережено на пристрої, після холодного старту список активних стопів порожній — трейдер ставить новий, а старий продовжує жити на боці системи.
Зворотний бік тієї самої проблеми — дублі: повторне надсилання після таймауту створює другу заявку, і позиція закривається подвійним обсягом.
Для торгового рахунку це обертається незакритою позицією, прослизанням і ручними розборами замість роботи. Розбираємо, як це закривається на рівні застосунку.
Що дає коректна робота умовних заявок
Коректність стоп-ордера вимірюється не фактом наявності рядка в списку заявок, а часткою виконаних умовних заявок: умова спрацювала — ордер пішов на сервер і підтверджений.
За журналом подій ця частка видна напряму: рахуємо всі спрацювання й віднімаємо ті, де заявка залишилася локальною через обрив зв’язку або конфлікт стану.
Час від торкання умови до надсилання — друга метрика. Він залежить від того, де умова зіставляється з потоком котирувань: якщо чекати на серверне сповіщення, додається круг доставки, і ордер іде з прослизанням.
Локальне зіставлення з наступним підтвердженням скорочує вікно спрацювання в рази й робить його передбачуваним під час перевантаження каналу.
Третій зріз — класи відмов заявок. Зникають втрата заявки під час перемикання мережі й згортання застосунку, дублі при повторному надсиланні, завислі стоп-ордери після сну пристрою.
Локальний журнал станів та ідемпотентний ключ заявки дають повторне надсилання без дублів: сервер розпізнає повтор і не створює другу заявку.
Стійкість торгової логіки перевіряється набором сценаріїв, а не одним прогоном: обрив зв’язку в момент спрацювання, зміна мережі, тривалий сон, відновлення сесії.
Прогоняємо збірки на реальних пристроях і нестабільних мережах через TestFlight — так клас відмов ловиться до релізу, а не в день волатильності.
Режими розміщення стоп-ордера: порівняння підходів
Умовна заявка відрізняється від звичайної тим, що не потрапляє до стакана одразу: вона чекає, поки ціна дійде до порогу, і лише тоді перетворюється на ринкову або лімітну. Звідси головне питання реалізації — де живе перевірка умови і за якою ціною її рахувати.
| Режим | Де живе логіка | Як відпрацьовує умову | Обмеження |
|---|---|---|---|
| Стоп на боці сервісу | Умовна заявка зберігається на сервері | Сервіс стежить за розрахунковою ціною і виставляє заявку сам | Спрацьовує при закритому застосунку; потрібен контроль, що стоп не втрачено |
| Локальна логіка в застосунку | Поріг зберігається в застосунку | Порівнює потік цін із порогом і надсилає заявку | Лише поки застосунок активний і є зв’язок |
| Гібрид | Умова на сервісі, розміщення підписує застосунок | Сервіс спрацьовує, застосунок підтверджує виконання | Надійніше за локальний, але з’являється вікно до підтвердження |
| Умова за розрахунковою ціною | Точка порівняння — розрахункова ціна | Поріг звіряється зі згладженим значенням за кількома джерелами | Менше хибних спрацювань, але значення оновлюється рідше |
Порівнювати поріг з останньою угодою небезпечно: на тонкому стакані одна велика заявка дає викид, стоп спрацьовує, а ціна тут же повертається — клієнт отримує виконання без причини. Тому умову прив’язують до розрахункової ціни: спрацювань менше, але кожне обґрунтоване.
Вибір режиму — це компроміс між надійністю спрацювання та миттєвістю реакції, і задає його сам продукт. Якщо стоп захищає позицію, логіку тримають на боці сервісу, а стан дублюють у застосунку; локальна логіка доречна лише як допоміжна і з чесним попередженням про межі роботи.
Як ми впроваджуємо умовні заявки: етапи робіт
Умовна заявка — відкладене рішення з ціною спрацювання, обсягом і поведінкою при розриві зв’язку.
Помилка в будь-якому з цих полів коштує дорожче за помилку в інтерфейсі, тому етапи впровадження торгової логіки вибудовуємо так, щоб кожен спирався на зафіксований результат попереднього.
- Аудит сценаріїв заявок. Збираємо перелік: стоп-лос і тейк-профіт, стоп-ліміт, прив’язка до останньої угоди або до ціни маркування, поведінка при гепі та частковому виконанні. На виході — матриця «сценарій / умова спрацювання / очікувана поведінка», узгоджена з вашою командою.
- Проєктування схеми. Вирішуємо, де живе стан заявки — на клієнті, на сервері чи в торговому ядрі, — і як він звіряється після перепідключення. Окремо закриваємо захист від дублів: повторне надсилання при обриві мережі не повинно створювати другу заявку.
- Реалізація. Шар умовних заявок пишемо окремо від інтерфейсу, щоб логіку спрацювання можна було змінювати без перезбирання екранів. Обробку цінових подій ведемо одним потоком із явною чергою — це прибирає гонки при різкому русі ринку.
- Тестовий контур. Піднімаємо середовище з потоком котирувань і відгуком торгового ядра, включно з відмовами: таймаути, відхилені заявки, розсинхрон стану. Кожен пункт матриці закриваємо автотестом.
- Перевірка заявок на історичних даних. Програємо реальні торгові дні з гепами та низькою ліквідністю: рахуємо, де заявка спрацювала за очікуваною ціною, де прослизнула, де логіка розійшлася з біржовою.
- Передача та регламенти. Віддаємо схему станів, опис конфігурації, порядок розбору інцидентів і метрики: частка відхилених заявок, затримка від отримання ціни до надсилання, кількість розсинхронів.
Конфігурації, схеми розрахунку та регламенти передачі
Після завершення робіт замовник отримує не архів з вихідним кодом, а комплект, за яким торгову логіку можна супроводжувати й розвивати силами своєї команди. Перелік артефактів фіксується до старту, тому до здачі не з’являється «сюрпризів» — що обіцяли, те й на руках.
- Документація з торгової логіки: життєвий цикл стоп-ордера — розміщення, умови активації, спрацювання, скасування, обробка розривів зв’язку та повторних спроб.
- Схема розрахунку ціни заявки: звідки беруться ринкові дані, як ціна й обсяг округлюються під крок і мінімальний лот, як співвідносяться стоп-ціна й лімітна ціна.
- Специфікація обміну з торговим ядром: формати повідомлень, коди помилок і те, як кожен із них показується користувачу.
- Набір автотестів: сценарії спрацювання, скасування та відхилення заявок, перевірки граничних значень ціни й обсягу.
- Регламент супроводу: порядок випуску змін у торгових правилах, обов’язкові перевірки перед викаткою, строки реакції на інцидент.
- Схеми моніторингу: які показники щодо стоп-ордерів відстежуються і за яких відхилень черговий отримує сигнал.
- Журнал інженерних рішень: чому правила активації та обробки збоїв вибрані саме такими.
Комплект збирається по ходу робіт, а не відновлюється в кінці, тому передача займає один-два розбори, а не місяць.
Кейс: як скоротили кількість неспрацьованих заявок
Ситуація до
Клієнт — біржа цифрових активів — тримав стоп-ордери на боці застосунку: ціна тригера перевірялася у фоні на телефоні, а заявка йшла на сервер лише якщо процес був живий. Згорнув застосунок, система вивантажила його з пам’яті — стоп не спрацьовував.
На різких рухах ринку частка неспрацьованих стоп-заявок сягала 6,4%, і майже кожна перетворювалася на звернення до підтримки з ручним розбором.
Що змінили і що вийшло
Логіку перенесли на серверний бік: застосунок лише перевіряє коректність параметрів і надсилає стоп-заявку, а тригер, контроль маржі та допустимого відхилення ціни живуть у торговому ядрі.
Кожній заявці присвоюється незмінний ключ — повторне надсилання після обриву зв’язку не створює дубль. При перепідключенні клієнт отримує актуальний знімок стану заявок, а не дораховує його з локальної копії, тому розходження «на екрані ще стоїть, на біржі вже виконано» зникло.
Після доопрацювання частка неспрацьованих стоп-заявок — 0,7%, і це переважно вихід ціни за допустиме відхилення, де система чесно скасовує заявку й показує причину. Звернень до підтримки щодо стоп-ордерів стало в сім разів менше, дублів заявок — нуль.
У журналі по кожній заявці видно, коли спрацював тригер, що відповіло торгове ядро і з якої причини заявка не пройшла.
Умовна заявка з лімітом або за ринком: що вибрати
Стоп-ордер спрацьовує за тригером, але далі все залежить від типу заявки: умовна заявка з лімітом і заявка за ринком відрізняються тим, що саме гарантовано після торкання рівня. У першому випадку фіксується ціна, у другому — факт виконання. До спрацювання обидві стоять у стакані однаково.
Умовна заявка з лімітом після тригера перетворюється на звичайну лімітну. Клієнт захищений від просідання при виконанні: угода пройде за вказаною ціною або кращою, але не гіршою.
Зворотний бік — гарантії виконання немає: на різкому русі ціна йде від рівня, заявка залишається невиконаною, і позиція продовжує висіти незакритою.
Заявка за ринком закриває позицію за будь-якою доступною ціною в межах глибини стакана. Тут гарантовано виконання, а не ціна: чим тонший стакан, тим помітніше просідання при виконанні.
На ліквідному інструменті розходження з рівнем тригера вимірюється частками кроку ціни, на тонкому — кількома рівнями, особливо якщо обсяг зіставний із найкращими котируваннями.
Окремий ризик тонкого ринку — часткове виконання та розриви між рівнями: велика заявка виїдає ближні рівні й добирає обсяг глибше. Тому в мобільному застосунку очікуване просідання рахують і показують до підтвердження, а не за фактом угоди.
Вибір типу спрацювання зводиться до пріоритету: захист ціни або захист від невиконання. Для захисного стопа за ліквідним інструментом зазвичай достатньо ринкової заявки — вихід важливіший за кілька кроків ціни.
Для входу на тонкому ринку розумніше ліміт із запасом від тригера, щоб виконання не зірвалося на першому ж імпульсі.
Технічні сумніви: запитання та відповіді щодо заявок
Нижче — чотири сумніви, які найчастіше порушують на розборі задачі. Відповідаємо предметно: як поводиться стоп-ордер при закритому застосунку, що відбувається при обриві зв’язку і як перевірити логіку, не ризикуючи позиціями.
Чи спрацює стоп-ордер, якщо застосунок закрито?
Так. Після підтвердження умовна заявка живе на боці торгового ядра, а телефон лише передає параметри: ціну активації, обсяг, строк дії. Спрацювання та розміщення в стакан виконує сервер, тому вимкнений екран або зникла мережа умову не скасовують. Сповіщення про спрацювання — наслідок, а не механізм.
Що відбувається при обриві зв’язку в момент розміщення?
Запит іде з ключем повтору: якщо відповідь не дійшла, застосунок надсилає його знову, а ядро розпізнає дубль замість другої заявки. Після відновлення зв’язку список звіряється з журналом заявок, а не з пам’яттю телефона. Так на екрані не з’являються «фантомні» стоп-ордери і не губляться реальні.
Як перевірити логіку, не ризикуючи позиціями?
Прогоняємо сценарії на тестовому контурі з тим самим ядром: різкий розрив ціни, часткове виконання, скасування на межі активації, повторне розміщення. Окремо перевіряємо мінімальний обсяг і крок ціни — часта причина відмови вже при підтвердженні. Бойовий рахунок у цих прогонах не задіяний.
Чи не загубляться заявки після оновлення застосунку?
Локальний кеш ми не вважаємо джерелом правди. При зміні схеми зберігання закладено міграцію, а при першому запуску оновленої версії клієнт звіряє список із сервером за ідентифікатором — відсутні умовні заявки повертаються в інтерфейс. Окремий сценарій — відкат на попередню версію: він не повинен ламати вже розміщені стоп-ордери.
Обговоримо задачу: підготуйте вхідні дані з торгової логіки
Щоб повернутися з оцінкою доопрацювання та робочим планом, нам потрібні вхідні дані з торгової логіки — не загальний опис, а те, як стоп-ордер має поводитися саме у вашому продукті. Нижче мінімум, який знімає більшу частину питань до першого дзвінка.
- Типи й зв’язки заявок: лише стоп-лос чи стоп-ліміт, чи потрібні тейк-профіт і зв’язка, де виконання однієї заявки знімає парну.
- Тригер: за останньою ціною, за розрахунковою позначкою чи за індексом; що вважаємо джерелом і як чинимо при розходженні між джерелами.
- Режими рахунку: спот, маржинальна торгівля, строковий ринок; як стоп поєднується з ризик-лімітами, плечем і примусовим закриттям позиції.
- Обсяги та правила зняття: доступний і заблокований під заявку обсяг, часткове виконання, перенесення стопа вслід за позицією, ліміт одночасно активних заявок.
- Поведінка при збоях: обрив зв’язку з біржею, рестарт сервісу, повторне надсилання — де зберігається стан заявки і як виключаємо дублі.
- Події та сповіщення: що йде в історію операцій і журнал, що показуємо клієнту на екрані та в сповіщеннях.
- Дані для перевірки: доступ до тестового контуру біржі, рахунки в різних режимах і список проблемних випадків із підтримки.
Якщо частина відповідей є в документації біржі — достатньо посилання на потрібний розділ. Опишіть задачу, додайте поточні макети й логи спірних спрацювань — обговоримо задачу і повернемося з оцінкою доопрацювання, складом етапів і планом робіт.







