Update README.md
This commit is contained in:
parent
6044610719
commit
f49c3c061a
92
README.md
92
README.md
@ -1,7 +1,5 @@
|
|||||||
# HT Data Engine | TSE & IFB | WebSocket
|
# HT Data Engine | TSE & IFB | WebSocket
|
||||||
|
|
||||||
## Real-Time Market Streams (TSE & IFB)
|
## Real-Time Market Streams (TSE & IFB)
|
||||||
|
|
||||||
### WebSocket • High-Frequency • Low-Latency
|
### WebSocket • High-Frequency • Low-Latency
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -9,7 +7,6 @@
|
|||||||
## 1. Overview
|
## 1. Overview
|
||||||
|
|
||||||
This documentation describes the **HT Data Engine WebSocket API** for subscribing to real-time market data for **TSE & IFB** symbols.
|
This documentation describes the **HT Data Engine WebSocket API** for subscribing to real-time market data for **TSE & IFB** symbols.
|
||||||
|
|
||||||
The API provides multiple channels delivering structured financial data such as order books, aggregate trades, OHLCV, and fund/contract information.
|
The API provides multiple channels delivering structured financial data such as order books, aggregate trades, OHLCV, and fund/contract information.
|
||||||
|
|
||||||
All WebSocket endpoints require **JWT token-based authentication** and support multiple symbols or ISINs in a single connection.
|
All WebSocket endpoints require **JWT token-based authentication** and support multiple symbols or ISINs in a single connection.
|
||||||
@ -28,13 +25,13 @@ Send a `POST` request to:
|
|||||||
https://core.hedgetech.ir/auth/user/token/issue
|
https://core.hedgetech.ir/auth/user/token/issue
|
||||||
```
|
```
|
||||||
|
|
||||||
**Headers:**
|
Headers:
|
||||||
|
|
||||||
```
|
```
|
||||||
Content-Type: application/x-www-form-urlencoded
|
Content-Type: application/x-www-form-urlencoded
|
||||||
```
|
```
|
||||||
|
|
||||||
**Body:**
|
Body:
|
||||||
|
|
||||||
```
|
```
|
||||||
username=your_username&password=your_password
|
username=your_username&password=your_password
|
||||||
@ -72,7 +69,6 @@ Authorization: <your_token>
|
|||||||
| `wss://core.hedgetech.ir/data-engine/tse-ifb/live/data/websocket/symbol/name` | Subscribe using **symbol names** |
|
| `wss://core.hedgetech.ir/data-engine/tse-ifb/live/data/websocket/symbol/name` | Subscribe using **symbol names** |
|
||||||
|
|
||||||
**Note:** The output payload structure is identical for both endpoints, except the symbol identifier field:
|
**Note:** The output payload structure is identical for both endpoints, except the symbol identifier field:
|
||||||
|
|
||||||
- `symbolIsin` for `/symbol/isin`
|
- `symbolIsin` for `/symbol/isin`
|
||||||
- `symbolName` for `/symbol/name`
|
- `symbolName` for `/symbol/name`
|
||||||
|
|
||||||
@ -93,15 +89,14 @@ The data engine provides **two separate WebSocket endpoints**:
|
|||||||
```
|
```
|
||||||
|
|
||||||
Both endpoints deliver **identical payload structures**, including the same channels and the same `data` schema.
|
Both endpoints deliver **identical payload structures**, including the same channels and the same `data` schema.
|
||||||
|
|
||||||
The **only difference** is the identifier field inside each message:
|
The **only difference** is the identifier field inside each message:
|
||||||
|
|
||||||
| Endpoint | Identifier Field in Payload |
|
| Endpoint | Identifier Field in Payload |
|
||||||
|----------|----------------------------|
|
|----------|------------------------------|
|
||||||
| `/symbol/isin` | `"symbolIsin": "<ISIN>"` |
|
| `/symbol/isin` | `"symbolIsin": "<ISIN>"` |
|
||||||
| `/symbol/name` | `"symbolName": "<Symbol>"` |
|
| `/symbol/name` | `"symbolName": "<Symbol>"` |
|
||||||
|
|
||||||
**Example for ISIN endpoint:**
|
Example for ISIN endpoint:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@ -112,7 +107,7 @@ The **only difference** is the identifier field inside each message:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**Example for Symbol-Name endpoint:**
|
Example for Symbol-Name endpoint:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@ -136,16 +131,17 @@ No other structural difference exists between these two WebSocket services.
|
|||||||
## 4. Connection Flow (Updated)
|
## 4. Connection Flow (Updated)
|
||||||
|
|
||||||
1. Establish WebSocket connection with the proper `Authorization` header.
|
1. Establish WebSocket connection with the proper `Authorization` header.
|
||||||
|
|
||||||
2. Include query parameters in the URL. **Each symbol/ISIN and channel is repeated as a separate query parameter**:
|
2. Include query parameters in the URL. **Each symbol/ISIN and channel is repeated as a separate query parameter**:
|
||||||
|
|
||||||
For ISIN endpoint:
|
|
||||||
```
|
```
|
||||||
wss://core.hedgetech.ir/data-engine/tse-ifb/live/data/websocket/symbol/isin?
|
wss://core.hedgetech.ir/data-engine/tse-ifb/live/data/websocket/symbol/isin?
|
||||||
channels=<channel1>&channels=<channel2>&
|
channels=<channel1>&channels=<channel2>&
|
||||||
symbol_isins=<ISIN1>&symbol_isins=<ISIN2>
|
symbol_isins=<ISIN1>&symbol_isins=<ISIN2>
|
||||||
```
|
```
|
||||||
|
|
||||||
For symbol names endpoint:
|
or for symbol names:
|
||||||
|
|
||||||
```
|
```
|
||||||
wss://core.hedgetech.ir/data-engine/tse-ifb/live/data/websocket/symbol/name?
|
wss://core.hedgetech.ir/data-engine/tse-ifb/live/data/websocket/symbol/name?
|
||||||
channels=<channel1>&channels=<channel2>&
|
channels=<channel1>&channels=<channel2>&
|
||||||
@ -153,6 +149,7 @@ No other structural difference exists between these two WebSocket services.
|
|||||||
```
|
```
|
||||||
|
|
||||||
3. If verification passes, the WebSocket connection is accepted.
|
3. If verification passes, the WebSocket connection is accepted.
|
||||||
|
|
||||||
4. Real-time messages are streamed continuously until the connection is closed.
|
4. Real-time messages are streamed continuously until the connection is closed.
|
||||||
|
|
||||||
**Important:** Unauthorized connections are closed immediately with **code 1008**.
|
**Important:** Unauthorized connections are closed immediately with **code 1008**.
|
||||||
@ -230,6 +227,8 @@ All messages are delivered in the following **JSON structure**:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### 6.2 Example: `order-book`
|
### 6.2 Example: `order-book`
|
||||||
|
|
||||||
```json
|
```json
|
||||||
@ -256,6 +255,8 @@ All messages are delivered in the following **JSON structure**:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### 6.3 Example: `ohlcv-last-1m`
|
### 6.3 Example: `ohlcv-last-1m`
|
||||||
|
|
||||||
```json
|
```json
|
||||||
@ -273,6 +274,8 @@ All messages are delivered in the following **JSON structure**:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### 6.4 Example: `aggregate`
|
### 6.4 Example: `aggregate`
|
||||||
|
|
||||||
```json
|
```json
|
||||||
@ -296,6 +299,8 @@ All messages are delivered in the following **JSON structure**:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### 6.5 Example: `institutional-vs-individual`
|
### 6.5 Example: `institutional-vs-individual`
|
||||||
|
|
||||||
```json
|
```json
|
||||||
@ -316,6 +321,8 @@ All messages are delivered in the following **JSON structure**:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### 6.6 Example: `contract-info`
|
### 6.6 Example: `contract-info`
|
||||||
|
|
||||||
```json
|
```json
|
||||||
@ -331,6 +338,8 @@ All messages are delivered in the following **JSON structure**:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
### 6.7 Example: `fund-info`
|
### 6.7 Example: `fund-info`
|
||||||
|
|
||||||
```json
|
```json
|
||||||
@ -349,7 +358,24 @@ All messages are delivered in the following **JSON structure**:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 7. Error Handling
|
### 7. Other Channels
|
||||||
|
|
||||||
|
Payload models follow the **Pydantic models** provided (`Aggregate`, `OrderBook`, `InstitutionalVsIndividual`, `ContractInfo`, `FundInfo`) and always adhere to the format:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"channel": "<channel-name>",
|
||||||
|
"symbolIsin": "<symbolIsin>",
|
||||||
|
"timestamp": "<ISO8601 timestamp>",
|
||||||
|
"data": { ...channel-specific data... }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
> NOTE: Replace `symbolIsin` with `symbolName` when using the `/symbol/name` endpoint.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Error Handling
|
||||||
|
|
||||||
| Code | Description |
|
| Code | Description |
|
||||||
|------|-------------|
|
|------|-------------|
|
||||||
@ -358,9 +384,11 @@ All messages are delivered in the following **JSON structure**:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 8. Code Examples
|
## 9. Examples
|
||||||
|
|
||||||
### 8.1 Python (WebSocket Client)
|
### 9.1 Python (WebSocket Client)
|
||||||
|
|
||||||
|
This example adds a small helper to **support both endpoints** by checking which identifier field exists in incoming messages.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
import asyncio
|
import asyncio
|
||||||
@ -385,7 +413,7 @@ token = "<your_token>"
|
|||||||
asyncio.run(subscribe(url, token))
|
asyncio.run(subscribe(url, token))
|
||||||
```
|
```
|
||||||
|
|
||||||
### 8.2 JavaScript (WebSocket Client)
|
### 9.2 JavaScript (WebSocket Client)
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const WebSocket = require('ws');
|
const WebSocket = require('ws');
|
||||||
@ -409,7 +437,7 @@ ws.on('message', (data) => {
|
|||||||
ws.on('close', () => console.log('Disconnected'));
|
ws.on('close', () => console.log('Disconnected'));
|
||||||
```
|
```
|
||||||
|
|
||||||
### 8.3 Go (WebSocket Client)
|
### 9.3 Go (WebSocket Client)
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
@ -452,7 +480,25 @@ func main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 8.4 Rust (WebSocket Client)
|
### 9.4 Julia (WebSocket Client)
|
||||||
|
|
||||||
|
```julia
|
||||||
|
using WebSockets, JSON
|
||||||
|
|
||||||
|
url = "wss://core.hedgetech.ir/data-engine/tse-ifb/live/data/websocket/symbol/isin?channels=order-book&channels=best-limit&symbol_isins=IRT3SATF0001"
|
||||||
|
token = "<your_token>"
|
||||||
|
|
||||||
|
WebSockets.open(url, extra_headers=["Authorization" => token]) do ws
|
||||||
|
while !eof(ws)
|
||||||
|
msg = String(readavailable(ws))
|
||||||
|
data = JSON.parse(msg)
|
||||||
|
symbol = get(data, "symbolIsin", get(data, "symbolName", ""))
|
||||||
|
println(data["timestamp"], " ", symbol, " ", data["channel"])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
### 9.5 Rust (WebSocket Client)
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use tokio_tungstenite::connect_async;
|
use tokio_tungstenite::connect_async;
|
||||||
@ -479,7 +525,9 @@ async fn main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 8.5 Subscription Notes
|
---
|
||||||
|
|
||||||
|
### 9.6 Subscription Notes
|
||||||
|
|
||||||
- Multiple symbols and channels can be subscribed in a **single WebSocket connection**.
|
- Multiple symbols and channels can be subscribed in a **single WebSocket connection**.
|
||||||
- The server streams messages continuously; handle them asynchronously.
|
- The server streams messages continuously; handle them asynchronously.
|
||||||
@ -487,7 +535,7 @@ async fn main() {
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 9. Best Practices
|
## 10. Best Practices
|
||||||
|
|
||||||
- Reconnect with **exponential backoff** in case of disconnects.
|
- Reconnect with **exponential backoff** in case of disconnects.
|
||||||
- Validate your JWT **before subscribing**.
|
- Validate your JWT **before subscribing**.
|
||||||
@ -498,7 +546,7 @@ async fn main() {
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Appendix: Quick Developer Checklist (for avoiding common mistakes)
|
## Appendix: Quick developer checklist (for avoiding common mistakes)
|
||||||
|
|
||||||
- ✅ Use correct endpoint for your identifier type (`symbol/isin` vs `symbol/name`).
|
- ✅ Use correct endpoint for your identifier type (`symbol/isin` vs `symbol/name`).
|
||||||
- ✅ Provide `Authorization` header with a valid token on the WebSocket handshake.
|
- ✅ Provide `Authorization` header with a valid token on the WebSocket handshake.
|
||||||
@ -506,3 +554,5 @@ async fn main() {
|
|||||||
- ✅ Handle both `symbolIsin` and `symbolName` in your message parsing to make the client resilient.
|
- ✅ Handle both `symbolIsin` and `symbolName` in your message parsing to make the client resilient.
|
||||||
- ✅ Treat messages' `data` payload consistently across endpoints (same schema).
|
- ✅ Treat messages' `data` payload consistently across endpoints (same schema).
|
||||||
- ✅ Monitor for WS close code `1008` to detect authorization or policy errors.
|
- ✅ Monitor for WS close code `1008` to detect authorization or policy errors.
|
||||||
|
|
||||||
|
---
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user