fix

FIX protocol (Financial Information eXchange) implementation for Kit

Files

FileDescription
.editorconfigEditor formatting configuration
.gitignoreGit ignore rules for build artifacts and dependencies
.tool-versionsasdf tool versions (Zig, Kit)
LICENSEMIT license file
README.mdThis file
examples/market-data.kitExample: market data request fields
examples/simple-client.kitExample: new order single fields
kit.tomlPackage manifest with metadata and dependencies
src/main.kitFIX protocol module
tests/error-types.test.kitTests for FIX error types
tests/fix.test.kitTests for FIX protocol helpers

Dependencies

No Kit package dependencies.

Installation

kit add gitlab.com/kit-lang/packages/kit-fix.git

Usage

import Kit.Fix as FIX

main = fn =>
  # Build a new order single message
  order = FIX.new-order-single {
    cl-ord-id: "ORD-001", 
    account: None, 
    symbol: "AAPL", 
    side: FIX.Buy, 
    order-qty: 100.0, 
    price: Some 150.25, 
    stop-px: None, 
    ord-type: Some FIX.Limit, 
    time-in-force: FIX.fix-to-tif "0", 
    min-qty: None, 
    max-floor: None, 
    ex-destination: None
  }

  # Work with typed FIX values
  side = FIX.side-to-fix FIX.Buy
  order-type = FIX.order-type-to-fix FIX.Limit

  println "Side ${side}, order type ${order-type}"

  match order
    | NewOrderSingle details ->
      println "Order ${details.cl-ord-id}: ${details.symbol}"
    | _ ->
      println "Unexpected message"

  # Create a session configuration for a FIX 4.4 endpoint
  config = FIX.SessionConfig {
    host: "fix.broker.example", 
    port: 9878, 
    sender-comp-id: "CLIENT1", 
    target-comp-id: "BROKER", 
    heartbeat-interval: 30, 
    version: FIX.FIX44, 
    username: None, 
    password: None, 
    reset-seq-num: false, 
    socket-timeout-ms: 30000, 
    recv-timeout-ms: 5000, 
    store-max-messages: 1000
  }

  println "Configured FIX session for ${config.sender-comp-id}"

main

Development

Running Examples

Run examples with the interpreter:

kit run examples/simple-client.kit

Compile examples to a native binary:

kit build examples/simple-client.kit && ./simple-client

Running Tests

Run the test suite:

kit test

Run the test suite with coverage:

kit test --coverage

Running kit dev

Run the standard development workflow (format, check, test):

kit dev

This will:

  1. Format and check source files in src/
  2. Check examples in examples/
  3. Run tests in tests/ with coverage

Running Parity

Compare interpreted and compiled example behavior:

kit parity --no-spinner --failures-only

Generating Documentation

Generate API documentation from doc comments:

kit doc

Note: Kit sources with doc comments (##) will generate HTML documents in docs/*.html

Cleaning Build Artifacts

Remove generated files, caches, and build artifacts:

kit task clean

Note: Defined in kit.toml.

Local Installation

To install this package locally for development:

kit install

This installs the package to ~/.kit/packages/@kit/fix/, making it available for import as Kit.Fix in other projects.

License

This package is released under the MIT License - see LICENSE for details.

Exported Functions & Types

FIXVersion

Supported FIX protocol versions.

Variants

FIX42
FIX44
FIX50

FIXError

FIX protocol error type for typed error handling.

Variants

FIXConnectionError {message}
FIXSessionError {message}
FIXLogonError {message}
FIXLogoutError {message}
FIXSendError {message}
FIXRecvError {message}
FIXParseError {message}
FIXChecksumError {expected, actual}
FIXSequenceError {expected, received}
FIXTimeoutError {message}
FIXRejectError {ref-seq-num, reason}
FIXGapError {begin-seq, end-seq}

tags

Standard FIX field tags. See https://www.onixs.biz/fix-dictionary.html for complete reference.

msg-types

FIX message type codes.

Side

Order side enumeration.

Variants

Buy
Sell
BuyMinus
SellPlus
SellShort
SellShortExempt

side-to-fix

Convert side to FIX value.

Side -> String

fix-to-side

Parse side from FIX value.

String -> Option Side

OrderType

Order type enumeration.

Variants

Market
Limit
Stop
StopLimit
MarketOnClose
WithOrWithout
LimitOrBetter
LimitWithOrWithout

order-type-to-fix

Convert order type to FIX value.

OrderType -> String

fix-to-order-type

Parse order type from FIX value.

String -> Option OrderType

TimeInForce

Time in force enumeration.

Variants

Day
GTC
AtTheOpening
IOC
FOK
GoodTillCrossing
GoodTillDate
AtTheClose

tif-to-fix

Convert time in force to FIX value.

TimeInForce -> String

fix-to-tif

Parse time in force from FIX value.

String -> Option TimeInForce

ExecType

Execution type enumeration.

Variants

ExecNew
PartialFill
Fill
DoneForDay
Canceled
Replaced
PendingCancel
Stopped
Rejected
Suspended
PendingNew
Calculated
Expired
PendingReplace
Trade
TradeCorrect
TradeCancel
OrderStatus

fix-to-exec-type

Parse execution type from FIX value.

String -> Option ExecType

OrdStatus

Order status enumeration.

Variants

OrdNew
PartiallyFilled
Filled
DoneForDay
Canceled
Replaced
PendingCancel
Stopped
Rejected
Suspended
PendingNew
Calculated
Expired
AcceptedForBidding
PendingReplace

fix-to-ord-status

Parse order status from FIX value.

String -> Option OrdStatus

MDUpdateAction

MD Update Action enumeration.

Variants

MDNew
MDChange
MDDelete

fix-to-md-update-action

Parse MD update action from FIX value.

String -> Option MDUpdateAction

SessionStatus

Session status for state machine.

Variants

Disconnected
SocketConnected
LogonSent
LoggedOn
ResendRequested
LogoutSent
LogoutReceived

FIXMessage

FIX message algebraic data type.

Variants

Logon {encrypt-method, heartbeat-int, reset-seq-num, username, password}
Logout {text}
Heartbeat {test-req-id}
TestRequest {test-req-id}
ResendRequest {begin-seq-no, end-seq-no}
SequenceReset {gap-fill, new-seq-no}
Reject {ref-seq-num, ref-tag-id, ref-msg-type, session-reject-reason, text}
NewOrderSingle {cl-ord-id, account, symbol, side, order-qty, price, stop-px, ord-type, time-in-force, min-qty, max-floor, ex-destination, transact-time}
OrderCancelRequest {cl-ord-id, orig-cl-ord-id, order-id, symbol, side, order-qty, transact-time}
OrderCancelReplaceRequest {cl-ord-id, orig-cl-ord-id, order-id, account, symbol, side, order-qty, price, stop-px, ord-type, time-in-force, transact-time}
OrderStatusRequest {cl-ord-id, order-id, symbol, side}
ExecutionReport {order-id, secondary-order-id, cl-ord-id, orig-cl-ord-id, exec-id, exec-type, ord-status, ord-rej-reason, account, symbol, side, order-qty, ord-type, price, stop-px, time-in-force, last-px, last-qty, leaves-qty, cum-qty, avg-px, transact-time, text}
OrderCancelReject {order-id, cl-ord-id, orig-cl-ord-id, ord-status, cxl-rej-response-to, cxl-rej-reason, text}
MarketDataRequest {md-req-id, subscription-type, market-depth, md-update-type, aggregated-book, symbols, entry-types}
MarketDataSnapshot {md-req-id, symbol, entries}
MarketDataIncremental {md-req-id, entries}
MarketDataRequestReject {md-req-id, md-req-rej-reason, text}
RawMessage {msg-type, fields}

MDEntry

Market data entry.

Variants

MDEntry {update-action, entry-type, price, size, symbol, position-no}

MessageStore

Message store for tracking sent messages (needed for resend).

Variants

MessageStore {messages, max-size}

message-store-new

Create a new message store.

PositiveInt -> MessageStore

message-store-add

Store a sent message.

MessageStore -> Int -> String -> MessageStore

message-store-get-range

Get messages for resend.

MessageStore -> Int -> Int -> List String

SessionConfig

FIX session configuration.

Variants

SessionConfig {host, port, sender-comp-id, target-comp-id, heartbeat-interval, version, username, password, reset-on-logon, recv-timeout-ms, send-timeout-ms, store-max-messages}

default-config

Default session configuration.

SessionState

FIX session state.

Variants

SessionState {socket, config, status, out-seq-num, in-seq-num, last-sent-time, last-recv-time, test-request-id, message-store, recv-buffer}

calculate-checksum

Calculate FIX checksum.

String -> Int

timestamp

Get current timestamp in FIX format (YYYYMMDD-HH:MM:SS.sss).

String

encode

Encode a FIX message to wire format.

SessionState -> FIXMessage -> String

decode

Decode a FIX message from wire format.

String -> Result FIXMessage FIXError

connect

Connect to a FIX server and establish a session.

SessionConfig -> Result SessionState FIXError

disconnect

Disconnect from a FIX session.

SessionState -> Unit

send

Send a FIX message.

SessionState -> FIXMessage -> Result SessionState FIXError

recv

Receive a FIX message with admin message handling.

SessionState -> Result (FIXMessage, SessionState) FIXError

recv-timeout

Receive a FIX message with timeout.

SessionState -> NonNegativeInt -> Result (FIXMessage, SessionState) FIXError

check-heartbeat

Check and send heartbeat if needed.

SessionState -> Result SessionState FIXError

is-active?

Check if session is active.

SessionState -> Bool

status

Get session status.

SessionState -> SessionStatus

out-seq-num

Get outbound sequence number.

SessionState -> Int

in-seq-num

Get inbound sequence number.

SessionState -> Int

new-order-single

Create a new order single message.

{cl-ord-id: String, account: Option String, symbol: String, side: Side, order-qty: Float, price: Option Float, stop-px: Option Float, ord-type: Option OrderType, time-in-force: Option TimeInForce, min-qty: Option Float, max-floor: Option Float, ex-destination: Option String} -> FIXMessage

cancel-order

Create an order cancel request message.

{cl-ord-id: String, orig-cl-ord-id: String, order-id: Option String, symbol: String, side: Side, order-qty: Float} -> FIXMessage

replace-order

Create an order cancel/replace request message.

{cl-ord-id: String, orig-cl-ord-id: String, order-id: Option String, account: Option String, symbol: String, side: Side, order-qty: Float, price: Option Float, stop-px: Option Float, ord-type: Option OrderType, time-in-force: Option TimeInForce} -> FIXMessage

order-status

Create an order status request message.

{cl-ord-id: Option String, order-id: Option String, symbol: String, side: Side} -> FIXMessage

market-data-request

Create a market data request message. Note: Due to Kit type inference bug with variant constructors containing List fields, this function must be implemented manually by the user for now. Use: MarketDataRequest { md-req-id: ..., subscription-type: ..., market-depth: ..., md-update-type: ..., aggregated-book: ..., symbols: ..., entry-types: ... }

{md-req-id: String, symbols: List String, subscription-type: Option Int, market-depth: Option Int, md-update-type: Option Int, aggregated-book: Option Bool, entry-types: Option (List Int)} -> FIXMessage

market-data-unsubscribe

Unsubscribe from market data.

String -> FIXMessage

HeartbeatMsg

Heartbeat monitor message types.

Variants

Tick
UpdateSentTime {time, seq-num}
UpdateRecvTime {time}
Stop

start-heartbeat-monitor

Start a background heartbeat monitor for a FIX session. Returns the actor ID for the heartbeat manager.

The monitor runs in a separate thread and automatically: - Sends heartbeats when idle - Sends TestRequests when no data received - Detects connection failures

You should call notify-sent? and notify-recv? when you send/receive messages to keep the timing accurate.

SessionState -> Ptr

session = FIX.connect config
hb-actor = FIX.start-heartbeat-monitor session
defer FIX.stop-heartbeat-monitor hb-actor

# ... trading logic ...
FIX.send session order
FIX.notify-sent? hb-actor session

stop-heartbeat-monitor

Stop the heartbeat monitor.

Ptr -> Unit

tick-heartbeat-monitor?

Manually tick the heartbeat monitor. Call this periodically (e.g., once per second) to check heartbeat timing.

Ptr -> Unit

notify-sent?

Notify the heartbeat monitor that a message was sent. Call this after every FIX.send to keep timing accurate.

Ptr -> SessionState -> Unit

notify-recv?

Notify the heartbeat monitor that a message was received. Call this after every FIX.recv to reset the timeout.

Ptr -> Unit

heartbeat-alive?

Check if the heartbeat monitor detected a dead connection.

Ptr -> Bool

AutoSession

Enhanced session state with automatic heartbeat.

Variants

AutoSession {session, heartbeat-actor}

connect-auto

Connect with automatic heartbeat monitoring. Returns an AutoSession that manages heartbeats in the background.

SessionConfig -> Result AutoSession FIXError

auto-session = FIX.connect-auto config
defer FIX.disconnect-auto auto-session

FIX.send-auto auto-session order
match FIX.recv-auto auto-session
  | Ok (msg, updated) -> ...

disconnect-auto

Disconnect an auto-heartbeat session.

AutoSession -> Unit

send-auto

Send a message via an auto-heartbeat session.

AutoSession -> FIXMessage -> Result AutoSession FIXError

recv-auto

Receive a message via an auto-heartbeat session.

AutoSession -> Result (FIXMessage, AutoSession) FIXError

recv-timeout-auto

Receive with timeout via an auto-heartbeat session.

AutoSession -> NonNegativeInt -> Result (FIXMessage, AutoSession) FIXError

is-healthy?

Check if the auto-session's heartbeat monitor is still alive.

AutoSession -> Bool