У першій частині ми розібрали базову ідею: торговий радник — це не «робот, який торгує замість вас», а система, яка отримує ринкові дані, формує сигнал (і пояснення) і показує результат людині.
Ми пройшлися мінімальною архітектурою: модуль котирувань → складання промпту → виклик моделі → збереження результату → веб-інтерфейс та повідомлення. І окремо відзначили опціональний прошарок контексту — новини, які можна додавати в промпт у вигляді саммарі.
У другій частині буде менше «загалом» і більше практики: які дані справді потрібні на старті, де вилазять нюанси API бірж, що зберігати в базі, як не відлетіти в ліміти, і чому без кешу, логування та обмежень ваш радник розвалиться рівно тоді, коли ви на нього розраховуєте.
Які дані брати на старті
На старті у вас є три основні класи ринкових даних, які можна отримувати з біржі через API. Найзрозуміліший і найпоширеніший - OHLCV-свічки: Open/High/Low/Close плюс обсяг за інтервал. Це “стисле” уявлення ціни, яке зручно зберігати, кешувати та передавати у модель як стабільний шматок контексту (наприклад, останні N свічок обраного таймфрейму1).
Якщо потрібно бачити, що відбувається всередині свічки, підключають стрічку угод (trades / tape) — потік фактичних виконань: ціна, кількість, час (іноді сторона). Такий шар додає деталізацію за активністю та імпульсами і зазвичай використовується як більш “зернисте” джерело, ніж свічки.
Третій варіант - склянка заявок (order book): рівні bid/ask та обсяги на кожному рівні. Це вже дані про мікроструктуру та ліквідність: не “що сталося”, а “що зараз стоїть у черзі”. Зазвичай його беруть як окремий шар контексту, коли потрібно враховувати глибину ринку, дисбаланс попит/пропозицію та реакцію на рівні.
Поки що зупинимося на найпростішому варіанті — OHLCV-свічках. У своїй реалізації ви можете додати і угоди, і склянку, але завдання цієї статті ознайомлювально-освітнє: зібрати зрозумілий каркас і не потонути в деталях.
Єдиний формат даних та історія
Як тільки ви починаєте отримувати котирування не з одного місця, спливає неприємна реальність: різні джерела дають одні й самі дані в різних форматах. Десь свічка — це масив чисел, десь об'єкт із полями, десь час у мілісекундах, десь за секунди, а назви та порядок полів можуть відрізнятися навіть у «схожих» API..
Якщо не ввести єдиний формат на своїй стороні, система швидко перетворюється на набір милиць: кожне нове джерело тягне за собою окремі парсери, винятки та “особливі випадки”. Тому в модулі отримання котирувань майже завжди потрібний загальний внутрішній формат — мінімально достатній для подальшого аналізу. Для нашого поточного рівня це зазвичай: інструмент, таймфрейм1, timestamp
Рейт-ліміти: чому це важливо
Майже кожна біржа має обмеження на частоту запитів — рейт-ліміти. Причина проста: якщо дати всім клієнтам нескінченно "смикати" котирування, API ляже навіть без DDoS.
У контексті радника це важливо подвійно. Запити виконуються не безперервно, а за таймером - і якщо ви неправильно вибрали періодичність або помножили її на кількість інструментів, ви дуже швидко упретеся в ліміт. Результат зазвичай однаковий: помилки 429/ban на ключ, дірки в даних та «мовчання» системи саме тоді, коли ринок рухається найсильніше.
Робочий підхід тут прагматичний: заздалегідь вважати бюджет запитів (періодичність × інструменти × типи даних), кешувати результати, не вимагати те саме двічі, і коректно обробляти ліміти (backoff/повтор через паузу замість спаму запитами).
Промпт та нейромережі: той самий API, інші правила
З отриманням даних розібралися — тепер можна переходити до наступного рівня: промпт та робота з нейромережами.
На перший погляд це дуже схоже на запит котирувань: знову API, знову обмеження по частоті, знову потрібно думати про ретраї, таймаути та кеші. Тільки замість “дай свічки” у вас запит виду “ось дані, ось контекст, поверни сигнал та пояснення”.
Далі починаються відмінності.. У біржі відповідь — це структура даних, модель — результат інтерпретації. Тому промпт стає контрактом, а не просто “текстом”, і до нього доводиться ставитися так само, як до формату даних: версіонувати, перевіряти, обмежувати та логувати.
Момент, який дуже спрощує життя на інтеграції: у промпті можна заздалегідь зафіксувати структуру відповіді. Наприклад, попросити модель повернути результат суворо в JSON — з полями на кшталт signal, confidence та reasons. Це не “магія”, але як мінімум дисциплінує формат, а на стороні програми дає можливість автоматично парсувати та валідувати відповіді замість того, щоб розбирати вільний текст.
Особливо варто згадати MCP (Model Context Protocol): це підхід/протокол, який допомагає стандартизувати, як моделі отримують контекст і як підключаються зовнішні джерела даних та інструменти. Навіть якщо зараз ви використовуєте прямі виклики конкретного API, пам'ятати MCP-подібний шар корисно — він дисциплінує архітектуру і спрощує розширення.
І так, у перспективі “аналітик” не може бути зовнішнім сервісом. Якщо з'являться ресурси та мотивація, цей модуль можна замінити власною моделлю (або донавченою опенсорсною), не переписуючи решту системи — за умови, що інтерфейси спочатку розділені правильно.
Сховище: простіше, ніж здається
На цьому етапі ми вже маємо мінімум два “масиви” даних: ринкові свічки та результати аналізу. А якщо дивитися трохи вперед — додадуться історія новин (і їх саммарі) плюс збереження промптів/відповідей моделі для дебага і повторного аналізу. Іншими словами, даних стає досить багато, і вони з'являються у різних місцях конвеєра.
Тому має сенс заздалегідь подумати про уніфіковане зберігання. Специфіка таких даних часто дозволяє не тягнути повноцінну SQL-схему: у багатьох випадках вистачає бази, що вбудовується, і простого ключ-значення підходу.
KV-сховище (key-value) — це модель, де дані зберігаються як пари “ключ → значення”: по ключу ви швидко дістаєте потрібний об'єкт (наприклад, свічки для інструменту та таймфрейму1..
Інтерфейс: мінімум, без якого радник не є корисним
І нарешті - інтерфейс. У UI/UX зараз не заглиблюємося, але нагадаю базову думку з першої частини: як мінімум потрібен веб-інтерфейс, а як приємне доповнення — повідомлення Telegram.
На практичному рівні користувачеві потрібні лише кілька речей. По-перше, бачити поточні сигнали та алерти (і швидко розуміти, що “зараз відбувається”). По-друге, вміти запросити аналіз на вимогу отримати свіжі дані і сигнал в один клік. І, по-третє, налаштовувати систему: вибирати інструменти та джерела даних, керувати API-ключами, і що важливо — редагувати промпти та параметри аналізу, не лізучи в код.
Ядро: “кільце”, яке все пов'язує
У Толкіна було “одне кільце, щоб правити всіма... і в темряві їх зв'язати”. В архітектурі радника це кільце теж є лише без пафосу: ядро системи, яке тримає всі модулі разом.
Ядро відповідає не за аналіз як такий, а за лайфцикл: старт/стоп програми, ініціалізацію залежностей, планувальник завдань, маршрутизацію запитів (на вимогу та за розкладом), коректне завершення роботи. Саме тут вирішується, що і коли запускається, куди пишуться дані, і як компоненти спілкуються між собою, не перетворюючись на клубок.
Якщо хочете додавати нові джерела котирувань, змінювати LLM-провайдера, підключати новини і при цьому не переписувати все щоразу — ядро має бути простим, але строгим: модулі — за інтерфейсами, залежно — явно, конфігурація — централізовано, а життєвий цикл — передбачуваний.
На цьому місці можна зупинитися і чесно сказати: “скелет” радника вже видно. Дані надходять, промпт збирається, модель відповідає, результат зберігається і показується користувачеві - і все це тримається на ядрі, яке керує життєвим циклом. У наступній статті я спущусь на рівень нижче: розберемо технічні деталі реалізації - як виглядає єдиний інтерфейс джерел котирувань, як влаштувати кеш і ретраї, де зберігати історію, як валідувати відповіді моделі (включаючи JSON-формат), і що робити, щоб система не ламалася від лімітів, часу..
Виноски
- Таймфрейм – це тривалість однієї свічки (інтервал агрегації даних): наприклад 1m, 5m, 1h, 1d. Він визначає, як саме "стискається" потік цін у OHLCV.
- Timestamp – це мітка часу (зазвичай у UTC), до якої прив'язана свічка/угода. Класична помилка: переплутати секунди та мілісекунди (або локальний час та UTC), після чого дані «з'їжджають» та аналіз ламається.
За матеріалами itprolab.dev
Читайте також
Приймаємо оплату в bitcoin: Частина Третя, свій testnet. З блекджеком
У минулій статті я розповів, як встановити bitcoind (ну як мінімум на Ubuntu Linux) і як підключиться до testnet. Але testnet – гарне рішення, коли ви проводите тести готового сайту, вже розгорнутого на сервері в інтернеті. А ось для локальної розробки це далеко не найзручніше рішення.
EthBackNode: навіщо вашому додатку “прокладка” між ним та Ethereum-нодою
Якщо ви коли-небудь пробували написати крипто-гаманець, платіжний шлюз або просто "бекенд, який вміє відправляти та приймати ETH", то досить швидко з'ясовується неприємна річ: Ethereum-нода - це не ваш бекенд
