添加tick推送,增加订单操作功能
This commit is contained in:
+193
-6
@@ -167,7 +167,7 @@ Start-ScheduledTask -TaskName "Mt5Bridge"
|
||||
说明:
|
||||
|
||||
- 仅更新 `Mt5Bridge.dll` / `Mt5Bridge.exe` 这一侧,就会影响 HTTP API、健康检查、参数校验、错误处理、重连逻辑等桥接服务行为。
|
||||
- `Alpha Trend.ex5` 不属于桥接服务本体,不替换也不会影响 `/health`、`/account`、`/symbols`、`/rates/from-pos`、`/positions`、`/orders`、`/history/deals`、`/gvar`、`/order/check`、`/order/send` 这些 API 的正常工作。
|
||||
- `Alpha Trend.ex5` 不属于桥接服务本体,不替换也不会影响 `/health`、`/account`、`/symbols`、`/rates/from-pos`、`/positions`、`/orders`、`/history/deals`、`/gvar`、`/order/check`、`/order/send`、`/stream/ticks/{symbol}`、`/stream/ticks-sse/{symbol}` 这些 API 的正常工作。
|
||||
- 只有在你需要新版指标导出逻辑时,才需要同步替换 `Alpha Trend.ex5`。新版指标变化包括:只输出已收盘 K 线信号,以及使用带周期/参数作用域的 GlobalVariable 名称。
|
||||
|
||||
---
|
||||
@@ -310,6 +310,8 @@ GET /account
|
||||
GET /symbols/{symbol}
|
||||
```
|
||||
|
||||
bid/ask 从实时 tick 数据获取(自动等待最多 3 秒),避免品种刚加入 Market Watch 时返回 0 的问题。
|
||||
|
||||
**示例:** `/symbols/XAUUSDc`
|
||||
|
||||
**响应字段:**
|
||||
@@ -338,6 +340,8 @@ GET /symbols/{symbol}
|
||||
GET /symbols/{symbol}/tick
|
||||
```
|
||||
|
||||
自动将品种加入 MT5 Market Watch,并等待最多 3 秒获取真实 tick 数据(解决品种未订阅时返回空值的问题)。
|
||||
|
||||
**示例:** `/symbols/XAUUSDc/tick`
|
||||
|
||||
**响应字段:**
|
||||
@@ -352,6 +356,79 @@ GET /symbols/{symbol}/tick
|
||||
| time_msc | string | 毫秒级时间 |
|
||||
| volume_real | number | 真实成交量 |
|
||||
|
||||
### 实时 Tick 推送(WebSocket)
|
||||
|
||||
```
|
||||
WS /stream/ticks/{symbol}
|
||||
```
|
||||
|
||||
MT5 每收到一条 tick 就立即推给所有订阅者,避免轮询开销。
|
||||
|
||||
- 走 `X-API-Key` 认证(握手 Header 或 `?key=` query 参数)
|
||||
- 连接时自动把品种加入 MT5 Market Watch;最后一个订阅者断开时自动移除
|
||||
- 同一品种可被多个客户端同时订阅,互不影响
|
||||
- 每个品种最多 50 个订阅者(WS + SSE 共用),超出返回 `429`
|
||||
- 每 30 秒发一条心跳包,无 tick 时也发,用于穿透 NAT 保持连接
|
||||
|
||||
**Python 示例(需 `pip install websocket-client`):**
|
||||
|
||||
```python
|
||||
import websocket, json
|
||||
|
||||
ws = websocket.WebSocketApp(
|
||||
"ws://你的IP:13485/stream/ticks/XAUUSDc",
|
||||
header=["X-API-Key: 你的密码"],
|
||||
on_message=lambda ws, msg: print(json.loads(msg)),
|
||||
)
|
||||
ws.run_forever()
|
||||
```
|
||||
|
||||
**浏览器示例(用 query 参数传 key):**
|
||||
|
||||
```js
|
||||
const ws = new WebSocket("ws://你的IP:13485/stream/ticks/XAUUSDc?key=你的密码");
|
||||
ws.onmessage = (e) => console.log(JSON.parse(e.data));
|
||||
```
|
||||
|
||||
**推送格式(每条 tick 一帧 JSON):**
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "tick",
|
||||
"symbol": "XAUUSDc",
|
||||
"time": "2026-07-08T10:30:45",
|
||||
"bid": 4180.0,
|
||||
"ask": 4180.5,
|
||||
"last": 4180.2,
|
||||
"volume": 100,
|
||||
"time_msc": "2026-07-08T10:30:45.123000",
|
||||
"flags": 6
|
||||
}
|
||||
```
|
||||
|
||||
心跳包:`{"type":"heartbeat","time":"2026-07-08T10:31:15"}`
|
||||
|
||||
### 实时 Tick 推送(SSE,不能用 WebSocket 时)
|
||||
|
||||
```
|
||||
GET /stream/ticks-sse/{symbol} → text/event-stream
|
||||
```
|
||||
|
||||
面向无法建 WebSocket 的客户端(部分老浏览器、内网代理、curl 等)。
|
||||
|
||||
```bash
|
||||
curl -N -H "X-API-Key: 你的密码" http://你的IP:13485/stream/ticks-sse/XAUUSDc
|
||||
```
|
||||
|
||||
每条 tick 一帧 SSE:
|
||||
|
||||
```
|
||||
data: {"type":"tick","symbol":"XAUUSDc","bid":4180.0,...}
|
||||
|
||||
data: {"type":"heartbeat","time":"2026-07-08T10:31:15"}
|
||||
|
||||
```
|
||||
|
||||
### 历史 K 线
|
||||
|
||||
```
|
||||
@@ -385,9 +462,11 @@ GET /rates/from-pos?symbol={symbol}&timeframe={timeframe}&start_pos={start}&coun
|
||||
### 当前持仓
|
||||
|
||||
```
|
||||
GET /positions
|
||||
GET /positions[?symbol={symbol}]
|
||||
```
|
||||
|
||||
symbol 为可选过滤参数。
|
||||
|
||||
**响应字段:**
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
@@ -405,6 +484,76 @@ GET /positions
|
||||
| comment | string | 注释 |
|
||||
| magic | number | Magic Number |
|
||||
|
||||
### 平仓
|
||||
|
||||
```
|
||||
POST /position/close
|
||||
```
|
||||
|
||||
```json
|
||||
{ "ticket": 12345678 }
|
||||
{ "ticket": 12345678, "volume": 0.05 } // 部分平仓
|
||||
```
|
||||
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|------|------|------|------|
|
||||
| ticket | number | ✅ | 持仓编号 |
|
||||
| volume | number | ❌ | 平仓手数;不传/0=全平,>0=部分平仓 |
|
||||
| deviation | number | ❌ | 允许滑点(默认 10) |
|
||||
|
||||
### 改持仓 SL/TP
|
||||
|
||||
```
|
||||
POST /position/modify
|
||||
```
|
||||
|
||||
```json
|
||||
{ "ticket": 12345678, "sl": 4170.0, "tp": 4190.0 }
|
||||
```
|
||||
|
||||
`sl`/`tp` 设为 `0` 表示清除。
|
||||
|
||||
### 对冲平仓(节省点差)
|
||||
|
||||
```
|
||||
POST /position/close-by
|
||||
```
|
||||
|
||||
```json
|
||||
{ "position": 111, "position_by": 222 }
|
||||
```
|
||||
|
||||
两张持仓必须 **同品种 + 反向**。MT5 用净额结算,只收一次点差。
|
||||
|
||||
### 批量平仓
|
||||
|
||||
```
|
||||
POST /positions/close-batch
|
||||
```
|
||||
|
||||
```json
|
||||
{ "magic": 123456 }
|
||||
{ "symbol": "XAUUSDc", "magic": 123456 }
|
||||
```
|
||||
|
||||
`symbol` 和 `magic` **至少传一个**。返回 `{closed, failed, data:[...]}`。
|
||||
|
||||
### 移动止损
|
||||
|
||||
服务端不做轮询,由客户端结合 `/positions` 拉取和 `/position/modify` 实现:
|
||||
|
||||
```python
|
||||
while True:
|
||||
for p in bridge.positions():
|
||||
cur = p["price_current"]
|
||||
new_sl = cur - 50 if p["type"] == 0 else cur + 50
|
||||
if abs(new_sl - p["sl"]) >= 10:
|
||||
bridge.modify_position(p["ticket"], sl=new_sl)
|
||||
time.sleep(1)
|
||||
```
|
||||
|
||||
也可订阅 WebSocket tick 流(`/stream/ticks/{symbol}`),按 tick 回调触发,更实时。
|
||||
|
||||
### 挂单
|
||||
|
||||
```
|
||||
@@ -413,12 +562,34 @@ GET /orders?symbol={symbol}
|
||||
|
||||
symbol 为可选参数,不传则返回所有挂单。
|
||||
|
||||
### 撤单
|
||||
|
||||
```
|
||||
POST /order/cancel
|
||||
```
|
||||
|
||||
```json
|
||||
{ "ticket": 87654321 }
|
||||
```
|
||||
|
||||
### 改挂单
|
||||
|
||||
```
|
||||
POST /order/modify
|
||||
```
|
||||
|
||||
```json
|
||||
{ "ticket": 87654321, "price": 4180.0, "sl": 4170.0, "tp": 4190.0 }
|
||||
```
|
||||
|
||||
### 订单预检
|
||||
|
||||
```
|
||||
POST /order/check
|
||||
```
|
||||
|
||||
**填充模式自动适配**:服务端会根据品种的 `SYMBOL_FILLING_MODE` 自动选择经纪商支持的填充模式。如果请求的 `type_filling` 不被支持,会按 IOC(1) → FOK(0) → RETURN(2) 顺序降级,无需客户端手动判断。
|
||||
|
||||
**请求体:**
|
||||
```json
|
||||
{
|
||||
@@ -431,7 +602,8 @@ POST /order/check
|
||||
"tp": 4190.0,
|
||||
"magic": 123456,
|
||||
"comment": "test",
|
||||
"deviation": 10
|
||||
"deviation": 10,
|
||||
"type_filling": 0
|
||||
}
|
||||
```
|
||||
|
||||
@@ -447,6 +619,17 @@ POST /order/check
|
||||
| magic | number | Magic Number |
|
||||
| comment | string | 注释 |
|
||||
| deviation | number | 偏差 |
|
||||
| type_filling | number | 填充模式:0=FOK, 1=IOC, 2=RETURN(自动适配,不传也行) |
|
||||
|
||||
**type_filling 说明:**
|
||||
|
||||
| 值 | 含义 | 说明 |
|
||||
|------|------|------|
|
||||
| 0 | FOK (Fill or Kill) | 必须全部成交,否则取消 |
|
||||
| 1 | IOC (Immediate or Cancel) | 能成交多少成交多少 |
|
||||
| 2 | RETURN | 剩余部分留在订单簿 |
|
||||
|
||||
> 不同经纪商支持的填充模式不同(如 ICMarkets 只支持 IOC),服务端会自动降级,客户端无需关心。
|
||||
|
||||
### 下单
|
||||
|
||||
@@ -454,6 +637,8 @@ POST /order/check
|
||||
POST /order/send
|
||||
```
|
||||
|
||||
与 `/order/check` 相同,`type_filling` 会自动适配经纪商支持的填充模式。
|
||||
|
||||
**请求体:**
|
||||
```json
|
||||
{
|
||||
@@ -467,7 +652,8 @@ POST /order/send
|
||||
"tp": 4190.0,
|
||||
"magic": 123456,
|
||||
"comment": "test",
|
||||
"deviation": 10
|
||||
"deviation": 10,
|
||||
"type_filling": 0
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -609,7 +795,8 @@ resp = requests.post(f"{BRIDGE}/order/send", headers=HEADERS, json={
|
||||
"tp": 4190.0,
|
||||
"magic": 123456,
|
||||
"comment": "test",
|
||||
"deviation": 10
|
||||
"deviation": 10,
|
||||
"type_filling": 0
|
||||
}
|
||||
})
|
||||
print(resp.json())
|
||||
@@ -628,7 +815,7 @@ curl -H "X-API-Key: 你的密码" http://IP:端口/account
|
||||
curl -X POST http://IP:端口/order/send \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-API-Key: 你的密码" \
|
||||
-d '{"request":{"action":1,"symbol":"XAUUSDc","volume":0.01,"order_type":0,"price":4180.0,"sl":4170.0,"tp":4190.0,"magic":123456,"comment":"test","deviation":10}}'
|
||||
-d '{"request":{"action":1,"symbol":"XAUUSDc","volume":0.01,"order_type":0,"price":4180.0,"sl":4170.0,"tp":4190.0,"magic":123456,"comment":"test","deviation":10,"type_filling":0}}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user