Pro-возможности

Протокол FIX

Нагрузочное тестирование FIX-площадок — сессии, ордера, маркет-дата

Обзор

perfscale умеет нагружать FIX (Financial Information eXchange) площадки: открывать initiator-сессии, логиниться, слать поток ордеров/запросов маркет-даты и замерять round-trip задержку вместе с метриками HTTP/TCP/UDP.

FIX — платная возможность (планы Scale и Enterprise). Тесты с действиями pro/fix* отклоняются при создании для тенантов на плане Starter.

Действия

pro/fix@v1 — запуск сессии

Открывает TCP-соединение, логинится, отправляет заданные сообщения, делает logout и замеряет обмен. Шаг падает, если logon отклонён либо произошла ошибка транспорта/таймаут; задержка учитывается как у любого другого действия.

steps:
  - uses: pro/fix@v1
    with:
      host: fix.venue.com
      port: 9823
      begin_string: FIXT.1.1
      default_appl_ver_id: "9"        # FIX 5.0 SP2
      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
ПараметрПо умолчаниюОписание
host + port / addressЦель (обязательно, если не через connection)
connectionПрофиль подключения (см. ниже), задаёт значения по умолчанию
sender_comp_id / target_comp_idSenderCompID (49) / TargetCompID (56), обязательны
begin_stringFIX.4.4BeginString (8), напр. FIXT.1.1
heart_bt_int30HeartBtInt (108)
reset_seq_numtrueResetSeqNumFlag (141)
default_appl_ver_idDefaultApplVerID (1137), для FIXT.1.1
username / passwordUsername (553) / Password (554)
tlsfalseПодключение по TLS (шифрованный порт гейта)
tls_server_namehostSNI / имя хоста для проверки сертификата
skipTLSVerifyfalseПринять любой сертификат (только self-signed staging)
schemaтолько сессияСловарь FIX — URL / контент FIX44.xml / inline JSON; см. ниже
messages[]Прикладные сообщения после logon
read_repliestrueЧитать один ответный фрейм на сообщение
logouttrueОтправлять Logout в конце
timeout10000Миллисекунды на всю сессию

pro/fix-config@v1 — переиспользуемый профиль подключения

Валидирует профиль (host/port/учётные данные/skipTLSVerify/schema) и выдаёт его как config-объект. Размещайте в блоке before: конфиг-файла, чтобы много шагов делили одно подключение:

# config.yaml
vus: 50
duration: 5m
before:
  - uses: pro/fix-config@v1
    with:
      host: fix.venue.com
      port: 9823
      sender_comp_id: CLIENT
      target_comp_id: VENUE
      schema:
        fields: { AlgoTag: 7001 }
    outputs: venue
# test.yaml — host/port/schema наследуются через connection
steps:
  - uses: pro/fix@v1
    with:
      connection: "${{ config.venue }}"
      messages:
        - MsgType: NewOrderSingle
          ClOrdID: "${uuid}"
          Symbol: EURUSD
          Side: 1
          OrderQty: 100000
          OrdType: 1

Словарь FIX (data dictionary)

schema позволяет писать сообщения именами полей вместо сырых тегов и падать сразу при отсутствии обязательного поля. Словарь загружается из спеки венью — QuickFIX FIX44.xml, ровно то, что CoinAPI поставляет как DataDictionary=FIX44.xml — а не хардкодится. Встроен только сессионный слой (стандартный заголовок/трейлер + admin-сообщения), поэтому голый logon работает без схемы, а числовые теги доступны всегда.

schema можно задать как URL, как контент, полученный движком, или inline JSON:

before:
  # 1) URL — скачивается один раз при сборке конфига
  - uses: pro/fix-config@v1
    with:
      schema: https://raw.githubusercontent.com/quickfix/quickfix/master/spec/FIX44.xml

  # 2) скачать движком, передать тело
  - uses: std/http@v1
    with: { url: https://.../FIX44.xml }
    outputs: dict
  - uses: pro/fix-config@v1
    with:
      schema: "${{ dict.body }}"

Inline JSON тоже работает — для пары кастомных полей поверх сессионной базы:

schema:
  fields: { AlgoTag: 7001 }
  messages:
    NewOrderSingle: { required: [ClOrdID, Symbol, Side, OrderQty, OrdType] }

После загрузки словаря ключи сообщения — имена полей или числовые теги, а значение MsgType — имя (NewOrderSingle) или код (D).

Подключение к боевой площадке (CoinAPI)

Market Data FIX от CoinAPI — конкретная FIX 4.4 цель: TLS-гейт fix.coinapi.io:3303, SenderCompID = ваш API-ключ, TargetCompID COINAPI_V2. Подписка на живой поток сделок:

# config.yaml — грузим FIX44.xml CoinAPI, строим TLS-профиль
before:
  - uses: std/http@v1
    with: { url: https://raw.githubusercontent.com/quickfix/quickfix/master/spec/FIX44.xml }
    outputs: dict
  - uses: pro/fix-config@v1
    with:
      host: fix.coinapi.io
      port: 3303
      tls: true
      sender_comp_id: YOUR_COINAPI_KEY   # инжектить, не коммитить
      target_comp_id: COINAPI_V2
      heart_bt_int: 10
      schema: "${{ dict.body }}"
    outputs: coinapi
# test.yaml — подписка на сделки
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

Динамические сообщения (генерация сделок)

Значения полей могут содержать токены ${...}, раскрываемые на каждую отправку, а сообщение несёт _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 мс

Токены переменных сообщения

ТокенРаскрывается в
${seq}Монотонный счётчик, уникален на отправку (общий для всех полей сообщения)
${uuid}Случайный id из 32 hex-символов
${now}Текущее UTC-время в формате FIX YYYYMMDD-HH:MM:SS.sss
${rand(a,b)}Случайное целое в [a, b]
${randf(a,b)} / ${randf(a,b,dp)}Случайное дробное в [a, b], dp знаков (по умолчанию 2)
${choice(x|y|z)}Случайный выбор из вариантов

Эти одинарные ${...} отличаются от движковой интерполяции ${{ ... }} (config/variables/выходы шагов), которая раскрывается до запуска шага.

Директивы сообщения

ДирективаПо умолчаниюОписание
_repeat1Отправить сообщение N раз; токены раскрываются заново каждый раз
_interval_ms (алиас _interval)0Задержка между повторами, мс

Для устойчивой нагрузки комбинируйте с конфигом: vus параллельных сессий × цикл итераций × _repeat на итерацию.

Вывод и проверки

Вывод шага содержит logon, sent, received, duration_ms, разобранные ответные messages и склеенный сырой body. Проверяйте через check:

    check:
      body_contains: "35=8"   # пришёл ExecutionReport

См. также

  • SOAP — вторая pro-фича для корпоративных протоколов: WSDL-профили, envelopes, разбор SOAP Fault.