Отметим: когда криптобиржа решает выйти на институциональный рынок, первый вопрос клиентов — наличие FIX API. Без него prime brokers и HFT-фирмы не подключатся: их роботы не умеют работать с REST. FIX протокол — стандарт для низколатентной торговли, используемый на традиционных биржах с конца XX века. Мы разрабатываем FIX API под ключ, обеспечивая совместимость с QuickFIX, высокую пропускную способность (до 10 000 сообщений/сек) и надёжную сессионную модель с автоматическим восстановлением. Наш опыт включает реализацию FIX серверов для бирж с суточной торговлей более $100 млн. Для такой биржи переход на FIX API может сэкономить до $200 000 в год на транзакционных издержках. В этой статье разберём архитектуру FIX сервера, типовые проблемы интеграции и этапы работ. Закажите разработку FIX API — свяжитесь с нами для консультации.
FIX API: почему разработка критична для криптобиржи
FIX — текстовый протокол поверх TCP. Сообщение — набор полей тег=значение, разделённых SOH (0x01): 8=FIX.4.4 | 9=178 | 35=D | 49=CLIENT1 | 56=EXCHANGE | 34=123 | 52=20241201-14:30:00.000 | 11=ORDER-001 | 55=BTC/USD | 54=1 | 38=0.1 | 40=2 | 44=42000 | 59=1 | 10=087. Ключевые теги: 35=D (New Order Single), 55 — инструмент, 54 — сторона, 38 — количество, 40 — тип ордера, 44 — цена, 59 — Time in Force.
FIX предпочтительнее REST для институционалов по нескольким причинам. Стандартный протокол — их системы уже умеют с ним работать. Низкая latency: микросекундные задержки против миллисекундных у REST — FIX быстрее в 10–50 раз. Надёжная сессионная модель с автоматическим восстановлением после разрывов и sequencing сообщений.
Какие проблемы решает FIX API при интеграции?
Поддержка множества одновременных сессий
Каждый клиент подключается через отдельную FIX-сессию с уникальными CompID. Сервер должен корректно обрабатывать тысячи сессий, не теряя порядок сообщений. Sequencing (MsgSeqNum) гарантирует целостность: при разрыве клиент запрашивает ResendRequest, и сервер повторяет пропущенные сообщения. Наши тесты показывают стабильную работу при 2000+ одновременных сессий с нагрузкой 5000 ордеров/сек.
Восстановление после разрыва соединения
FIX-сессия поддерживает автоматическое переподключение с восстановлением последовательности. HeartBtInt (heartbeat) и ReconnectInterval настраиваются в конфиге. Если сессия потеряна, сервер отправит SequenceReset для синхронизации. Мы тестируем сценарии разрыва на уровне 1000 одновременных сессий, гарантируя нулевую потерю данных.
Аутентификация без встроенных средств
FIX 4.4 не имеет встроенной аутентификации. Мы используем комбинацию: IP whitelist + TLS + кастомное поле 96 (RawData) для API-ключа с подписью. Пример валидации в FromAdmin.
Как мы реализуем FIX сервер?
QuickFIX/Go — основная реализация
QuickFIX — reference implementation FIX engine с портами для Go, Java, C++, Python. Go-версия (quickfixgo) — отличная база для production-биржи.
import (
"github.com/quickfixgo/quickfix"
"github.com/quickfixgo/quickfix/field"
"github.com/quickfixgo/quickfix/fix44"
"github.com/quickfixgo/quickfix/fix44/newordersingle"
)
type FIXApplication struct {
orderEngine *OrderEngine
sessionManager *SessionManager
}
func (app *FIXApplication) OnCreate(sessionID quickfix.SessionID) {
log.Info("FIX session created", "sessionID", sessionID)
}
func (app *FIXApplication) OnLogon(sessionID quickfix.SessionID) {
log.Info("FIX client logged on", "sessionID", sessionID)
app.sessionManager.SetOnline(sessionID)
}
func (app *FIXApplication) OnLogout(sessionID quickfix.SessionID) {
log.Info("FIX client logged out", "sessionID", sessionID)
app.sessionManager.SetOffline(sessionID)
}
func (app *FIXApplication) FromApp(msg *quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError {
msgType, err := msg.Header.GetString(field.NewMsgType())
if err != nil {
return err
}
switch msgType {
case "D": // New Order Single
return app.handleNewOrder(msg, sessionID)
case "F": // Order Cancel Request
return app.handleCancelOrder(msg, sessionID)
case "G": // Order Cancel/Replace Request (amend)
return app.handleAmendOrder(msg, sessionID)
case "H": // Order Status Request
return app.handleStatusRequest(msg, sessionID)
}
return quickfix.NewMessageRejectError("Unknown message type", 35, nil)
}
Обработка New Order Single
func (app *FIXApplication) handleNewOrder(msg *quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError {
nos := newordersingle.New(
field.NewClOrdID(""),
field.NewSide(0),
field.NewTransactTime(time.Now()),
field.NewOrdType(0),
)
if err := quickfix.Unmarshal(msg, &nos); err != nil {
return err
}
clOrdID, _ := nos.GetClOrdID()
symbol, _ := nos.GetSymbol()
sideInt, _ := nos.GetSide()
ordType, _ := nos.GetOrdType()
qty, _ := nos.GetOrderQty()
price, _ := nos.GetPrice()
tif, _ := nos.GetTimeInForce()
order := Order{
ClientOrderID: string(clOrdID),
Pair: normalizePair(string(symbol)),
Side: fixSideToInternal(sideInt),
Type: fixOrdTypeToInternal(ordType),
Quantity: decimal.NewFromFloat(float64(qty)),
Price: decimal.NewFromFloat(float64(price)),
TimeInForce: fixTIFToInternal(tif),
}
app.sendExecReport(sessionID, order, ExecTypeNew, OrdStatusPendingNew)
trades, err := app.orderEngine.PlaceOrder(order)
if err != nil {
app.sendExecReport(sessionID, order, ExecTypeRejected, OrdStatusRejected)
return nil
}
for _, trade := range trades {
app.sendFillReport(sessionID, order, trade)
}
if order.RemainingQty().IsPositive() {
status := OrdStatusNew
if len(trades) > 0 {
status = OrdStatusPartiallyFilled
}
app.sendExecReport(sessionID, order, ExecTypeNew, status)
}
return nil
}
Отправка Execution Report
func (app *FIXApplication) sendExecReport(sessionID quickfix.SessionID, order Order, execType ExecType, ordStatus OrdStatus) {
report := fix44executionreport.New(
field.NewOrderID(order.ID),
field.NewExecID(generateExecID()),
field.NewExecType(fix44.ExecType(execType)),
field.NewOrdStatus(fix44.OrdStatus(ordStatus)),
field.NewSymbol(denormalizePair(order.Pair)),
field.NewSide(fix44.Side(internalSideToFIX(order.Side))),
field.NewLeavesQty(order.RemainingQty().InexactFloat64(), 8),
field.NewCumQty(order.FilledQty.InexactFloat64(), 8),
field.NewAvgPx(order.AvgPrice().InexactFloat64(), 8),
)
report.SetClOrdID(order.ClientOrderID)
report.SetOrderQty(order.Quantity.InexactFloat64(), 8)
report.SetTransactTime(time.Now())
quickfix.SendToTarget(report.ToMessage(), sessionID)
}
Сессионная модель и безопасность
FIX-сессия поддерживает sequencing: каждое сообщение имеет MsgSeqNum (34). При разрыве соединения клиент восстанавливает сессию с последним известным SeqNum. Сервер может отправить ResendRequest (2) или SequenceReset (4).
Пример конфигурации FIX-сессии
func createFIXSettings() *quickfix.Settings {
settings := quickfix.NewSettings()
globalSection := quickfix.NewSessionSettings()
globalSection.Set("FileStorePath", "./fix-sessions")
globalSection.Set("FileLogPath", "./fix-logs")
settings.GlobalSettings().SetGlobalSection(globalSection)
sessionSection := quickfix.NewSessionSettings()
sessionSection.Set(quickfix.BeginString, "FIX.4.4")
sessionSection.Set(quickfix.SenderCompID, "EXCHANGE")
sessionSection.Set(quickfix.TargetCompID, "CLIENT1")
sessionSection.Set("HeartBtInt", "30")
sessionSection.Set("ReconnectInterval", "5")
sessionSection.Set("StartTime", "00:00:00")
sessionSection.Set("EndTime", "00:00:00")
return settings
}
FIX 4.4 не имеет встроенной аутентификации. Стандартные подходы:
- IP whitelist: только разрешённые IP подключаются к FIX-порту.
- TLS: шифрование соединения (FIX over SSL).
- Logon с password: поле 96 (RawData) или кастомный тег для API-ключа с подписью.
func (app *FIXApplication) FromAdmin(msg *quickfix.Message, sessionID quickfix.SessionID) quickfix.MessageRejectError {
msgType, _ := msg.Header.GetString(field.NewMsgType())
if msgType == "A" { // Logon
apiKey, _ := msg.Body.GetString(9001)
signature, _ := msg.Body.GetString(9002)
timestamp, _ := msg.Body.GetString(9003)
if !app.auth.Verify(apiKey, signature, timestamp) {
return quickfix.NewMessageRejectError("Authentication failed", 58, nil)
}
app.sessionManager.SetAPIKey(sessionID, apiKey)
}
return nil
}
Безопасность FIX соединения: три уровня защиты
Мы гарантируем защиту на трёх уровнях: транспортный (TLS), сетевой (IP whitelist) и прикладной (аутентификация с подписью). Дополнительно реализуем аудит сессий и Drop Copy для compliance. Это стандарт для бирж, работающих с институциональными клиентами.
Объём работ при разработке FIX API
- Разработка сервера FIX 4.4 на Go (QuickFIX)
- Реализация типовых сообщений: New Order, Cancel, Amend, Execution Reports
- Market Data feed (подписка на стакан и сделки)
- Безопасность: TLS, IP whitelist, аутентификация по ключам
- Drop Copy для compliance
- Документация и тестирование (нагрузочное, регрессионное)
- Обучение команды и поддержка на этапе внедрения
Процесс работы и сроки
- Аналитика: изучаем ваши требования и существующую архитектуру.
- Проектирование: разрабатываем схему сессий, очередность сообщений и политики безопасности.
- Реализация: пишем код — от парсинга сообщений до взаимодействия с matching engine.
- Тестирование: нагрузочное (1000+ ордеров/сек) и регрессионное.
- Деплой: развертывание, мониторинг и обучение вашей команды.
Ориентировочные сроки: от 4 недель для базовой интеграции до 2–3 месяцев для полноценного production-ready решения.
| Характеристика | FIX | REST |
|---|---|---|
| Задержка | Микросекунды (<100 мкс) | Миллисекунды |
| Надёжность | Встроенное восстановление | Сложнее |
| Аутентификация | Внешняя (TLS + ключи) | API-ключи |
| Стандартизация | Единый протокол | Разные реализации |
| Этап | Длительность |
|---|---|
| Аналитика и проектирование | 1–2 недели |
| Разработка базового сервера | 3–4 недели |
| Market Data и Drop Copy | 2–3 недели |
| Тестирование (нагрузочное, регрессионное) | 2 недели |
| Деплой и обучение | 1 неделя |
Типичные ошибки при разработке FIX API
Некорректный sequencing: если MsgSeqNum сбивается, сессия уходит в broken state. Используйте файловое или БД-хранилище для SeqNum, а не in-memory. Игнорирование HeartBtInt: клиенты отключаются при отсутствии heartbeats. Настройте HeartBtInt на 30 секунд и обрабатывайте MissedHeartBeat. Отсутствие ResendRequest: при разрыве клиент должен запросить повтор. Убедитесь, что сервер хранит все сообщения для повторной отправки.
Получите консультацию по FIX API для вашей биржи — свяжитесь с нами для оценки объёма работ. Запросите тестовую интеграцию: мы предоставим доступ к инстансу FIX-сервера для ваших разработчиков.
Спецификация FIX протокола: FIX protocol







