agentsclimarketplace

Fix protocol financial trading

Skill hamzabellouch/agent-skills/Financial and Fintech Engineering/fix-protocol-financial-trading

Comprehensive collection of 380+ production-ready Agent Skills (26 domains) conforming to the Agent Skills Standard, featuring native auto-discovery for Antigravity, Gemini CLI, Claude Code, Cursor, and Codex.

Install
npx -y skills add hamzabellouch/agent-skills --skill fix-protocol-financial-trading

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • 19 days oldThe repository was created 19 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
  • 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Master high-frequency FIX (Financial Information eXchange) protocol messaging (FIX 4.2/4.4/5.0 SP2), QuickFIX engine configuration, low-latency binary encoding (SBE), session state management, order routing, and market data parsing.

SKILL.md

12.0 KB, ~3.0k tokens by cl100k_base, as published. Nobody here has run it

FIX Protocol Financial Trading & Messaging Architecture

This skill package defines enterprise standards for high-frequency financial trading systems, order management systems (OMS), and execution management systems (EMS) utilizing FIX (Financial Information eXchange) protocol versions 4.2, 4.4, and 5.0 SP2 (FIXML / SBE).


1. Core Session & Application Architecture

Session Layer Management & Resend Recovery

  • Session State Persistence: Maintain strictly synchronized sequence numbers (MsgSeqNum, Tag 34) for incoming and outgoing messages. Store session state in memory-mapped files (MMAP) or persistent low-latency disk storage.
  • Sequence Gap Handling & Recovery:
    • When an incoming MsgSeqNum is greater than expected, immediately issue a ResendRequest (MsgType 2, Tag 35=2).
    • Respond to incoming ResendRequest messages by re-sending administrative messages as SequenceReset-GapFill (MsgType 4, Tag 35=4, Tag 123 GapFillFlag=Y) and re-sending application messages with PossDupFlag=Y (Tag 43).
  • Heartbeat & Test Request Loop: Send Heartbeat (Tag 35=0) at specified HeartBtInt (Tag 108) intervals. If no activity is received within HeartBtInt + Margin, issue a TestRequest (Tag 35=1) with a unique TestReqID (Tag 112). Drop session if response is absent.

Low-Latency Messaging Engineering

  • Zero-GC & Zero-Copy Memory Management: Eliminate object allocations on hot execution paths. Utilize ring buffers (e.g., LMAX Disruptor pattern) and pre-allocated byte buffers for message serialization.
  • Encoding Formats: Use SBE (Simple Binary Encoding) or FAST (FIX Adapted for STreaming) for ultra-low latency market data feeds over UDP multicast, replacing legacy tag-value pairs.
  • Transport Security & Network Topologies: Enforce mTLS 1.3 or IPsec VPN tunnels across dedicated cross-connects (Equinix NY4, LD4, TY3). Enable TCP_NODELAY (disable Nagle's algorithm) and pin thread CPU affinity.

2. Key FIX Tag Reference Matrix

Tag #Field NameRequired / EnumDescription
8BeginStringFIX.4.2 / FIX.4.4 / FIXT.1.1Protocol version identifier
9BodyLengthIntegerLength of message body between Tag 9 and Tag 10
35MsgTypeD (New Order), 8 (ExecReport), 2 (ResendReq)Message type code
49SenderCompIDStringSubmitting institution identifier
56TargetCompIDStringReceiving counterparty/exchange identifier
34MsgSeqNumInteger (1-based counter)Message sequence counter
11ClOrdIDUnique StringClient assigned unique identifier for order
55SymbolStringFinancial instrument ticker (e.g., AAPL, EUR/USD)
54Side1=Buy, 2=Sell, 5=Sell ShortOrder side specification
40OrdType1=Market, 2=Limit, 3=Stop, P=PeggedOrder type execution style
38OrderQtyQuantity / DecimalTotal quantity of shares/contracts
44PriceCurrency PriceLimit price per unit
10CheckSum3-digit zero-padded StringModulo 256 sum of all characters up to 10=

3. Production Code Implementations

Python Implementation: Production QuickFIX Initiator for Order Routing

import sys
import time
import logging
import quickfix as fix
import quickfix44 as fix44

logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")

class FIXOrderRoutingApplication(fix.Application):
    def __init__(self):
        super().__init__()
        self.session_id = None

    def onCreate(self, sessionID: fix.SessionID):
        logging.info(f"Session Created: {sessionID}")

    def onLogon(self, sessionID: fix.SessionID):
        logging.info(f"Logon Successful: {sessionID}")
        self.session_id = sessionID

    def onLogout(self, sessionID: fix.SessionID):
        logging.warning(f"Session Logged Out: {sessionID}")
        self.session_id = None

    def toAdmin(self, message: fix.Message, sessionID: fix.SessionID):
        msg_type = fix.MsgType()
        message.getHeader().getField(msg_type)
        if msg_type.getValue() == fix.MsgType_Logon:
            # Add Username/Password credentials for authentication
            message.setField(fix.RawData("SuperSecretAuthToken"))
            message.setField(fix.RawDataLength(len("SuperSecretAuthToken")))

    def fromAdmin(self, message: fix.Message, sessionID: fix.SessionID):
        pass

    def toApp(self, message: fix.Message, sessionID: fix.SessionID):
        logging.info(f"Sending Outbound App Message: {message}")

    def fromApp(self, message: fix.Message, sessionID: fix.SessionID):
        self._route_app_message(message, sessionID)

    def send_limit_order(self, cl_ord_id: str, symbol: str, side: str, qty: float, price: float):
        """
        Constructs and sends a FIX 4.4 NewOrderSingle (MsgType D)
        """
        if not self.session_id:
            raise RuntimeError("Cannot send order: FIX Session not active")

        order = fix44.NewOrderSingle()
        order.setField(fix.ClOrdID(cl_ord_id))
        
        # Side: 1=Buy, 2=Sell
        side_val = fix.Side_BUY if side.upper() == "BUY" else fix.Side_SELL
        order.setField(fix.Side(side_val))
        
        order.setField(fix.TransactTime())
        order.setField(fix.OrdType(fix.OrdType_LIMIT))
        order.setField(fix.Symbol(symbol))
        order.setField(fix.OrderQty(qty))
        order.setField(fix.Price(price))
        order.setField(fix.TimeInForce(fix.TimeInForce_DAY))

        # Send order asynchronously via QuickFIX engine
        success = fix.Session.sendToTarget(order, self.session_id)
        if not success:
            logging.error(f"Failed to submit ClOrdID: {cl_ord_id}")
        else:
            logging.info(f"Submitted Limit Order {cl_ord_id} for {symbol}")

    def _route_app_message(self, message: fix.Message, sessionID: fix.SessionID):
        msg_type = fix.MsgType()
        message.getHeader().getField(msg_type)

        if msg_type.getValue() == fix.MsgType_ExecutionReport:
            exec_id = fix.ExecID()
            cl_ord_id = fix.ClOrdID()
            ord_status = fix.OrdStatus()
            symbol = fix.Symbol()
            cum_qty = fix.CumQty()
            avg_px = fix.AvgPx()

            message.getField(exec_id)
            message.getField(cl_ord_id)
            message.getField(ord_status)
            message.getField(symbol)
            message.getField(cum_qty)
            message.getField(avg_px)

            logging.info(
                f"ExecutionReport Received | ExecID: {exec_id.getValue()} | "
                f"ClOrdID: {cl_ord_id.getValue()} | Status: {ord_status.getValue()} | "
                f"Symbol: {symbol.getValue()} | CumQty: {cum_qty.getValue()} | AvgPx: {avg_px.getValue()}"
            )

def main():
    settings = fix.SessionSettings("fix_initiator.cfg")
    application = FIXOrderRoutingApplication()
    store_factory = fix.FileStoreFactory(settings)
    log_factory = fix.FileLogFactory(settings)
    initiator = fix.SocketInitiator(application, store_factory, settings, log_factory)

    logging.info("Starting FIX Socket Initiator...")
    initiator.start()

    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        logging.info("Stopping FIX Initiator...")
        initiator.stop()

if __name__ == "__main__":
    main()

TypeScript Implementation: High-Throughput Zero-Allocation FIX Parser

export class FastFixParser {
  private static readonly SOH = 0x01; // SOH (Start of Header \x01)

  /**
   * Fast zero-copy zero-allocation parser for Tag-Value FIX buffers
   */
  public parse(buffer: Buffer): Map<number, string> {
    const fields = new Map<number, string>();
    let cursor = 0;
    const len = buffer.length;

    while (cursor < len) {
      const tagStart = cursor;
      while (cursor < len && buffer[cursor] !== 0x3d /* '=' */) {
        cursor++;
      }
      if (cursor >= len) break;

      const tag = parseInt(buffer.toString('ascii', tagStart, cursor), 10);
      cursor++; // Skip '='

      const valStart = cursor;
      while (cursor < len && buffer[cursor] !== FastFixParser.SOH) {
        cursor++;
      }

      const value = buffer.toString('utf8', valStart, cursor);
      fields.set(tag, value);
      cursor++; // Skip SOH
    }

    this.validateChecksum(buffer, fields.get(10));
    return fields;
  }

  /**
   * Computes checksum modulo 256 over all bytes up to tag 10=
   */
  private validateChecksum(buffer: Buffer, expectedChecksum?: string): void {
    if (!expectedChecksum) return;

    const sohIndex = buffer.lastIndexOf('\x0110=');
    if (sohIndex === -1) return;

    let sum = 0;
    for (let i = 0; i <= sohIndex; i++) {
      sum += buffer[i];
    }
    const computed = (sum % 256).toString().padStart(3, '0');

    if (computed !== expectedChecksum) {
      throw new Error(`FIX Checksum Error: Computed=${computed}, Expected=${expectedChecksum}`);
    }
  }

  /**
   * Formats a raw key-value map into a raw FIX wire protocol Buffer
   */
  public serialize(msgType: string, senderCompId: string, targetCompId: string, seqNum: number, tags: Map<number, string>): Buffer {
    let bodyStr = `35=${msgType}\x0149=${senderCompId}\x0156=${targetCompId}\x0134=${seqNum}\x01`;
    
    for (const [tag, val] of tags.entries()) {
      if ([8, 9, 35, 49, 56, 34, 10].includes(tag)) continue;
      bodyStr += `${tag}=${val}\x01`;
    }

    const bodyLength = Buffer.byteLength(bodyStr, 'ascii');
    const headerStr = `8=FIX.4.4\x019=${bodyLength}\x01`;
    const fullMsgWithoutChecksum = headerStr + bodyStr;

    let sum = 0;
    const msgBuffer = Buffer.from(fullMsgWithoutChecksum, 'ascii');
    for (let i = 0; i < msgBuffer.length; i++) {
      sum += msgBuffer[i];
    }
    const checksumStr = `10=${(sum % 256).toString().padStart(3, '0')}\x01`;

    return Buffer.concat([msgBuffer, Buffer.from(checksumStr, 'ascii')]);
  }
}

4. Anti-Patterns & Critical Mistakes

  1. Dynamic Memory Allocation in the Hot Path

    • Impact: Garbage collection pauses (GC stalls) cause execution latencies to spike from microseconds to hundreds of milliseconds, triggering slippage or rejected limit orders.
    • Remediation: Pre-allocate object pools, fix ring buffer sizes, and use off-heap memory.
  2. Incorrect Gap Fill Processing (SequenceReset-GapFill)

    • Impact: Exchange disconnects the session or rejects subsequent valid orders due to unsynchronized sequence numbers.
    • Remediation: Ensure admin messages (Logon, Heartbeat, TestRequest) are skipped using GapFillFlag=Y while incrementing NewSeqNo (Tag 36) appropriately.
  3. Synchronous Disk I/O on Session Persistence

    • Impact: Blocking file appends stall the event loop thread during market volatility bursts.
    • Remediation: Perform async I/O or flush memory-mapped files off the critical path using dedicated background writer threads.
  4. Ignoring Sub-Millisecond Timestamp Precision

    • Impact: Regulatory non-compliance under MiFID II (RTS 25) requiring clock synchronization accuracy within 100 microseconds for high-frequency trading.
    • Remediation: Format SendingTime (Tag 52) and TransactTime (Tag 60) with microsecond (YYYYMMDD-HH:MM:SS.uuuuuu) or nanosecond resolution against PTP (Precision Time Protocol / IEEE 1588) synchronized clocks.

5. Verification & Testing Playbook

  • Mock Acceptor Integration: Connect Initiator against QuickFIX Acceptor harness or TT/FIX Simulator.
  • Sequence Number Gap Injection Test: Force gap by sending MsgSeqNum = N + 5 and verify incoming ResendRequest generation and proper SequenceReset handling.
  • Latency Profiling: Measure end-to-end wire-to-cancel throughput using perf and low-overhead tick counters (RDTSC).

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.