Как получать данные фондового рынка
Что проверяют
Это вопрос на проектирование интеграции, а не на http.Get. Интервьюер смотрит, различаете ли вы исторические данные и поток котировок, думаете ли о лимитах, обрывах соединения и точности чисел. Следом обычно спрашивают, что делать с медленным потребителем и как не потерять тики при переподключении.
Как отвечать
Разведите два режима:
- история и свечи: REST или gRPC API провайдера, запрос по диапазону дат с пагинацией. Здесь важны лимиты, поэтому клиент ограничивается через
golang.org/x/time/rate, а ответы кэшируются: прошлые свечи не меняются; - реальное время: WebSocket от брокера или агрегатора, у профессиональных источников протокол FIX и бинарные фиды биржи. Бесплатные источники часто отдают котировки с задержкой, реальное время обычно платное и лицензируется отдельно.
Каркас на Go:
- клиент: свой
http.ClientсTimeoutиcontext.Contextна каждый запрос, потому что у клиента по умолчанию таймаута нет; - поток: горутина читает сокет, при обрыве переподключается с экспоненциальной задержкой и джиттером, после переподключения берёт снапшот и сверяет порядковые номера сообщений, чтобы заметить пропуски;
- раздача: fan-out через каналы. Медленному потребителю не дают тормозить весь поток: либо буферизованный канал с отбрасыванием, либо конфляция, когда хранится только последняя цена по тикеру;
- хранение: временные ряды в ClickHouse или TimescaleDB, время биржи и время получения отдельными полями, всё в UTC.
Где спотыкаются
Хранят цену в float64. Для денег это ошибка округления на каждой операции: цену держат целым числом в минимальных единицах или в десятичном типе вроде shopspring/decimal.
Пишут http.Get в цикле по тикерам. Без таймаута зависший ответ держит горутину бесконечно, а последовательные запросы по сотне бумаг сразу упираются в лимиты API. Нужны пакетные эндпоинты или подписка на поток.
Не думают о торговом календаре. Выходные, праздники, разные сессии и часовые пояса площадок дают «дыры» в данных, которые система без знания расписания принимает за сбой провайдера.