Connect to the HFT EDGE LDX Feed in your language. Production-ready guides and copy-paste examples for FIX, WebSocket, and ITCH across five languages.
HFT EDGE LDX Feed publishes real-time market data over three transports. Choose the one that matches your latency budget and integration style — all three carry identical instrumentation from LD4 and NY4.
| Protocol | Transport | Encoding | Latency | Best for |
|---|---|---|---|---|
| WebSocket | WSS / TLS | JSON | < 1.5ms | Apps, dashboards, fast integration |
| FIX 4.4 | TCP / TLS | Tag-value | < 0.8ms | EMS / OMS, institutional order flow |
| ITCH | UDP multicast + TCP recovery | Binary | < 100µs | Ultra-low-latency HFT desks |
The official LDX Feed SDK (ldxfeed) wraps the WebSocket and FIX transports with reconnect, heartbeat, and sequence handling out of the box. ITCH is consumed directly as a binary stream.
pip install ldxfeeddotnet add package LdxFeed.Sdk<dependency>
<groupId>com.ldxfeed</groupId>
<artifactId>ldxfeed-sdk</artifactId>
<version>1.0.0</version>
</dependency>npm install @ldxfeed/sdkgo get github.com/ldxfeed/sdk-goAuthentication depends on the transport you use:
?api_key=...) or in the opening hello frame.35=A) carrying your SenderCompID, TargetCompID, and password. The SDK performs this automatically when you call logon().Never expose your API key in client-side code. All connections must be made over TLS.
Subscribe to the live EUR/USD order book in under ten lines using the SDK.
from ldxfeed import Feed
feed = Feed(api_key="YOUR_API_KEY", region="ld4")
@feed.on("book")
def on_book(msg):
print(msg["symbol"], msg["bids"])
feed.connect()
feed.subscribe(channel="book", symbol="EUR/USD", depth=10)
feed.run()using LdxFeed;
var feed = new Feed("YOUR_API_KEY", region: Region.Ld4);
feed.OnBook += (s, msg) =>
Console.WriteLine($"{msg.Symbol} {msg.Bids[0]}");
await feed.ConnectAsync();
await feed.SubscribeAsync(channel: "book", symbol: "EUR/USD", depth: 10);
await feed.RunAsync();import com.ldxfeed.Feed;
import com.ldxfeed.Book;
Feed feed = Feed.connect("YOUR_API_KEY", Feed.Region.LD4);
feed.onBook((Book msg) -> {
System.out.println(msg.symbol + " " + msg.bids[0]);
return null;
});
feed.subscribe("book", "EUR/USD", 10);
feed.run();import { Feed } from "@ldxfeed/sdk";
const feed = new Feed({ apiKey: "YOUR_API_KEY", region: "ld4" });
feed.on("book", (msg) => console.log(msg.symbol, msg.bids[0]));
await feed.connect();
await feed.subscribe({ channel: "book", symbol: "EUR/USD", depth: 10 });
await feed.run();package main
import "github.com/ldxfeed/sdk-go"
func main() {
feed := ldxfeed.New("YOUR_API_KEY", ldxfeed.RegionLD4)
feed.OnBook(func(m ldxfeed.Book) {
println(m.Symbol, m.Bids[0])
})
feed.Connect()
feed.Subscribe("book", "EUR/USD", 10)
feed.Run()
}Prefer raw sockets? Connect directly to the WebSocket endpoint without the SDK. The server pushes JSON frames for every subscribed channel.
import asyncio, json, websockets
URL = "wss://ws.ld4.hftedge.com/v1?api_key=YOUR_API_KEY"
async def stream():
async with websockets.connect(URL) as ws:
await ws.send(json.dumps({
"op": "subscribe", "channel": "book",
"symbol": "EUR/USD", "depth": 10
}))
async for raw in ws:
msg = json.loads(raw)
print(msg["symbol"], msg.get("bids"))
asyncio.run(stream())using System.Net.WebSockets;
using System.Text;
using var ws = new ClientWebSocket();
await ws.ConnectAsync(new Uri(
"wss://ws.ld4.hftedge.com/v1?api_key=YOUR_API_KEY"), default);
string sub = "{\"op\":\"subscribe\",\"channel\":\"book\",\"symbol\":\"EUR/USD\",\"depth\":10}";
await ws.SendAsync(Encoding.UTF8.GetBytes(sub),
WebSocketMessageType.Text, true, default);
var buf = new byte[8192];
while (ws.State == WebSocketState.Open)
{
var r = await ws.ReceiveAsync(buf, default);
Console.WriteLine(Encoding.UTF8.GetString(buf, 0, r.Count));
}import java.net.URI;
import java.net.http.*;
var client = HttpClient.newHttpClient();
WebSocket ws = client.newWebSocketBuilder()
.buildAsync(URI.create("wss://ws.ld4.hftedge.com/v1?api_key=YOUR_KEY"),
new WebSocket.Listener() {
public java.util.concurrent.CompletionStage<?> onText(
WebSocket w, CharSequence d, boolean last) {
System.out.println(d);
return null;
}
}).join();
ws.sendText("{\"op\":\"subscribe\",\"channel\":\"book\","
+ "\"symbol\":\"EUR/USD\",\"depth\":10}", true);import WebSocket from "ws";
const ws = new WebSocket("wss://ws.ld4.hftedge.com/v1?api_key=YOUR_API_KEY");
ws.on("open", () => {
ws.send(JSON.stringify({
op: "subscribe", channel: "book", symbol: "EUR/USD", depth: 10
}));
});
ws.on("message", (raw) => {
const msg = JSON.parse(raw.toString());
console.log(msg.symbol, msg.bids);
});package main
import (
"encoding/json"
"fmt"
"github.com/gorilla/websocket"
)
func main() {
c, _, _ := websocket.DefaultDialer.Dial(
"wss://ws.ld4.hftedge.com/v1?api_key=YOUR_API_KEY", nil)
defer c.Close()
sub, _ := json.Marshal(map[string]any{
"op": "subscribe", "channel": "book",
"symbol": "EUR/USD", "depth": 10,
})
c.WriteMessage(websocket.TextMessage, sub)
for {
_, msg, err := c.ReadMessage()
if err != nil { break }
fmt.Println(string(msg))
}
}Start a FIX 4.4 session and request a market-data stream. The SDK handles logon, heartbeats, and sequence numbers; you send a MarketDataRequest and iterate the inbound messages.
from ldxfeed.fix import FixSession, Message
session = FixSession(
host="fix.ld4.hftedge.com", port=5201,
sender="YOUR_COMP_ID", target="HFT_EDGE",
password="YOUR_PASSWORD")
session.logon()
req = Message("V") # MarketDataRequest
req[262] = "MDREQ001" # MDReqID
req[263] = "1" # Snapshot + Updates
req[264] = "10" # MarketDepth
req[269] = ["0", "1"] # Bid + Offer
req[55] = "EUR/USD" # Symbol
session.send(req)
for msg in session: # inbound stream
print(msg[55], msg.get(270)) # symbol, priceusing LdxFeed.Fix;
var session = new FixSession("fix.ld4.hftedge.com", 5201,
sender: "YOUR_COMP_ID", target: "HFT_EDGE",
password: "YOUR_PASSWORD");
session.Logon();
var req = new Message("V");
req[262] = "MDREQ001";
req[263] = "1";
req[264] = "10";
req[269] = new[] { "0", "1" };
req[55] = "EUR/USD";
session.Send(req);
foreach (var msg in session) // inbound stream
Console.WriteLine($"{msg[55]} {msg[270]}");import com.ldxfeed.fix.*;
FixSession session = FixSession.builder()
.host("fix.ld4.hftedge.com").port(5201)
.sender("YOUR_COMP_ID").target("HFT_EDGE")
.password("YOUR_PASSWORD").connect();
session.logon();
Message req = new Message("V");
req.set(262, "MDREQ001");
req.set(263, "1");
req.set(264, "10");
req.set(269, "0"); req.set(269, "1");
req.set(55, "EUR/USD");
session.send(req);
for (Message msg : session) {
System.out.println(msg.get(55) + " " + msg.get(270));
}import { FixSession, Message } from "@ldxfeed/sdk/fix";
const session = new FixSession({
host: "fix.ld4.hftedge.com", port: 5201,
sender: "YOUR_COMP_ID", target: "HFT_EDGE",
password: "YOUR_PASSWORD"
});
await session.logon();
const req = new Message("V");
req.set(262, "MDREQ001");
req.set(263, "1");
req.set(264, "10");
req.set(269, ["0", "1"]);
req.set(55, "EUR/USD");
await session.send(req);
for await (const msg of session) {
console.log(msg.get(55), msg.get(270));
}package main
import "github.com/ldxfeed/sdk-go/fix"
func main() {
s := fix.NewSession("fix.ld4.hftedge.com", 5201,
"YOUR_COMP_ID", "HFT_EDGE", "YOUR_PASSWORD")
s.Logon()
req := fix.NewMessage("V")
req.Set(262, "MDREQ001")
req.Set(263, "1")
req.Set(264, "10")
req.Set(269, "0"); req.Set(269, "1")
req.Set(55, "EUR/USD")
s.Send(req)
for msg := range s.Messages() {
println(msg.Get(55), msg.Get(270))
}
}ITCH is a raw binary multicast feed with no framing library — join the UDP group and decode each message by its leading type byte. Below, each client decodes an Add Order ('A') message from the LD4 stream.
import socket, struct
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(("", 10000))
mreq = struct.pack("4sl", socket.inet_aton("233.1.2.3"), socket.INADDR_ANY)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
while True:
pkt, _ = sock.recvfrom(2048)
if pkt[0:1] != b"A": # Add Order
continue
ts, ref, side, shares = struct.unpack_from("<QQcI", pkt, 1)
symbol = pkt[22:30].rstrip(b"\x00").decode()
price = struct.unpack_from("<Q", pkt, 30)[0]
print(symbol, "B" if side == ord("B") else "S", shares, price)using System.Net.Sockets;
using System.Text;
using var udp = new UdpClient(10000);
udp.JoinMulticastGroup(System.Net.IPAddress.Parse("233.1.2.3"));
var ep = new IPEndPoint(0, 0);
while (true)
{
byte[] pkt = udp.Receive(ref ep);
if (pkt[0] != (byte)'A') continue; // Add Order
long ts = BitConverter.ToInt64(pkt, 1);
long refNo = BitConverter.ToInt64(pkt, 9);
char side = (char)pkt[17];
int shares = BitConverter.ToInt32(pkt, 18);
string sym = Encoding.ASCII.GetString(pkt, 22, 8).TrimEnd('\0');
long price = BitConverter.ToInt64(pkt, 30);
Console.WriteLine($"{sym} {side} {shares} {price}");
}import java.net.*;
import java.nio.*;
var group = InetAddress.getByName("233.1.2.3");
try (var sock = new MulticastSocket(10000)) {
sock.joinGroup(group);
var pkt = new DatagramPacket(new byte[2048], 2048);
while (true) {
sock.receive(pkt);
var b = ByteBuffer.wrap(pkt.getData())
.order(ByteOrder.LITTLE_ENDIAN);
if ((char) b.get() != 'A') continue;
long ts = b.getLong();
long refNo = b.getLong();
char side = (char) b.get();
int shares = b.getInt();
byte[] sym = new byte[8]; b.get(sym);
long price = b.getLong();
System.out.println(new String(sym).trim()
+ " " + side + " " + shares + " " + price);
}
}import dgram from "node:dgram";
const sock = dgram.createSocket({ type: "udp4", reuseAddr: true });
sock.on("message", (pkt) => {
if (pkt[0] !== 0x41) return; // 'A' = Add Order
const ts = pkt.readBigUInt64LE(1);
const refNo = pkt.readBigUInt64LE(9);
const side = String.fromCharCode(pkt[17]);
const shares = pkt.readUInt32LE(18);
const symbol = pkt.subarray(22, 30).toString("ascii").replace(/\0/g, "");
const price = pkt.readBigUInt64LE(30);
console.log(symbol, side, shares, price);
});
sock.bind(10000, () => sock.addMembership("233.1.2.3"));package main
import (
"encoding/binary"
"fmt"
"net"
)
func main() {
addr, _ := net.ResolveUDPAddr("udp", "233.1.2.3:10000")
sock, _ := net.ListenMulticastUDP("udp", nil, addr)
buf := make([]byte, 2048)
for {
n, _, err := sock.ReadFromUDP(buf)
if err != nil || n < 39 || buf[0] != 'A' {
continue
}
refNo := binary.LittleEndian.Uint64(buf[9:17])
shares := binary.LittleEndian.Uint32(buf[18:22])
symbol := string(buf[22:30])
price := binary.LittleEndian.Uint64(buf[30:38])
fmt.Println(symbol, string(buf[17]), shares, price, refNo)
}
}Production consumers must stay healthy across network drops. The SDK handles all of the following automatically; raw consumers must implement them.
Every connection exposes a status event you can subscribe to for logging and alerting.
Ready to trade on the edge? Generate your API key and ship your first feed today.
Get API Access