HT_DataEngine_IME_websocket/README.md
2026-05-23 16:42:16 +03:30

373 lines
6.6 KiB
Markdown

# IME Live Data WebSocket Documentation
## 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.
---
# WebSocket Endpoints
# 1. WebSocket By Contract Name
```text
wss://YOUR_DOMAIN/live/data/websocket/contract/name
```
## Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| contract_names | list[string] | Yes | List of contract names |
---
## Example Connection
```text
wss://YOUR_DOMAIN/live/data/websocket/contract/name?contract_names=ContractA&contract_names=ContractB
```
---
## Python Example
```python
import asyncio
import websockets
import json
async def main():
uri = (
"ws://127.0.0.1:8000/live/data/websocket/contract/name"
"?contract_names=ContractA"
"&contract_names=ContractB"
)
async with websockets.connect(uri) as websocket:
while True:
message = await websocket.recv()
data = json.loads(message)
print(json.dumps(data, indent=4))
asyncio.run(main())
```
---
# 2. WebSocket By Contract ID
```text
wss://YOUR_DOMAIN/live/data/websocket/contract/id
```
## Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| contract_id | list[string] | Yes | List of contract IDs |
---
## Example Connection
```text
wss://YOUR_DOMAIN/live/data/websocket/contract/id?contract_id=12345&contract_id=67890
```
---
## Python Example
```python
import asyncio
import websockets
import json
async def main():
uri = (
"ws://127.0.0.1:8000/live/data/websocket/contract/id"
"?contract_id=12345"
"&contract_id=67890"
)
async with websockets.connect(uri) as websocket:
while True:
message = await websocket.recv()
data = json.loads(message)
print(json.dumps(data, indent=4))
asyncio.run(main())
```
---
# Authentication
All WebSocket endpoints require authentication.
If authentication fails, the connection will be closed with:
```text
1008 POLICY VIOLATION
```
---
# Message Structure
## Response Structure (Contract Name)
```json
{
"channel": "IME Stream",
"contractName": "ContractA",
"timestamp": "2026-05-23T15:10:00.000000",
"data": {}
}
```
---
## Response Structure (Contract ID)
```json
{
"channel": "IME Stream",
"ContractId": "12345",
"timestamp": "2026-05-23T15:10:00.000000",
"data": {}
}
```
---
# Data Payload Structure
The `data` field contains the complete live contract market data.
---
## Full Payload Example
```json
{
"BestLimit": {
"1": {
"buy_quantity": 0,
"buy_price": 0,
"sell_quantity": 0,
"sell_price": 0
},
"2": {
"buy_quantity": 0,
"buy_price": 0,
"sell_quantity": 0,
"sell_price": 0
},
"3": {
"buy_quantity": 0,
"buy_price": 0,
"sell_quantity": 0,
"sell_price": 0
}
},
"Aggregate": {
"date": "",
"time": "",
"trade_count": 0,
"total_volume": 0,
"total_value": 0,
"closing_price": 0,
"last_price": 0,
"low_price": 0,
"high_price": 0,
"open_price": 0,
"previous_close": 0
},
"AllowedPriceRange": {
"minAllowedPrice": 1,
"maxAllowedPrice": 9999999999
},
"ContractInfo": {
"open_interest": 0,
"open_interest_changes": 0
}
}
```
---
# Payload Fields Description
# BestLimit
Represents the top buy and sell order book levels.
## Levels
| Level | Description |
|---|---|
| 1 | Best market level |
| 2 | Second order book level |
| 3 | Third order book level |
## Fields
| Field | Description |
|---|---|
| buy_quantity | Buy order quantity |
| buy_price | Buy order price |
| sell_quantity | Sell order quantity |
| sell_price | Sell order price |
---
# Aggregate
Aggregated market statistics for the contract.
| Field | Description |
|---|---|
| date | Trading date |
| time | Last update time |
| trade_count | Number of trades |
| total_volume | Total traded volume |
| total_value | Total traded value |
| closing_price | Closing price |
| last_price | Last traded price |
| low_price | Lowest traded price |
| high_price | Highest traded price |
| open_price | Opening price |
| previous_close | Previous closing price |
---
# AllowedPriceRange
Allowed trading price range.
| Field | Description |
|---|---|
| minAllowedPrice | Minimum allowed price |
| maxAllowedPrice | Maximum allowed price |
---
# ContractInfo
Additional contract information.
| Field | Description |
|---|---|
| open_interest | Open interest |
| open_interest_changes | Open interest changes |
---
# Error Handling
## Invalid Authentication
```text
WebSocket closed with code 1008
```
---
## Invalid Contract
If an invalid contract name or contract ID is provided, the connection will be closed.
```text
WebSocket closed with code 1008
```
---
# 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.
---
# Recommended Client Strategy
For production usage, it is recommended to:
- Implement automatic reconnect logic
- Enable heartbeat / ping interval
- Process messages asynchronously
- Use internal message queues
- Configure WebSocket timeout handling
---
# Recommended Python Reconnect Example
```python
import asyncio
import json
import websockets
URI = (
"ws://127.0.0.1:8000/live/data/websocket/contract/id"
"?contract_id=12345"
)
async def connect():
while True:
try:
async with websockets.connect(
URI,
ping_interval=20,
ping_timeout=20
) as websocket:
print("Connected")
while True:
message = await websocket.recv()
data = json.loads(message)
print(data)
except Exception as e:
print("Disconnected:", e)
await asyncio.sleep(5)
asyncio.run(connect())
```