Update README.md
This commit is contained in:
parent
c7aeb221ad
commit
907df6b7d8
790
README.md
790
README.md
@ -1,465 +1,593 @@
|
||||
# HedgeTech IME Live Data WebSocket API
|
||||
|
||||
Professional real-time WebSocket streaming service for Iran Mercantile Exchange (IME) market data.
|
||||
# HT Data Engine | IME | WebSocket
|
||||
## Real-Time Mercantile Exchange Streams (IME)
|
||||
### WebSocket • Real-Time • Low-Latency
|
||||
|
||||
---
|
||||
|
||||
# Overview
|
||||
# 1. Overview
|
||||
|
||||
The HedgeTech IME Live Data WebSocket service provides ultra low-latency real-time streaming market data for IME contracts.
|
||||
This documentation describes the **HT Data Engine IME WebSocket API** for subscribing to real-time market data streams from the **Iran Mercantile Exchange (IME)**.
|
||||
|
||||
The service is designed for:
|
||||
The service provides low-latency real-time updates for IME contracts including:
|
||||
|
||||
- Trading Platforms
|
||||
- HFT Systems
|
||||
- Algorithmic Trading
|
||||
- Quantitative Infrastructure
|
||||
- Market Monitoring Systems
|
||||
- Real-Time Dashboards
|
||||
- Risk Engines
|
||||
- Best bid/ask limits
|
||||
- Aggregate trading statistics
|
||||
- Allowed price ranges
|
||||
- Contract open interest information
|
||||
|
||||
All streams are powered by Redis Pub/Sub infrastructure and asynchronously distributed through FastAPI WebSocket endpoints.
|
||||
The API supports two independent subscription endpoints:
|
||||
|
||||
- Subscription using **Contract Names**
|
||||
- Subscription using **Contract IDs**
|
||||
|
||||
All WebSocket connections require valid authentication and support subscribing to multiple contracts in a single connection.
|
||||
|
||||
---
|
||||
|
||||
# Base URL
|
||||
# 2. Authentication
|
||||
|
||||
All IME WebSocket endpoints require authentication.
|
||||
|
||||
Clients must provide a valid JWT token during the WebSocket handshake.
|
||||
|
||||
## Token Endpoint
|
||||
|
||||
```text
|
||||
https://core.hedgetech.ir/data-engine/ime
|
||||
https://core.hedgetech.ir/auth/user/token/issue
|
||||
```
|
||||
|
||||
## Request
|
||||
|
||||
### Headers
|
||||
|
||||
```text
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
```
|
||||
|
||||
### Body
|
||||
|
||||
```text
|
||||
username=your_username&password=your_password
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Available WebSocket Endpoints
|
||||
## Response Example
|
||||
|
||||
| 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"
|
||||
```json
|
||||
{
|
||||
"Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# WebSocket: Subscribe By Contract Name
|
||||
## WebSocket Authorization Header
|
||||
|
||||
## Endpoint
|
||||
```text
|
||||
Authorization: <your_token>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Important Notes
|
||||
|
||||
- Unauthorized connections are rejected with WebSocket close code `1008`
|
||||
- Tokens may be invalidated if account policies or security rules change
|
||||
- Ensure your account has access to IME live market data services
|
||||
|
||||
---
|
||||
|
||||
# 3. WebSocket Endpoints
|
||||
|
||||
| Endpoint | Description |
|
||||
|---|---|
|
||||
| `wss://core.hedgetech.ir/data-engine/ime/live/data/websocket/contract/name` | Subscribe using contract names |
|
||||
| `wss://core.hedgetech.ir/data-engine/ime/live/data/websocket/contract/id` | Subscribe using contract IDs |
|
||||
|
||||
---
|
||||
|
||||
# 4. Important Clarification: Contract Name vs Contract ID Endpoints
|
||||
|
||||
The IME data engine exposes two separate WebSocket endpoints.
|
||||
|
||||
## Contract Name Endpoint
|
||||
|
||||
```text
|
||||
wss://core.hedgetech.ir/data-engine/ime/live/data/websocket/contract/name
|
||||
```
|
||||
|
||||
---
|
||||
Messages contain:
|
||||
|
||||
## Query Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|---|---|---|---|
|
||||
| contract_name | list[string] | Yes | List of contract names |
|
||||
|
||||
---
|
||||
|
||||
## Example Connection
|
||||
|
||||
```text
|
||||
wss://core.hedgetech.ir/data-engine/ime/live/data/websocket/contract/name?contract_name=ContractA&contract_name=ContractB
|
||||
```json
|
||||
"contractName": "<CONTRACT_NAME>"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Python Example
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
import json
|
||||
import websockets
|
||||
|
||||
async def main():
|
||||
|
||||
uri = (
|
||||
"wss://core.hedgetech.ir/data-engine/ime/live/data/websocket/contract/name"
|
||||
"?contract_name=ContractA"
|
||||
"&contract_name=ContractB"
|
||||
)
|
||||
|
||||
headers = {
|
||||
"Authorization": "Bearer YOUR_ACCESS_TOKEN"
|
||||
}
|
||||
|
||||
async with websockets.connect(
|
||||
uri,
|
||||
additional_headers=headers,
|
||||
ping_interval=20,
|
||||
ping_timeout=20,
|
||||
) as websocket:
|
||||
|
||||
while True:
|
||||
|
||||
message = await websocket.recv()
|
||||
|
||||
data = json.loads(message)
|
||||
|
||||
print(json.dumps(data, indent=4))
|
||||
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# WebSocket: Subscribe By Contract ID
|
||||
|
||||
## Endpoint
|
||||
## Contract ID Endpoint
|
||||
|
||||
```text
|
||||
wss://core.hedgetech.ir/data-engine/ime/live/data/websocket/contract/id
|
||||
```
|
||||
|
||||
---
|
||||
Messages contain:
|
||||
|
||||
## Query Parameters
|
||||
|
||||
| Parameter | Type | Required | Description |
|
||||
|---|---|---|---|
|
||||
| contract_id | list[string] | Yes | List of contract IDs |
|
||||
|
||||
---
|
||||
|
||||
## Example Connection
|
||||
|
||||
```text
|
||||
wss://core.hedgetech.ir/data-engine/ime/live/data/websocket/contract/id?contract_id=12345&contract_id=67890
|
||||
```json
|
||||
"contractId": "<CONTRACT_ID>"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Python Example
|
||||
## Important
|
||||
|
||||
Both endpoints return:
|
||||
|
||||
- The exact same market data
|
||||
- The same payload structure
|
||||
- The same channel schema
|
||||
|
||||
The only difference is the identifier field.
|
||||
|
||||
| Endpoint | Identifier Field |
|
||||
|---|---|
|
||||
| `/contract/name` | `contractName` |
|
||||
| `/contract/id` | `contractId` |
|
||||
|
||||
---
|
||||
|
||||
## Why This Matters
|
||||
|
||||
Client applications must correctly detect which identifier field exists in incoming messages.
|
||||
|
||||
Recommended approach:
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
import json
|
||||
import websockets
|
||||
identifier = message.get("contractId") or message.get("contractName")
|
||||
```
|
||||
|
||||
async def main():
|
||||
This prevents parsing issues when switching between endpoints.
|
||||
|
||||
uri = (
|
||||
"wss://core.hedgetech.ir/data-engine/ime/live/data/websocket/contract/id"
|
||||
"?contract_id=12345"
|
||||
"&contract_id=67890"
|
||||
)
|
||||
---
|
||||
|
||||
headers = {
|
||||
"Authorization": "Bearer YOUR_ACCESS_TOKEN"
|
||||
# 5. Connection Flow
|
||||
|
||||
1. Establish WebSocket connection
|
||||
|
||||
2. Provide the Authorization header
|
||||
|
||||
3. Pass query parameters in the URL
|
||||
|
||||
4. Server validates:
|
||||
- JWT token
|
||||
- Contract identifiers
|
||||
- Subscription permissions
|
||||
|
||||
5. If validation succeeds:
|
||||
- WebSocket connection is accepted
|
||||
- Real-time streams begin immediately
|
||||
|
||||
6. If validation fails:
|
||||
- Connection closes with code `1008`
|
||||
|
||||
---
|
||||
|
||||
# 6. Query Parameters
|
||||
|
||||
## Contract Name Endpoint
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|---|---|---|
|
||||
| `contract_name` | repeated string | IME contract names |
|
||||
|
||||
### Example
|
||||
|
||||
```text
|
||||
wss://core.hedgetech.ir/data-engine/ime/live/data/websocket/contract/name?contract_name=GOLD-APR&contract_name=CEMENT-MAY
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Contract ID Endpoint
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|---|---|---|
|
||||
| `contract_id` | repeated string | IME contract IDs |
|
||||
|
||||
### Example
|
||||
|
||||
```text
|
||||
wss://core.hedgetech.ir/data-engine/ime/live/data/websocket/contract/id?contract_id=1001&contract_id=1002
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 7. Message Structure
|
||||
|
||||
All WebSocket messages follow the same envelope structure.
|
||||
|
||||
---
|
||||
|
||||
## Contract Name Endpoint Example
|
||||
|
||||
```json
|
||||
{
|
||||
"channel": "IME Stream",
|
||||
"contractName": "GOLD-APR",
|
||||
"timestamp": "2026-05-29T12:00:00.000000Z",
|
||||
"data": {
|
||||
"...": "..."
|
||||
}
|
||||
|
||||
async with websockets.connect(
|
||||
uri,
|
||||
additional_headers=headers,
|
||||
ping_interval=20,
|
||||
ping_timeout=20,
|
||||
) as websocket:
|
||||
|
||||
while True:
|
||||
|
||||
message = await websocket.recv()
|
||||
|
||||
data = json.loads(message)
|
||||
|
||||
print(json.dumps(data, indent=4))
|
||||
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# WebSocket Response Structure
|
||||
|
||||
Both endpoints stream identical payload structures.
|
||||
|
||||
The only difference is:
|
||||
|
||||
- `contractName` exists in Name endpoint
|
||||
- `contractId` exists in ID endpoint
|
||||
|
||||
---
|
||||
|
||||
## Response Example (Contract Name)
|
||||
|
||||
```json
|
||||
{
|
||||
"channel": "IME Stream",
|
||||
"contractName": "ContractA",
|
||||
"timestamp": "2026-05-23T15:10:00.000000",
|
||||
"data": {}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Response Example (Contract ID)
|
||||
## Contract ID Endpoint Example
|
||||
|
||||
```json
|
||||
{
|
||||
"channel": "IME Stream",
|
||||
"contractId": "12345",
|
||||
"timestamp": "2026-05-23T15:10:00.000000",
|
||||
"data": {}
|
||||
"contractId": "1001",
|
||||
"timestamp": "2026-05-29T12:00:00.000000Z",
|
||||
"data": {
|
||||
"...": "..."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Data Payload Structure
|
||||
# 8. Data Payload Schema
|
||||
|
||||
The `data` field contains the complete real-time contract market state.
|
||||
The `data` field contains multiple market data sections grouped into a single payload.
|
||||
|
||||
---
|
||||
|
||||
# Full Payload Example
|
||||
# 8.1 BestLimit
|
||||
|
||||
Top bid/ask levels for the contract.
|
||||
|
||||
## Example
|
||||
|
||||
```json
|
||||
{
|
||||
"BestLimit": {
|
||||
"1": {
|
||||
"buy_quantity": 0,
|
||||
"buy_price": 0,
|
||||
"sell_quantity": 0,
|
||||
"sell_price": 0
|
||||
"buy_quantity": 150,
|
||||
"buy_price": 245000,
|
||||
"sell_quantity": 100,
|
||||
"sell_price": 246000
|
||||
},
|
||||
"2": {
|
||||
"buy_quantity": 0,
|
||||
"buy_price": 0,
|
||||
"sell_quantity": 0,
|
||||
"sell_price": 0
|
||||
"buy_quantity": 120,
|
||||
"buy_price": 244500,
|
||||
"sell_quantity": 90,
|
||||
"sell_price": 246500
|
||||
},
|
||||
"3": {
|
||||
"buy_quantity": 0,
|
||||
"buy_price": 0,
|
||||
"sell_quantity": 0,
|
||||
"sell_price": 0
|
||||
"buy_quantity": 80,
|
||||
"buy_price": 244000,
|
||||
"sell_quantity": 70,
|
||||
"sell_price": 247000
|
||||
}
|
||||
},
|
||||
|
||||
"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 Field Documentation
|
||||
|
||||
# BestLimit
|
||||
|
||||
Represents top order book levels.
|
||||
|
||||
---
|
||||
|
||||
## Order Book Levels
|
||||
|
||||
| Level | Description |
|
||||
|---|---|
|
||||
| 1 | Best market level |
|
||||
| 2 | Second order book level |
|
||||
| 3 | Third order book level |
|
||||
|
||||
---
|
||||
|
||||
## BestLimit Fields
|
||||
## Fields
|
||||
|
||||
| Field | Description |
|
||||
|---|---|
|
||||
| buy_quantity | Buy order quantity |
|
||||
| buy_price | Buy order price |
|
||||
| sell_quantity | Sell order quantity |
|
||||
| sell_price | Sell order price |
|
||||
| `buy_quantity` | Total bid quantity |
|
||||
| `buy_price` | Bid price |
|
||||
| `sell_quantity` | Total ask quantity |
|
||||
| `sell_price` | Ask price |
|
||||
|
||||
---
|
||||
|
||||
# Aggregate
|
||||
# 8.2 Aggregate
|
||||
|
||||
Aggregated trading statistics.
|
||||
Aggregate trading statistics for the contract.
|
||||
|
||||
| Field | Description |
|
||||
|---|---|
|
||||
| date | Trading date |
|
||||
| time | Last update time |
|
||||
| trade_count | Total 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 |
|
||||
## Example
|
||||
|
||||
---
|
||||
|
||||
# AllowedPriceRange
|
||||
|
||||
Allowed trading range.
|
||||
|
||||
| Field | Description |
|
||||
|---|---|
|
||||
| minAllowedPrice | Minimum allowed price |
|
||||
| maxAllowedPrice | Maximum allowed price |
|
||||
|
||||
---
|
||||
|
||||
# ContractInfo
|
||||
|
||||
Contract-level metadata.
|
||||
|
||||
| Field | Description |
|
||||
|---|---|
|
||||
| open_interest | Open interest |
|
||||
| open_interest_changes | Open interest changes |
|
||||
|
||||
---
|
||||
|
||||
# Error Handling
|
||||
|
||||
---
|
||||
|
||||
## Authentication Failure
|
||||
|
||||
If the access token is invalid or missing:
|
||||
|
||||
```text
|
||||
WebSocket closed with code 1008 POLICY VIOLATION
|
||||
```json
|
||||
{
|
||||
"Aggregate": {
|
||||
"date": "2026-05-29",
|
||||
"time": "12:00:00",
|
||||
"trade_count": 120,
|
||||
"total_volume": 4500,
|
||||
"total_value": 1102500000,
|
||||
"closing_price": 245500,
|
||||
"last_price": 245700,
|
||||
"low_price": 244000,
|
||||
"high_price": 247000,
|
||||
"open_price": 244500,
|
||||
"previous_close": 243000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Invalid Contract
|
||||
## Fields
|
||||
|
||||
If invalid contract names or IDs are provided:
|
||||
| Field | Description |
|
||||
|---|---|
|
||||
| `trade_count` | Number of executed trades |
|
||||
| `total_volume` | Total traded volume |
|
||||
| `total_value` | Total traded value |
|
||||
| `closing_price` | Current settlement/closing price |
|
||||
| `last_price` | Last traded price |
|
||||
| `low_price` | Session low |
|
||||
| `high_price` | Session high |
|
||||
| `open_price` | Session open |
|
||||
| `previous_close` | Previous settlement/close price |
|
||||
|
||||
```text
|
||||
WebSocket closed with code 1008 POLICY VIOLATION
|
||||
---
|
||||
|
||||
# 8.3 AllowedPriceRange
|
||||
|
||||
Allowed trading price boundaries for the contract.
|
||||
|
||||
## Example
|
||||
|
||||
```json
|
||||
{
|
||||
"AllowedPriceRange": {
|
||||
"minAllowedPrice": 220000,
|
||||
"maxAllowedPrice": 270000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Architecture Notes
|
||||
## Fields
|
||||
|
||||
- All streams are asynchronous
|
||||
- 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
|
||||
| Field | Description |
|
||||
|---|---|
|
||||
| `minAllowedPrice` | Minimum allowed trading price |
|
||||
| `maxAllowedPrice` | Maximum allowed trading price |
|
||||
|
||||
---
|
||||
|
||||
# Production Recommendations
|
||||
# 8.4 ContractInfo
|
||||
|
||||
For production-grade integrations:
|
||||
Contract open interest statistics.
|
||||
|
||||
- Implement automatic reconnect logic
|
||||
- Enable WebSocket heartbeat
|
||||
- Configure proper timeout handling
|
||||
- Monitor connection lifecycle
|
||||
- Handle transient disconnects gracefully
|
||||
## Example
|
||||
|
||||
```json
|
||||
{
|
||||
"ContractInfo": {
|
||||
"open_interest": 5400,
|
||||
"open_interest_changes": 120
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Production Reconnect Example
|
||||
## Fields
|
||||
|
||||
| Field | Description |
|
||||
|---|---|
|
||||
| `open_interest` | Current open interest |
|
||||
| `open_interest_changes` | Change in open interest |
|
||||
|
||||
---
|
||||
|
||||
# 9. Complete Example Payload
|
||||
|
||||
```json
|
||||
{
|
||||
"channel": "IME Stream",
|
||||
"contractId": "1001",
|
||||
"timestamp": "2026-05-29T12:00:00.000000Z",
|
||||
"data": {
|
||||
"BestLimit": {
|
||||
"1": {
|
||||
"buy_quantity": 150,
|
||||
"buy_price": 245000,
|
||||
"sell_quantity": 100,
|
||||
"sell_price": 246000
|
||||
},
|
||||
"2": {
|
||||
"buy_quantity": 120,
|
||||
"buy_price": 244500,
|
||||
"sell_quantity": 90,
|
||||
"sell_price": 246500
|
||||
},
|
||||
"3": {
|
||||
"buy_quantity": 80,
|
||||
"buy_price": 244000,
|
||||
"sell_quantity": 70,
|
||||
"sell_price": 247000
|
||||
}
|
||||
},
|
||||
"Aggregate": {
|
||||
"date": "2026-05-29",
|
||||
"time": "12:00:00",
|
||||
"trade_count": 120,
|
||||
"total_volume": 4500,
|
||||
"total_value": 1102500000,
|
||||
"closing_price": 245500,
|
||||
"last_price": 245700,
|
||||
"low_price": 244000,
|
||||
"high_price": 247000,
|
||||
"open_price": 244500,
|
||||
"previous_close": 243000
|
||||
},
|
||||
"AllowedPriceRange": {
|
||||
"minAllowedPrice": 220000,
|
||||
"maxAllowedPrice": 270000
|
||||
},
|
||||
"ContractInfo": {
|
||||
"open_interest": 5400,
|
||||
"open_interest_changes": 120
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 10. Error Handling
|
||||
|
||||
| Code | Description |
|
||||
|---|---|
|
||||
| `1008` | Invalid token, invalid contract, or unauthorized access |
|
||||
| Connection Closed | Internal server error or Redis stream interruption |
|
||||
|
||||
---
|
||||
|
||||
# 11. Python Example
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
import json
|
||||
import websockets
|
||||
|
||||
URI = (
|
||||
"wss://core.hedgetech.ir/data-engine/ime/live/data/websocket/contract/id"
|
||||
"?contract_id=12345"
|
||||
)
|
||||
async def subscribe(url: str, token: str):
|
||||
|
||||
HEADERS = {
|
||||
"Authorization": "Bearer YOUR_ACCESS_TOKEN"
|
||||
}
|
||||
|
||||
async def connect():
|
||||
|
||||
while True:
|
||||
|
||||
try:
|
||||
headers = {
|
||||
"Authorization": token
|
||||
}
|
||||
|
||||
async with websockets.connect(
|
||||
URI,
|
||||
additional_headers=HEADERS,
|
||||
ping_interval=20,
|
||||
ping_timeout=20,
|
||||
) as websocket:
|
||||
url,
|
||||
additional_headers=headers
|
||||
) as ws:
|
||||
|
||||
print("Connected")
|
||||
async for message in ws:
|
||||
|
||||
while True:
|
||||
payload = json.loads(message)
|
||||
|
||||
message = await websocket.recv()
|
||||
identifier = (
|
||||
payload.get("contractId")
|
||||
or payload.get("contractName")
|
||||
)
|
||||
|
||||
data = json.loads(message)
|
||||
print(
|
||||
payload["timestamp"],
|
||||
identifier,
|
||||
payload["channel"]
|
||||
)
|
||||
|
||||
print(data)
|
||||
print(payload["data"])
|
||||
|
||||
except Exception as e:
|
||||
url = (
|
||||
"wss://core.hedgetech.ir/"
|
||||
"data-engine/ime/live/data/websocket/contract/id"
|
||||
"?contract_id=1001"
|
||||
"&contract_id=1002"
|
||||
)
|
||||
|
||||
print("Disconnected:", e)
|
||||
token = "<your_token>"
|
||||
|
||||
await asyncio.sleep(5)
|
||||
|
||||
asyncio.run(connect())
|
||||
asyncio.run(subscribe(url, token))
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 12. JavaScript Example
|
||||
|
||||
# HedgeTech
|
||||
```javascript
|
||||
const WebSocket = require('ws');
|
||||
|
||||
const url =
|
||||
'wss://core.hedgetech.ir/data-engine/ime/live/data/websocket/contract/id?contract_id=1001&contract_id=1002';
|
||||
|
||||
const token = '<your_token>';
|
||||
|
||||
const ws = new WebSocket(
|
||||
url,
|
||||
{
|
||||
headers: {
|
||||
Authorization: token
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
ws.on('open', () => {
|
||||
console.log('Connected');
|
||||
});
|
||||
|
||||
ws.on('message', (message) => {
|
||||
|
||||
const data = JSON.parse(message);
|
||||
|
||||
const identifier =
|
||||
data.contractId ||
|
||||
data.contractName;
|
||||
|
||||
console.log(
|
||||
data.timestamp,
|
||||
identifier,
|
||||
data.channel
|
||||
);
|
||||
|
||||
console.log(data.data);
|
||||
});
|
||||
|
||||
ws.on('close', () => {
|
||||
console.log('Disconnected');
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# 13. Subscription Notes
|
||||
|
||||
- Multiple contracts can be subscribed in a single connection
|
||||
- Query parameters must be repeated
|
||||
- Streams are pushed continuously in real time
|
||||
- Connections should be handled asynchronously
|
||||
- Invalid contracts cause immediate connection rejection
|
||||
|
||||
---
|
||||
|
||||
# 14. Best Practices
|
||||
|
||||
- Reconnect using exponential backoff
|
||||
- Subscribe only to required contracts
|
||||
- Handle disconnects gracefully
|
||||
- Normalize `contractId` and `contractName`
|
||||
- Monitor WebSocket close code `1008`
|
||||
- Use asynchronous processing pipelines for high-frequency streams
|
||||
|
||||
---
|
||||
|
||||
# 15. Developer Checklist
|
||||
|
||||
- Use the correct endpoint
|
||||
- Provide valid Authorization header
|
||||
- Pass repeated query parameters
|
||||
- Handle both identifier field types
|
||||
- Parse the nested `data` payload correctly
|
||||
- Monitor connection lifecycle events
|
||||
- Handle reconnect scenarios
|
||||
|
||||
---
|
||||
|
||||
# 16. Future Compatibility Notes
|
||||
|
||||
The IME streaming architecture is designed to remain schema-compatible across both endpoint types.
|
||||
|
||||
Future extensions may include:
|
||||
|
||||
- Additional market channels
|
||||
- Incremental order-book streams
|
||||
- Snapshot recovery
|
||||
- Binary transport protocols
|
||||
- Sequence numbers
|
||||
- Compression support
|
||||
- Dynamic subscribe/unsubscribe actions
|
||||
|
||||
Clients are encouraged to write flexible parsers to remain forward-compatible.
|
||||
|
||||
Developed and maintained by HedgeTech Infrastructure Team.
|
||||
Loading…
Reference in New Issue
Block a user