Get Started — Overview

The Bridge Connector is a lightweight C-based communication layer that exposes two dedicated TCP sockets for client applications. One socket accepts inbound request strings (orders or commands) from clients; the other socket sends outbound responses (acknowledgements, execution reports, errors) back to the client. This interface is designed to be:

High-level Architecture

TCP
Client App
(sends strings)
-- Request Socket -->
Bridge Service
(C executable)
<-- Response Socket --

Key points

Features

Connection Details

Protocol: TCP
Default ports (example):

Address: Bind to 0.0.0.0 on the server for production, or 127.0.0.1 for local testing.
Message encoding: UTF-8 (recommended)
Message termination: \n (newline). All messages MUST be terminated by newline to allow proper framing.
Max message length: 4096 bytes (configurable)

REQUEST New Order

2000|5|52166|BANKNIFTY|02/24/2022|OPTIDX|36200.00|CE|PRO|0|202202241021|1|25|35|2|0.0|25|0
PosFieldDescription
12000New Order Request
25Exchange identifier
352166Instrument token
4BANKNIFTYTrading symbol
502/24/2022Contract expiry
6OPTIDXInstrument type
736200.00Option strike price
8CEOption Type
9PROTrading client
100Order Id
11202202241021Echo Back Client reference
121Order Type Market / Limit
1325Order quantity
1435Order price
152Order action 1=Buy, 2=Sell
160.0SL trigger price
1725Total order quantity
180Remain quantity

REQUEST Modify Order

2040|5|52166|BANKNIFTY|02/24/2022|OPTIDX|36200.00|CE|PRO|404404480000101|202202241021|1|25|35|2|0.0|25|0
PosFieldDescription
12040Modify Request
25Exchange identifier
352166Instrument token
4BANKNIFTYTrading symbol
502/24/2022Contract expiry
6OPTIDXInstrument type
736200.00Option strike price
8CEOption Type
9PROTrading client
10404404480000101Order Id
11202202241021Echo Back Client reference
121Order type Market / Limit
1325Order quantity
1435Order price
152Order action 1=Buy, 2=Sell
160.0SL trigger price
1725Total order quantity
180Remain quantity

REQUEST Cancel Order

2070|5|52166|BANKNIFTY|02/24/2022|OPTIDX|36200.00|CE|PRO|404404480000101|202202241021|1|25|35|2|0.0|25|0
PosFieldDescription
12070Cancel Request
25Exchange identifier
352166Instrument token
4BANKNIFTYTrading symbol
502/24/2022Contract expiry
6OPTIDXInstrument type
736200.00Option strike price
8CEOption Type
9PROTrading client
10404404480000101Order Id
11202202241021Echo Back Client reference
121Order type Market / Limit
1325Order quantity
1435Order price
152Order action 1=Buy, 2=Sell
160.0SL trigger price
1725Total order quantity
180Remain quantity

RESPONSE Order Confirmation

2073|5|52166|BANKNIFTY|02/24/2022|OPTIDX|36200.00|CE|PRO|404404480000101|0|0|35.0000|202202241021|2|0|0|1330161808|1330161808|12345|123456789012345|25|25
PosFieldDescription
12073Order Confirmation
25Exchange identifier
352166Instrument token
4BANKNIFTYTrading symbol
502/24/2022Contract expiry
6OPTIDXInstrument type
736200.00Option strike price
8CEOption Type
9PROTrading client
10404404480000101Order Id
110Trade No
120Executed quantity
1335.0000Execution price
14202202241021Echo Back Client reference
1521=Buy, 2=Sell
160Error Code
170Reason Code
181330161808Exchange timestamp
191330161808Last modification time
2112345Participent (client id)
22123456789012345Term Ctcl
2325Remain quantity
2425Total original quantity

RESPONSE Modify Confirmation

2074|5|52166|BANKNIFTY|02/24/2022|OPTIDX|36200.00|CE|PRO|404404480000101|0|0|35.0000|202202241021|2|0|0|1330161808|1330161808|12345|123456789012345|25|25
PosFieldDescription
12074Order Modification Confirmation
25Exchange identifier
352166Instrument token
4BANKNIFTYTrading symbol
502/24/2022Contract expiry
6OPTIDXInstrument type
736200.00Option strike price
8CEOption Type
9PROTrading client
10404404480000101Order Id
110Trade No
120Executed quantity
1335.0000Execution price
14202202241021Echo Back Client reference
1521=Buy, 2=Sell
160Error Code
170Reason Code
181330161808Exchange timestamp
191330161808Last modification time
2112345Participent (client id)
22123456789012345Term Ctcl
2325Remain quantity
2425Total Original quantity

RESPONSE Cancel Confirmation

2075|5|52166|BANKNIFTY|02/24/2022|OPTIDX|36200.00|CE|PRO|404404480000101|0|0|35.0000|202202241021|2|0|0|1330161808|1330161808|12345|123456789012345|25|25
PosFieldDescription
12075Order Cancel Confirmation
25Exchange identifier
352166Instrument token
4BANKNIFTYTrading symbol
502/24/2022Contract expiry
6OPTIDXInstrument type
736200.00Option strike price
8CEOption Type
9PROTrading client
10404404480000101Order Id
110Trade No
120Executed quantity
1335.0000Execution price
14202202241021Echo Back Client reference
1521=Buy, 2=Sell
160Error Code
170Reason Code
181330161808Exchange timestamp
191330161808Last modification time
2012345Participent (client id)
21123456789012345Term Ctcl
2225Remain quantity
2325Total Original quantity

TRADE Trade Confirmation

2222|5|52166|BANKNIFTY|02/24/2022|OPTIDX|36200.00|CE|PRO|404404480000101|20046|25|35.0000|202202241021|2|0|0|1330161808|1330161808|12345|123456789012345|0|25
PosFieldDescription
12222Trade Confirmation
25Exchange identifier
352166Instrument token
4BANKNIFTYTrading symbol
502/24/2022Contract expiry
6OPTIDXInstrument type
736200.00Option strike price
8CEOption Type
9PROTrading client
10404404480000101Order Id
1120046Trade No
1225Executed quantity
1335.0000Execution price
14202202241021Echo Back Client reference
1521=Buy, 2=Sell
160Error Code
170Reason Code
181330161808Exchange timestamp
191330161808Last modification time
2012345Participent (client id)
21123456789012345Term Ctcl
220Remain quantity
2325Total Original quantity

REJECT Rejection

-9999|5|52166|BANKNIFTY|02/24/2022|OPTIDX|36200.00|CE|PRO|Rejected|0|0|35|202202241021|2|-1106|0|0|0|12345|123456789012345|0|25|Dealer TotalBuyValue M:50000.00 N:49300.50
PosFieldDescription
1-9999Rejection
25Exchange identifier
352166Instrument token
4BANKNIFTYTrading symbol
502/24/2022Contract expiry
6OPTIDXInstrument type
736200.00Option strike price
8CEOption Type
9PROTrading client
10RejectedOrder Id
110Trade No
120Executed quantity
1335Execution price
14202202241021Echo Back Client reference
1521=Buy, 2=Sell
16-1106Error Code
170Reason Code
180Exchange timestamp
190Last modification time
2012345Participent (client id)
21123456789012345Term Ctcl
220Remain quantity
2325Total Original quantity
23Dealer TotalBuyValue M:50000.00 N:49300.50Error Message

Broadcast Format

57439|NIFTY|5|03/03/2022|OPTIDX|PE|17400.00|50|76625|73550|150|73490|550|73930|50|73935|200|25400|0
PosFieldDescription
157439Token
2NIFTYScrip
35Exchange
403/03/2022Expiry_date
5OPTIDXInstrument
6CEOption Type
717000.00Strike price
850Last trade quantity
99165Last traded price
109150Bid price1
11900Bid quantity1
129145Bid price2
13500Bid quantity2
149170Ask price1
15400Ask quantity1
169175Ask price2
17900Ask quantity2
1853087000Total traded quantity
190Open interest

Socket Authentication

You MUST protect production sockets. Below are recommended options from simple to most secure.

Shared Secret (Simple)

Pros: Easy to implement.
Cons: Secret can be intercepted unless used with TLS.

Handshake example:
1. Server sends AUTH_REQUIRED\n
2. Client sends AUTH|<secret-key>\n
3. Server replies AUTH_OK\n or AUTH_FAIL\n

Heartbeat / Keepalive

Order Request/Response Client Example (Authenticated)

A complete, runnable client that builds an order request string, sends it on the request socket, and reads and validates the response on the response socket. It uses the same shared-secret handshake described in Socket Authentication on both sockets, and the same request/response field layouts documented in New Order and Order Confirmation. If your client runs on the same trusted machine/network as the Bridge and you don't need this handshake, see Order Request/Response Client Example (Trusted, No Auth) below instead.

Scenarios covered

Note: this script performs a single request/response cycle and then exits - it's a reference example to adapt into a long-lived client. See Performance & Best Practices for keeping sockets long-lived in production.

Configuration

REQUEST_ADDR = ("localhost", 9090) # request socket (client -> bridge) RESPONSE_ADDR = ("localhost", 9091) # response socket (bridge -> client) AUTH_KEY = "CHANGE_ME_SHARED_SECRET" # shared secret, must match the server

request_client_auth.py

#!/usr/bin/env python3 """ Request/response order client - reference example (authenticated). Builds an order request string, sends it on the request socket, then reads and validates the response on the response socket. Both sockets use the shared-secret handshake described in "Socket Authentication". Scenarios covered: - Local validation of the request code before anything is sent. - Shared-secret authentication on both the request and response sockets. - Connection failures (server unreachable, connection refused/reset). - Authentication failures / unexpected handshake replies. - Empty/closed response from the server. - Unrecognized response codes. - Displaying every response field using its documented name. This script performs a single request/response cycle and then exits - it's a template to adapt into a long-lived client (see "Performance & Best Practices" for keeping sockets long-lived in production). If your client runs on the same trusted machine/network as the Bridge, see request_client_no_auth.py for a simpler version without this handshake. """ import socket # Request/response use two separate sockets - one to send order # requests, one to read the corresponding confirmations/rejections. REQUEST_ADDR = ("localhost", 9090) # request socket (client -> bridge) RESPONSE_ADDR = ("localhost", 9091) # response socket (bridge -> client) # Shared secret key both client and server must agree on (see # "Socket Authentication"). Change this before pointing at a real server. AUTH_KEY = "CHANGE_ME_SHARED_SECRET" def authenticate(sock: socket.socket, key: str) -> bool: """ Perform the shared-secret handshake (see "Socket Authentication") on an already-connected socket: server -> "AUTH_REQUIRED\\n" client -> "AUTH|\\n" server -> "AUTH_OK\\n" if the key is correct "AUTH_FAIL\\n" otherwise Returns True only if the server explicitly replies AUTH_OK. Every other outcome (dropped connection, wrong prompt, wrong reply, rejected key) returns False after printing why. """ # Step 1: the server should speak first and ask us to authenticate. try: raw = sock.recv(1024) except (ConnectionResetError, ConnectionAbortedError, OSError) as exc: print(f"ERROR: could not read auth prompt: {exc}") return False if not raw: # recv() returning b"" means the peer closed the connection. print("ERROR: connection closed by server during auth handshake.") return False prompt = raw.decode(errors="replace").strip() if prompt != "AUTH_REQUIRED": # Server is speaking a different protocol than we expect - # fail loudly instead of guessing. print(f"ERROR: unexpected auth prompt from server: {prompt!r}") return False # Step 2: send the shared secret in the documented format. sock.sendall(f"AUTH|{key}\n".encode()) # Step 3: read the server's verdict. try: raw = sock.recv(1024) except (ConnectionResetError, ConnectionAbortedError, OSError) as exc: print(f"ERROR: could not read auth reply: {exc}") return False if not raw: print("ERROR: connection closed by server during auth handshake.") return False reply = raw.decode(errors="replace").strip() if reply == "AUTH_OK": return True if reply == "AUTH_FAIL": print("ERROR: server rejected the shared secret.") return False print(f"ERROR: unexpected auth reply from server: {reply!r}") return False def connect(addr): """Connect to (host, port), reporting connection errors clearly. Using a short timeout means a server that's down or unreachable fails fast with a clear message instead of hanging indefinitely. """ host, port = addr try: return socket.create_connection(addr, timeout=5) except (ConnectionRefusedError, socket.timeout, OSError) as exc: print(f"ERROR: could not connect to {host}:{port} - {exc}") raise SystemExit(1) # ---- valid request / response codes ---- # Used to fail fast, locally, before anything is sent over the wire. VALID_REQUEST_CODES = { "2000": "New Order Request", "2040": "Order Modify Request", "2070": "Order Cancel Request", } VALID_RESPONSE_CODES = { "2222": "Order Trade Confirmation", "2073": "New Order Confirmation", "2074": "Order Modification Confirmation", "2075": "Order Cancel Confirmation", } # ---- field names, in order, for request and response strings ---- # Mirrors the pipe-delimited positions documented in "New Order" and # "Order Confirmation" - used only to label output, not to validate it. REQUEST_FIELD_NAMES = [ "Request Code", "Exchange identifier", "Instrument token", "Trading symbol", "Contract expiry", "Instrument type", "Option strike price", "Option Type", "Trading client", "Order Id", "Echo Back Client reference", "Order Type Market/Limit", "Order quantity", "Order price", "Order action 1=Buy, 2=Sell", "SL trigger price", "Total order quantity", "Remain quantity", ] RESPONSE_FIELD_NAMES = [ "Response Code", "Exchange identifier", "Instrument token", "Trading symbol", "Contract expiry", "Instrument type", "Option strike price", "Option Type", "Trading client", "Order Id", "Trade No", "Executed quantity", "Execution price", "Echo Back Client reference", "Order action 1=Buy, 2=Sell", "Error Code", "Reason Code", "Exchange timestamp", "Last modification time", "Participant (client id)", "Term Ctcl", "Remain quantity", "Total original quantity", ] # ---- request fields (all editable) ---- # Edit these to build a different order. request_code selects which # kind of request this is (new/modify/cancel) - see VALID_REQUEST_CODES. request_code = "2000" # must be one of VALID_REQUEST_CODES segment = "5" # exchange identifier, e.g. 5 = NSE Options token = "52166" # instrument token from the contract master symbol = "BANKNIFTY" # trading symbol expiry_date = "02/24/2022" # contract expiry, MM/DD/YYYY instrument = "OPTIDX" # instrument type strike_price = "36200.00" # option strike price option_type = "CE" # CE (call) or PE (put) client_type = "PRO" # trading client type order_id = "0" # 0 for a new order; existing order id for modify/cancel client_ref = "202202241021" # echo-back reference, returned as-is in the response order_type = "1" # order type, e.g. 1 = Limit order_qty = "25" # quantity for this order order_price = "35" # limit price order_action = "2" # 1 = Buy, 2 = Sell sl_trigger = "0.0" # stop-loss trigger price, 0.0 if not used total_qty = "25" # total order quantity remain_qty = "0" # remaining quantity (0 for a fresh order) # Field order here MUST match REQUEST_FIELD_NAMES / the "New Order" # table exactly - the server parses this by position, not by name. request_fields = [ request_code, segment, token, symbol, expiry_date, instrument, strike_price, option_type, client_type, order_id, client_ref, order_type, order_qty, order_price, order_action, sl_trigger, total_qty, remain_qty, ] # ---- validate request code before doing anything else ---- # Catches typos locally instead of sending a request the server would # have to reject. if request_code not in VALID_REQUEST_CODES: valid_list = ", ".join(f"{code} ({desc})" for code, desc in VALID_REQUEST_CODES.items()) print(f"ERROR: Invalid request code '{request_code}'. Must be one of: {valid_list}") raise SystemExit(1) # Build the final pipe-delimited request string. request = "|".join(request_fields) print(f"Request code {request_code} recognized as: {VALID_REQUEST_CODES[request_code]}") # ---- send request (authenticated) ---- req_sock = connect(REQUEST_ADDR) try: if not authenticate(req_sock, AUTH_KEY): print("Authentication failed on request socket. Aborting.") raise SystemExit(1) # Every message MUST be newline-terminated (see "Connection Details"). req_sock.sendall((request + "\n").encode()) print("Sent request:", request) finally: # Always close, whether the send succeeded or we're bailing out. req_sock.close() # ---- read response (authenticated) ---- # Response socket is separate from the request socket and needs its # own connection + its own authentication. resp_sock = connect(RESPONSE_ADDR) try: if not authenticate(resp_sock, AUTH_KEY): print("Authentication failed on response socket. Aborting.") raise SystemExit(1) try: response = resp_sock.recv(4096).decode(errors="replace").strip() except (ConnectionResetError, ConnectionAbortedError, OSError) as exc: print(f"ERROR: failed reading response: {exc}") raise SystemExit(1) if not response: # An empty read means the server closed the connection without # sending anything - treat it as a failure, not an empty message. print("ERROR: connection closed before a response was received.") raise SystemExit(1) finally: resp_sock.close() print("\nReceived response:", response) # ---- separate fields ---- fields = response.split("|") # ---- validate response code ---- response_code = fields[0] if fields else "" if response_code not in VALID_RESPONSE_CODES: valid_list = ", ".join(f"{code} ({desc})" for code, desc in VALID_RESPONSE_CODES.items()) print(f"ERROR: Invalid response code '{response_code}'. Must be one of: {valid_list}") raise SystemExit(1) print(f"Response code {response_code} recognized as: {VALID_RESPONSE_CODES[response_code]}") # ---- display fields using their proper names ---- # Zips positional values back up with their documented field names so # the output is readable without cross-referencing the docs by hand. print("\n--- Fields ---") for i, value in enumerate(fields): name = RESPONSE_FIELD_NAMES[i] if i < len(RESPONSE_FIELD_NAMES) else f"Field{i}" print(f"{name}: {value}")

Run

python3 request_client_auth.py

Request/response flow

StepDirectionMessage
1connectClient connects to request socket (9090)
2server -> clientAUTH_REQUIRED
3client -> serverAUTH|CHANGE_ME_SHARED_SECRET
4server -> clientAUTH_OK
5client -> server2000|5|52166|BANKNIFTY|02/24/2022|OPTIDX|36200.00|CE|PRO|0|202202241021|1|25|35|2|0.0|25|0
6connectClient connects to response socket (9091)
7server -> clientAUTH_REQUIRED
8client -> serverAUTH|CHANGE_ME_SHARED_SECRET
9server -> clientAUTH_OK
10server -> client2073|5|52166|BANKNIFTY|02/24/2022|OPTIDX|36200.00|CE|PRO|404404480000101|0|0|35.0000|202202241021|2|0|0|1330161808|1330161808|12345|123456789012345|25|25

Expected output

Request code 2000 recognized as: New Order Request Sent request: 2000|5|52166|BANKNIFTY|02/24/2022|OPTIDX|36200.00|CE|PRO|0|202202241021|1|25|35|2|0.0|25|0 Received response: 2073|5|52166|BANKNIFTY|02/24/2022|OPTIDX|36200.00|CE|PRO|404404480000101|0|0|35.0000|202202241021|2|0|0|1330161808|1330161808|12345|123456789012345|25|25 Response code 2073 recognized as: New Order Confirmation --- Fields --- Response Code: 2073 Exchange identifier: 5 Instrument token: 52166 Trading symbol: BANKNIFTY Contract expiry: 02/24/2022 Instrument type: OPTIDX Option strike price: 36200.00 Option Type: CE Trading client: PRO Order Id: 404404480000101 Trade No: 0 Executed quantity: 0 Execution price: 35.0000 Echo Back Client reference: 202202241021 Order action 1=Buy, 2=Sell: 2 Error Code: 0 Reason Code: 0 Exchange timestamp: 1330161808 Last modification time: 1330161808 Participant (client id): 12345 Term Ctcl: 123456789012345 Remain quantity: 25 Total original quantity: 25

Error-handling cases

CaseWhere it's caughtBehavior
Invalid request code (not in VALID_REQUEST_CODES)Before connectingPrints the invalid code and the allowed list, exits - nothing is sent.
Server unreachable / connection refused / connect timeoutconnect()Prints host:port and the underlying error, exits.
Connection closed or reset during the auth handshakeauthenticate()Prints that the connection was closed during auth, returns False.
Server sends an auth prompt/reply that doesn't match the documented protocolauthenticate()Prints the unexpected value received, returns False.
Server rejects the shared secret (AUTH_FAIL)authenticate()Prints that the secret was rejected, aborts before sending/reading.
Response socket closes before sending any dataAfter recv() on the response socketPrints that the connection closed before a response arrived, exits.
Unrecognized response code (not in VALID_RESPONSE_CODES)After splitting response fieldsPrints the unrecognized code and the allowed list, exits.

Order Request/Response Client Example (Trusted, No Auth)

Same request/response flow as the authenticated example above, but with the Socket Authentication handshake removed entirely. Use this only when the client is running on a trusted machine or network - for example, on the same host as the Bridge, or inside a private network the Bridge is not exposed beyond.

Important: skipping authentication means anything that can reach these ports can send orders. Only use this on a trusted machine/network, and never expose these ports to an untrusted network without the handshake from the authenticated example.

Configuration

REQUEST_ADDR = ("localhost", 9090) # request socket (client -> bridge) RESPONSE_ADDR = ("localhost", 9091) # response socket (bridge -> client)

request_client_no_auth.py

#!/usr/bin/env python3 """ Request/response order client - reference example (trusted, no auth). Same as request_client_auth.py, minus the shared-secret handshake. Use this ONLY when the client is on a trusted machine/network (e.g. the same host as the Bridge, or a private network it isn't exposed beyond) - see "Socket Authentication" for the authenticated version. Scenarios covered: - Local validation of the request code before anything is sent. - Connection failures (server unreachable, connection refused/reset). - Empty/closed response from the server. - Unrecognized response codes. - Displaying every response field using its documented name. """ import socket # Request/response use two separate sockets - one to send order # requests, one to read the corresponding confirmations/rejections. REQUEST_ADDR = ("localhost", 9090) # request socket (client -> bridge) RESPONSE_ADDR = ("localhost", 9091) # response socket (bridge -> client) def connect(addr): """Connect to (host, port), reporting connection errors clearly. Using a short timeout means a server that's down or unreachable fails fast with a clear message instead of hanging indefinitely. """ host, port = addr try: return socket.create_connection(addr, timeout=5) except (ConnectionRefusedError, socket.timeout, OSError) as exc: print(f"ERROR: could not connect to {host}:{port} - {exc}") raise SystemExit(1) # ---- valid request / response codes ---- # Used to fail fast, locally, before anything is sent over the wire. VALID_REQUEST_CODES = { "2000": "New Order Request", "2040": "Order Modify Request", "2070": "Order Cancel Request", } VALID_RESPONSE_CODES = { "2222": "Order Trade Confirmation", "2073": "New Order Confirmation", "2074": "Order Modification Confirmation", "2075": "Order Cancel Confirmation", } # ---- field names, in order, for request and response strings ---- # Mirrors the pipe-delimited positions documented in "New Order" and # "Order Confirmation" - used only to label output, not to validate it. REQUEST_FIELD_NAMES = [ "Request Code", "Exchange identifier", "Instrument token", "Trading symbol", "Contract expiry", "Instrument type", "Option strike price", "Option Type", "Trading client", "Order Id", "Echo Back Client reference", "Order Type Market/Limit", "Order quantity", "Order price", "Order action 1=Buy, 2=Sell", "SL trigger price", "Total order quantity", "Remain quantity", ] RESPONSE_FIELD_NAMES = [ "Response Code", "Exchange identifier", "Instrument token", "Trading symbol", "Contract expiry", "Instrument type", "Option strike price", "Option Type", "Trading client", "Order Id", "Trade No", "Executed quantity", "Execution price", "Echo Back Client reference", "Order action 1=Buy, 2=Sell", "Error Code", "Reason Code", "Exchange timestamp", "Last modification time", "Participant (client id)", "Term Ctcl", "Remain quantity", "Total original quantity", ] # ---- request fields (all editable) ---- # Edit these to build a different order. request_code selects which # kind of request this is (new/modify/cancel) - see VALID_REQUEST_CODES. request_code = "2000" # must be one of VALID_REQUEST_CODES segment = "5" # exchange identifier, e.g. 5 = NSE Options token = "52166" # instrument token from the contract master symbol = "BANKNIFTY" # trading symbol expiry_date = "02/24/2022" # contract expiry, MM/DD/YYYY instrument = "OPTIDX" # instrument type strike_price = "36200.00" # option strike price option_type = "CE" # CE (call) or PE (put) client_type = "PRO" # trading client type order_id = "0" # 0 for a new order; existing order id for modify/cancel client_ref = "202202241021" # echo-back reference, returned as-is in the response order_type = "1" # order type, e.g. 1 = Limit order_qty = "25" # quantity for this order order_price = "35" # limit price order_action = "2" # 1 = Buy, 2 = Sell sl_trigger = "0.0" # stop-loss trigger price, 0.0 if not used total_qty = "25" # total order quantity remain_qty = "0" # remaining quantity (0 for a fresh order) # Field order here MUST match REQUEST_FIELD_NAMES / the "New Order" # table exactly - the server parses this by position, not by name. request_fields = [ request_code, segment, token, symbol, expiry_date, instrument, strike_price, option_type, client_type, order_id, client_ref, order_type, order_qty, order_price, order_action, sl_trigger, total_qty, remain_qty, ] # ---- validate request code before doing anything else ---- # Catches typos locally instead of sending a request the server would # have to reject. if request_code not in VALID_REQUEST_CODES: valid_list = ", ".join(f"{code} ({desc})" for code, desc in VALID_REQUEST_CODES.items()) print(f"ERROR: Invalid request code '{request_code}'. Must be one of: {valid_list}") raise SystemExit(1) # Build the final pipe-delimited request string. request = "|".join(request_fields) print(f"Request code {request_code} recognized as: {VALID_REQUEST_CODES[request_code]}") # ---- send request (no auth) ---- req_sock = connect(REQUEST_ADDR) try: # Every message MUST be newline-terminated (see "Connection Details"). req_sock.sendall((request + "\n").encode()) print("Sent request:", request) finally: # Always close, whether the send succeeded or we're bailing out. req_sock.close() # ---- read response (no auth) ---- # Response socket is separate from the request socket and needs its # own connection. resp_sock = connect(RESPONSE_ADDR) try: try: response = resp_sock.recv(4096).decode(errors="replace").strip() except (ConnectionResetError, ConnectionAbortedError, OSError) as exc: print(f"ERROR: failed reading response: {exc}") raise SystemExit(1) if not response: # An empty read means the server closed the connection without # sending anything - treat it as a failure, not an empty message. print("ERROR: connection closed before a response was received.") raise SystemExit(1) finally: resp_sock.close() print("\nReceived response:", response) # ---- separate fields ---- fields = response.split("|") # ---- validate response code ---- response_code = fields[0] if fields else "" if response_code not in VALID_RESPONSE_CODES: valid_list = ", ".join(f"{code} ({desc})" for code, desc in VALID_RESPONSE_CODES.items()) print(f"ERROR: Invalid response code '{response_code}'. Must be one of: {valid_list}") raise SystemExit(1) print(f"Response code {response_code} recognized as: {VALID_RESPONSE_CODES[response_code]}") # ---- display fields using their proper names ---- # Zips positional values back up with their documented field names so # the output is readable without cross-referencing the docs by hand. print("\n--- Fields ---") for i, value in enumerate(fields): name = RESPONSE_FIELD_NAMES[i] if i < len(RESPONSE_FIELD_NAMES) else f"Field{i}" print(f"{name}: {value}")

Run

python3 request_client_no_auth.py

Request/response flow

StepDirectionMessage
1connectClient connects to request socket (9090)
2client -> server2000|5|52166|BANKNIFTY|02/24/2022|OPTIDX|36200.00|CE|PRO|0|202202241021|1|25|35|2|0.0|25|0
3connectClient connects to response socket (9091)
4server -> client2073|5|52166|BANKNIFTY|02/24/2022|OPTIDX|36200.00|CE|PRO|404404480000101|0|0|35.0000|202202241021|2|0|0|1330161808|1330161808|12345|123456789012345|25|25

Expected output

Request code 2000 recognized as: New Order Request Sent request: 2000|5|52166|BANKNIFTY|02/24/2022|OPTIDX|36200.00|CE|PRO|0|202202241021|1|25|35|2|0.0|25|0 Received response: 2073|5|52166|BANKNIFTY|02/24/2022|OPTIDX|36200.00|CE|PRO|404404480000101|0|0|35.0000|202202241021|2|0|0|1330161808|1330161808|12345|123456789012345|25|25 Response code 2073 recognized as: New Order Confirmation --- Fields --- Response Code: 2073 Exchange identifier: 5 Instrument token: 52166 Trading symbol: BANKNIFTY Contract expiry: 02/24/2022 Instrument type: OPTIDX Option strike price: 36200.00 Option Type: CE Trading client: PRO Order Id: 404404480000101 Trade No: 0 Executed quantity: 0 Execution price: 35.0000 Echo Back Client reference: 202202241021 Order action 1=Buy, 2=Sell: 2 Error Code: 0 Reason Code: 0 Exchange timestamp: 1330161808 Last modification time: 1330161808 Participant (client id): 12345 Term Ctcl: 123456789012345 Remain quantity: 25 Total original quantity: 25

Error-handling cases

CaseWhere it's caughtBehavior
Invalid request code (not in VALID_REQUEST_CODES)Before connectingPrints the invalid code and the allowed list, exits - nothing is sent.
Server unreachable / connection refused / connect timeoutconnect()Prints host:port and the underlying error, exits.
Response socket closes before sending any dataAfter recv() on the response socketPrints that the connection closed before a response arrived, exits.
Unrecognized response code (not in VALID_RESPONSE_CODES)After splitting response fieldsPrints the unrecognized code and the allowed list, exits.

Subscription (CSV) Format

The broadcast component does not send all instruments by default - it only sends data for the instruments listed in a subscription list, provided as a pipe-delimited (|) file with a .csv extension. There is no way to subscribe/unsubscribe by sending a request over the socket at runtime.

Important: the subscription CSV is read once, at startup. If you add or change instruments in the file, the broadcast component must be restarted to pick up the changes - it does not re-read the file while running.

Format

One instrument per line, five pipe-delimited fields, no header row required:

PosFieldDescription
1SCRIP_NAMEUnderlying/scrip symbol, e.g. BANKNIFTY
2EXPIRY_DATEContract expiry, MM/DD/YYYY
3INSTR_NMInstrument type, e.g. OPTIDX, FUTIDX, OPTSTK
4OPTION_TYPECE or PE (blank for futures)
5STRIKE_PRICEStrike price (blank for futures)

subscriptions.csv

SCRIP_NAME|EXPIRY_DATE|INSTR_NM|OPTION_TYPE|STRIKE_PRICE BANKNIFTY|06/30/2026|OPTIDX|CE|43500.00 BANKNIFTY|06/30/2026|OPTIDX|PE|43500.00 NIFTY|06/25/2026|OPTIDX|CE|24000.00

Once the subscription file is in place and the broadcast component has been (re)started, connect to the broadcast socket as usual (see the examples below) - you'll only receive broadcasts for the instruments listed in the file. Unlisted instruments are never sent, so there's no need to filter them out on the client side. To add or change instruments later, edit the CSV and restart the broadcast component again.

Broadcast Reader - TCP (Primary Example)

This is the reference example for reading market data broadcasts: a single TCP connection to the broadcast socket, using plain Python with no external dependencies. It's intentionally the simplest thing that handles broadcast data correctly, including the error handling every production reader needs:

Configuration

HOST = "127.0.0.1" # Bridge server IP PORT = 10124 # broadcast / response socket port

read_broadcast_tcp.py

#!/usr/bin/env python3 """ Broadcast reader - primary example (single TCP connection, plain Python). Handles the basics every production reader needs: partial/split messages, malformed messages, falling behind the data rate, and clear error reporting. See "Subscription (CSV) Format" for how to limit the broadcast to specific instruments before running this. """ import socket import time from datetime import datetime HOST = "127.0.0.1" # Bridge server IP PORT = 10124 # broadcast / response socket port RECV_CHUNK = 4096 # bytes requested per recv() call POLL_TIMEOUT = 1.0 # seconds to wait for data before looping EXPECTED_FIELD_COUNT = 19 RECONNECT_DELAY_SECONDS = 5 # If the unprocessed buffer grows past this many bytes, the reader is # not keeping up with the incoming data rate. LAG_WARNING_BYTES = 65536 def log(level, message): ts = datetime.now().strftime("%Y-%m-%d %H:%M:%S") print(f"[{ts}] [{level}] {message}") def print_fields(fields): print("-------------------------------------") print(f"token = {fields[0]}") print(f"scrip = {fields[1]}") print(f"exchange = {fields[2]}") print(f"expiry_date = {fields[3]}") print(f"instrument = {fields[4]}") print(f"option_type = {fields[5]}") print(f"strike_price = {fields[6]}") print(f"last_trade_quantity = {fields[7]}") print(f"last_traded_price = {fields[8]}") print(f"bid_price1 = {fields[9]}") print(f"bid_quantity1 = {fields[10]}") print(f"bid_price2 = {fields[11]}") print(f"bid_quantity2 = {fields[12]}") print(f"ask_price1 = {fields[13]}") print(f"ask_quantity1 = {fields[14]}") print(f"ask_price2 = {fields[15]}") print(f"ask_quantity2 = {fields[16]}") print(f"total_traded_qty = {fields[17]}") print(f"open_interest = {fields[18]}") print("-------------------------------------\n") def connect(): while True: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(POLL_TIMEOUT) try: log("INFO", f"Connecting to {HOST}:{PORT} ...") s.connect((HOST, PORT)) log("INFO", "Connected.") return s except OSError as exc: log("ERROR", f"Connect failed: {exc}. Retrying in {RECONNECT_DELAY_SECONDS}s.") s.close() time.sleep(RECONNECT_DELAY_SECONDS) def main(): sock = connect() buffer = "" while True: try: data = sock.recv(RECV_CHUNK) if not data: log("WARN", "Connection closed by server. Reconnecting.") sock.close() sock = connect() buffer = "" continue buffer += data.decode(errors="replace") # --- Falling-behind detection --- if len(buffer) > LAG_WARNING_BYTES: log("WARN", f"Buffer size {len(buffer)} bytes exceeds {LAG_WARNING_BYTES} - " f"reader may be falling behind the incoming data rate.") # --- Partial message handling --- # Only complete, newline-terminated lines are processed. # Anything after the last \n is incomplete and stays in the # buffer until the rest arrives on a later recv(). while "\n" in buffer: line, buffer = buffer.split("\n", 1) line = line.strip() if not line: continue fields = line.split("|") # --- Malformed message detection --- if len(fields) != EXPECTED_FIELD_COUNT: log("ERROR", f"Malformed broadcast: expected {EXPECTED_FIELD_COUNT} " f"fields, got {len(fields)}. Raw line: {line}") continue print_fields(fields) except socket.timeout: continue # no data within POLL_TIMEOUT - normal, keep looping except OSError as exc: log("ERROR", f"Read error: {exc}. Reconnecting.") sock.close() sock = connect() buffer = "" if __name__ == "__main__": try: main() except KeyboardInterrupt: print("\nStopping (Ctrl+C).")

Run

python3 read_broadcast_tcp.py

Expected output

[2026-07-21 09:15:02] [INFO] Connecting to 127.0.0.1:10124 ... [2026-07-21 09:15:02] [INFO] Connected. ------------------------------------- token = 57439 scrip = NIFTY exchange = 5 expiry_date = 03/03/2022 instrument = OPTIDX option_type = PE strike_price = 17400.00 last_trade_quantity = 50 last_traded_price = 76625 bid_price1 = 73550 bid_quantity1 = 150 bid_price2 = 73490 bid_quantity2 = 550 ask_price1 = 73930 ask_quantity1 = 50 ask_price2 = 73935 ask_quantity2 = 200 total_traded_qty = 25400 open_interest = 0 ------------------------------------- [2026-07-21 09:15:07] [ERROR] Malformed broadcast: expected 19 fields, got 17. Raw line: 57439|NIFTY|5|03/03/2022|OPTIDX|PE|17400.00|50|76625|73550|150|73490|550|73930|50 [2026-07-21 09:16:40] [WARN] Buffer size 71328 bytes exceeds 65536 - reader may be falling behind the incoming data rate.

Broadcast Reader - Multicast (UDP)

Use this instead of the TCP example when your deployment delivers market data over multicast rather than a TCP broadcast socket. Both mechanisms carry the same pipe-delimited message format described in Broadcast Format - only the transport differs.

AspectTCPMulticast (UDP)
Connection modelConnection-oriented; must connect/reconnectConnectionless; join a multicast group, no connect/reconnect logic
Ordering & deliveryOrdered, reliable streamPackets can arrive out of order or be dropped - no retransmission
Message framingStream can split a message across recv() calls - needs bufferingEach UDP packet is a discrete unit as sent; framing issues are rare but possible if a packet holds multiple lines
Client configServer IP + portMulticast group IP + port, plus joining the group (IP_ADD_MEMBERSHIP)
Scaling to many clientsOne socket per client on the serverServer sends once; any number of clients can join the group
Note: the multicast group address/port below are placeholders - confirm the actual group IP and port for your deployment with your network/infra team.

Configuration

MCAST_GROUP = "239.1.1.10" # confirm with your network/infra team MCAST_PORT = 20125 LOCAL_BIND_IP = "0.0.0.0"

read_broadcast_multicast.py

#!/usr/bin/env python3 """ Broadcast reader - Multicast (UDP) example. Connectionless: there's no persistent socket to the Bridge, so reconnect logic doesn't apply. Still validates every message, since UDP packets can be dropped or arrive out of order. """ import socket import struct from datetime import datetime MCAST_GROUP = "239.1.1.10" # confirm with your network/infra team MCAST_PORT = 20125 LOCAL_BIND_IP = "0.0.0.0" EXPECTED_FIELD_COUNT = 19 def log(level, message): ts = datetime.now().strftime("%Y-%m-%d %H:%M:%S") print(f"[{ts}] [{level}] {message}") def print_fields(fields): print("-------------------------------------") print(f"token = {fields[0]}") print(f"scrip = {fields[1]}") print(f"exchange = {fields[2]}") print(f"expiry_date = {fields[3]}") print(f"instrument = {fields[4]}") print(f"option_type = {fields[5]}") print(f"strike_price = {fields[6]}") print(f"last_trade_quantity = {fields[7]}") print(f"last_traded_price = {fields[8]}") print(f"bid_price1 = {fields[9]}") print(f"bid_quantity1 = {fields[10]}") print(f"bid_price2 = {fields[11]}") print(f"bid_quantity2 = {fields[12]}") print(f"ask_price1 = {fields[13]}") print(f"ask_quantity1 = {fields[14]}") print(f"ask_price2 = {fields[15]}") print(f"ask_quantity2 = {fields[16]}") print(f"total_traded_qty = {fields[17]}") print(f"open_interest = {fields[18]}") print("-------------------------------------\n") def main(): sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.bind((LOCAL_BIND_IP, MCAST_PORT)) mreq = struct.pack("4sl", socket.inet_aton(MCAST_GROUP), socket.INADDR_ANY) sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq) log("INFO", f"Joined multicast group {MCAST_GROUP}:{MCAST_PORT}") while True: try: packet, addr = sock.recvfrom(4096) except OSError as exc: log("ERROR", f"Socket error: {exc}") continue # A packet may contain one or more newline-terminated lines. for line in packet.decode(errors="replace").splitlines(): line = line.strip() if not line: continue fields = line.split("|") if len(fields) != EXPECTED_FIELD_COUNT: log("ERROR", f"Malformed packet from {addr}: expected {EXPECTED_FIELD_COUNT} " f"fields, got {len(fields)}. Raw: {line}") continue print_fields(fields) if __name__ == "__main__": try: main() except KeyboardInterrupt: print("\nStopping (Ctrl+C).")

Run

python3 read_broadcast_multicast.py

Expected output

[2026-07-21 09:15:02] [INFO] Joined multicast group 239.1.1.10:20125 ------------------------------------- token = 57439 scrip = NIFTY exchange = 5 expiry_date = 03/03/2022 instrument = OPTIDX option_type = PE strike_price = 17400.00 last_trade_quantity = 50 last_traded_price = 76625 bid_price1 = 73550 bid_quantity1 = 150 bid_price2 = 73490 bid_quantity2 = 550 ask_price1 = 73930 ask_quantity1 = 50 ask_price2 = 73935 ask_quantity2 = 200 total_traded_qty = 25400 open_interest = 0 -------------------------------------

Broadcast Reader - Multiple Connections (Advanced)

Once you're comfortable with the primary TCP example, this variant shows how to read from several TCP connections to the same broadcast instance at the same time - for example, multiple readers/strategies consuming the same feed, or redundant connections for resiliency. It's the same buffering, partial-message, and malformed-message handling as the primary example, just applied to each connection in turn, using plain sequential Python (no external libraries).

Each socket gets a short read timeout. The main loop checks connection 1, then 2, then 3, and so on, repeatedly; the timeout lets the loop move on instead of blocking on a connection with no data. If one connection drops, only that one reconnects - the others keep running untouched.

Important: a single broadcast instance sends the same subscribed instruments to every connection made to it - multiple connections to one instance do not let you subscribe to different instruments on different connections. If you need different instruments on different connections, run multiple instances of the broadcast component, each on its own port with its own subscription CSV (see Subscription (CSV) Format), and point each reader connection at the instance/port carrying the instruments you want.

Configuration

HOST = "127.0.0.1" # same host:port for every connection - one broadcast instance PORT = 10125 NUM_CONNECTIONS = 3 # change this one number to open more/fewer connections

read_broadcast_multi.py

#!/usr/bin/env python3 """ Multi-connection broadcast reader - plain sequential Python. - All connections go to the SAME HOST:PORT, i.e. one broadcast instance, and therefore all receive the SAME subscribed instruments (see the note above). Edit HOST/PORT below. - To open more or fewer connections, change NUM_CONNECTIONS by one number. - How it works: each socket has a short timeout (POLL_TIMEOUT). The main loop just checks connection 1, then 2, then 3, ... one after another, over and over. If a connection has data, it's printed. If not, the short timeout lets the loop move on to the next connection instead of waiting forever. - If one connection disconnects, only that one stops (or reconnects, see AUTO_RECONNECT) - the others keep running untouched. - Subscriptions are NOT sent here - this script only reads broadcasts. See "Subscription (CSV) Format" for how the broadcast instance's feed is configured. """ import socket import time HOST = "127.0.0.1" PORT = 10125 NUM_CONNECTIONS = 3 AUTO_RECONNECT = True RECONNECT_DELAY_SECONDS = 5 POLL_TIMEOUT = 0.2 EXPECTED_FIELD_COUNT = 19 sockets = {} # connection_id -> socket, or None if not connected buffers = {} # connection_id -> leftover partial data next_retry_at = {} # connection_id -> time.time() to try reconnecting def connect(connection_id): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print(f"[Conn-{connection_id}] Connecting to {HOST}:{PORT} ...") try: s.connect((HOST, PORT)) s.settimeout(POLL_TIMEOUT) sockets[connection_id] = s print(f"[Conn-{connection_id}] Connected.\n") except OSError as exc: sockets[connection_id] = None next_retry_at[connection_id] = time.time() + RECONNECT_DELAY_SECONDS print(f"[Conn-{connection_id}] Connect failed: {exc}") def disconnect(connection_id, reason): sock = sockets.get(connection_id) if sock is not None: sock.close() sockets[connection_id] = None print(f"[Conn-{connection_id}] {reason}") if AUTO_RECONNECT: next_retry_at[connection_id] = time.time() + RECONNECT_DELAY_SECONDS print(f"[Conn-{connection_id}] Reconnecting in {RECONNECT_DELAY_SECONDS}s ...") def print_fields(connection_id, fields): print(f"------------------------------------- [Conn-{connection_id}]") print(f"token = {fields[0]}") print(f"scrip = {fields[1]}") print(f"exchange = {fields[2]}") print(f"expiry_date = {fields[3]}") print(f"instrument = {fields[4]}") print(f"option_type = {fields[5]}") print(f"strike_price = {fields[6]}") print(f"last_trade_quantity = {fields[7]}") print(f"last_traded_price = {fields[8]}") print(f"bid_price1 = {fields[9]}") print(f"bid_quantity1 = {fields[10]}") print(f"bid_price2 = {fields[11]}") print(f"bid_quantity2 = {fields[12]}") print(f"ask_price1 = {fields[13]}") print(f"ask_quantity1 = {fields[14]}") print(f"ask_price2 = {fields[15]}") print(f"ask_quantity2 = {fields[16]}") print(f"total_traded_qty = {fields[17]}") print(f"open_interest = {fields[18]}") print("-------------------------------------\n") def handle_data(connection_id, data): buffers[connection_id] += data.decode(errors="replace") while "\n" in buffers[connection_id]: line, buffers[connection_id] = buffers[connection_id].split("\n", 1) line = line.strip() if not line: continue fields = line.split("|") if len(fields) != EXPECTED_FIELD_COUNT: print(f"[Conn-{connection_id}] Invalid broadcast: expected " f"{EXPECTED_FIELD_COUNT} fields, got {len(fields)} -> {line}") continue print_fields(connection_id, fields) def main(): if NUM_CONNECTIONS < 1: print("NUM_CONNECTIONS must be 1 or more.") return for connection_id in range(1, NUM_CONNECTIONS + 1): buffers[connection_id] = "" connect(connection_id) try: while True: for connection_id in range(1, NUM_CONNECTIONS + 1): if sockets.get(connection_id) is None: if AUTO_RECONNECT and time.time() >= next_retry_at.get(connection_id, 0): connect(connection_id) continue sock = sockets[connection_id] try: data = sock.recv(4096) if not data: disconnect(connection_id, "Connection closed by server.") continue handle_data(connection_id, data) except socket.timeout: pass except OSError as exc: disconnect(connection_id, f"Read error: {exc}") except KeyboardInterrupt: print("\nStopping (Ctrl+C).") if __name__ == "__main__": main()

Run

python3 read_broadcast_multi.py

Expected output

[Conn-1] Connecting to 127.0.0.1:10125 ... [Conn-1] Connected. [Conn-2] Connecting to 127.0.0.1:10125 ... [Conn-2] Connected. [Conn-3] Connecting to 127.0.0.1:10125 ... [Conn-3] Connected. ------------------------------------- [Conn-1] token = 57439 scrip = NIFTY exchange = 5 expiry_date = 03/03/2022 instrument = OPTIDX option_type = PE strike_price = 17400.00 last_trade_quantity = 50 last_traded_price = 76625 bid_price1 = 73550 bid_quantity1 = 150 bid_price2 = 73490 bid_quantity2 = 550 ask_price1 = 73930 ask_quantity1 = 50 ask_price2 = 73935 ask_quantity2 = 200 total_traded_qty = 25400 open_interest = 0 ------------------------------------- ------------------------------------- [Conn-2] token = 57439 scrip = NIFTY ... -------------------------------------

Server-side (Bridge) Behavior

Error Handling & Response Codes

Use consistent error responses. Example values:

Example error reply:
1004|REJECTED|Requested order string is not as per requirement.\n

Performance & Best Practices

For example:

These give customers confidence that your system is reliable

RMS

Risk Management System is a control layer that ensures all trades follow predefined risk limits and regulatory rules before orders are sent to the exchange.

RMS ensures that only valid and permitted orders are placed in the market. It protects traders, brokers, and exchanges from financial, operational, and compliance risks.

Orders are validated against predefined RMS rules.

Note: The RMS checks listed above are standard validations. Users can add various other custom RMS checks as per their specific requirements. Our system is flexible and can accommodate additional risk management rules beyond those mentioned here.

Margin

Margin checks are applied post order acceptance.

We show Total Margin.
API has facility to restrict order on margin breach.

Real-Time Trade Monitor

The Bridge API provides comprehensive real-time monitoring capabilities to track all your trading activities. Our monitoring interface gives you complete visibility into your trades, positions, and order execution status.

Live Trade View

Monitor all executed trades in real-time with detailed information including instance number, execution time, symbol, quantity, and price. The live trade view helps you track your trading activity as it happens, providing instant feedback on order executions.

Live Trade Monitor

Live Trade Monitor - Real-time view of all executed trades

Detailed Net Position View

Get comprehensive position tracking with our detailed net position monitor. This view provides in-depth analysis including quantity exposure, rupee exposure, threshold quantities, buy/sell values, profit/loss calculations, and real-time margin requirements. The square-off thresholds help you manage risk effectively.

Detailed Net Position Monitor

Detailed Net Position Monitor - Comprehensive position tracking with P&L analysis

Key Features

Troubleshooting & FAQ

If the order execution socket disconnects due to any network issue, the Bridge API automatically cancels all open orders and shuts down to prevent unintended trades. This safety mechanism ensures no orphaned orders remain active during connectivity issues.

Yes, the Bridge API can be seamlessly integrated with exchange simulation or test environments to validate order flows and strategy behavior before live deployment. This allows you to thoroughly test your strategies in a risk-free environment.

Market data, provided directly by the broker, is delivered through a dedicated broadcast socket that runs continuously during market hours. This ensures real-time, reliable data streaming for your trading strategies.

Yes. Users can provide a configuration file specifying selected securities/instruments to subscribe to. This allows you to receive market data only for the instruments you're interested in, reducing bandwidth and processing requirements.

The exchange rejection or system level RMS rejection is sent back to the client via the response socket with appropriate error and reason codes. This allows your application to handle rejections gracefully and take appropriate action.

The Bridge API is engineered for low-latency order execution, typically delivering millisecond-level processing depending on the network topology and deployment environment. Actual latency may vary based on your infrastructure and network conditions.

Yes. Bridge API maintains detailed logs for orders, responses, trades, and system events for audit and troubleshooting. These logs are essential for compliance, debugging, and performance analysis.

The number of strategies is not limited, as the system operates over socket-based connectivity. Users can create multiple socket connections to run different strategies simultaneously, allowing for flexible and scalable trading operations.

On restart or failure, the Bridge API ensures safety by cancelling open orders and requiring fresh client connections. This prevents stale orders from being executed and ensures a clean state after any system interruption.