Skip to content

MarketDataClient Documentation

The MarketDataClient is a WebSocket client designed to connect to a market data streaming service, allowing you to subscribe to real-time market data for various instruments. This documentation provides an overview of how to use the MarketDataClient class, including setup, callbacks, methods, and FlatBuffer message schemas.


  1. Introduction
  2. Message Types and Flows
  3. Initialization
  4. Connecting to the WebSocket
  5. Setting Up Callbacks
  6. Subscription Types
  7. Market Data Payload Examples
  8. Example Usage
  9. Limitations
  10. FlatBuffer Message Schema
  11. Conclusion

Introduction

The MarketDataClient allows users to connect to a market data WebSocket, subscribe to various instruments, and receive real-time tick data. It supports multiple subscription types and leverages FlatBuffers for efficient message processing.


Message Types and Flows

  1. Login Flow
  2. Client sends LoginRequest upon WebSocket connection.
  3. Server responds with LoginResponse.

  4. Subscription Flow

  5. Client sends SubscribeRequest.
  6. Server responds with SubscriptionResponse.
  7. Server sends MarketDataMessage continuously.

  8. Unsubscription Flow

  9. Client sends UnsubscribeRequest.
  10. Server responds with UnsubscriptionResponse.

Initialization

To start using the MarketDataClient, initialize the client:

from brokerage_client.data import MarketDataClient

# Initialize the MarketDataClient instance
client = MarketDataClient()

Connecting to the WebSocket

Provide your UCC (User Client Code) and AUTH_TOKEN to connect:

AUTH_TOKEN = "your_auth_token_here"

UCC = "your_ucc_here"

client.connect(UCC, AUTH_TOKEN)

If you want the WebSocket connection to run in a separate thread, pass threaded=True:

AUTH_TOKEN = "your_auth_token_here"

UCC = "your_ucc_here"

client.connect(UCC, AUTH_TOKEN, threaded=True)

When using threaded=True, the WebSocket connection runs in the background. You must ensure that the main thread remains active; otherwise, the program may exit before processing data.

Example:


client.connect(UCC, AUTH_TOKEN, threaded=True)

try:
    while True:  # Keeps the main thread alive
        pass 
except KeyboardInterrupt:
    print("KeyboardInterrupt received, closing connection...")
    client.close()

Setting Up Callbacks

The MarketDataClient provides several callbacks that you can assign to handle different events:

  • on_connect: Triggered when the WebSocket connection is successfully established.
  • on_ticks: Triggered when market data (ticks) are received.
  • on_close: Triggered when the WebSocket connection is closed.

Example:

def on_connect(ws):
    print("Connection established.")
    subscription_list = [
        {"symbol": "RELIANCE.NSE.EQ", "sub_type": "ltp"},
        {"symbol": "NIFTY25FEBFUT", "sub_type": "mtick", "expiry": 20250227},
        {"symbol": "NIFTY25FEBFUT", "sub_type": "utick", "expiry": 20250227},

    ]
    client.subscribe("sub1", subscription_list)

def on_ticks(ws, ticks):

    for i, tick in enumerate(ticks):
        print(f"\nTick {i + 1}:")
        for key, value in tick.items():
            print(f"  {key}: {value}")

def on_close(ws):
    print(f"WebSocket Connection closed")

# Initialize the MarketDataClient instance
client = MarketDataClient()

# Assign callback functions
client.init(on_connect=on_connect,on_ticks=on_ticks,on_close=on_close)


Subscription Types

sub_type Description
ltp Last Traded Price data
mtick Market depth data
utick Options chain data (Futures symbol required)

Market Data Payload Examples

The tick structure represents real-time market data updates and is passed to the on_ticks callback. Each tick contains key market attributes such as price, volume, and market depth levels.

Before receiving market data for the requested symbols, you will first receive the DPR (Daily Price Range) values for those symbols in ticks .

Response Example - DPR Values

[
  {
    "response_type": "Subscription DPR Values",
    "request_id": "sub1",
    "symbol": "RELIANCE.NSE.EQ",
    "type": "DprPayload",
    "dpr_low": 117480.25,
    "dpr_high": 143580.78
  },
  {
    "response_type": "Subscription DPR Values",
    "request_id": "sub1",
    "symbol": "NIFTY25FEBFUT",
    "type": "DprPayload",
    "dpr_low": 2118090.21,
    "dpr_high": 2588775.34
  },
  {
    "response_type": "Subscription DPR Values",
    "request_id": "sub1",
    "symbol": "NIFTY25FEBFUT",
    "type": "DprPayload",
    "dpr_low": 2118090.45,
    "dpr_high": 2588775.56
  }
]

UtickPayload Example

{
  "response_type": "Market Data",
  "symbol": "NIFTY25FEBFUT",
  "seq_no": 1,
  "sub_type": "utick",
  "sending_time": 1740462338221772895,
  "type": "UtickPayload",
  "iv": 0.12,
  "spot_price": 2352210.00,
  "options": [
    { "strike_price": 2330000.00, "option_type": 67, "ltp": 61440.00, "oi": 220425.00, "volume": 133800 },
    { "strike_price": 2335000.00, "option_type": 67, "ltp": 58515.00, "oi": 21075.00, "volume": 22875 },
    { "strike_price": 2340000.00, "option_type": 67, "ltp": 55785.00, "oi": 177225.00, "volume": 133275 },
    { "strike_price": 2345000.00, "option_type": 67, "ltp": 52810.00, "oi": 56625.00, "volume": 13950 },
    { "strike_price": 2350000.00, "option_type": 67, "ltp": 50205.00, "oi": 890175.00, "volume": 703575 }
    .......................................
  ]
}

MtickPayload Example

{
  "response_type": "Market Data",
  "symbol": "NIFTY25FEBFUT",
  "seq_no": 1,
  "sub_type": "mtick",
  "sending_time": 1740462338221772895,
  "type": "MtickPayload",
  "ltp": 2352210.00,
  "volume": 75,
  "levels": [
    { "bid": 2352260.00, "bid_qty": 300, "ask": 2352995.00, "ask_qty": 600 },
    { "bid": 2352200.00, "bid_qty": 75, "ask": 2353000.00, "ask_qty": 825 },
    { "bid": 2352195.00, "bid_qty": 225, "ask": 2353385.00, "ask_qty": 75 },
    { "bid": 2352190.00, "bid_qty": 600, "ask": 2353495.00, "ask_qty": 75 },
    { "bid": 2352185.00, "bid_qty": 375, "ask": 2353515.00, "ask_qty": 750 }
  ]
}

LtpPayload

{
  "response_type": "Market Data",
  "symbol": "RELIANCE.NSE.EQ",
  "seq_no": 1,
  "sub_type": "ltp",
  "sending_time": 1740462338221772895,
  "type": "LtpPayload",
  "ltp": 129315.00,
  "volume": 5
}

DprPayload

Incase if the DPR range for any symbol changes in middle of the day

{
  "response_type": "Dpr Update",
  "symbol": "NIFTY25FEBFUT",
  "type": "DprUpdate",
  "dpr_low": 2119887.00,
  "dpr_high": 2679554.00
}

Full Response Example - Market Data

[
  {
    "response_type": "Market Data",
    "symbol": "RELIANCE.NSE.EQ",
    "seq_no": 1,
    "sub_type": "ltp",
    "sending_time": 1740462338221772895,
    "type": "LtpPayload",
    "ltp": 129315.00,
    "ltq": 5
  },
  {
    "response_type": "Market Data",
    "symbol": "NIFTY25FEBFUT",
    "seq_no": 1,
    "sub_type": "mtick",
    "sending_time": 1740462338221772895,
    "type": "MtickPayload",
    "ltp": 2352210.00,
    "ltq": 75,
    "levels": [
      { "bid": 2352260.00, "bid_qty": 300, "ask": 2352995.00, "ask_qty": 600 },
      { "bid": 2352200.00, "bid_qty": 75, "ask": 2353000.00, "ask_qty": 825 },
      { "bid": 2352195.00, "bid_qty": 225, "ask": 2353385.00, "ask_qty": 75 },
      { "bid": 2352190.00, "bid_qty": 600, "ask": 2353495.00, "ask_qty": 75 },
      { "bid": 2352185.00, "bid_qty": 375, "ask": 2353515.00, "ask_qty": 750 }
    ]
  },
  {
    "response_type": "Market Data",
    "symbol": "NIFTY25FEBFUT",
    "seq_no": 1,
    "sub_type": "utick",
    "sending_time": 1740462338221772895,
    "type": "UtickPayload",
    "iv": 0.12,
    "spot_price": 2352210.00,
    "options": [
      { "strike_price": 2330000.00, "option_type": 67, "ltp": 61440.00, "oi": 220425.00, "volume": 133800 },
      { "strike_price": 2335000.00, "option_type": 67, "ltp": 58515.00, "oi": 21075.00, "volume": 22875 },
      { "strike_price": 2340000.00, "option_type": 67, "ltp": 55785.00, "oi": 177225.00, "volume": 133275 },
      { "strike_price": 2345000.00, "option_type": 67, "ltp": 52810.00, "oi": 56625.00, "volume": 13950 },
      { "strike_price": 2350000.00, "option_type": 67, "ltp": 50205.00, "oi": 890175.00, "volume": 703575 },
      ........................................................
    ]
  }
]

Limitations

  1. A user can establish up to 10 WebSocket connections.
  2. Each subscription request can include up to 200 symbols, but a user can subscribe to a maximum of 2000 symbols by making multiple subscription requests.

FlatBuffer Message Schema

Request Schema (RequestWrapper.fbs)

Response Schema (ResponseWrapper.fbs)


Example Usage

from brokerage_client.data import MarketDataClient

AUTH_TOKEN = "your_auth_token_here"
UCC = "your_ucc_here"

def on_connect(ws):
    print("Connection established.")
    subscription_list = [
        {"symbol": "RELIANCE.NSE.EQ", "sub_type": "ltp"},
        {"symbol": "NIFTY25FEBFUT", "sub_type": "mtick", "expiry": 20250227},
        {"symbol": "NIFTY25FEBFUT", "sub_type": "utick", "expiry": 20250227},

    ]
    client.subscribe("sub1", subscription_list)

def on_ticks(ws, ticks):

    for i, tick in enumerate(ticks):
        print(f"\nTick {i + 1}:")
        for key, value in tick.items():
            print(f"  {key}: {value}")

def on_close(ws):
    print(f"WebSocket Connection closed")

# Initialize the MarketDataClient instance
client = MarketDataClient()

client.init(on_connect=on_connect,on_ticks=on_ticks,on_close=on_close)

# Connect to the market data WebSocket
client.connect(UCC, AUTH_TOKEN)

Conclusion

The MarketDataClient provides a robust way to connect to a market data streaming service using FlatBuffer serialization. By following this documentation, you can establish connections, subscribe to market data, and process the incoming data efficiently.