roq-fix-bridge#

Purpose#

  • Gateway bridge using a FIX 4.4 based message protocol

  • Integration with third-party vendors

Description#

The FIX bridge allows FIX clients to connect with gateways, receive market data, and manage orders.

The FIX bridge configuration defines a list of exchanges and corresponding symbols (regex). This implementation use exchange/symbol for all message routing!

Note

Some FIX clients may rely on TradingSessionID for state management. For many Crypto exchanges, this is not a well-defined concept. The implementation choice is to use the source_name of the gateway (as specified using the gateway --name command-line flag) to mean TradingSessionID. The concept of TradingSessionID is otherwise not used directly by the FIX bridge for any message routing.

The FIX bridge will automatically manage gateway connectivity.

Upon connecting to a gateway, the FIX bridge will discover the universe of exchange/symbol as well as order management capabilities, e.g. whether order rewrite is supported by a gateway. Furthermore, a “ready”-state is being maintained based on gateway notifications around account availability.

Note

FIX clients should expect and manager order action rejects if the exchange/symbol has not yet been discovered and/or the account is not yet in the ready state (e.g. due to disconnect).

Order management has been implemented to conform to FIX Order State Changes.

This effectively means that ClOrdId/OrigClOrdId chaining is supported when modifying and canceling orders.

When possible, gateways will try to pass enough information to the exchange such that later order download will be able to notify the FIX bridge with the correct ClOrdId/OrigClOrdId information. This is however only best effort and the feature should not be relied upon!

Note

The FIX bridge and the gateways are all designed for low latency and there is no database persistence layer causing latency anywhere in the path of order routing. Furthermore, not all exchanges support rewriting client order identifiers. The FIX bridge and the gateways maintain in-memory maps between exchange order identifiers and outstanding requests on the one side, and ClOrdId/OrigClOrdId on the other side. Correct updates around ClOrdId/OrigClOrdId chaining should only be expected if both FIX bridge and gateway remain connected. Reconnection may work, but it’s best effort, only.

To manage uncertainties around disconnects, the FIX bridge may be configured such that gateways are instructed to auto-cancel orders upon disconnect. Similarly, when possible, gateways may be configured such that exchanges are instructed to auto-cancel orders upon disconnect.

Conda#

$ mamba install \
  --channel https://roq-trading.com/conda/stable \
  roq-fix-bridge
$ cp $CONDA_PREFIX/share/roq-fix-bridge/config.toml $CONFIG_FILE_PATH

# Then modify $CONFIG_FILE_PATH to match your specific configuration
$ roq-fix-bridge \
      --name "fix-bridge" \
      --config_file "$CONFIG_FILE_PATH" \
      --service_listen_address "$TCP_LISTEN_PORT_FOR_METRICS" \
      --client_listen_address "$TCP_LISTEN_PORT_FOR_FIX_CLIENTS" \
      --flagfile "$FLAG_FILE" \
      [<gateway unix domain sockets>]

Config#

A list of exchanges and corresponding symbols.

[symbols]

 [symbols.bitmex]
 regex=["XBTUSD", "XBT.*"]

 [symbols.deribit]
 regex=".*"

A list of FIX clients allowed to connect to the FIX bridge.

[users]

 [users.MD1]
 component="roq-fix-client-test"
 username="tbmd1"

An optional list of mapping overrides. This may be necessary because FIX 4.4 has a limited set of market data types (MDEntryType).

[statistics]

  [statistics.FUNDING_RATE]
  fix_md_entry_type="SETTLEMENT_PRICE"

Flags#

$ roq-fix-bridge --help

--config_file

Config file (path)

--client_listen_address

Listen address (network address)

--cancel_on_disconnect

Instruct gateway to cancel all open orders on (client or bridge) disconnect?

--fix_version

FIX version, e.g. 4.4

--fix_comp_id

Component identifier

--fix_logon_timeout

Logon timeout. Must be less than or equal to heartbeat frequency. Heartbeat frequency is chosen if this flag is unspecified

--fix_heartbeat_freq

Heartbeat frequency (server to client)

--fix_debug

Debug FIX msesages?

--fix_log_path

Filename for logging FIX messages

--init_missing_md_entry_type_to_zero

Can be used to initialize non-existing statistics types to zero.

--execution_report_using_quote_currency

Use quote currency for execution report?

--exchange_time_as_sending_time

Use exchange time for sending time (tag 52)?

--top_of_book_from_market_by_price

Use market by price as the source for top of book?

Session#

Client → Server#

Tag

Name

Comments

98

EncryptMethod

108

HeartBtInt

Heartbeat interval in seconds

141

ResetSeqNumFlag

Reset sequence numbers?

789

NextExpectedMsgSeqNum

553

Username

554

Password

Tag

Name

Comments

58

Text

Informative text

Tag

Name

Comments

112

TestReqId

Pass-through value (will be returned with Heartbeat)

Tag

Name

Comments

112

TestReqId

Pass-through value (copied from TestRequest)

Tag

Name

Comments

45

RefSeqNum

Sequence number causing the reject

58

Text

Informative text

371

RefTagID

Tag ID causing the reject

372

RefMsgType

Message type causing the reject

373

SessionRejectReason

Tag

Name

Comments

7

BeginSeqNo

First sequence number to replay

16

EndSeqNo

Last sequence number to replay

Server → Client#

Tag

Name

Comments

108

HeartBtInt

Heartbeat interval (seconds)

Tag

Name

Comments

58

Text

Informative text

Tag

Name

Comments

112

TestReqId

Pass-through value (will be returned with Heartbeat)

Tag

Name

Comments

112

TestReqId

Some pass-through value (copied from TestRequest)

Tag

Name

Comments

45

RefSeqNum

Sequence number causing the reject

58

Text

Informative text

371

RefTagID

Tag ID causing the reject

372

RefMsgType

Message type causing the reject

373

SessionRejectReason

Tag

Name

Comments

7

BeginSeqNo

First sequence number to replay

16

EndSeqNo

Last sequence number to replay

Market Data#

Client → Server#

Tag

Name

Comments

335

TradSesReqID

Request ID

336

TradingSessionID

Specific name

263

SubscriptionRequestType

Snapshot, subscribe, unsubscribe

Tag

Name

Comments

320

SecurityReqId

Request ID

559

SecurityListRequestType

Request type

55

Symbol

207

SecurityExchange

336

TradingSessionID

263

SubscriptionRequestType

Snapshot, subscribe, unsubscribe

Tag

Name

Comments

320

SecurityReqId

Request ID

321

SecurityRequestType

Request type

55

Symbol

207

SecurityExchange

336

TradingSessionID

263

SubscriptionRequestType

Snapshot, subscribe, unsubscribe

Tag

Name

Comments

324

SecurityStatusReqId

Request ID

55

Symbol

Symbol

207

SecurityExchange

Exchange

263

SubscriptionRequestType

Snapshot, subscribe, unsubscribe

336

TradingSessionID

Tag

Name

Comments

262

MDReqID

Request ID

263

SubscriptionRequestType

Snapshot, Subscribe, Unsubscribe

264

MarketDepth

Depth?

265

MDUpdateType

Update type. Note! we currently only support incremental updates

266

AggregateBook

Using TopOfBook if true

267

NoMDEntryTypes

Count

269

MDEntryType

146

NoRelatedSym

Count

55

Symbol

207

SecurityExchange

386

NoTradingSessions

Count

336

TradingSessionID

20000

CustomType

Enum (string): VWAP

20001

CustomValue

Value (double) depending on CustomType

Server → Client#

Tag

Name

Comments

335

TradSesReqID

Request ID

336

TradingSessionID

Specific name

325

UnsolicitedIndicator

567

TradSesStatusRejReason

58

Text

Tag

Name

Comments

320

SecurityReqId

Request ID (only snapshot)

322

SecurityResponseID

Response ID

560

SecurityRequestResult

Result type

146

NoRelatedSym

Count

55

Symbol

231

ContractMultiplier

207

SecurityExchange

562

MinTradeVol

336

TradingSessionID

Tag

Name

Comments

320

SecurityReqId

Request ID

322

SecurityResponseID

Response ID

323

SecurityResponseType

Response type

55

Symbol

231

ContractMultiplier

207

SecurityExchange

562

MinTradeVol

336

TradingSessionID

Tag

Name

Comments

324

SecurityStatusReqId

Request ID (only snapshot)

55

Symbol

207

SecurityExchange

336

TradingSessionID

325

UnsolicitedIndicator

False if snapshot, True if incremental update

326

SecurityTradingStatus

Market status

Tag

Name

Comments

262

MDReqID

Request ID

55

Symbol

207

SecurityExchange

268

NoMDEntries

Count

269

MDEntryType

Field

270

MDEntryPx

Price

271

MDEntrySize

Size

272

MDEntryDate

Begin time (UTC)

273

MDEntryTime

Begin time (UTC)

336

TradingSessionID

126

ExpireTime

End time (UTC)

37

OrderID

Order ID (optional)

346

NumberOfOrders

Number of orders (MBP)

290

MDEntryPositionNo

Order priority (MBO)

Tag

Name

Comments

268

NoMDEntries

Count

279

MDUpdateAction

Update action

269

MDEntryType

Field

55

Symbol

207

SecurityExchange

270

MDEntryPx

Price

271

MDEntrySize

Size

272

MDEntryDate

Begin time (UTC)

273

MDEntryTime

Begin time (UTC)

336

TradingSessionID

126

ExpireTime

End time (UTC)

37

OrderID

346

NumberOfOrders

Number of orders (MBP)

290

MDEntryPositionNo

Order priority (MBO)

Tag

Name

Comments

262

MDReqID

Request ID

281

MDReqRejReason

Reject reason

58

Text

Informative text

Order Management#

Client → Server#

Tag

Name

Comments

37

OrderID

11

ClOrdID

790

OrdStatusReqID

Unique ID (for the request)

55

Symbol

207

SecurityExchange

54

Side

Tag

Name

Comments

584

MassStatusReqID

Unique ID (for the request)

585

MassStatusReqType

Request type

336

TradingSessionID

55

Symbol

207

SecurityExchange

54

Side

Tag

Name

Comments

11

ClOrdID

Unique ID (for the request)

453

NoPartyIDs

448

PartyID

447

PartyIDSource

452

PartyRole

1

Account

21

HandlInst

18

ExecInst

Execution instruction

386

NoTradingSessions

Count

336

TradingSessionID

55

Symbol

207

SecurityExchange

54

Side

60

TransactTime

Request timestamp

38

OrderQty

Total intended order quantity

40

OrdType

Order type

44

Price

99

StopPx

Stop price

59

TimeInForce

58

Text

77

PositionEffect

210

MaxShow

Max quantity to show (if supported by exchange)

Tag

Name

Comments

41

OrigClOrdID

ClOrdID of the previous non-rejected order

37

OrderID

11

ClOrdID

Unique ID (for the request)

55

Symbol

207

SecurityExchange

54

Side

60

TransactTime

Request timestamp

38

OrderQty

58

Text

Tag

Name

Comments

37

OrderID

Order ID

41

OrigClOrdID

ClOrdID of the previous non-rejected order

11

ClOrdID

Unique ID (for the request)

55

Symbol

207

SecurityExchange

38

OrderQty

Total intended order quantity

44

Price

54

Side

60

TransactTime

Request timestamp

40

OrdType

Order type

Tag

Name

Comments

11

ClOrdID

Unique ID (for the request)

530

MassCancelRequestType

Type of request (only supporting 7 = cancel all orders)

336

TradingSessionID

60

TransactTime

Request timestamp

Server → Client#

Tag

Name

Comments

37

OrderID

11

ClOrdID

Client order ID

41

OrigClOrdID

Original client order ID

790

OrdStatusReqID

Request ID (if response to OrderStatusRequest)

584

MassStatusReqID

Request ID (if response to OrderMassStatusRequest)

911

TotNumReports

Total number of reports (if response to OrderMassStatusRequest)

912

LastRptRequested

True if last report (if response to OrderMassStatusRequest)

17

ExecID

Execution ID

150

ExecType

Execution type

39

OrdStatus

Order status

636

WorkingIndicator

103

OrdrejReason

Order reject reason

1

Account

581

AccountType

55

Symbol

207

SecurityExchange

54

Side

40

OrdType

38

OrderQty

Order quantity

44

Price

99

StopPx

Stop price

15

Currency

Currency (from reference data, if available)

59

TimeInForce

18

ExecInst

Execution instruction

32

LastQty

Fill quantity (if trade)

31

LastPx

Fill price (if trade)

336

TradingSessionID

151

LeavesQty

Remaining order quantity

14

CumQty

Cummulative traded quantity

6

AvgPx

Average fill price

60

TransactTime

Transaction time

77

PositionEffect

Position effect

210

MaxShow

Max shown quantity

58

Text

851

LastLiquidityInd

Liquidity indicator of fill (if trade, maker or taker)

Tag

Name

Comments

37

OrderID

11

ClOrdID

Client order ID

41

OrigClOrdID

Original client order ID

39

OrdStatus

Order status

636

WorkingIndicator

1

Account

434

CxlRejResponseTo

Origin of request (OrderCancel or OrderCancelReplace)

102

CxlRejReason

Reason for reject

58

Text

Tag

Name

Comments

11

ClOrdID

Unique ID (for the request)

37

OrderID

Unique ID (from the server)

530

MassCancelRequestType

Request type

531

MassCancelResponse

Response type

532

MassCancelRejectReason

Reason for reject

58

Text

Trade Reporting#

Client → Server#

Tag

Name

Comments

568

TradeRequestID

569

TradeRequestType

263

SubscriptionRequestType

37

OrderID

11

ClOrdID

880

TrdMatchID

Server → Client#

Tag

Name

Comments

571

TradeReportID

568

TradeRequestID

150

ExecType

748

TotNumTradeReports

912

LastRptRequested

325

UnsolicitedIndicator

880

TrdMatchID

55

Symbol

207

SecurityExchange

32

LastQty

31

LastPx

60

TransactTime

552

NoSides

54

Side

37

OrderID

11

ClOrdID

1

Account

581

AccountType

77

PositionEffect

Tag

Name

Comments

568

TradeRequestID

569

TradeRequestType

749

TradeRequestResult

750

TradeRequestStatus

Position Management#

Client → Server#

Tag

Name

Comments

710

PosReqID

724

PosReqtype

263

SubscriptionRequestType

55

Symbol

207

SecurityExchange

386

NoTradingSessions

Count

336

TradingSessionID

Server → Client#

Tag

Name

Comments

721

PosMaintRptID

710

PosReqID

724

PosReqType

263

SubscriptionRequestType

727

TotalNumPosReports

325

UnsolicitedIndicator

728

PosReqResult

715

ClearingBusinessDate

1

Account

581

AccountType

55

Symbol

207

SecurityExchange

730

SettlPrice

731

SettlPriceType

734

PriorSettlPrice

702

NoPositions

703

PosType

704

LongQty

705

ShortQty

753

NoPosAmt

707

PosAmtType

708

PosAmt

Miscellaneous#

Server → Client#

Tag

Name

Comments

45

RefSeqNum

372

RefMsgTyp

379

BusinessRejectRefID

380

BusinessRejectReason

58

Text

Constraints#

  • The bridge must register as a regular user to the gateways. The implication is that the bridge only has visibility to that user, i.e. there is no option to see the orders managed by other users. Thus, there is currently no option to implement a true drop-copy solution.

  • The bridge requires each downstream client to be mapped 1:1 with an account. This is currently the only option to route order acks, order updates and trades back to the correct client. Note! The C++ API does support account multiplexing.

  • The universe of {exchange, symbol} is dynamic and can not always be known at the time when a FIX client issues a request. The FIX protocol also does not allow for a client to receive notifications when an exchange hase become ready. Thus, a FIX client must expect rejects (when an {exchange, symbol} combination has not yet become available, for example) and implement a retry policy.

  • Successful FIX client subscriptions will be cached and survive gateway reconnects. This is done because the FIX protocol does not allow for a client to receive notifications when a subscription is broken. Thus, a FIX client must expect stale subscriptions and implement a timeout policy.

  • The FIX protocol requires subsequent order actions to be rejected if a previous request has been rejected. Full support is only possible if the exchanges support it or if the gateways disallow pipelining (sending multiple requests without first waiting for the previous request’s response). A low-latency configuration should allow pipelining (at the gateway level) and the FIX bridge can therefore not be fully FIX compliant (for the reasons just described).

  • Custom order book calculations are supported but constrained to one custom calculation per market data request. It is not possible to overlap custom calculations with regular updates (like top of book or market by price) due to the FIX protocol allowing for any other special identifiers with the full/incremental updates.