From 39deb5f7ba1824e55817c8d3409272fffb2ce838 Mon Sep 17 00:00:00 2001 From: gavindiaz Date: Wed, 8 Jul 2026 21:17:02 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0tick=E6=8E=A8=E9=80=81?= =?UTF-8?q?=EF=BC=8C=E5=A2=9E=E5=8A=A0=E8=AE=A2=E5=8D=95=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- API使用指南.md | 421 +++++++- Program.cs | 901 ++++++++++++++---- README.md.md | 199 +++- __pycache__/test_all.cpython-312.pyc | Bin 0 -> 25006 bytes bin/Release/net8.0/Mt5Bridge.dll | Bin 71680 -> 95744 bytes bin/Release/net8.0/Mt5Bridge.exe | Bin 151552 -> 151552 bytes bin/Release/net8.0/Mt5Bridge.pdb | Bin 27756 -> 32184 bytes obj/Mt5Bridge.csproj.nuget.dgspec.json | 10 +- obj/Release/net8.0/Mt5Bridge.AssemblyInfo.cs | 2 +- .../net8.0/Mt5Bridge.AssemblyInfoInputs.cache | 2 +- ....GeneratedMSBuildEditorConfig.editorconfig | 4 +- obj/Release/net8.0/Mt5Bridge.assets.cache | Bin 160 -> 160 bytes .../Mt5Bridge.csproj.AssemblyReference.cache | Bin 4045 -> 4045 bytes .../Mt5Bridge.csproj.CoreCompileInputs.cache | 2 +- .../Mt5Bridge.csproj.FileListAbsolute.txt | 28 + obj/Release/net8.0/Mt5Bridge.dll | Bin 71680 -> 95744 bytes .../net8.0/Mt5Bridge.genruntimeconfig.cache | 2 +- obj/Release/net8.0/Mt5Bridge.pdb | Bin 27756 -> 32184 bytes obj/Release/net8.0/apphost.exe | Bin 151552 -> 151552 bytes obj/Release/net8.0/ref/Mt5Bridge.dll | Bin 12800 -> 16384 bytes obj/Release/net8.0/refint/Mt5Bridge.dll | Bin 12800 -> 16384 bytes obj/project.assets.json | 6 +- obj/project.nuget.cache | 4 +- test_all.py | 416 ++++++++ 延迟测试.py | 53 -- 25 files changed, 1756 insertions(+), 294 deletions(-) create mode 100644 __pycache__/test_all.cpython-312.pyc create mode 100644 test_all.py delete mode 100644 延迟测试.py diff --git a/API使用指南.md b/API使用指南.md index 9de8e07..8f14bef 100644 --- a/API使用指南.md +++ b/API使用指南.md @@ -11,6 +11,10 @@ | 地址 | `http://61.164.252.86:13485` | | 认证 | `X-API-Key` Header 或 `?key=` URL 参数 | | 格式 | 所有返回均为 JSON | +| WebSocket | `ws://61.164.252.86:13485`,握手时用 Header `X-API-Key` | +| SSE | `http://.../stream/ticks-sse/{symbol}`,Header 或 `?key=` 均可 | + +> **浏览器注意**:原生 `WebSocket` 不支持自定义 Header,须用 `?key=` URL 参数;SSE 用 `new EventSource(url + '?key=...')` 同理。Node/Python/Java 客户端用 Header 更干净。 --- @@ -42,7 +46,34 @@ print(api("/health")) ## API 接口速查 -### 1. 健康检查 +| 分类 | 方法 | 端点 | 用途 | +|------|------|------|------| +| **系统** | `GET` | `/health` | 健康检查 + MT5 连接状态 | +| **账户** | `GET` | `/account` | 余额/净值/保证金/杠杆 | +| **行情** | `GET` | `/symbols/{symbol}` | 品种信息(点值/手数/合约) | +| | `GET` | `/symbols/{symbol}/tick` | 拉取一次 tick | +| | `WS` | `/stream/ticks/{symbol}` | **实时 tick 推送**(推荐) | +| | `GET` | `/stream/ticks-sse/{symbol}` | SSE 推送(浏览器/内网代理友好) | +| **K 线** | `GET` | `/rates/from-pos` | K 线(按偏移量) | +| | `GET` | `/rates/from-date` | **K 线(按时间范围)⭐** | +| **持仓** | `GET` | `/positions[?symbol=]` | 当前持仓列表 | +| | `POST` | `/position/close` | 平仓(全/部分) | +| | `POST` | `/position/modify` | 改 SL/TP | +| | `POST` | `/position/close-by` | 对冲平仓(节省点差) | +| | `POST` | `/positions/close-batch` | 批量平仓(按 magic/symbol) | +| **挂单** | `GET` | `/orders[?symbol=]` | 挂单列表 | +| | `POST` | `/order/cancel` | 撤单 | +| | `POST` | `/order/modify` | 改挂单价/SL/TP | +| **下单** | `POST` | `/order/check` | 预检(不成交) | +| | `POST` | `/order/send` | 实际下单 | +| **历史** | `GET` | `/history/deals` | 历史成交 | +| **信号** | `GET/POST/DELETE` | `/gvar[/{name}]` | MQL5 全局变量(指标信号桥) | + +> 推送类端点(WS/SSE):每品种最多 50 个订阅者,超出返回 `429`;每 30 秒发一条心跳包用于穿透 NAT 保持连接。 + +--- + +## 1. 健康检查 ``` GET /health @@ -55,7 +86,7 @@ status = api("/health") --- -### 2. 账户信息 +## 2. 账户信息 ``` GET /account @@ -86,12 +117,16 @@ print(f"杠杆: 1:{acc['leverage']}, 币种: {acc['currency']}") --- -### 3. 实时行情 +## 3. 实时行情 + +#### 3-1. 主动拉取(一次性) ``` GET /symbols/{symbol}/tick ``` +自动将品种加入 MT5 Market Watch,并等待最多 3 秒获取真实 tick 数据(解决品种未订阅时返回空值的问题)。 + ```python def get_tick(symbol): data = api(f"/symbols/{symbol}/tick")["data"][0] @@ -111,14 +146,145 @@ print(f"XAUUSD Bid: {bid} Ask: {ask} Spread: {ask - bid}") | volume | 成交量 | | time | 时间 | +#### 3-2. 订阅推送(WebSocket 流式)⭐ 推荐 + +``` +WS /stream/ticks/{symbol} +``` + +MT5 每收到一个 tick 就立即推给所有订阅者,省去轮询。 + +- 走 `X-API-Key` 认证(Header `X-API-Key: your-key`,WebSocket 客户端在握手 Header 里带) +- 连上时自动把品种加入 MT5 Market Watch;最后一个订阅者断开时自动移除 +- 每个品种最多 50 个订阅者(含 WS + SSE 总数),超出返回 `429` +- 每 30 秒发一条心跳(无 tick 时也发),客户端可用于保活与断线检测 + +**推送格式(每条 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 +} +``` + +**心跳包:** + +```json +{"type":"heartbeat","time":"2026-07-08T10:31:15"} +``` + +#### 3-3. SSE 推送(不能用 WebSocket 的环境) + +``` +GET /stream/ticks-sse/{symbol} → Content-Type: text/event-stream +``` + +面向无法建 WebSocket 的客户端(部分老浏览器、内网代理、curl 测试等)。语义同 3-2,每条 tick 一帧 SSE: + +``` +data: {"type":"tick","symbol":"XAUUSDc","bid":4180.0,...} + +data: {"type":"tick","symbol":"XAUUSDc","bid":4181.0,...} + +``` + +**curl 测试:** + +```bash +curl -N -H "X-API-Key: your-api-key" \ + http://61.164.252.86:13485/stream/ticks-sse/XAUUSDc +``` + +**Python SSE 客户端(`sseclient-py`):** + +```python +from sseclient import SSEClient +import json + +messages = SSEClient("http://61.164.252.86:13485/stream/ticks-sse/XAUUSDc", + headers={"X-API-Key": "your-api-key"}) +for msg in messages: + data = json.loads(msg.data) + if data.get("type") == "heartbeat": + continue + print(data["symbol"], data["bid"], data["ask"]) +``` + +**Python 示例(需安装 `websocket-client`):** + +```python +import websocket +import threading + +def on_message(ws, msg): + tick = eval(msg) # 或 json.loads(msg) + print(f"{tick['symbol']} Bid:{tick['bid']} Ask:{tick['ask']}") + +def on_open(ws): + print("connected") + +def on_close(ws, code, reason): + print(f"disconnected: {code} {reason}") + +ws = websocket.WebSocketApp( + f"ws://61.164.252.86:13485/stream/ticks/XAUUSDc", + header=[f"X-API-Key: your-api-key"], + on_message=on_message, + on_open=on_open, + on_close=on_close, +) +ws.run_forever() +``` + +**`websockets` 库(asyncio 版):** + +```python +import asyncio +import websockets +import json + +async def watch_ticks(): + headers = {"X-API-Key": "your-api-key"} + async with websockets.connect( + "ws://61.164.252.86:13485/stream/ticks/XAUUSDc", + additional_headers=headers, + ) as ws: + async for raw in ws: + tick = json.loads(raw) + print(tick["symbol"], tick["bid"], tick["ask"]) + +asyncio.run(watch_ticks()) +``` + +**浏览器控制台测试:** + +```js +const ws = new WebSocket("ws://61.164.252.86:13485/stream/ticks/XAUUSDc", { + headers: { "X-API-Key": "your-api-key" } // 浏览器原生 WS 不支持自定义 Header,需走 ?key= 参数,见下 +}); +// 浏览器场景:用 query 参数传 key +const ws2 = new WebSocket("ws://61.164.252.86:13485/stream/ticks/XAUUSDc?key=your-api-key"); +ws2.onmessage = (e) => console.log(JSON.parse(e.data)); +``` + --- -### 4. 品种信息 +## 4. 品种信息 ``` GET /symbols/{symbol} ``` +bid/ask 从实时 tick 数据获取(自动等待最多 3 秒),避免品种刚加入 Market Watch 时返回 0 的问题。 + ```python def get_symbol_info(symbol): info = api(f"/symbols/{symbol}")["data"][0] @@ -131,7 +297,7 @@ def get_symbol_info(symbol): --- -### 5. 历史 K 线(按偏移量) +## 5. 历史 K 线(按偏移量) ``` GET /rates/from-pos?symbol={symbol}&timeframe={timeframe}&start_pos={start}&count={count} @@ -203,15 +369,17 @@ print(df.head()) --- -### 6. 当前持仓 +## 6. 当前持仓 ``` -GET /positions +GET /positions[?symbol={symbol}] ``` +symbol 可选过滤。 + ```python -def get_positions(): - return api("/positions")["data"] +def get_positions(symbol=None): + return api("/positions", params={"symbol": symbol} if symbol else None)["data"] positions = get_positions() for pos in positions: @@ -222,9 +390,132 @@ for pos in positions: **返回字段:** `ticket`, `symbol`, `type`(0=买,1=卖), `volume`, `price_open`, `sl`, `tp`, `price_current`, `swap`, `profit`, `comment`, `magic` +### 6-1. 平仓 + +``` +POST /position/close +``` + +```json +// 全平 +{ "ticket": 12345678 } +// 部分平仓 +{ "ticket": 12345678, "volume": 0.05 } +``` + +| 字段 | 必填 | 说明 | +|------|------|------| +| ticket | ✅ | 持仓编号 | +| volume | ❌ | 平仓手数;不传/0 = 全平;>0 = 部分平仓 | +| deviation | ❌ | 允许滑点(默认 10) | + +```python +def close_position(ticket, volume=None): + body = {"ticket": ticket} + if volume: body["volume"] = volume + return api_post("/position/close", body)["data"] + +close_position(12345678) # 全平 +close_position(12345678, volume=0.05) # 部分平 +``` + +### 6-2. 改持仓 SL/TP + +``` +POST /position/modify +``` + +```json +{ "ticket": 12345678, "sl": 4170.0, "tp": 4190.0 } +``` + +SL/TP 设为 0 表示清除对应止损/止盈。 + +```python +def modify_position(ticket, sl=0, tp=0): + return api_post("/position/modify", {"ticket": ticket, "sl": sl, "tp": tp})["data"] +``` + +### 6-3. 对冲平仓(节省点差) + +``` +POST /position/close-by +``` + +用一张反向持仓对冲平仓,只收一次点差(MT5 净额结算),适合双向网格 / 锁仓策略快速离场。 + +```json +{ "position": 111, "position_by": 222 } +``` + +要求:两张持仓 **同品种 + 反向**。 + +```python +def close_by(ticket_a, ticket_b): + return api_post("/position/close-by", {"position": ticket_a, "position_by": ticket_b})["data"] +``` + +### 6-4. 移动止损(客户端轮询模式) + +Bridge 不在服务端跑轮询,暴露 `/position/modify` 由客户端自己做: + +```python +def trail_stop(ticket, distance, step): + """distance: 跟踪距离(如 50 点);step: 最小推进步长(如 10 点)""" + pos = next((p for p in bridge.positions() if p["ticket"] == ticket), None) + if not pos: + return + current = pos["price_current"] + if pos["type"] == 0: # 多单 + new_sl = current - distance + if new_sl - pos["sl"] >= step: + bridge.modify_position(ticket, sl=new_sl) + else: # 空单 + new_sl = current + distance + if pos["sl"] - new_sl >= step: + bridge.modify_position(ticket, sl=new_sl) + +# 每秒跑一次 +while True: + for p in bridge.positions(): + trail_stop(p["ticket"], distance=50, step=10) + time.sleep(1) +``` + +也可以用 WebSocket tick 流推送驱动,把 `time.sleep(1)` 换成 tick 回调,反应更快。 + +### 6-5. 批量平仓 + +``` +POST /positions/close-batch +``` + +按 `symbol` 和/或 `magic` 批量平仓。**至少传一个**过滤条件,避免误清整个账户。 + +```json +{ "magic": 123456 } +{ "symbol": "XAUUSDc", "magic": 123456 } +{ "symbol": "XAUUSDc" } +``` + +| 字段 | 必填 | 说明 | +|------|------|------| +| symbol | 一 | 品种过滤 | +| magic | 一 | Magic Number 过滤 | +| deviation | ❌ | 允许滑点(默认 10) | + +```python +def close_by_magic(magic): + return api_post("/positions/close-batch", {"magic": magic})["data"] + +result = close_by_magic(123456) +print(f"已平 {result['closed']} 单,失败 {result['failed']} 单") +# data 数组里有每张单的 ticket / symbol / retcode / comment +``` + --- -### 7. 挂单 +## 7. 挂单 ``` GET /orders?symbol={symbol} @@ -238,9 +529,43 @@ for o in orders: print(f"{o['ticket']} {o['symbol']} 类型:{o['type']} 手数:{o['volume_initial']}") ``` +### 7-1. 撤单 + +``` +POST /order/cancel +``` + +```json +{ "ticket": 87654321 } +``` + +```python +def cancel_order(ticket): + return api_post("/order/cancel", {"ticket": ticket})["data"] + +cancel_order(87654321) +``` + +### 7-2. 改挂单 + +``` +POST /order/modify +``` + +```json +{ "ticket": 87654321, "price": 4180.0, "sl": 4170.0, "tp": 4190.0 } +``` + +sl/tp 设为 0 表示清除。 + +```python +def modify_order(ticket, price, sl=0, tp=0): + return api_post("/order/modify", {"ticket": ticket, "price": price, "sl": sl, "tp": tp})["data"] +``` + --- -### 8. 订单预检 +## 8. 订单预检 ``` POST /order/check @@ -248,6 +573,8 @@ POST /order/check 下单前验证,不会真正执行。检查保证金是否足够、价格是否有效等。 +**填充模式自动适配**:服务端会根据品种的 `SYMBOL_FILLING_MODE` 自动选择经纪商支持的填充模式。如果请求的 `type_filling` 不被支持,会按 IOC(1) → FOK(0) → RETURN(2) 顺序降级,无需客户端手动判断。 + ```python def check_order(symbol, volume, order_type, price, sl=None, tp=None, magic=0, comment=""): """预检订单""" @@ -261,7 +588,8 @@ def check_order(symbol, volume, order_type, price, sl=None, tp=None, magic=0, co "tp": tp or 0, "magic": magic, "comment": comment, - "deviation": 10 + "deviation": 10, + "type_filling": 0 # 0=FOK, 1=IOC, 2=RETURN — 服务端自动适配,不传也行 } result = api_post("/order/check", data)["data"] print(f"预检结果: retcode={result['retcode']}, comment={result['comment']}") @@ -274,14 +602,26 @@ def check_order(symbol, volume, order_type, price, sl=None, tp=None, magic=0, co check_order("XAUUSD", 0.01, 0, 4180.0, sl=4170.0, tp=4190.0) ``` +**type_filling 说明:** + +| 值 | 含义 | 说明 | +|------|------|------| +| 0 | FOK (Fill or Kill) | 必须全部成交,否则取消 | +| 1 | IOC (Immediate or Cancel) | 能成交多少成交多少 | +| 2 | RETURN | 剩余部分留在订单簿 | + +> 不同经纪商支持的填充模式不同(如 ICMarkets 只支持 IOC),服务端会自动降级,客户端无需关心。 + --- -### 9. 下单 +## 9. 下单 ``` POST /order/send ``` +与 `/order/check` 相同,`type_filling` 会自动适配经纪商支持的填充模式。 + ```python def send_order(symbol, volume, order_type, price, sl=None, tp=None, magic=0, comment=""): """下单""" @@ -296,7 +636,8 @@ def send_order(symbol, volume, order_type, price, sl=None, tp=None, magic=0, com "tp": tp or 0, "magic": magic, "comment": comment, - "deviation": 10 + "deviation": 10, + "type_filling": 0 # 自动适配,不传也行 } } result = api_post("/order/send", data)["data"] @@ -320,7 +661,7 @@ result = send_order("XAUUSD", 0.01, 0, 4180.0, sl=4170.0, tp=4190.0) --- -### 10. 历史成交 +## 10. 历史成交 ``` GET /history/deals?date_from={from}&date_to={to}&symbol={symbol} @@ -340,7 +681,7 @@ for d in deals: --- -### 11. 全局变量(MQL5 信号桥) +## 11. 全局变量(MQL5 信号桥) > 让 MQL5 指标/EA 把信号写出来,Python 通过 Bridge 读取。不用翻译 MQL5 代码。 @@ -468,6 +809,25 @@ class Mt5Bridge: r.raise_for_status() return r.json() + def stream_ticks(self, symbol, on_tick): + """订阅 tick 推送,on_tick 回调收到 dict,阻塞运行。需 pip install websocket-client""" + import websocket + url = f"{BRIDGE.replace('http', 'ws', 1)}/stream/ticks/{symbol}" + ws = websocket.WebSocketApp( + url, + header=[f"X-API-Key: {KEY}"], + on_message=lambda ws, msg: on_tick(eval(msg)), + on_error=lambda ws, err: print(f"ws error: {err}"), + ) + ws.run_forever() + + def stream_ticks_async(self, symbol, on_tick): + """后台线程订阅 tick,不阻塞主线程""" + import threading + t = threading.Thread(target=self.stream_ticks, args=(symbol, on_tick), daemon=True) + t.start() + return t + # ── 行情 ── def tick(self, symbol): d = self._get(f"/symbols/{symbol}/tick")["data"][0] @@ -490,12 +850,37 @@ class Mt5Bridge: return self._get("/account")["data"][0] # ── 持仓 ── - def positions(self): - return self._get("/positions")["data"] + def positions(self, symbol=None): + return self._get("/positions", params={"symbol": symbol} if symbol else None)["data"] def has_position(self, symbol): return any(p["symbol"] == symbol for p in self.positions()) + def close(self, ticket, volume=None): + body = {"ticket": ticket} + if volume: body["volume"] = volume + return self._post("/position/close", body)["data"] + + def modify_position(self, ticket, sl=0, tp=0): + return self._post("/position/modify", {"ticket": ticket, "sl": sl, "tp": tp})["data"] + + def close_by(self, ticket_a, ticket_b): + return self._post("/position/close-by", {"position": ticket_a, "position_by": ticket_b})["data"] + + def close_batch(self, magic=None, symbol=None, deviation=None): + body = {k: v for k, v in {"magic": magic, "symbol": symbol, "deviation": deviation}.items() if v is not None} + return self._post("/positions/close-batch", body) + + # ── 挂单 ── + def orders(self, symbol=None): + return self._get("/orders", params={"symbol": symbol} if symbol else None)["data"] + + def cancel_order(self, ticket): + return self._post("/order/cancel", {"ticket": ticket})["data"] + + def modify_order(self, ticket, price, sl=0, tp=0): + return self._post("/order/modify", {"ticket": ticket, "price": price, "sl": sl, "tp": tp})["data"] + # ── 下单 ── def buy(self, symbol, volume, price, sl=0, tp=0, magic=0, comment=""): return self._send(symbol, volume, 0, price, sl, tp, magic, comment) diff --git a/Program.cs b/Program.cs index 36e6db9..5ad31c4 100644 --- a/Program.cs +++ b/Program.cs @@ -2,6 +2,10 @@ using MtApi5; using Microsoft.AspNetCore.Mvc; using System.Reflection; using System.Globalization; +using System.Collections.Concurrent; +using System.Net.WebSockets; +using System.Text; +using Newtonsoft.Json; var builder = WebApplication.CreateBuilder(args); builder.WebHost.UseUrls("http://0.0.0.0:8080"); @@ -42,6 +46,7 @@ builder.Services.AddCors(options => }); var app = builder.Build(); app.UseCors(); +app.UseWebSockets(); app.UseExceptionHandler(errorApp => { @@ -78,71 +83,59 @@ app.Use(async (context, next) => await next(); }); -app.MapGet("/health", async (MtApi5Client mt, SemaphoreSlim gate) => +app.MapGet("/health", (MtApi5Client mt) => { - await gate.WaitAsync(); - try - { - var connected = mt.ConnectionState == Mt5ConnectionState.Connected; - return connected - ? Results.Ok(new { status = "healthy", mt5_connected = true, mt5_version = "unknown", api_version = "1.0.0" }) - : Results.Json(new { status = "disconnected", mt5_connected = false, mt5_version = "unknown", api_version = "1.0.0" }, statusCode: StatusCodes.Status503ServiceUnavailable); - } - finally - { - gate.Release(); - } + var connected = mt.ConnectionState == Mt5ConnectionState.Connected; + return connected + ? Results.Ok(new { status = "healthy", mt5_connected = true, mt5_version = "unknown", api_version = "1.0.0" }) + : Results.Json(new { status = "disconnected", mt5_connected = false, mt5_version = "unknown", api_version = "1.0.0" }, statusCode: StatusCodes.Status503ServiceUnavailable); }); -app.MapGet("/account", async (MtApi5Client mt, SemaphoreSlim gate) => +app.MapGet("/account", (MtApi5Client mt) => { - await gate.WaitAsync(); - try - { - var login = (ulong)mt.AccountInfoInteger(ENUM_ACCOUNT_INFO_INTEGER.ACCOUNT_LOGIN); - var leverage = (uint)mt.AccountInfoInteger(ENUM_ACCOUNT_INFO_INTEGER.ACCOUNT_LEVERAGE); - var tradeAllowed = mt.AccountInfoInteger(ENUM_ACCOUNT_INFO_INTEGER.ACCOUNT_TRADE_ALLOWED) != 0; - var tradeExpert = mt.AccountInfoInteger(ENUM_ACCOUNT_INFO_INTEGER.ACCOUNT_TRADE_EXPERT) != 0; - var currency = mt.AccountInfoString(ENUM_ACCOUNT_INFO_STRING.ACCOUNT_CURRENCY) ?? "USD"; - var server = mt.AccountInfoString(ENUM_ACCOUNT_INFO_STRING.ACCOUNT_SERVER) ?? ""; - var name = mt.AccountInfoString(ENUM_ACCOUNT_INFO_STRING.ACCOUNT_NAME) ?? ""; - var company = mt.AccountInfoString(ENUM_ACCOUNT_INFO_STRING.ACCOUNT_COMPANY) ?? ""; - var balance = mt.AccountInfoDouble(ENUM_ACCOUNT_INFO_DOUBLE.ACCOUNT_BALANCE); - var equity = mt.AccountInfoDouble(ENUM_ACCOUNT_INFO_DOUBLE.ACCOUNT_EQUITY); - var profit = mt.AccountInfoDouble(ENUM_ACCOUNT_INFO_DOUBLE.ACCOUNT_PROFIT); - var margin = mt.AccountInfoDouble(ENUM_ACCOUNT_INFO_DOUBLE.ACCOUNT_MARGIN); - var marginFree = mt.AccountInfoDouble(ENUM_ACCOUNT_INFO_DOUBLE.ACCOUNT_MARGIN_FREE); - var marginLevel = mt.AccountInfoDouble(ENUM_ACCOUNT_INFO_DOUBLE.ACCOUNT_MARGIN_LEVEL); + var login = (ulong)mt.AccountInfoInteger(ENUM_ACCOUNT_INFO_INTEGER.ACCOUNT_LOGIN); + var leverage = (uint)mt.AccountInfoInteger(ENUM_ACCOUNT_INFO_INTEGER.ACCOUNT_LEVERAGE); + var tradeAllowed = mt.AccountInfoInteger(ENUM_ACCOUNT_INFO_INTEGER.ACCOUNT_TRADE_ALLOWED) != 0; + var tradeExpert = mt.AccountInfoInteger(ENUM_ACCOUNT_INFO_INTEGER.ACCOUNT_TRADE_EXPERT) != 0; + var currency = mt.AccountInfoString(ENUM_ACCOUNT_INFO_STRING.ACCOUNT_CURRENCY) ?? "USD"; + var server = mt.AccountInfoString(ENUM_ACCOUNT_INFO_STRING.ACCOUNT_SERVER) ?? ""; + var name = mt.AccountInfoString(ENUM_ACCOUNT_INFO_STRING.ACCOUNT_NAME) ?? ""; + var company = mt.AccountInfoString(ENUM_ACCOUNT_INFO_STRING.ACCOUNT_COMPANY) ?? ""; + var balance = mt.AccountInfoDouble(ENUM_ACCOUNT_INFO_DOUBLE.ACCOUNT_BALANCE); + var equity = mt.AccountInfoDouble(ENUM_ACCOUNT_INFO_DOUBLE.ACCOUNT_EQUITY); + var profit = mt.AccountInfoDouble(ENUM_ACCOUNT_INFO_DOUBLE.ACCOUNT_PROFIT); + var margin = mt.AccountInfoDouble(ENUM_ACCOUNT_INFO_DOUBLE.ACCOUNT_MARGIN); + var marginFree = mt.AccountInfoDouble(ENUM_ACCOUNT_INFO_DOUBLE.ACCOUNT_MARGIN_FREE); + var marginLevel = mt.AccountInfoDouble(ENUM_ACCOUNT_INFO_DOUBLE.ACCOUNT_MARGIN_LEVEL); - return Results.Ok(new + return Results.Ok(new + { + data = new[] { - data = new[] - { - new { login, leverage, trade_allowed = tradeAllowed, trade_expert = tradeExpert, currency, currency_digits = 2, server, name, company, balance, equity, profit, margin, margin_free = marginFree, margin_level = marginLevel } - }, - count = 1, - format = "json" - }); - } - finally - { - gate.Release(); - } + new { login, leverage, trade_allowed = tradeAllowed, trade_expert = tradeExpert, currency, currency_digits = 2, server, name, company, balance, equity, profit, margin, margin_free = marginFree, margin_level = marginLevel } + }, + count = 1, + format = "json" + }); }); -app.MapGet("/symbols/{symbol}", async (string symbol, MtApi5Client mt, SemaphoreSlim gate, ILoggerFactory loggerFactory) => +app.MapGet("/symbols/{symbol}", (string symbol, MtApi5Client mt, ILoggerFactory loggerFactory) => { if (string.IsNullOrWhiteSpace(symbol)) return Results.BadRequest(new { detail = "Symbol is required." }); - - await gate.WaitAsync(); try { + // ponytail: SymbolSelect(true) subscribes to MT5 quotes for this symbol — without it + // SymbolInfoDouble returns 0 for bid/ask until a tick arrives naturally. + mt.SymbolSelect(symbol, true); var digits = (int)mt.SymbolInfoInteger(symbol, ENUM_SYMBOL_INFO_INTEGER.SYMBOL_DIGITS); var spreadFloat = mt.SymbolInfoInteger(symbol, ENUM_SYMBOL_INFO_INTEGER.SYMBOL_SPREAD_FLOAT) != 0; var spread = (int)mt.SymbolInfoInteger(symbol, ENUM_SYMBOL_INFO_INTEGER.SYMBOL_SPREAD); var point = mt.SymbolInfoDouble(symbol, ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_POINT); - var bid = mt.SymbolInfoDouble(symbol, ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_BID); - var ask = mt.SymbolInfoDouble(symbol, ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_ASK); + double bid = 0, ask = 0; + var tickInfo = WaitForTick(mt, symbol); + if (tickInfo != null) { bid = tickInfo.bid; ask = tickInfo.ask; } + if (bid == 0) bid = mt.SymbolInfoDouble(symbol, ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_BID); + if (ask == 0) ask = mt.SymbolInfoDouble(symbol, ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_ASK); var volumeMin = mt.SymbolInfoDouble(symbol, ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_VOLUME_MIN); var volumeMax = mt.SymbolInfoDouble(symbol, ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_VOLUME_MAX); var volumeStep = mt.SymbolInfoDouble(symbol, ENUM_SYMBOL_INFO_DOUBLE.SYMBOL_VOLUME_STEP); @@ -169,56 +162,218 @@ app.MapGet("/symbols/{symbol}", async (string symbol, MtApi5Client mt, Semaphore loggerFactory.CreateLogger("SymbolsEndpoint").LogError(ex, "Failed to read symbol info for {Symbol}", symbol); return Results.Problem("Failed to read symbol info.", statusCode: StatusCodes.Status502BadGateway); } - finally - { - gate.Release(); - } }); -app.MapGet("/symbols/{symbol}/tick", async (string symbol, MtApi5Client mt, SemaphoreSlim gate) => +app.MapGet("/symbols/{symbol}/tick", (string symbol, MtApi5Client mt) => { if (string.IsNullOrWhiteSpace(symbol)) return Results.BadRequest(new { detail = "Symbol is required." }); - await gate.WaitAsync(); + mt.SymbolSelect(symbol, true); + var tick = WaitForTick(mt, symbol); + if (tick == null) return Results.NotFound(new { detail = $"Tick for {symbol} not found" }); + + return Results.Json(new + { + data = new[] + { + new + { + time = tick.time.ToString("yyyy-MM-ddTHH:mm:ss"), + bid = tick.bid, + ask = tick.ask, + last = tick.last, + volume = tick.volume, + time_msc = tick.time.ToString("yyyy-MM-ddTHH:mm:ss.fff000"), + flags = 6, + volume_real = tick.volume_real + } + }, + count = 1, + format = "json" + }); +}); + +// Tick stream via WebSocket. Connect: ws://host:8080/stream/ticks/{symbol} +// MT5 must be in Market Watch for the symbol; this endpoint auto-adds it on connect +// and removes it when the last subscriber disconnects. +app.Map("/stream/ticks/{symbol}", async (string symbol, HttpContext ctx, MtApi5Client mt, SemaphoreSlim gate, ILoggerFactory loggerFactory) => +{ + var logger = loggerFactory.CreateLogger("TickStream"); + if (string.IsNullOrWhiteSpace(symbol)) + { + ctx.Response.StatusCode = 400; + await ctx.Response.WriteAsJsonAsync(new { detail = "Symbol is required." }); + return; + } + if (!ctx.WebSockets.IsWebSocketRequest) + { + ctx.Response.StatusCode = 400; + await ctx.Response.WriteAsJsonAsync(new { detail = "WebSocket required. Use ws://.../stream/ticks/{symbol}." }); + return; + } + if (mt.ConnectionState != Mt5ConnectionState.Connected) + { + ctx.Response.StatusCode = 503; + await ctx.Response.WriteAsJsonAsync(new { detail = "MT5 is not connected." }); + return; + } + + await gate.WaitAsync(ctx.RequestAborted); try { - var tick = mt.SymbolInfoTick(symbol); - if (tick == null) return Results.NotFound(new { detail = $"Tick for {symbol} not found" }); - - return Results.Json(new + if (!mt.SymbolSelect(symbol, true)) { - data = new[] - { - new - { - time = tick.time.ToString("yyyy-MM-ddTHH:mm:ss"), - bid = tick.bid, - ask = tick.ask, - last = tick.last, - volume = tick.volume, - time_msc = tick.time.ToString("yyyy-MM-ddTHH:mm:ss.fff000"), - flags = 6, - volume_real = tick.volume_real - } - }, - count = 1, - format = "json" - }); + ctx.Response.StatusCode = 404; + await ctx.Response.WriteAsJsonAsync(new { detail = $"Symbol '{symbol}' not found." }); + return; + } } finally { gate.Release(); } + + var subs = MtConnectionService.TickSubscribers.GetOrAdd(symbol, _ => new ConcurrentDictionary()); + if (subs.Count >= MtConnectionService.MaxSubscribersPerSymbol) + { + ctx.Response.StatusCode = 429; + await ctx.Response.WriteAsJsonAsync(new { detail = $"Too many subscribers for {symbol} (limit={MtConnectionService.MaxSubscribersPerSymbol})." }); + return; + } + + using var ws = await ctx.WebSockets.AcceptWebSocketAsync(); + var subscriber = new WsSubscriber(ws); + subs[subscriber] = 1; + logger.LogInformation("Tick stream subscribed for {Symbol} via WS (subscribers={Count})", symbol, subs.Count); + + var buf = new byte[1024]; + try + { + while (ws.State == WebSocketState.Open && !ctx.RequestAborted.IsCancellationRequested) + { + var result = await ws.ReceiveAsync(buf, ctx.RequestAborted); + if (result.MessageType == WebSocketMessageType.Close) + { + await ws.CloseAsync(WebSocketCloseStatus.NormalClosure, "bye", CancellationToken.None); + break; + } + } + } + catch (OperationCanceledException) { } + catch (WebSocketException) { } + finally + { + subs.TryRemove(subscriber, out _); + MtConnectionService.TickSubscribers.TryRemove(symbol, out _); + if (subs.IsEmpty) + { + try + { + if (mt.ConnectionState == Mt5ConnectionState.Connected) + { + await gate.WaitAsync(); + try { mt.SymbolSelect(symbol, false); } + finally { gate.Release(); } + } + } + catch (Exception ex) { logger.LogWarning(ex, "Failed to remove {Symbol} from Market Watch", symbol); } + } + logger.LogInformation("Tick stream disconnected for {Symbol} via WS (remaining={Count})", symbol, subs.Count); + } }); -app.MapGet("/rates/from-pos", async (string symbol, string timeframe, int start_pos, int count, MtApi5Client mt, SemaphoreSlim gate, ILoggerFactory loggerFactory) => +// Tick stream via Server-Sent Events. Same semantics as /stream/ticks/{symbol}, +// one-way push over HTTP for clients that can't open a WebSocket. +// ponytail: SSE = no receive loop, just keep the response open and let the broadcast +// loop (OnQuoteUpdate + heartbeat timer) push data frames. +app.MapGet("/stream/ticks-sse/{symbol}", async (string symbol, HttpContext ctx, MtApi5Client mt, SemaphoreSlim gate, ILoggerFactory loggerFactory) => +{ + var logger = loggerFactory.CreateLogger("TickStream"); + if (string.IsNullOrWhiteSpace(symbol)) + { + ctx.Response.StatusCode = 400; + await ctx.Response.WriteAsJsonAsync(new { detail = "Symbol is required." }); + return; + } + if (mt.ConnectionState != Mt5ConnectionState.Connected) + { + ctx.Response.StatusCode = 503; + await ctx.Response.WriteAsJsonAsync(new { detail = "MT5 is not connected." }); + return; + } + + await gate.WaitAsync(ctx.RequestAborted); + try + { + if (!mt.SymbolSelect(symbol, true)) + { + ctx.Response.StatusCode = 404; + await ctx.Response.WriteAsJsonAsync(new { detail = $"Symbol '{symbol}' not found." }); + return; + } + } + finally + { + gate.Release(); + } + + var subs = MtConnectionService.TickSubscribers.GetOrAdd(symbol, _ => new ConcurrentDictionary()); + if (subs.Count >= MtConnectionService.MaxSubscribersPerSymbol) + { + ctx.Response.StatusCode = 429; + await ctx.Response.WriteAsJsonAsync(new { detail = $"Too many subscribers for {symbol} (limit={MtConnectionService.MaxSubscribersPerSymbol})." }); + return; + } + + ctx.Response.StatusCode = 200; + ctx.Response.ContentType = "text/event-stream"; + ctx.Response.Headers.CacheControl = "no-cache"; + ctx.Response.Headers.Connection = "keep-alive"; + ctx.Response.Headers["X-Accel-Buffering"] = "no"; // disable nginx buffering + + var subscriber = new SseSubscriber(ctx.Response.Body); + subs[subscriber] = 1; + logger.LogInformation("Tick stream subscribed for {Symbol} via SSE (subscribers={Count})", symbol, subs.Count); + + try + { + // Initial comment to flush headers and confirm connection + await ctx.Response.WriteAsync(": connected\n\n", ctx.RequestAborted); + await ctx.Response.Body.FlushAsync(ctx.RequestAborted); + + // Hold the request open until client disconnects; ticks/heartbeats arrive via OnQuoteUpdate + timer. + await Task.Delay(Timeout.Infinite, ctx.RequestAborted); + } + catch (OperationCanceledException) { } + catch (Exception ex) { logger.LogDebug(ex, "SSE stream ended for {Symbol}", symbol); } + finally + { + subs.TryRemove(subscriber, out _); + MtConnectionService.TickSubscribers.TryRemove(symbol, out _); + if (subs.IsEmpty) + { + try + { + if (mt.ConnectionState == Mt5ConnectionState.Connected) + { + await gate.WaitAsync(); + try { mt.SymbolSelect(symbol, false); } + finally { gate.Release(); } + } + } + catch (Exception ex) { logger.LogWarning(ex, "Failed to remove {Symbol} from Market Watch", symbol); } + } + logger.LogInformation("Tick stream disconnected for {Symbol} via SSE (remaining={Count})", symbol, subs.Count); + } +}); + +app.MapGet("/rates/from-pos", (string symbol, string timeframe, int start_pos, int count, MtApi5Client mt, ILoggerFactory loggerFactory) => { if (string.IsNullOrWhiteSpace(symbol)) return Results.BadRequest(new { detail = "Symbol is required." }); if (!TryParseTimeframe(timeframe, out var tf)) return Results.BadRequest(new { detail = $"Unsupported timeframe '{timeframe}'." }); if (start_pos < 0) return Results.BadRequest(new { detail = "start_pos must be greater than or equal to 0." }); if (count <= 0 || count > 10000) return Results.BadRequest(new { detail = "count must be between 1 and 10000." }); - await gate.WaitAsync(); try { const int chunkSize = 1000; @@ -230,7 +385,6 @@ app.MapGet("/rates/from-pos", async (string symbol, string timeframe, int start_ { int chunk = Math.Min(remaining, chunkSize); var result = mt.CopyRates(symbol, tf, currentPos, chunk, out MqlRates[]? rates); - Console.WriteLine($"CopyRates pos={currentPos} chunk={chunk} result={result}, rates={(rates != null ? rates.Length.ToString() : "null")}"); if (rates != null && rates.Length > 0) { @@ -264,79 +418,102 @@ app.MapGet("/rates/from-pos", async (string symbol, string timeframe, int start_ loggerFactory.CreateLogger("RatesEndpoint").LogError(ex, "Failed to read rates for {Symbol} {Timeframe}", symbol, timeframe); return Results.Problem("Failed to read rates.", statusCode: StatusCodes.Status502BadGateway); } - finally +}); + +app.MapGet("/rates/from-date", (string symbol, string timeframe, string date_from, string date_to, MtApi5Client mt, ILoggerFactory loggerFactory) => +{ + if (string.IsNullOrWhiteSpace(symbol)) return Results.BadRequest(new { detail = "Symbol is required." }); + if (!TryParseTimeframe(timeframe, out var tf)) return Results.BadRequest(new { detail = $"Unsupported timeframe '{timeframe}'." }); + if (!TryParseClientDate(date_from, out var fromDate)) return Results.BadRequest(new { detail = "date_from must be a valid ISO-8601 or yyyy-MM-dd value." }); + if (!TryParseClientDate(date_to, out var toDate)) return Results.BadRequest(new { detail = "date_to must be a valid ISO-8601 or yyyy-MM-dd value." }); + if (fromDate > toDate) return Results.BadRequest(new { detail = "date_from must be earlier than or equal to date_to." }); + + try { - gate.Release(); + // ponytail: Bars(from, to) is half-open [from, to). Same-day query would yield 0 + // without this nudge — bump toDate by one day to include the entire end day. + var effectiveTo = (toDate.Date == fromDate.Date) ? toDate.Date.AddDays(1) : toDate; + + var total = mt.Bars(symbol, tf, fromDate, effectiveTo); + if (total <= 0) return Results.Ok(new { data = Array.Empty(), count = 0, format = "json" }); + if (total > 10000) return Results.BadRequest(new { detail = $"Date range covers {total} bars (max 10000). Narrow the range." }); + + var result = mt.CopyRates(symbol, tf, total - 1, total, out MqlRates[]? rates); + if (rates == null || rates.Length == 0) return Results.Ok(new { data = Array.Empty(), count = 0, format = "json" }); + + var data = rates.Select(r => new + { + time = r.time.ToString("yyyy-MM-ddTHH:mm:ss"), + r.open, + r.high, + r.low, + r.close, + tick_volume = r.tick_volume, + r.spread, + real_volume = r.real_volume + }).ToArray(); + return Results.Ok(new { data, count = data.Length, format = "json" }); + } + catch (Exception ex) + { + loggerFactory.CreateLogger("RatesFromDateEndpoint").LogError(ex, "Failed to read rates for {Symbol} {Timeframe} {DateFrom}~{DateTo}", symbol, timeframe, date_from, date_to); + return Results.Problem("Failed to read rates.", statusCode: StatusCodes.Status502BadGateway); } }); -app.MapGet("/positions", async (MtApi5Client mt, SemaphoreSlim gate) => +app.MapGet("/positions", (string? symbol, MtApi5Client mt) => { - await gate.WaitAsync(); - try + var total = mt.PositionsTotal(); + var positions = new List(); + for (int i = 0; i < total; i++) { - var total = mt.PositionsTotal(); - var positions = new List(); - for (int i = 0; i < total; i++) + var ticket = mt.PositionGetTicket(i); + if (ticket == 0) continue; + var posSymbol = mt.PositionGetString(ENUM_POSITION_PROPERTY_STRING.POSITION_SYMBOL); + if (!string.IsNullOrWhiteSpace(symbol) && posSymbol != symbol) continue; + positions.Add(new { - var ticket = mt.PositionGetTicket(i); - if (ticket == 0) continue; - positions.Add(new - { - ticket, - symbol = mt.PositionGetString(ENUM_POSITION_PROPERTY_STRING.POSITION_SYMBOL), - type = (int)mt.PositionGetInteger(ENUM_POSITION_PROPERTY_INTEGER.POSITION_TYPE), - volume = mt.PositionGetDouble(ENUM_POSITION_PROPERTY_DOUBLE.POSITION_VOLUME), - price_open = mt.PositionGetDouble(ENUM_POSITION_PROPERTY_DOUBLE.POSITION_PRICE_OPEN), - sl = mt.PositionGetDouble(ENUM_POSITION_PROPERTY_DOUBLE.POSITION_SL), - tp = mt.PositionGetDouble(ENUM_POSITION_PROPERTY_DOUBLE.POSITION_TP), - price_current = mt.PositionGetDouble(ENUM_POSITION_PROPERTY_DOUBLE.POSITION_PRICE_CURRENT), - swap = mt.PositionGetDouble(ENUM_POSITION_PROPERTY_DOUBLE.POSITION_SWAP), - profit = mt.PositionGetDouble(ENUM_POSITION_PROPERTY_DOUBLE.POSITION_PROFIT), - comment = mt.PositionGetString(ENUM_POSITION_PROPERTY_STRING.POSITION_COMMENT), - magic = (ulong)mt.PositionGetInteger(ENUM_POSITION_PROPERTY_INTEGER.POSITION_MAGIC) - }); - } - return Results.Ok(new { data = positions, count = positions.Count, format = "json" }); - } - finally - { - gate.Release(); + ticket, + symbol = posSymbol, + type = (int)mt.PositionGetInteger(ENUM_POSITION_PROPERTY_INTEGER.POSITION_TYPE), + volume = mt.PositionGetDouble(ENUM_POSITION_PROPERTY_DOUBLE.POSITION_VOLUME), + price_open = mt.PositionGetDouble(ENUM_POSITION_PROPERTY_DOUBLE.POSITION_PRICE_OPEN), + sl = mt.PositionGetDouble(ENUM_POSITION_PROPERTY_DOUBLE.POSITION_SL), + tp = mt.PositionGetDouble(ENUM_POSITION_PROPERTY_DOUBLE.POSITION_TP), + price_current = mt.PositionGetDouble(ENUM_POSITION_PROPERTY_DOUBLE.POSITION_PRICE_CURRENT), + swap = mt.PositionGetDouble(ENUM_POSITION_PROPERTY_DOUBLE.POSITION_SWAP), + profit = mt.PositionGetDouble(ENUM_POSITION_PROPERTY_DOUBLE.POSITION_PROFIT), + comment = mt.PositionGetString(ENUM_POSITION_PROPERTY_STRING.POSITION_COMMENT), + magic = (ulong)mt.PositionGetInteger(ENUM_POSITION_PROPERTY_INTEGER.POSITION_MAGIC) + }); } + return Results.Ok(new { data = positions, count = positions.Count, format = "json" }); }); -app.MapGet("/orders", async (string? symbol, MtApi5Client mt, SemaphoreSlim gate) => +app.MapGet("/orders", (string? symbol, MtApi5Client mt) => { - await gate.WaitAsync(); - try + var total = mt.OrdersTotal(); + var orders = new List(); + for (int i = 0; i < total; i++) { - var total = mt.OrdersTotal(); - var orders = new List(); - for (int i = 0; i < total; i++) + var ticket = mt.OrderGetTicket(i); + if (ticket == 0) continue; + var orderSymbol = mt.OrderGetString(ENUM_ORDER_PROPERTY_STRING.ORDER_SYMBOL); + if (!string.IsNullOrWhiteSpace(symbol) && orderSymbol != symbol) continue; + orders.Add(new { - var ticket = mt.OrderGetTicket(i); - if (ticket == 0) continue; - var orderSymbol = mt.OrderGetString(ENUM_ORDER_PROPERTY_STRING.ORDER_SYMBOL); - if (!string.IsNullOrWhiteSpace(symbol) && orderSymbol != symbol) continue; - orders.Add(new - { - ticket, - symbol = orderSymbol, - type = (int)mt.OrderGetInteger(ENUM_ORDER_PROPERTY_INTEGER.ORDER_TYPE), - volume_initial = mt.OrderGetDouble(ENUM_ORDER_PROPERTY_DOUBLE.ORDER_VOLUME_INITIAL), - price_open = mt.OrderGetDouble(ENUM_ORDER_PROPERTY_DOUBLE.ORDER_PRICE_OPEN), - sl = mt.OrderGetDouble(ENUM_ORDER_PROPERTY_DOUBLE.ORDER_SL), - tp = mt.OrderGetDouble(ENUM_ORDER_PROPERTY_DOUBLE.ORDER_TP), - magic = (ulong)mt.OrderGetInteger(ENUM_ORDER_PROPERTY_INTEGER.ORDER_MAGIC), - comment = mt.OrderGetString(ENUM_ORDER_PROPERTY_STRING.ORDER_COMMENT) - }); - } - return Results.Ok(new { data = orders, count = orders.Count, format = "json" }); - } - finally - { - gate.Release(); + ticket, + symbol = orderSymbol, + type = (int)mt.OrderGetInteger(ENUM_ORDER_PROPERTY_INTEGER.ORDER_TYPE), + volume_initial = mt.OrderGetDouble(ENUM_ORDER_PROPERTY_DOUBLE.ORDER_VOLUME_INITIAL), + price_open = mt.OrderGetDouble(ENUM_ORDER_PROPERTY_DOUBLE.ORDER_PRICE_OPEN), + sl = mt.OrderGetDouble(ENUM_ORDER_PROPERTY_DOUBLE.ORDER_SL), + tp = mt.OrderGetDouble(ENUM_ORDER_PROPERTY_DOUBLE.ORDER_TP), + magic = (ulong)mt.OrderGetInteger(ENUM_ORDER_PROPERTY_INTEGER.ORDER_MAGIC), + comment = mt.OrderGetString(ENUM_ORDER_PROPERTY_STRING.ORDER_COMMENT) + }); } + return Results.Ok(new { data = orders, count = orders.Count, format = "json" }); }); app.MapPost("/order/check", async (TradeRequestDto body, MtApi5Client mt, SemaphoreSlim gate) => @@ -344,6 +521,7 @@ app.MapPost("/order/check", async (TradeRequestDto body, MtApi5Client mt, Semaph var validationError = ValidateTradeRequest(body); if (validationError != null) return Results.BadRequest(new { detail = validationError }); + body.type_filling = (uint)ResolveFillingMode(mt, body.symbol, body.type_filling ?? 0); var request = ToMqlTradeRequest(body); await gate.WaitAsync(); try @@ -363,6 +541,7 @@ app.MapPost("/order/send", async (TradeRequestBody body, MtApi5Client mt, Semaph var validationError = ValidateTradeRequest(body.request); if (validationError != null) return Results.BadRequest(new { detail = validationError }); + body.request.type_filling = (uint)ResolveFillingMode(mt, body.request.symbol, body.request.type_filling ?? 0); var request = ToMqlTradeRequest(body.request); await gate.WaitAsync(); try @@ -377,88 +556,234 @@ app.MapPost("/order/send", async (TradeRequestBody body, MtApi5Client mt, Semaph } }); -app.MapGet("/history/deals", async (string date_from, string date_to, string? symbol, MtApi5Client mt, SemaphoreSlim gate) => +app.MapPost("/position/close", async (ClosePositionDto body, MtApi5Client mt, SemaphoreSlim gate) => +{ + if (body == null || body.ticket == 0) return Results.BadRequest(new { detail = "ticket is required." }); + await gate.WaitAsync(); + try + { + bool ok; + if (body.volume is > 0) + { + // ponytail: PositionClosePartial has no MqlTradeResult overload — return bool only. + ok = mt.PositionClosePartial(body.ticket, body.volume.Value, body.deviation ?? 10); + } + else + { + mt.PositionClose(body.ticket, body.deviation ?? 10, out MqlTradeResult? result); + if (result == null) return Results.Ok(new { data = new { retcode = 0u, order = 0ul, comment = "Close failed" }, count = 1, format = "json" }); + return Results.Ok(new { data = new { retcode = result.Retcode, order = result.Order, comment = result.Comment ?? "" }, count = 1, format = "json" }); + } + return Results.Ok(new + { + data = new { retcode = ok ? 10009u : 10004u, order = body.ticket, comment = ok ? (body.volume is > 0 ? "Partial closed" : "Closed") : "Close failed" }, + count = 1, + format = "json" + }); + } + finally + { + gate.Release(); + } +}); + +app.MapPost("/position/modify", async (ModifyPositionDto body, MtApi5Client mt, SemaphoreSlim gate) => +{ + if (body == null || body.ticket == 0) return Results.BadRequest(new { detail = "ticket is required." }); + if (body.sl < 0 || body.tp < 0) return Results.BadRequest(new { detail = "sl/tp must be non-negative." }); + await gate.WaitAsync(); + try + { + // ponytail: MtApi5 PositionModify returns bool, no MqlTradeResult — pack into our uniform envelope. + var ok = mt.PositionModify(body.ticket, body.sl, body.tp); + return Results.Ok(new + { + data = new { retcode = ok ? 10009u : 10004u, order = body.ticket, comment = ok ? "Modified" : "Modify failed" }, + count = 1, + format = "json" + }); + } + finally + { + gate.Release(); + } +}); + +app.MapPost("/order/cancel", async (OrderTicketDto body, MtApi5Client mt, SemaphoreSlim gate) => +{ + if (body == null || body.ticket == 0) return Results.BadRequest(new { detail = "ticket is required." }); + await gate.WaitAsync(); + try + { + // ponytail: MtApi5 has no OrderDelete — reuse OrderSend with TRADE_ACTION_REMOVE. + var req = new MqlTradeRequest + { + Action = ENUM_TRADE_REQUEST_ACTIONS.TRADE_ACTION_REMOVE, + Order = body.ticket, + }; + mt.OrderSend(req, out MqlTradeResult? result); + if (result == null) return Results.Ok(new { data = new { retcode = 0u, order = 0ul, comment = "Cancel failed" }, count = 1, format = "json" }); + return Results.Ok(new { data = new { retcode = result.Retcode, order = result.Order, comment = result.Comment ?? "" }, count = 1, format = "json" }); + } + finally + { + gate.Release(); + } +}); + +app.MapPost("/position/close-by", async (CloseByDto body, MtApi5Client mt, SemaphoreSlim gate) => +{ + if (body == null || body.position == 0 || body.position_by == 0) + return Results.BadRequest(new { detail = "position and position_by are required." }); + await gate.WaitAsync(); + try + { + // ponytail: TRADE_ACTION_CLOSE_BY lets MT5 net two opposite positions instead of + // two separate market closes — saves one side of the spread. + var req = new MqlTradeRequest + { + Action = ENUM_TRADE_REQUEST_ACTIONS.TRADE_ACTION_CLOSE_BY, + Position = body.position, + PositionBy = body.position_by, + }; + mt.OrderSend(req, out MqlTradeResult? result); + if (result == null) return Results.Ok(new { data = new { retcode = 0u, order = 0ul, comment = "Close-by failed" }, count = 1, format = "json" }); + return Results.Ok(new { data = new { retcode = result.Retcode, order = result.Order, comment = result.Comment ?? "" }, count = 1, format = "json" }); + } + finally + { + gate.Release(); + } +}); + +app.MapPost("/positions/close-batch", async (BatchCloseDto body, MtApi5Client mt, SemaphoreSlim gate, ILoggerFactory loggerFactory) => +{ + if (body == null || (string.IsNullOrWhiteSpace(body.symbol) && body.magic == null)) + return Results.BadRequest(new { detail = "At least one of `symbol` or `magic` is required." }); + + var logger = loggerFactory.CreateLogger("BatchClose"); + var results = new List(); + int closed = 0, failed = 0; + // ponytail: hold the gate for the whole batch — one logical op, brief duration. + // Clients wanting concurrent writes should not use batch close. + await gate.WaitAsync(); + try + { + var total = mt.PositionsTotal(); + for (int i = 0; i < total; i++) + { + var ticket = mt.PositionGetTicket(i); + if (ticket == 0) continue; + var posSymbol = mt.PositionGetString(ENUM_POSITION_PROPERTY_STRING.POSITION_SYMBOL); + if (!string.IsNullOrWhiteSpace(body.symbol) && posSymbol != body.symbol) continue; + if (body.magic is ulong m && mt.PositionGetInteger(ENUM_POSITION_PROPERTY_INTEGER.POSITION_MAGIC) != (long)m) continue; + + mt.PositionClose(ticket, body.deviation ?? 10, out MqlTradeResult? result); + if (result != null && result.Retcode == 10009) + { + closed++; + results.Add(new { ticket, symbol = posSymbol, retcode = result.Retcode, comment = "closed" }); + } + else + { + failed++; + var comment = result?.Comment ?? "unknown"; + logger.LogWarning("Batch close failed for ticket {Ticket} ({Symbol}): {Comment}", ticket, posSymbol, comment); + results.Add(new { ticket, symbol = posSymbol, retcode = result?.Retcode ?? 0u, comment }); + } + } + return Results.Ok(new { data = results, count = results.Count, closed, failed, format = "json" }); + } + finally + { + gate.Release(); + } +}); + +app.MapPost("/order/modify", async (ModifyOrderDto body, MtApi5Client mt, SemaphoreSlim gate) => +{ + if (body == null || body.ticket == 0) return Results.BadRequest(new { detail = "ticket is required." }); + if (body.price <= 0) return Results.BadRequest(new { detail = "price must be positive." }); + if (body.sl < 0 || body.tp < 0) return Results.BadRequest(new { detail = "sl/tp must be non-negative." }); + await gate.WaitAsync(); + try + { + var req = new MqlTradeRequest + { + Action = ENUM_TRADE_REQUEST_ACTIONS.TRADE_ACTION_MODIFY, + Order = body.ticket, + Price = body.price, + Sl = body.sl, + Tp = body.tp, + }; + mt.OrderSend(req, out MqlTradeResult? result); + if (result == null) return Results.Ok(new { data = new { retcode = 0u, order = 0ul, comment = "Modify failed" }, count = 1, format = "json" }); + return Results.Ok(new { data = new { retcode = result.Retcode, order = result.Order, comment = result.Comment ?? "" }, count = 1, format = "json" }); + } + finally + { + gate.Release(); + } +}); + +app.MapGet("/history/deals", (string date_from, string date_to, string? symbol, MtApi5Client mt) => { if (!TryParseClientDate(date_from, out var fromDt) || !TryParseClientDate(date_to, out var toDt)) return Results.BadRequest(new { detail = "date_from and date_to must be valid ISO-8601 or yyyy-MM-dd values." }); if (fromDt > toDt) return Results.BadRequest(new { detail = "date_from must be earlier than or equal to date_to." }); - await gate.WaitAsync(); - try + mt.HistorySelect(fromDt, toDt); + var total = mt.HistoryDealsTotal(); + var dealList = new List(); + for (int i = 0; i < total; i++) { - mt.HistorySelect(fromDt, toDt); - var total = mt.HistoryDealsTotal(); - var dealList = new List(); - for (int i = 0; i < total; i++) + var ticket = mt.HistoryDealGetTicket(i); + if (ticket == 0) continue; + var dealSymbol = mt.HistoryDealGetString(ticket, ENUM_DEAL_PROPERTY_STRING.DEAL_SYMBOL); + if (!string.IsNullOrWhiteSpace(symbol) && dealSymbol != symbol) continue; + var dealTime = MtTimeToDateTime(mt.HistoryDealGetInteger(ticket, ENUM_DEAL_PROPERTY_INTEGER.DEAL_TIME)); + dealList.Add(new { - var ticket = mt.HistoryDealGetTicket(i); - if (ticket == 0) continue; - var dealSymbol = mt.HistoryDealGetString(ticket, ENUM_DEAL_PROPERTY_STRING.DEAL_SYMBOL); - if (!string.IsNullOrWhiteSpace(symbol) && dealSymbol != symbol) continue; - var dealTime = MtTimeToDateTime(mt.HistoryDealGetInteger(ticket, ENUM_DEAL_PROPERTY_INTEGER.DEAL_TIME)); - dealList.Add(new - { - ticket, - time = dealTime.ToString("yyyy-MM-ddTHH:mm:ss"), - entry = (int)mt.HistoryDealGetInteger(ticket, ENUM_DEAL_PROPERTY_INTEGER.DEAL_ENTRY), - magic = (ulong)mt.HistoryDealGetInteger(ticket, ENUM_DEAL_PROPERTY_INTEGER.DEAL_MAGIC), - volume = mt.HistoryDealGetDouble(ticket, ENUM_DEAL_PROPERTY_DOUBLE.DEAL_VOLUME), - price = mt.HistoryDealGetDouble(ticket, ENUM_DEAL_PROPERTY_DOUBLE.DEAL_PRICE), - profit = mt.HistoryDealGetDouble(ticket, ENUM_DEAL_PROPERTY_DOUBLE.DEAL_PROFIT), - commission = mt.HistoryDealGetDouble(ticket, ENUM_DEAL_PROPERTY_DOUBLE.DEAL_COMMISSION), - swap = mt.HistoryDealGetDouble(ticket, ENUM_DEAL_PROPERTY_DOUBLE.DEAL_SWAP), - symbol = dealSymbol, - comment = mt.HistoryDealGetString(ticket, ENUM_DEAL_PROPERTY_STRING.DEAL_COMMENT) ?? "" - }); - } - return Results.Ok(new { data = dealList, count = dealList.Count, format = "json" }); - } - finally - { - gate.Release(); + ticket, + time = dealTime.ToString("yyyy-MM-ddTHH:mm:ss"), + entry = (int)mt.HistoryDealGetInteger(ticket, ENUM_DEAL_PROPERTY_INTEGER.DEAL_ENTRY), + magic = (ulong)mt.HistoryDealGetInteger(ticket, ENUM_DEAL_PROPERTY_INTEGER.DEAL_MAGIC), + volume = mt.HistoryDealGetDouble(ticket, ENUM_DEAL_PROPERTY_DOUBLE.DEAL_VOLUME), + price = mt.HistoryDealGetDouble(ticket, ENUM_DEAL_PROPERTY_DOUBLE.DEAL_PRICE), + profit = mt.HistoryDealGetDouble(ticket, ENUM_DEAL_PROPERTY_DOUBLE.DEAL_PROFIT), + commission = mt.HistoryDealGetDouble(ticket, ENUM_DEAL_PROPERTY_DOUBLE.DEAL_COMMISSION), + swap = mt.HistoryDealGetDouble(ticket, ENUM_DEAL_PROPERTY_DOUBLE.DEAL_SWAP), + symbol = dealSymbol, + comment = mt.HistoryDealGetString(ticket, ENUM_DEAL_PROPERTY_STRING.DEAL_COMMENT) ?? "" + }); } + return Results.Ok(new { data = dealList, count = dealList.Count, format = "json" }); }); -app.MapGet("/gvar", async (HttpContext context, SemaphoreSlim gate) => +app.MapGet("/gvar", (HttpContext context) => { var mt = context.RequestServices.GetRequiredService(); - await gate.WaitAsync(); - try + var total = mt.GlobalVariablesTotal(); + var vars = new List(); + for (int i = 0; i < total; i++) { - var total = mt.GlobalVariablesTotal(); - var vars = new List(); - for (int i = 0; i < total; i++) - { - var name = mt.GlobalVariableName(i) ?? ""; - var value = mt.GlobalVariableGet(name); - vars.Add(new { name, value }); - } - return Results.Ok(new { data = vars, count = vars.Count, format = "json" }); - } - finally - { - gate.Release(); + var name = mt.GlobalVariableName(i) ?? ""; + var value = mt.GlobalVariableGet(name); + vars.Add(new { name, value }); } + return Results.Ok(new { data = vars, count = vars.Count, format = "json" }); }); -app.MapGet("/gvar/{name}", async (HttpContext context, string name, SemaphoreSlim gate) => +app.MapGet("/gvar/{name}", (HttpContext context, string name) => { if (string.IsNullOrWhiteSpace(name)) return Results.BadRequest(new { detail = "Global variable name is required." }); var mt = context.RequestServices.GetRequiredService(); - await gate.WaitAsync(); - try - { - if (!mt.GlobalVariableCheck(name)) - return Results.NotFound(new { detail = $"GlobalVariable '{name}' not found" }); - var value = mt.GlobalVariableGet(name); - return Results.Ok(new { name, value }); - } - finally - { - gate.Release(); - } + if (!mt.GlobalVariableCheck(name)) + return Results.NotFound(new { detail = $"GlobalVariable '{name}' not found" }); + var value = mt.GlobalVariableGet(name); + return Results.Ok(new { name, value }); }); app.MapPost("/gvar/{name}", async (HttpContext context, string name, SemaphoreSlim gate) => @@ -530,6 +855,45 @@ bool TryParseClientDate(string value, out DateTime parsed) || DateTime.TryParseExact(value, "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out parsed); } +MqlTick? WaitForTick(MtApi5Client mt, string symbol, int timeoutMs = 3000) +{ + for (int i = 0; i < timeoutMs / 100; i++) + { + var tick = mt.SymbolInfoTick(symbol); + if (tick != null && tick.bid > 0) return tick; + Thread.Sleep(100); + } + return mt.SymbolInfoTick(symbol); +} + +uint ResolveFillingMode(MtApi5Client mt, string symbol, uint requestedFilling) +{ + try + { + var modeFlags = (long)mt.SymbolInfoInteger(symbol, ENUM_SYMBOL_INFO_INTEGER.SYMBOL_FILLING_MODE); + bool fokSupported = (modeFlags & 1) != 0; + bool iocSupported = (modeFlags & 2) != 0; + + bool requestedSupported = requestedFilling switch + { + 0 => fokSupported, + 1 => iocSupported, + 2 => true, + _ => false + }; + + if (requestedSupported) return requestedFilling; + + if (iocSupported) return 1; + if (fokSupported) return 0; + return 2; + } + catch + { + return requestedFilling; + } +} + string? ValidateTradeRequest(TradeRequestDto request) { if (!Enum.IsDefined(typeof(ENUM_TRADE_REQUEST_ACTIONS), (int)request.action)) @@ -567,7 +931,9 @@ MqlTradeRequest ToMqlTradeRequest(TradeRequestDto r) Comment = r.comment ?? "", Order = r.order ?? 0, Position = r.position ?? 0, - Deviation = r.deviation ?? 0 + Deviation = r.deviation ?? 0, + Type_filling = (ENUM_ORDER_TYPE_FILLING)(r.type_filling ?? 0), + Type_time = (ENUM_ORDER_TYPE_TIME)(r.type_time ?? 0), }; } @@ -585,6 +951,8 @@ class TradeRequestDto public ulong? order { get; set; } public ulong? position { get; set; } public ulong? deviation { get; set; } + public uint? type_filling { get; set; } // 0=FOK, 1=IOC, 2=RETURN — 经纪商常要求显式指定 + public uint? type_time { get; set; } // 0=GTC, 1=DAY, 2=SPECIFIED, 3=SPECIFIED_DAY } class TradeRequestBody @@ -597,18 +965,102 @@ class GvarSetDto public double value { get; set; } } +class ClosePositionDto +{ + public ulong ticket { get; set; } + public double? volume { get; set; } // null/0 = 全平;>0 = 部分平仓 + public ulong? deviation { get; set; } +} + +class ModifyPositionDto +{ + public ulong ticket { get; set; } + public double sl { get; set; } + public double tp { get; set; } +} + +class OrderTicketDto +{ + public ulong ticket { get; set; } +} + +class ModifyOrderDto +{ + public ulong ticket { get; set; } + public double price { get; set; } + public double sl { get; set; } + public double tp { get; set; } +} + +class CloseByDto +{ + public ulong position { get; set; } + public ulong position_by { get; set; } +} + +class BatchCloseDto +{ + public string? symbol { get; set; } + public ulong? magic { get; set; } + public ulong? deviation { get; set; } +} + +abstract class TickSubscriber +{ + public abstract ValueTask SendAsync(ReadOnlyMemory payload); + public abstract bool IsAlive { get; } +} + +sealed class WsSubscriber : TickSubscriber +{ + readonly WebSocket _ws; + public WsSubscriber(WebSocket ws) => _ws = ws; + public override bool IsAlive => _ws.State == WebSocketState.Open; + public override ValueTask SendAsync(ReadOnlyMemory payload) => + _ws.SendAsync(payload, WebSocketMessageType.Text, true, CancellationToken.None); +} + +sealed class SseSubscriber : TickSubscriber +{ + readonly Stream _stream; + static readonly byte[] Prefix = Encoding.UTF8.GetBytes("data: "); + static readonly byte[] Suffix = Encoding.UTF8.GetBytes("\n\n"); + public SseSubscriber(Stream stream) => _stream = stream; + public override bool IsAlive => _stream.CanWrite; + public override async ValueTask SendAsync(ReadOnlyMemory payload) + { + await _stream.WriteAsync(Prefix); + await _stream.WriteAsync(payload); + await _stream.WriteAsync(Suffix); + await _stream.FlushAsync(); + } +} + class MtConnectionService : BackgroundService { + // Tick subscribers, keyed by symbol name. Each value is the set of connected + // client sinks (WebSocket or SSE) listening to that symbol's tick stream. + public static readonly ConcurrentDictionary> TickSubscribers = new(); + public const int MaxSubscribersPerSymbol = 50; + private readonly MtApi5Client _client; private readonly ILogger _logger; private readonly TimeSpan _connectTimeout; private const int Port = 8228; + private static readonly TimeSpan HeartbeatInterval = TimeSpan.FromSeconds(30); + + private static readonly JsonSerializerSettings JsonSettings = new() + { + DateFormatString = "yyyy-MM-ddTHH:mm:ss", + Formatting = Formatting.None + }; public MtConnectionService(MtApi5Client client, ILogger logger) { _client = client; _logger = logger; _connectTimeout = TimeSpan.FromSeconds(15); + _client.QuoteUpdate += OnQuoteUpdate; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) @@ -677,4 +1129,51 @@ class MtConnectionService : BackgroundService _client.ConnectionStateChanged -= handler; } } -} + + private void OnQuoteUpdate(object? sender, Mt5QuoteEventArgs e) + { + if (!MtConnectionService.TickSubscribers.TryGetValue(e.Quote.Instrument, out var subs)) return; + var payload = JsonConvert.SerializeObject(new + { + type = "tick", + symbol = e.Quote.Instrument, + time = e.Quote.Time, + bid = e.Quote.Bid, + ask = e.Quote.Ask, + last = e.Quote.Last, + volume = e.Quote.Volume, + time_msc = e.Quote.Time.ToString("yyyy-MM-ddTHH:mm:ss.fff000"), + flags = 6 + }, JsonSettings); + var bytes = Encoding.UTF8.GetBytes(payload); + // ponytail: fire-and-forget. Slow clients get dropped by SendAsync fault; cleanup happens on disconnect. + foreach (var sub in subs.Keys) + { + if (sub.IsAlive) _ = sub.SendAsync(bytes); + } + } + + // ponytail: periodic heartbeat so clients behind NAT/firewall can detect liveness + // even on low-liquidity symbols with no ticks for minutes. + private static readonly byte[] HeartbeatPayload = Encoding.UTF8.GetBytes( + JsonConvert.SerializeObject(new { type = "heartbeat", time = DateTime.UtcNow })); + + private static void BroadcastHeartbeat(object? _) + { + foreach (var subs in TickSubscribers.Values) + { + foreach (var sub in subs.Keys) + { + if (sub.IsAlive) _ = sub.SendAsync(HeartbeatPayload); + } + } + } + + private readonly Timer _heartbeat = new(BroadcastHeartbeat, null, HeartbeatInterval, HeartbeatInterval); + + public override async Task StopAsync(CancellationToken cancellationToken) + { + await _heartbeat.DisposeAsync(); + await base.StopAsync(cancellationToken); + } +} \ No newline at end of file diff --git a/README.md.md b/README.md.md index 8c1f449..130ffdf 100644 --- a/README.md.md +++ b/README.md.md @@ -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}}' ``` --- diff --git a/__pycache__/test_all.cpython-312.pyc b/__pycache__/test_all.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f491b06b4b0bc84da37d06526d5286dde72eb0ca GIT binary patch literal 25006 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 literal 0 HcmV?d00001 diff --git a/bin/Release/net8.0/Mt5Bridge.dll b/bin/Release/net8.0/Mt5Bridge.dll index fb622b20fbaae91f3729cafd2172cf88537c2c78..48fc6e014d643f7cb76dfa4190a00be7b73f0864 100644 GIT binary patch literal 95744 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,rNES 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 literal 71680 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

P^RwL& z|AyOFJ0;t2udi>(&H#tj_Q-r4FY`OC@K4$O>g>@^1AZBNDLWT3A7|rP+NjK_P$#Lk z3aV60RG@^>P^4{)n35a>TAHmgueu^ zQMAogtJT=NIihnVzGWMm*CPDY!tWE#X5pMAoGp-?n73W{JA{9O@OKJlmv9~tPQT!9 z3vL*++-0z@3c*JU-YEEN!J7HFz*kFncf{zxw!DNq(!kKNJ1si7Lw?XoQD}~=8{MEu=E&M*=Zx;S`!FLFL zgUH+ z1ojIwEYTydQDBR}%>uVrw0Vc%y9D+NG(6HuV57hmftv+x_sA#&-zoSm!5{Td+aBTc z3rBfnEMCzjuu))(z|8`82;3#GU!dWmyxT`@Oje@TfyhZRn!8Z%OL*Oof z{Q?cY^e(VbV2i-b0=N5REQ0S8e3#&l`eiJ_=@*Vlm$9UaHi3--TLf+vxI^GBf&BuF z43QUDnL(Y6g0~3VEO2{<*dX{$!FLJ1NAUg(MyAS?-ZLdi1vUz75!jkZ&6@?^A#j(# ze(rQt%eR`vl)C_;y<+`#kmcf)>E93N{P8F`IgJ zW>dp1;p`E-AGlela>VAG^Hfe@x!@IoSLTQxfR8L}0UTGjML63kAN`WoH=@Wdj;M)b?CHNk}`$P1P%4Mr^ffc!;NAT^r^#9IW=CqxH z?-6{D;O~f}%44m{qhz_@<$^Z|Y|5jym4f#P+%E7&;qMfDk3f|#8U!{7Y|59mg7*pB zE^w#7N2PX;;Hp5{3T!Ai3tnvye5K$k1@9BMUEofEdj!5yz+P0LXb{*`DE$iF3Vdo_ zpWr(MJ}R|)1aBz1M9s`=DiV3%>+*IM(HoBnXOG~jn4EHfmBrN7Ab3OZCF;t&m4dGX z{!m_@;C;Z~%G+Fgp6V>z0{Q&lcHwUa-^$-9_)g%p`FjN41AJlrJ0ht{WG+fBQPKPc z!5e^ImcLT)mB1g!Z!MwDKH>C%^Je~b!M6i<7wi;#C-9nrJ%aB6zOdjOX{Aau6V>>w4FpUGKYm?h<#U``NU& z(n_tftR2?l))>zu&%vIho|T>s jKJdb#u^1R~d_x#=Sg~#w_dgpk5>mBRc>8tgh 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 AWB>pF diff --git a/bin/Release/net8.0/Mt5Bridge.exe b/bin/Release/net8.0/Mt5Bridge.exe index 77a528e1ec5a290482ca86e49ee1102f3ff375bb..7ce54dc6e06f9e7408933578496945d975e1382c 100644 GIT binary patch delta 107 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 NoRKjjkw6HMR7{H;7~%i` delta 55 zcmV-70LcHK0iXdXP)kQa3;+NCfM!a@tWdC<5Mdi95Gdod37D!{VL(Jk^Xhy?TNhQ= NoRKjjkw6HMR7?fy6ZHT9 diff --git a/obj/Release/net8.0/Mt5Bridge.csproj.AssemblyReference.cache b/obj/Release/net8.0/Mt5Bridge.csproj.AssemblyReference.cache index 4c38602e691c858a58480331857c6c65655b8821..055737cf39d555fe96ba57645644b6b52d7155e6 100644 GIT binary patch delta 159 zcmX>re^!2ix@2ypu5XE{Q&DD0da7=2VrE_pP$aj+G-;xP6kEgA{eQFXY)n|iWQ|iD zSZ7R5W>RsCZ;5kGW@=uEUP?|5BO?O?14RF3SLQoRxGkD&#iq;wQF)JJvLU0&=1w*j FP5>92Jgxu$ delta 159 zcmX>re^!2ix@2N2Prm&Qit+eH#a7%VzS1m zt|&7lJvAmLGpRVnx5POoGc~V7FC{03k&yui!1_14GT&jsZP8>aHf0Wo%6lA>4H;E7 Jce1%~0sv#&Ic5L= diff --git a/obj/Release/net8.0/Mt5Bridge.csproj.CoreCompileInputs.cache b/obj/Release/net8.0/Mt5Bridge.csproj.CoreCompileInputs.cache index e912a63..8868596 100644 --- a/obj/Release/net8.0/Mt5Bridge.csproj.CoreCompileInputs.cache +++ b/obj/Release/net8.0/Mt5Bridge.csproj.CoreCompileInputs.cache @@ -1 +1 @@ -fa7261daa8f6cd35b2cabdce49d64b4efa111ee76853926074d5c790bfffb9d6 +af30adee33ca0803429a173f4f51c3233f7e012d4c5cf604a4e29af73b3bdae7 diff --git a/obj/Release/net8.0/Mt5Bridge.csproj.FileListAbsolute.txt b/obj/Release/net8.0/Mt5Bridge.csproj.FileListAbsolute.txt index 5d5deb0..c258df0 100644 --- a/obj/Release/net8.0/Mt5Bridge.csproj.FileListAbsolute.txt +++ b/obj/Release/net8.0/Mt5Bridge.csproj.FileListAbsolute.txt @@ -26,3 +26,31 @@ C:\Users\Administrator\Desktop\active-fx-traders\my-Mt5Bridge\obj\Release\net8.0 C:\Users\Administrator\Desktop\active-fx-traders\my-Mt5Bridge\obj\Release\net8.0\Mt5Bridge.pdb C:\Users\Administrator\Desktop\active-fx-traders\my-Mt5Bridge\obj\Release\net8.0\Mt5Bridge.genruntimeconfig.cache C:\Users\Administrator\Desktop\active-fx-traders\my-Mt5Bridge\obj\Release\net8.0\ref\Mt5Bridge.dll +C:\Users\Administrator\Desktop\my-Mt5Bridge-main\my-mt5bridge\bin\Release\net8.0\Mt5Bridge.exe +C:\Users\Administrator\Desktop\my-Mt5Bridge-main\my-mt5bridge\bin\Release\net8.0\Mt5Bridge.deps.json +C:\Users\Administrator\Desktop\my-Mt5Bridge-main\my-mt5bridge\bin\Release\net8.0\Mt5Bridge.runtimeconfig.json +C:\Users\Administrator\Desktop\my-Mt5Bridge-main\my-mt5bridge\bin\Release\net8.0\Mt5Bridge.dll +C:\Users\Administrator\Desktop\my-Mt5Bridge-main\my-mt5bridge\bin\Release\net8.0\Mt5Bridge.pdb +C:\Users\Administrator\Desktop\my-Mt5Bridge-main\my-mt5bridge\bin\Release\net8.0\MtApi5.dll +C:\Users\Administrator\Desktop\my-Mt5Bridge-main\my-mt5bridge\bin\Release\net8.0\MtClient.dll +C:\Users\Administrator\Desktop\my-Mt5Bridge-main\my-mt5bridge\bin\Release\net8.0\Newtonsoft.Json.dll +C:\Users\Administrator\Desktop\my-Mt5Bridge-main\my-mt5bridge\obj\Release\net8.0\Mt5Bridge.csproj.AssemblyReference.cache +C:\Users\Administrator\Desktop\my-Mt5Bridge-main\my-mt5bridge\obj\Release\net8.0\Mt5Bridge.GeneratedMSBuildEditorConfig.editorconfig +C:\Users\Administrator\Desktop\my-Mt5Bridge-main\my-mt5bridge\obj\Release\net8.0\Mt5Bridge.AssemblyInfoInputs.cache +C:\Users\Administrator\Desktop\my-Mt5Bridge-main\my-mt5bridge\obj\Release\net8.0\Mt5Bridge.AssemblyInfo.cs +C:\Users\Administrator\Desktop\my-Mt5Bridge-main\my-mt5bridge\obj\Release\net8.0\Mt5Bridge.csproj.CoreCompileInputs.cache +C:\Users\Administrator\Desktop\my-Mt5Bridge-main\my-mt5bridge\obj\Release\net8.0\Mt5Bridge.MvcApplicationPartsAssemblyInfo.cache +C:\Users\Administrator\Desktop\my-Mt5Bridge-main\my-mt5bridge\obj\Release\net8.0\staticwebassets.build.json +C:\Users\Administrator\Desktop\my-Mt5Bridge-main\my-mt5bridge\obj\Release\net8.0\staticwebassets.development.json +C:\Users\Administrator\Desktop\my-Mt5Bridge-main\my-mt5bridge\obj\Release\net8.0\staticwebassets\msbuild.Mt5Bridge.Microsoft.AspNetCore.StaticWebAssets.props +C:\Users\Administrator\Desktop\my-Mt5Bridge-main\my-mt5bridge\obj\Release\net8.0\staticwebassets\msbuild.build.Mt5Bridge.props +C:\Users\Administrator\Desktop\my-Mt5Bridge-main\my-mt5bridge\obj\Release\net8.0\staticwebassets\msbuild.buildMultiTargeting.Mt5Bridge.props +C:\Users\Administrator\Desktop\my-Mt5Bridge-main\my-mt5bridge\obj\Release\net8.0\staticwebassets\msbuild.buildTransitive.Mt5Bridge.props +C:\Users\Administrator\Desktop\my-Mt5Bridge-main\my-mt5bridge\obj\Release\net8.0\staticwebassets.pack.json +C:\Users\Administrator\Desktop\my-Mt5Bridge-main\my-mt5bridge\obj\Release\net8.0\scopedcss\bundle\Mt5Bridge.styles.css +C:\Users\Administrator\Desktop\my-Mt5Bridge-main\my-mt5bridge\obj\Release\net8.0\Mt5Bridge.csproj.Up2Date +C:\Users\Administrator\Desktop\my-Mt5Bridge-main\my-mt5bridge\obj\Release\net8.0\Mt5Bridge.dll +C:\Users\Administrator\Desktop\my-Mt5Bridge-main\my-mt5bridge\obj\Release\net8.0\refint\Mt5Bridge.dll +C:\Users\Administrator\Desktop\my-Mt5Bridge-main\my-mt5bridge\obj\Release\net8.0\Mt5Bridge.pdb +C:\Users\Administrator\Desktop\my-Mt5Bridge-main\my-mt5bridge\obj\Release\net8.0\Mt5Bridge.genruntimeconfig.cache +C:\Users\Administrator\Desktop\my-Mt5Bridge-main\my-mt5bridge\obj\Release\net8.0\ref\Mt5Bridge.dll diff --git a/obj/Release/net8.0/Mt5Bridge.dll b/obj/Release/net8.0/Mt5Bridge.dll index fb622b20fbaae91f3729cafd2172cf88537c2c78..48fc6e014d643f7cb76dfa4190a00be7b73f0864 100644 GIT binary patch literal 95744 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,rNES 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 literal 71680 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

P^RwL& z|AyOFJ0;t2udi>(&H#tj_Q-r4FY`OC@K4$O>g>@^1AZBNDLWT3A7|rP+NjK_P$#Lk z3aV60RG@^>P^4{)n35a>TAHmgueu^ zQMAogtJT=NIihnVzGWMm*CPDY!tWE#X5pMAoGp-?n73W{JA{9O@OKJlmv9~tPQT!9 z3vL*++-0z@3c*JU-YEEN!J7HFz*kFncf{zxw!DNq(!kKNJ1si7Lw?XoQD}~=8{MEu=E&M*=Zx;S`!FLFL zgUH+ z1ojIwEYTydQDBR}%>uVrw0Vc%y9D+NG(6HuV57hmftv+x_sA#&-zoSm!5{Td+aBTc z3rBfnEMCzjuu))(z|8`82;3#GU!dWmyxT`@Oje@TfyhZRn!8Z%OL*Oof z{Q?cY^e(VbV2i-b0=N5REQ0S8e3#&l`eiJ_=@*Vlm$9UaHi3--TLf+vxI^GBf&BuF z43QUDnL(Y6g0~3VEO2{<*dX{$!FLJ1NAUg(MyAS?-ZLdi1vUz75!jkZ&6@?^A#j(# ze(rQt%eR`vl)C_;y<+`#kmcf)>E93N{P8F`IgJ zW>dp1;p`E-AGlela>VAG^Hfe@x!@IoSLTQxfR8L}0UTGjML63kAN`WoH=@Wdj;M)b?CHNk}`$P1P%4Mr^ffc!;NAT^r^#9IW=CqxH z?-6{D;O~f}%44m{qhz_@<$^Z|Y|5jym4f#P+%E7&;qMfDk3f|#8U!{7Y|59mg7*pB zE^w#7N2PX;;Hp5{3T!Ai3tnvye5K$k1@9BMUEofEdj!5yz+P0LXb{*`DE$iF3Vdo_ zpWr(MJ}R|)1aBz1M9s`=DiV3%>+*IM(HoBnXOG~jn4EHfmBrN7Ab3OZCF;t&m4dGX z{!m_@;C;Z~%G+Fgp6V>z0{Q&lcHwUa-^$-9_)g%p`FjN41AJlrJ0ht{WG+fBQPKPc z!5e^ImcLT)mB1g!Z!MwDKH>C%^Je~b!M6i<7wi;#C-9nrJ%aB6zOdjOX{Aau6V>>w4FpUGKYm?h<#U``NU& z(n_tftR2?l))>zu&%vIho|T>s jKJdb#u^1R~d_x#=Sg~#w_dgpk5>mBRc>8tgh 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 AWB>pF diff --git a/obj/Release/net8.0/Mt5Bridge.genruntimeconfig.cache b/obj/Release/net8.0/Mt5Bridge.genruntimeconfig.cache index ee3f349..9af975e 100644 --- a/obj/Release/net8.0/Mt5Bridge.genruntimeconfig.cache +++ b/obj/Release/net8.0/Mt5Bridge.genruntimeconfig.cache @@ -1 +1 @@ -78336b0d7c9548c22381256b41e61d95e308b055ebb5bde17d5389da512a3fb0 +ad262a91a68b408c9e09c711f30b4c7e0d95eec95987ff49ef173d2adbd218f3 diff --git a/obj/Release/net8.0/Mt5Bridge.pdb b/obj/Release/net8.0/Mt5Bridge.pdb index a22ee067e9dbffece2b546b75ebf235e981796c1..2fe07deb4ba9f798ba6088e6d0dab67c95d93098 100644 GIT binary patch delta 9934 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 diff --git a/obj/Release/net8.0/refint/Mt5Bridge.dll b/obj/Release/net8.0/refint/Mt5Bridge.dll index ed94ae4d3311a4231b1cd0b0e9e44d781dc7a674..701b726df7136b636646a60f7287e08a6e32c15a 100644 GIT binary patch literal 16384 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 diff --git a/obj/project.assets.json b/obj/project.assets.json index 619a9e7..cbf79ce 100644 --- a/obj/project.assets.json +++ b/obj/project.assets.json @@ -13,11 +13,11 @@ "project": { "version": "1.0.0", "restore": { - "projectUniqueName": "C:\\Users\\Administrator\\Desktop\\active-fx-traders\\my-Mt5Bridge\\Mt5Bridge.csproj", + "projectUniqueName": "C:\\Users\\Administrator\\Desktop\\my-Mt5Bridge-main\\my-mt5bridge\\Mt5Bridge.csproj", "projectName": "Mt5Bridge", - "projectPath": "C:\\Users\\Administrator\\Desktop\\active-fx-traders\\my-Mt5Bridge\\Mt5Bridge.csproj", + "projectPath": "C:\\Users\\Administrator\\Desktop\\my-Mt5Bridge-main\\my-mt5bridge\\Mt5Bridge.csproj", "packagesPath": "C:\\Users\\Administrator\\.nuget\\packages\\", - "outputPath": "C:\\Users\\Administrator\\Desktop\\active-fx-traders\\my-Mt5Bridge\\obj\\", + "outputPath": "C:\\Users\\Administrator\\Desktop\\my-Mt5Bridge-main\\my-mt5bridge\\obj\\", "projectStyle": "PackageReference", "configFilePaths": [ "C:\\Users\\Administrator\\AppData\\Roaming\\NuGet\\NuGet.Config" diff --git a/obj/project.nuget.cache b/obj/project.nuget.cache index 12920dd..86159bc 100644 --- a/obj/project.nuget.cache +++ b/obj/project.nuget.cache @@ -1,8 +1,8 @@ { "version": 2, - "dgSpecHash": "G66hRH3mPGs=", + "dgSpecHash": "rCHMtHhZMMQ=", "success": true, - "projectFilePath": "C:\\Users\\Administrator\\Desktop\\active-fx-traders\\my-Mt5Bridge\\Mt5Bridge.csproj", + "projectFilePath": "C:\\Users\\Administrator\\Desktop\\my-Mt5Bridge-main\\my-mt5bridge\\Mt5Bridge.csproj", "expectedPackageFiles": [], "logs": [] } \ No newline at end of file diff --git a/test_all.py b/test_all.py new file mode 100644 index 0000000..2f5dedc --- /dev/null +++ b/test_all.py @@ -0,0 +1,416 @@ +#!/usr/bin/env python3 +""" +Mt5Bridge end-to-end test. + +Usage: + python test_all.py # default remote, read-only + check + python test_all.py --trades # enable trade test (open/close) + python test_all.py --base http://host:p # custom base URL + python test_all.py --symbol XAUUSD # custom symbol +""" +import argparse +import json +import sys +import time +from typing import Callable + +try: + import requests +except ImportError: + print("missing requests: pip install requests") + sys.exit(1) + +try: + import websocket +except ImportError: + print("missing websocket-client: pip install websocket-client") + sys.exit(1) + + +# ─────────── Colors ─────────── +C_G = "\033[92m" +C_R = "\033[91m" +C_Y = "\033[93m" +C_B = "\033[96m" +C_X = "\033[0m" +C_D = "\033[2m" + + +# ─────────── Stats ─────────── +PASS = 0 +FAIL = 0 +ERRORS: list[str] = [] + + +def case(name: str, fn: Callable[[], bool]) -> None: + global PASS, FAIL + sys.stdout.write(f"{C_B}- {name}{C_X} ") + try: + ok = fn() + # lambda with walrus expressions returns tuple; take last element + if isinstance(ok, tuple): + ok = ok[-1] + if ok: + print(f"{C_G}PASS{C_X}") + PASS += 1 + else: + print(f"{C_R}FAIL{C_X}") + FAIL += 1 + ERRORS.append(name) + except AssertionError as e: + print(f"{C_R}FAIL{C_X} {C_D}{e}{C_X}") + FAIL += 1 + ERRORS.append(f"{name}: {e}") + except Exception as e: + msg = f"{type(e).__name__}: {e}" + print(f"{C_R}ERROR{C_X} {C_D}{msg}{C_X}") + FAIL += 1 + ERRORS.append(f"{name}: {msg}") + + +# ─────────── HTTP client ─────────── +class Bridge: + def __init__(self, base: str, key: str, timeout: float = 15.0): + self.base = base.rstrip("/") + self.key = key + self.timeout = timeout + self.s = requests.Session() + self.s.headers.update({"X-API-Key": key}) + + def get(self, path: str, params: dict | None = None) -> dict: + r = self.s.get(f"{self.base}{path}", params=params, timeout=self.timeout) + r.raise_for_status() + return r.json() + + def post(self, path: str, body: dict) -> dict: + r = self.s.post(f"{self.base}{path}", json=body, timeout=self.timeout) + r.raise_for_status() + return r.json() + + def delete(self, path: str) -> dict: + r = self.s.delete(f"{self.base}{path}", timeout=self.timeout) + r.raise_for_status() + return r.json() + + def expect_status(self, method: str, path: str, expected: int, **kw) -> int: + r = self.s.request(method, f"{self.base}{path}", timeout=self.timeout, **kw) + assert r.status_code == expected, f"HTTP {r.status_code} != {expected}: {r.text[:200]}" + return r.status_code + + +# ─────────── SSE ─────────── +def sse_first(base: str, key: str, symbol: str, timeout_sec: float) -> tuple[bool, str]: + """Open SSE, wait for first data: line or timeout.""" + import urllib.request + url = f"{base}/stream/ticks-sse/{symbol}?key={key}" + req = urllib.request.Request(url, headers={"X-API-Key": key, "Accept": "text/event-stream"}) + with urllib.request.urlopen(req, timeout=timeout_sec + 5) as resp: + deadline = time.time() + timeout_sec + while time.time() < deadline: + line = resp.readline() + if not line: + break + line = line.decode("utf-8", "ignore").rstrip("\r\n") + if line.startswith("data: "): + return True, line[6:80] + return False, "" + + +# ─────────── WebSocket ─────────── +def ws_first(base: str, key: str, symbol: str, timeout_sec: float) -> tuple[bool, str]: + ws_url = "ws" + base[4:] if base.startswith("http") else base + ws_url = f"{ws_url}/stream/ticks/{symbol}?key={key}" + deadline = time.time() + timeout_sec + ws = websocket.create_connection(ws_url, timeout=timeout_sec + 5, + header=[f"X-API-Key: {key}"]) + try: + ws.settimeout(1.0) + last_type = None + while time.time() < deadline: + try: + opcode, data = ws.recv_data() + except (websocket.WebSocketTimeoutException, TimeoutError): + continue + if opcode in (websocket.ABNF.OPCODE_TEXT,): + text = data.decode("utf-8", "ignore") + if '"type":"tick"' in text: + return True, text[:80] + last_type = "hb" + elif opcode == websocket.ABNF.OPCODE_CLOSE: + break + # fall back: got heartbeat means transport works, but MT5 may need time + return last_type == "hb", f"heartbeat (no tick yet)" + finally: + try: + ws.close() + except Exception: + pass + return False, "" + + +# ─────────── Warm-up ─────────── +def warmup(b: Bridge, symbol: str, timeout_sec: float = 15.0) -> None: + try: + ok, detail = ws_first(b.base, b.key, symbol, timeout_sec) + if "tick" in detail: + print(f"{C_D} [WS warm-up ok, tick received]{C_X}") + elif "heartbeat" in detail: + print(f"{C_D} [WS warm-up: got heartbeat, waiting for MT5 to initialize quote]{C_X}") + time.sleep(3) # give MT5 time to populate symbol data + else: + print(f"{C_D} [WS warm-up failed (no data)]{C_X}") + except Exception as e: + print(f"{C_D} [WS warm-up exception: {e}]{C_X}") + + +# ════════════════════════════════════════════════════════════════════ +def run(args) -> int: + b = Bridge(args.base, args.key) + sym = args.symbol + + print() + print(f"{C_Y}=== Mt5Bridge E2E test ==={C_X}") + print(f"Base : {args.base}") + print(f"Symbol : {sym}") + print(f"Trades : {'enabled (will place real orders)' if args.trades else 'disabled (--trades to enable)'}") + print() + + # ── system / account ── + case("1. GET /health", lambda: ( + r := b.get("/health"), + r["status"] == "healthy" and r["mt5_connected"] is True + )) + + case("2. GET /account", lambda: ( + r := b.get("/account"), + a := r["data"][0], + print(f" login={a['login']} server={a['server']} balance={a['balance']} currency={a['currency']}"), + a["login"] > 0 and a["balance"] >= 0 + )) + + # ── warm-up to add symbol to Market Watch ── + print(f"{C_D}-- warm-up (WS) --{C_X}") + warmup(b, sym, timeout_sec=6) + + # ── quote ── + case("3. GET /symbols/" + sym, lambda: ( + r := b.get(f"/symbols/{sym}"), + s := r["data"][0], + print(f" bid={s['bid']} ask={s['ask']} digits={s['digits']} point={s['point']}"), + s["bid"] > 0 and s["digits"] > 0 + )) + + case("4. GET /symbols/" + sym + "/tick", lambda: ( + r := b.get(f"/symbols/{sym}/tick"), + t := r["data"][0], + print(f" bid={t['bid']} ask={t['ask']} time={t['time']}"), + t["bid"] > 0 and t["ask"] >= t["bid"] + )) + + # ── rates ── + case("5. GET /rates/from-pos (H1, count=5)", lambda: ( + r := b.get("/rates/from-pos", {"symbol": sym, "timeframe": "TIMEFRAME_H1", + "start_pos": 0, "count": 5}), + print(f" count={r['count']} first={r['data'][0]['time']} last={r['data'][-1]['time']}"), + r["count"] == 5 + )) + + case("6. GET /rates/from-date (cross-day 7-7~7-8, H1)", lambda: ( + r := b.get("/rates/from-date", {"symbol": sym, "timeframe": "TIMEFRAME_H1", + "date_from": "2026-07-07", "date_to": "2026-07-08"}), + print(f" count={r['count']} first={r['data'][0]['time']}"), + r["count"] > 0 + )) + + case("6b. GET /rates/from-date (same day 7-7~7-7, M1)", lambda: ( + r := b.get("/rates/from-date", {"symbol": sym, "timeframe": "TIMEFRAME_M1", + "date_from": "2026-07-07", "date_to": "2026-07-07"}), + print(f" count={r['count']} (bug fix: should be > 0)"), + r["count"] > 0 + )) + + case("6c. GET /rates/from-date (date_from > date_to, expect 400)", lambda: ( + b.expect_status("GET", "/rates/from-date", 400, + params={"symbol": sym, "timeframe": "TIMEFRAME_H1", + "date_from": "2026-07-08", "date_to": "2026-07-01"}), + print(" status=400 ok"), + True + )) + + # ── positions / orders / history ── + case("7. GET /positions", lambda: ( + r := b.get("/positions"), + print(f" count={r['count']}"), + True + )) + + case("7b. GET /positions?symbol=__NOPE__", lambda: ( + r := b.get("/positions", {"symbol": "__NOPE__"}), + print(f" count={r['count']}"), + r["count"] == 0 + )) + + case("8. GET /orders", lambda: ( + r := b.get("/orders"), + print(f" count={r['count']}"), + True + )) + + case("9. GET /history/deals (7-1~7-8)", lambda: ( + r := b.get("/history/deals", {"date_from": "2026-07-01", "date_to": "2026-07-08", + "symbol": sym}), + print(f" count={r['count']}"), + True + )) + + # ── gvar ── + import uuid + gvar = f"TEST_{uuid.uuid4().hex[:8]}" + + case(f"10a. POST /gvar/{gvar}", lambda: ( + r := b.post(f"/gvar/{gvar}", {"value": 42.5}), + print(f" value={r['value']}"), + r["value"] == 42.5 + )) + + case(f"10b. GET /gvar/{gvar}", lambda: ( + r := b.get(f"/gvar/{gvar}"), + print(f" value={r['value']}"), + r["value"] == 42.5 + )) + + case("10c. GET /gvar (expect at least 1 TEST_*)", lambda: ( + r := b.get("/gvar"), + found := sum(1 for g in r["data"] if g["name"].startswith("TEST_")), + print(f" total={r['count']} TEST_*={found}"), + found >= 1 + )) + + case(f"10d. DELETE /gvar/{gvar}", lambda: ( + r := b.delete(f"/gvar/{gvar}"), + print(f" deleted={r['deleted']}"), + r["deleted"] == gvar + )) + + # ── order check ── + case("11. POST /order/check (buy 0.01 " + sym + ")", lambda: ( + bid := b.get(f"/symbols/{sym}/tick")["data"][0]["bid"], + r := b.post("/order/check", { + "action": 1, "symbol": sym, "volume": 0.01, "order_type": 0, + "price": bid, "sl": 0, "tp": 0, "magic": 0, "comment": "test", "deviation": 10, + "type_filling": 0, # ORDER_FILLING_FOK - required by ICMarkets + }), + rc := r["data"]["retcode"], + print(f" retcode={rc} comment={r['data']['comment']}"), + rc == 0 # with type_filling set, should be 0 + )) + + # ── SSE ── + case(f"12. SSE /stream/ticks-sse/{sym} (<=35s for tick or heartbeat)", lambda: ( + result := sse_first(b.base, b.key, sym, timeout_sec=35), + ok := result[0], + snippet := result[1], + print(f" {snippet}"), + ok + )) + + # ── WebSocket ── + case(f"13. WS /stream/ticks/{sym} (<=35s for tick or heartbeat)", lambda: ( + result := ws_first(b.base, b.key, sym, timeout_sec=35), + ok := result[0], + snippet := result[1], + print(f" {snippet}"), + ok + )) + + # ── trades (opt-in) ── + if args.trades: + print() + print(f"{C_Y}[!] TRADES enabled - will place real orders{C_X}") + print() + + case("14. POST /order/send -> /position/close (open 0.01 then close)", lambda: ( + bid := b.get(f"/symbols/{sym}/tick")["data"][0]["bid"], + r := b.post("/order/send", {"request": { + "action": 1, "symbol": sym, "volume": 0.01, "order_type": 0, + "price": bid, "sl": 0, "tp": 0, "magic": 99001, + "comment": "selftest", "deviation": 10, "type_filling": 0, + }}), + print(f" send retcode={r['data']['retcode']} order={r['data']['order']}"), + r["data"]["retcode"] == 10009, + time.sleep(0.5), + r2 := b.post("/position/close", {"ticket": r["data"]["order"]}), + print(f" close retcode={r2['data']['retcode']}"), + r2["data"]["retcode"] == 10009 + )) + + case("15. POST /position/modify (change SL/TP, then restore)", lambda: ( + r := b.get("/positions"), + print(f" positions count={r['count']}"), + (r["count"] == 0) and (print(" [no positions, skip]"), True)[-1] + or ( + p := r["data"][0], + orig_sl := p["sl"], orig_tp := p["tp"], + new_sl := round(p["price_current"] - 50, 2), + new_tp := round(p["price_current"] + 50, 2), + r2 := b.post("/position/modify", {"ticket": p["ticket"], "sl": new_sl, "tp": new_tp}), + print(f" modify retcode={r2['data']['retcode']}"), + r2["data"]["retcode"] == 10009, + r3 := b.post("/position/modify", {"ticket": p["ticket"], "sl": orig_sl, "tp": orig_tp}), + print(f" restore retcode={r3['data']['retcode']}"), + r3["data"]["retcode"] == 10009, + )[-1] + )) + + case("16. POST /positions/close-batch (magic=99001)", lambda: ( + r := b.post("/positions/close-batch", {"magic": 99001}), + print(f" closed={r['closed']} failed={r['failed']}"), + True + )) + + case("17. POST /order/cancel (place pending then cancel)", lambda: ( + bid := b.get(f"/symbols/{sym}/tick")["data"][0]["bid"], + pend_price := int(bid * 0.9), + r := b.post("/order/send", {"request": { + "action": 5, "symbol": sym, "volume": 0.01, "order_type": 2, + "price": pend_price, "sl": 0, "tp": 0, "magic": 99002, + "comment": "selftest-pending", "deviation": 0, "type_filling": 0, + }}), + print(f" place retcode={r['data']['retcode']} order={r['data']['order']}"), + r["data"]["retcode"] == 10009, + time.sleep(0.5), + r2 := b.post("/order/cancel", {"ticket": r["data"]["order"]}), + print(f" cancel retcode={r2['data']['retcode']}"), + r2["data"]["retcode"] == 10009 + )) + else: + print() + print(f"{C_D}[skip trades -- use --trades to enable]{C_X}") + + # ── summary ── + print() + print(f"{C_Y}=== Summary ==={C_X}") + print(f"Pass: {C_G}{PASS}{C_X}") + color = C_R if FAIL else C_G + print(f"Fail: {color}{FAIL}{C_X}") + if ERRORS: + print() + print(f"{C_R}Failed cases:{C_X}") + for e in ERRORS: + print(f" - {e}") + print() + return 0 if FAIL == 0 else 1 + + +def main(): + p = argparse.ArgumentParser(description="Mt5Bridge end-to-end test") + p.add_argument("--base", default="http://61.164.252.86:13485", help="Bridge base URL") + p.add_argument("--key", default="UiHMqtaYLZzwBdcuS4RFmEGhgDO8N2eI", help="API Key") + p.add_argument("--symbol", default="XAUUSD", help="Test symbol") + p.add_argument("--trades", action="store_true", help="Enable trade test (places real orders)") + args = p.parse_args() + sys.exit(run(args)) + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/延迟测试.py b/延迟测试.py deleted file mode 100644 index 077a5d3..0000000 --- a/延迟测试.py +++ /dev/null @@ -1,53 +0,0 @@ -import requests -import time -import statistics - -BRIDGE = "http://61.164.252.86:13485" -KEY = "UiHMqtaYLZzwBdcuS4RFmEGhgDO8N2eI" -HEADERS = {"X-API-Key": KEY} - -N = 20 # 测试次数 - -def test(name, func): - times = [] - for i in range(N): - t0 = time.perf_counter() - try: - func() - except Exception as e: - print(f" ❌ {name} 失败: {e}") - return - t1 = time.perf_counter() - times.append((t1 - t0) * 1000) - print(f" #{i+1:2d}: {times[-1]:.1f} ms", end="\r") - - print(f"\n{'='*50}") - print(f"{name}") - print(f" 最小: {min(times):.1f} ms") - print(f" 最大: {max(times):.1f} ms") - print(f" 平均: {statistics.mean(times):.1f} ms") - print(f" 中位: {statistics.median(times):.1f} ms") - -print(f"测试 {N} 次,请稍候...\n") - -# 1. 健康检查 -test("健康检查 /health", lambda: requests.get(f"{BRIDGE}/health", headers=HEADERS).raise_for_status()) - -# 2. 账户信息 -test("账户信息 /account", lambda: requests.get(f"{BRIDGE}/account", headers=HEADERS).raise_for_status()) - -# 3. 实时 Tick -test("实时 Tick /tick", lambda: requests.get(f"{BRIDGE}/symbols/XAUUSDc/tick", headers=HEADERS).raise_for_status()) - -# 4. 持仓查询 -test("持仓查询 /positions", lambda: requests.get(f"{BRIDGE}/positions", headers=HEADERS).raise_for_status()) - -# 5. 品种信息 -test("品种信息 /symbols", lambda: requests.get(f"{BRIDGE}/symbols/XAUUSDc", headers=HEADERS).raise_for_status()) - -# 6. K 线数据 -test("K 线 /rates (100根 H1)", lambda: requests.get(f"{BRIDGE}/rates/from-pos", headers=HEADERS, params={ - "symbol": "XAUUSDc", "timeframe": "TIMEFRAME_H1", "start_pos": 0, "count": 100 -}).raise_for_status()) - -print(f"\n总结: 你的网络 → MT5 云端 往返延迟") \ No newline at end of file