Биржи, брокеры и площадки ликвидности говорят на FIX — лаконичном tag-value протоколе, который носит поток ордеров и маркет-дату с 1992 года. Когда ваш торговый шлюз, OMS или раздача маркет-даты должны пережить бурное открытие рынка, тестировать их нужно так, как их реально используют: настоящие FIX-сессии, настоящие логоны, настоящие всплески ордеров. Теперь это работает по всему стеку Perfscale.
FIX — премиум-возможность, доступная на планах Scale и Enterprise. Тесты с действиями pro/fix* ограничены по плану; всё ниже работает одинаково, гоняете ли вы одну сессию из CLI или тысячи с парка машин.
Первая сессия
FIX-шаг открывает TCP- (или TLS-) соединение, логинится, шлёт заданные сообщения, делает logout и замеряет весь обмен. Задержка попадает в тот же гистограмм, что и HTTP — поэтому перцентили FIX стоят рядом со всем остальным.
# test.yaml
steps:
- uses: pro/fix@v1
with:
host: fix.venue.com
port: 9823
tls: true
begin_string: FIXT.1.1
sender_comp_id: CLIENT
target_comp_id: VENUE
heart_bt_int: 30
messages:
- MsgType: NewOrderSingle
ClOrdID: order-1
Symbol: EURUSD
Side: 1
OrderQty: 100000
OrdType: 1
perfscale run -f test.yaml -c load.yaml
Шаг успешен, когда logon принят и — при logout: true — сессия закрыта чисто. Проверяйте ответ через check, напр. body_contains: "35=8" для ExecutionReport.
Словарь берётся от площадки, а не от нас
Имена полей FIX (Symbol = 55, Side = 54) живут в словаре данных (data dictionary). Вместо того чтобы зашивать словарь в инструмент, Perfscale грузит собственный FIX44.xml площадки — тот самый файл, который движки QuickFIX используют как DataDictionary=FIX44.xml. Укажите pro/fix-config@v1 URL, либо скачайте движком и передайте тело:
# config.yaml
before:
- uses: std/http@v1
with: { url: https://.../FIX44.xml }
outputs: dict
- uses: pro/fix-config@v1
with:
host: fix.venue.com
port: 9823
tls: true
sender_comp_id: CLIENT
target_comp_id: VENUE
schema: "${{ dict.body }}"
outputs: venue
Профиль строится один раз и переиспользуется каждым шагом через connection: "${{ config.venue }}" — host, TLS, учётные данные и разобранный словарь наследуются. Встроен только сессионный слой (logon/logout/heartbeat); прикладные сообщения валидируются по реальной спеке площадки, и отсутствие обязательного поля роняет тест сразу, а не на проводе.
Генерация потока сделок
Один шаблон сообщения превращается в поток. Значения могут содержать токены ${…}, раскрываемые на каждую отправку, а _repeat / _interval_ms задают расписание — так каждый ордер уникален:
messages:
- MsgType: NewOrderSingle
ClOrdID: "ord-${seq}" # уникальный на каждый ордер
Symbol: "${choice(EURUSD|GBPUSD|USDJPY)}"
Side: "${rand(1,2)}"
OrderQty: "${rand(1000,100000)}"
Price: "${randf(1.05,1.15,5)}"
TransactTime: "${now}"
_repeat: 100 # 100 ордеров…
_interval_ms: 50 # …по одному каждые 50 мс
Умножьте на vus параллельных сессий и цикл итераций VU — и получите реалистичный устойчивый поток ордеров, а не одно заготовленное сообщение по кругу.
Проверка на реальной площадке: CoinAPI
Market Data FIX от CoinAPI — хорошая публичная цель. Это FIX 4.4 поверх TLS на fix.coinapi.io:3303, аутентификация задаётся установкой SenderCompID в ваш API-ключ, а подписки идут через MarketDataRequest (35=V). Загрузите их FIX44.xml как словарь и подпишитесь на живой поток сделок:
steps:
- uses: pro/fix@v1
with:
connection: "${{ config.coinapi }}"
messages:
- MsgType: MarketDataRequest
MDReqID: "perfscale-${uuid}"
SubscriptionRequestType: 1 # подписка
MarketDepth: 1
MDUpdateType: 1
NoMDEntryTypes: 1
MDEntryType: 2 # сделки
NoRelatedSym: 1
Symbol: COINBASE_SPOT_BTC_USD
timeout: 15000
Где это работает
FIX работает на нативном движке — без внешних бинарей — поэтому одинаково в CLI perfscale, агенте perfscaled и через оркестрацию controlplane. Полный справочник (все параметры, формы схемы и токены динамических сообщений) — в документации:
Если вы на Scale или Enterprise — направьте на свой шлюз и запускайте. Если ещё нет — это и есть повод для апгрейда.
