diff --git a/README.md b/README.md index 9fdb310..ac086ec 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,92 @@ -# IME Live Data WebSocket Documentation +# HedgeTech IME Live Data WebSocket API -## Introduction - -This WebSocket service provides real-time market data for Iran Mercantile Exchange (IME) contracts. - -The service streams live contract updates from Redis Pub/Sub channels and delivers them to connected WebSocket clients. - -Two WebSocket endpoints are available: - -1. WebSocket By Contract Name -2. WebSocket By Contract ID - -Both endpoints provide the exact same payload structure. -The only difference is how contracts are subscribed. +Professional real-time WebSocket streaming service for Iran Mercantile Exchange (IME) market data. --- -# WebSocket Endpoints +# Overview -# 1. WebSocket By Contract Name +The HedgeTech IME Live Data WebSocket service provides ultra low-latency real-time streaming market data for IME contracts. + +The service is designed for: + +- Trading Platforms +- HFT Systems +- Algorithmic Trading +- Quantitative Infrastructure +- Market Monitoring Systems +- Real-Time Dashboards +- Risk Engines + +All streams are powered by Redis Pub/Sub infrastructure and asynchronously distributed through FastAPI WebSocket endpoints. + +--- + +# Base URL ```text -wss://YOUR_DOMAIN/live/data/websocket/contract/name +https://core.hedgetech.ir/data-engine/ime ``` +--- + +# Available WebSocket Endpoints + +| Endpoint | Description | +|---|---| +| `/live/data/websocket/contract/name` | Subscribe using contract names | +| `/live/data/websocket/contract/id` | Subscribe using contract IDs | + +--- + +# Authentication + +All WebSocket endpoints require authentication. + +Authentication is performed during the WebSocket handshake phase using Authorization headers. + +--- + +## Authorization Header + +```text +Authorization: Bearer YOUR_ACCESS_TOKEN +``` + +--- + +## Example Authentication Flow + +```python +extra_headers = { + "Authorization": "Bearer YOUR_ACCESS_TOKEN" +} +``` + +--- + +# WebSocket: Subscribe By Contract Name + +## Endpoint + +```text +wss://core.hedgetech.ir/data-engine/ime/live/data/websocket/contract/name +``` + +--- + ## Query Parameters | Parameter | Type | Required | Description | |---|---|---|---| -| contract_names | list[string] | Yes | List of contract names | +| contract_name | list[string] | Yes | List of contract names | --- ## Example Connection ```text -wss://YOUR_DOMAIN/live/data/websocket/contract/name?contract_names=ContractA&contract_names=ContractB +wss://core.hedgetech.ir/data-engine/ime/live/data/websocket/contract/name?contract_name=ContractA&contract_name=ContractB ``` --- @@ -44,18 +95,27 @@ wss://YOUR_DOMAIN/live/data/websocket/contract/name?contract_names=ContractA&con ```python import asyncio -import websockets import json +import websockets async def main(): uri = ( - "ws://127.0.0.1:8000/live/data/websocket/contract/name" - "?contract_names=ContractA" - "&contract_names=ContractB" + "wss://core.hedgetech.ir/data-engine/ime/live/data/websocket/contract/name" + "?contract_name=ContractA" + "&contract_name=ContractB" ) - async with websockets.connect(uri) as websocket: + headers = { + "Authorization": "Bearer YOUR_ACCESS_TOKEN" + } + + async with websockets.connect( + uri, + additional_headers=headers, + ping_interval=20, + ping_timeout=20, + ) as websocket: while True: @@ -70,12 +130,16 @@ asyncio.run(main()) --- -# 2. WebSocket By Contract ID +# WebSocket: Subscribe By Contract ID + +## Endpoint ```text -wss://YOUR_DOMAIN/live/data/websocket/contract/id +wss://core.hedgetech.ir/data-engine/ime/live/data/websocket/contract/id ``` +--- + ## Query Parameters | Parameter | Type | Required | Description | @@ -87,7 +151,7 @@ wss://YOUR_DOMAIN/live/data/websocket/contract/id ## Example Connection ```text -wss://YOUR_DOMAIN/live/data/websocket/contract/id?contract_id=12345&contract_id=67890 +wss://core.hedgetech.ir/data-engine/ime/live/data/websocket/contract/id?contract_id=12345&contract_id=67890 ``` --- @@ -96,18 +160,27 @@ wss://YOUR_DOMAIN/live/data/websocket/contract/id?contract_id=12345&contract_id= ```python import asyncio -import websockets import json +import websockets async def main(): uri = ( - "ws://127.0.0.1:8000/live/data/websocket/contract/id" + "wss://core.hedgetech.ir/data-engine/ime/live/data/websocket/contract/id" "?contract_id=12345" "&contract_id=67890" ) - async with websockets.connect(uri) as websocket: + headers = { + "Authorization": "Bearer YOUR_ACCESS_TOKEN" + } + + async with websockets.connect( + uri, + additional_headers=headers, + ping_interval=20, + ping_timeout=20, + ) as websocket: while True: @@ -122,21 +195,18 @@ asyncio.run(main()) --- -# Authentication +# WebSocket Response Structure -All WebSocket endpoints require authentication. +Both endpoints stream identical payload structures. -If authentication fails, the connection will be closed with: +The only difference is: -```text -1008 POLICY VIOLATION -``` +- `contractName` exists in Name endpoint +- `ContractId` exists in ID endpoint --- -# Message Structure - -## Response Structure (Contract Name) +## Response Example (Contract Name) ```json { @@ -149,7 +219,7 @@ If authentication fails, the connection will be closed with: --- -## Response Structure (Contract ID) +## Response Example (Contract ID) ```json { @@ -164,11 +234,11 @@ If authentication fails, the connection will be closed with: # Data Payload Structure -The `data` field contains the complete live contract market data. +The `data` field contains the complete real-time contract market state. --- -## Full Payload Example +# Full Payload Example ```json { @@ -192,6 +262,7 @@ The `data` field contains the complete live contract market data. "sell_price": 0 } }, + "Aggregate": { "date": "", "time": "", @@ -205,10 +276,12 @@ The `data` field contains the complete live contract market data. "open_price": 0, "previous_close": 0 }, + "AllowedPriceRange": { "minAllowedPrice": 1, "maxAllowedPrice": 9999999999 }, + "ContractInfo": { "open_interest": 0, "open_interest_changes": 0 @@ -218,13 +291,15 @@ The `data` field contains the complete live contract market data. --- -# Payload Fields Description +# Payload Field Documentation # BestLimit -Represents the top buy and sell order book levels. +Represents top order book levels. -## Levels +--- + +## Order Book Levels | Level | Description | |---|---| @@ -232,7 +307,9 @@ Represents the top buy and sell order book levels. | 2 | Second order book level | | 3 | Third order book level | -## Fields +--- + +## BestLimit Fields | Field | Description | |---|---| @@ -245,13 +322,13 @@ Represents the top buy and sell order book levels. # Aggregate -Aggregated market statistics for the contract. +Aggregated trading statistics. | Field | Description | |---|---| | date | Trading date | | time | Last update time | -| trade_count | Number of trades | +| trade_count | Total number of trades | | total_volume | Total traded volume | | total_value | Total traded value | | closing_price | Closing price | @@ -265,7 +342,7 @@ Aggregated market statistics for the contract. # AllowedPriceRange -Allowed trading price range. +Allowed trading range. | Field | Description | |---|---| @@ -276,7 +353,7 @@ Allowed trading price range. # ContractInfo -Additional contract information. +Contract-level metadata. | Field | Description | |---|---| @@ -287,48 +364,55 @@ Additional contract information. # Error Handling -## Invalid Authentication +--- + +## Authentication Failure + +If the access token is invalid or missing: ```text -WebSocket closed with code 1008 +WebSocket closed with code 1008 POLICY VIOLATION ``` --- ## Invalid Contract -If an invalid contract name or contract ID is provided, the connection will be closed. +If invalid contract names or IDs are provided: ```text -WebSocket closed with code 1008 +WebSocket closed with code 1008 POLICY VIOLATION ``` --- -# Notes +# Architecture Notes -- The WebSocket streams real-time market data updates. -- Each contract is subscribed through a dedicated Redis Pub/Sub stream. -- Updates are only sent when market data changes. -- The WebSocket connection remains active until disconnected by the client. -- Multiple contracts can be subscribed simultaneously. -- Timestamps are provided in ISO 8601 format. +- All streams are asynchronous +- Redis Pub/Sub is used internally +- Data is pushed only on updates +- Multiple contracts can be subscribed simultaneously +- Connections remain active until disconnected +- ISO 8601 timestamps are used +- Built for high-throughput market infrastructure --- -# Recommended Client Strategy +# Production Recommendations -For production usage, it is recommended to: +For production-grade integrations: - Implement automatic reconnect logic -- Enable heartbeat / ping interval -- Process messages asynchronously -- Use internal message queues -- Configure WebSocket timeout handling +- Enable WebSocket heartbeat +- Use asynchronous processing pipelines +- Queue incoming messages internally +- Configure proper timeout handling +- Monitor connection lifecycle +- Handle transient disconnects gracefully --- -# Recommended Python Reconnect Example +# Production Reconnect Example ```python import asyncio @@ -336,10 +420,14 @@ import json import websockets URI = ( - "ws://127.0.0.1:8000/live/data/websocket/contract/id" + "wss://core.hedgetech.ir/data-engine/ime/live/data/websocket/contract/id" "?contract_id=12345" ) +HEADERS = { + "Authorization": "Bearer YOUR_ACCESS_TOKEN" +} + async def connect(): while True: @@ -348,8 +436,9 @@ async def connect(): async with websockets.connect( URI, + additional_headers=HEADERS, ping_interval=20, - ping_timeout=20 + ping_timeout=20, ) as websocket: print("Connected") @@ -370,3 +459,19 @@ async def connect(): asyncio.run(connect()) ``` + +--- + +# Technology Stack + +- FastAPI +- Redis Pub/Sub +- AsyncIO +- WebSocket Protocol +- Real-Time Streaming Infrastructure + +--- + +# HedgeTech + +Developed and maintained by HedgeTech Infrastructure Team. \ No newline at end of file