pub
把一条消息推送到运行中实盘订阅的频道,供平台外部的系统(TradingView 的 Webhook 告警、自建交易系统、监控脚本等)向实盘发送数据。实盘用GetChannelData读取,频道机制见策略实盘间通信。
与其它方法不同,pub不需要API KEY,也不签名:请求地址是https://www.fmz.com/api/v1?method=pub&robot={robotId}&channel={channel},消息放在请求体中(POST)。知道实盘Id和频道名的任何人都能推送,所以频道名要用难以猜到的随机字符串,策略也要把收到的内容当作不可信的输入来校验。
示例
接收端策略:订阅频道,把收到的JSON消息解析出来,并用id区分新旧消息。
javascript
// 接收端实盘(假设实盘Id为123456)
var CHANNEL = "6BC42A119B5DBFA2188A8279DA3B5C30"
function main() {
var lastId = null
while (true) {
var msg = GetChannelData(CHANNEL) // 第一次调用即订阅,返回null
if (typeof msg == "string") {
var obj = null
try {
obj = JSON.parse(msg) // 请求体是JSON文本时再解析一次
} catch (e) {
Log("非JSON消息:", msg)
}
if (obj && obj.id != lastId) { // 频道只保存最新一条,用id判断是否是新消息
lastId = obj.id
Log("收到外部消息:", obj)
}
}
Sleep(1000)
}
}
python
import json
CHANNEL = "6BC42A119B5DBFA2188A8279DA3B5C30"
def main():
lastId = None
while True:
msg = GetChannelData(CHANNEL) # 第一次调用即订阅,返回None
if isinstance(msg, str):
try:
obj = json.loads(msg) # 请求体是JSON文本时再解析一次
except ValueError:
obj = None
Log("非JSON消息:", msg)
if isinstance(obj, dict) and obj.get("id") != lastId:
lastId = obj.get("id")
Log("收到外部消息:", obj)
Sleep(1000)返回值
| 类型 | 描述 |
object | 推送成功时 |
参数
| 名称 | 类型 | 必填 | 描述 |
robot | number | 是 | 接收消息的实盘Id(URL参数)。该实盘必须正在运行,并且已经订阅了 |
channel | string | 是 | 频道名(URL参数),建议用32位随机字符串(UUID去掉连字符)。不能是纯数字(纯数字会被当作实盘Id,即实盘自己的频道);少于10个字符的频道名不会投递。 |
message | string | 否 | 消息内容。 |
属性
| 名称 | 类型 | 描述 |
data.status | string | 推送成功时为 |
data.robot | number | 本次请求的 |
data.channel | string | 本次请求的 |
data.message | string | 本次推送的消息。 |
data.affected | number | 收到消息的托管者数量。 |
备注
投递规则
- 先订阅、后推送:实盘第一次调用
GetChannelData(channel)即订阅该频道(返回空值),订阅随托管者心跳上报,稍等片刻后外部系统才能推送成功。没有实盘订阅时请求失败。 - 消息投递到
robot实盘所在的托管者,该托管者上所有订阅了同一频道的实盘都会收到;其它托管者上的实盘收不到。 - 频道只保存最新一条消息,不排队:
GetChannelData()每次返回最近收到的一条,读取不会清除它。需要区分新旧消息时,在消息中带上递增的编号或时间戳。 - 每个实盘最多订阅10个频道(含其它实盘的频道),超出时
GetChannelData()返回空值并记录错误日志channel subscriber exceed limit。 - 实盘收到的是字符串(请求体原文)。请求体是JSON文本时,策略需要自己再解析一次。
推送请求示例
外部系统推送一条消息:
bash
curl -X POST \
"https://www.fmz.com/api/v1?method=pub&robot=123456&channel=6BC42A119B5DBFA2188A8279DA3B5C30" \
-d '{"id": 1, "action": "buy", "symbol": "BTC_USDT"}'
在TradingView中使用时,把上面的URL填入告警的Webhook地址,告警消息内容就是请求体。
返回示例
json
{
"code": 0,
"data": {
"status": "ok",
"robot": 123456,
"channel": "6BC42A119B5DBFA2188A8279DA3B5C30",
"message": "{\"id\": 1, \"action\": \"buy\", \"symbol\": \"BTC_USDT\"}",
"affected": 1
}
}
没有实盘订阅该频道时:
json
{
"code": 5,
"error": "No subscribers for channel: 6BC42A119B5DBFA2188A8279DA3B5C30",
"data": null
}