扩展API接口
扩展API接口是平台的HTTP接口(https://www.fmz.com/api/v1),供脚本、定时任务等程序调用平台功能:查询账号、托管者、策略和实盘,创建、重启、停止实盘,向实盘发送交互命令等。
在AI助手(Claude Code、Cursor等)中交互式地操作平台时,优先使用AI接入(MCP服务):工具更全,参数按名称传递,权限可以按类别授予。两者可以使用同一把API KEY。
使用步骤:创建ApiKey,按验证方式发送请求,方法与参数见扩展API接口详解。
创建ApiKey
在账号设置 → API KEY页面(/m/account#apikey)点击「创建新的ApiKey」,得到一对AccessKey和SecretKey。SecretKey代表这把API KEY的全部权限,不要泄露。在该页面也可以修改已有API KEY的权限,或者禁用、删除API KEY。
权限
创建或修改时,在「API权限」输入框中填写逗号分隔的列表:
*:允许全部扩展API接口。- 方法名:只允许列出的方法,例如
GetRobotList,GetRobotDetail,CommandRobot。 !方法名:排除某个方法,通常与*搭配,例如*,!DeleteRobot,!DeleteNode。
同一把API KEY也可以用于AI接入(MCP服务)。MCP工具除了按工具名授权,还可以按权限类别授权:read、backtest、write、trade、danger(含义见AI接入页面),同样支持用!名称排除。权限类别只对MCP工具生效;扩展API接口只认方法名和*。
权限留空时,扩展API接口不限制方法(MCP开放danger以外的全部工具)。建议按用途只授予需要的方法,例如只用于TradingView警报的API KEY只授予CommandRobot。
验证方式
调用扩展API接口时有两种验证方式:
签名验证:用SecretKey对请求参数签名,SecretKey本身不在网络上传输。程序调用应使用这种方式。直接验证:把SecretKey直接放进请求URL,主要用于TradingView等只能填写一个URL的Webhook场景。
签名验证
请求格式
向https://www.fmz.com/api/v1发送POST请求,参数以表单(application/x-www-form-urlencoded)提交。服务端也接受把同样的参数放在URL查询串中的GET请求,但参数会留在各处的访问日志里,推荐使用POST。
| 参数 | 说明 |
|---|---|
| version | 版本号,固定为1.0。 |
| access_key | API KEY的AccessKey。 |
| method | 调用的方法名,例如GetNodeList。 |
| args | 方法参数组成的JSON字符串:按顺序排列的数组(如[]、[123, "ok"]),或按参数名传值的对象(如{"robotId": 123}),见扩展API接口详解。不传时按[]处理。 |
| nonce | 毫秒时间戳。与服务器时间相差不能超过1小时,并且必须大于这把API KEY上一次请求使用的nonce。 |
| sign | 签名,计算方法见下文。 |
请求中不包含SecretKey。
签名方式
按下面的格式拼接字符串,其中args是实际提交的JSON字符串原文:
plaintext
version + "|" + method + "|" + args + "|" + nonce + "|" + secretKey
对拼接结果计算MD5,转换为32位小写十六进制字符串,作为sign的值。
Python示例
python
import hashlib
import json
import time
import urllib.parse
import urllib.request
ACCESS_KEY = '' # API KEY 的 AccessKey
SECRET_KEY = '' # API KEY 的 SecretKey
def api(method, *args, **kwargs):
d = {
'version': '1.0',
'access_key': ACCESS_KEY,
'method': method,
# 位置参数传数组,关键字参数传对象(按参数名传值)
'args': json.dumps(kwargs if kwargs else list(args)),
'nonce': int(time.time() * 1000),
}
s = '%s|%s|%s|%d|%s' % (d['version'], d['method'], d['args'], d['nonce'], SECRET_KEY)
d['sign'] = hashlib.md5(s.encode('utf-8')).hexdigest()
body = urllib.parse.urlencode(d).encode('utf-8')
with urllib.request.urlopen('https://www.fmz.com/api/v1', body, timeout=10) as resp:
return json.loads(resp.read().decode('utf-8'))
print(api('GetNodeList')) # 托管者列表
print(api('GetRobotList', appId='member2')) # 按参数名传值:标签为 member2 的实盘
print(api('CommandRobot', 123, 'ok')) # 向实盘 123 发送交互命令
print(api('GetRobotDetail', 123)) # 实盘 123 的详细信息
Go示例
mylang
package main
import (
"crypto/md5"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"strconv"
"time"
)
const (
accessKey = "" // API KEY 的 AccessKey
secretKey = "" // API KEY 的 SecretKey
baseAPI = "https://www.fmz.com/api/v1"
)
var client = &http.Client{Timeout: 10 * time.Second}
func api(method string, args ...interface{}) (string, error) {
if args == nil {
args = []interface{}{}
}
b, err := json.Marshal(args)
if err != nil {
return "", err
}
nonce := strconv.FormatInt(time.Now().UnixMilli(), 10)
sum := md5.Sum([]byte("1.0|" + method + "|" + string(b) + "|" + nonce + "|" + secretKey))
form := url.Values{
"version": {"1.0"},
"access_key": {accessKey},
"method": {method},
"args": {string(b)},
"nonce": {nonce},
"sign": {hex.EncodeToString(sum[:])},
}
resp, err := client.PostForm(baseAPI, form)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
return string(body), err
}
func main() {
ret, err := api("GetNodeList")
fmt.Println(ret, err)
// 用新的配置重启实盘 123,settings 字段见「扩展API接口详解」中的实盘配置说明
settings := map[string]interface{}{
"name": "hedge test",
"strategy": 456,
"period": 60,
"node": 789,
"exchanges": []interface{}{
map[string]interface{}{"pid": 1001, "pair": "BTC_USDT"},
},
}
ret, err = api("RestartRobot", 123, settings)
fmt.Println(ret, err)
}
直接验证
直接验证不计算签名,而是把secret_key直接放在请求参数中,因此可以生成一个固定的URL,填到TradingView等只能设置一个URL的Webhook回调里。
**安全提示**:
secret_key写在URL中,会留在浏览器历史、代理和服务器的访问日志、Webhook服务方的配置里,任何拿到这个URL的人都能以这把API KEY的权限调用接口。建议只在CommandRobot的Webhook中使用直接验证,并为它单独创建一把只授权CommandRobot的API KEY(见创建ApiKey);一旦泄露,立即删除这把API KEY。
请求参数为access_key、secret_key、method、args(JSON数组,需要URL编码),不需要version、nonce、sign。CommandRobot不做nonce校验;其他方法仍会校验:不传nonce时服务器以当前时间(精确到秒)代替,同一秒内的第二次调用会返回Nonce错误(code为3)。
例如API KEY的AccessKey为xxx、SecretKey为yyy,访问下面的URL即可向Id为186515的实盘发送交互命令ok12345:
plaintext
https://www.fmz.com/api/v1?access_key=xxx&secret_key=yyy&method=CommandRobot&args=%5B186515%2C%22ok12345%22%5D
接收Webhook请求体
CommandRobot的命令参数为空字符串、请求为POST时,服务器把请求体(Body)作为交互命令发给实盘。例如在TradingView的Webhook URL中设置:
plaintext
https://www.fmz.com/api/v1?access_key=xxx&secret_key=yyy&method=CommandRobot&args=%5B186515%2C+%22%22%5D
其中args的值%5B186515%2C+%22%22%5D解码后为[186515, ""](+是URL编码中的空格),186515是实盘Id,命令为空字符串。
模拟TradingView发送Webhook警报:
javascript
function main() {
var options = {
method: "POST",
body: `{"test": 123}`,
headers: {"Content-Type": "application/json"}
}
// Webhook 警报会自动发送 POST 请求,并带上需要的 headers
return HttpQuery("https://www.fmz.com/api/v1?access_key=xxx&secret_key=yyy&method=CommandRobot&args=%5B186515%2C+%22%22%5D", options)
}
TradingView警报消息框中的内容就是请求体:
-
JSON格式:
plaintext{"close": {{close}}, "name": "aaa"}Id为
186515的实盘收到交互命令:{"close": 39773.75, "name": "aaa"}。 -
文本格式:
plaintextBTCUSDTPERP 穿过(Crossing) 39700.00 close: {{close}}Id为
186515的实盘收到交互命令:BTCUSDTPERP 穿过(Crossing) 39700.00 close: 39739.4。
Python、Go示例
python
import json
import urllib.parse
import urllib.request
ACCESS_KEY = '' # 只授权了 CommandRobot 的 API KEY 的 AccessKey
SECRET_KEY = '' # SecretKey
def api(method, *args):
query = urllib.parse.urlencode({
'access_key': ACCESS_KEY,
'secret_key': SECRET_KEY,
'method': method,
'args': json.dumps(list(args)),
})
with urllib.request.urlopen('https://www.fmz.com/api/v1?' + query, timeout=10) as resp:
return json.loads(resp.read().decode('utf-8'))
# API KEY 没有该方法的权限时返回 {'code': 4, 'data': None}
print(api('CommandRobot', 186515, 'ok12345'))
mylang
package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"time"
)
const (
accessKey = "" // 只授权了 CommandRobot 的 API KEY 的 AccessKey
secretKey = "" // SecretKey
baseAPI = "https://www.fmz.com/api/v1"
)
var client = &http.Client{Timeout: 10 * time.Second}
func api(method string, args ...interface{}) (string, error) {
if args == nil {
args = []interface{}{}
}
b, err := json.Marshal(args)
if err != nil {
return "", err
}
q := url.Values{
"access_key": {accessKey},
"secret_key": {secretKey},
"method": {method},
"args": {string(b)},
}
resp, err := client.Get(baseAPI + "?" + q.Encode())
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
return string(body), err
}
func main() {
ret, err := api("CommandRobot", 186515, "ok12345")
fmt.Println(ret, err)
}
参考:
扩展API接口详解
所有方法都通过https://www.fmz.com/api/v1调用,请求格式与签名见签名验证,返回结构与错误码见扩展API接口返回码。各方法页面示例中的api()即签名验证页面Python示例中的函数。
方法一览
| 对象 | 方法 | 参数(按顺序,方括号内可省略) | 说明 | 注意 |
|---|---|---|---|---|
| 账号 | GetAccount | 无 | 账号信息 | 只读 |
| 托管者 | GetNodeList | [offset, limit] | 托管者列表 | 只读 |
| 托管者 | DeleteNode | nid | 删除托管者 | 删除,不可恢复 |
| 交易所 | GetExchangeList | isSummary | 平台支持的交易所及配置项 | 只读 |
| 交易所 | GetPlatformList | [offset, limit] | 已添加的交易所账户 | 只读 |
| 策略 | GetStrategyList | offset, length, strategyType, category, language, kw[, groupId, orderBy] | 策略列表 | 只读 |
| 实盘 | GetRobotGroupList | 无 | 实盘分组 | 只读 |
| 实盘 | GetRobotList | [offset, length, customStatus, appId, kw, groupId, orderBy, strategyId] | 实盘列表 | 只读 |
| 实盘 | GetRobotDetail | robotId | 实盘详细信息 | 只读 |
| 实盘 | GetRobotLogs | robotId, logMinId, …, summaryLimit[, logExchange, logKeyword, logTypes] | 日志、收益、图表与状态栏数据 | 只读 |
| 实盘 | NewRobot | settings | 创建并启动实盘 | 扣费;实盘会真实交易 |
| 实盘 | RestartRobot | robotId[, settings] | 启动(重启)实盘 | 扣费;实盘会真实交易 |
| 实盘 | StopRobot | robotId | 停止实盘 | 不会平仓 |
| 实盘 | CommandRobot | robotId, cmd | 向实盘发送交互命令 | 策略可能据此下单 |
| 实盘 | DeleteRobot | robotId[, removeLog] | 删除实盘 | 删除,不可恢复 |
| 调试 | PluginRun | settings | 在托管者上执行一段代码 | 代码可以真实下单 |
API KEY需要有对应方法的权限,见创建ApiKey。
参数传法
args有两种写法:
- 数组:按上表的顺序传位置参数,例如
[123, "ok"]。 - 对象:按参数名传值,例如
{"robotId": 123, "cmd": "ok"}。参数名不区分大小写、忽略下划线,没有传的参数取默认值。可选参数多的方法(GetRobotList、GetRobotLogs、GetStrategyList)建议用这种写法。
实盘配置(settings)
NewRobot、RestartRobot、PluginRun的settings参数是一个JSON对象,常用字段如下:
| 字段 | 说明 |
|---|---|
| name | 实盘名称。 |
| strategy | 策略Id,可用GetStrategyList查询。RestartRobot不能更换实盘的策略。 |
| args | 策略参数,每个元素为["参数名", 值],例如[["Interval", 500]];策略没有参数时为[]。 |
| exchanges | 交易所对象配置数组,每个元素对应一个交易所对象,写法见下文。 |
| period | 默认K线周期,单位为秒,例如60、3600。 |
| node | 运行实盘的托管者Id,可用GetNodeList查询;不写或为-1时自动分配。 |
| group | 实盘分组Id,可用GetRobotGroupList查询。 |
| appid | 自定义标签,GetRobotList可以按标签筛选。 |
exchanges的元素有两种写法,同一个数组中不能混用(以第一个元素的写法为准):
- 引用平台上已添加的交易所账户:
{"pid": 123, "pair": "BTC_USDT"}。pid可用GetPlatformList查询(返回数据中的id)。 - 直接传入交易所配置:
{"eid": "Binance", "label": "test", "pair": "BTC_USDT", "meta": {"AccessKey": "...", "SecretKey": "..."}}。eid为交易所Id;meta的字段名见GetExchangeList返回的meta;label是交易所对象的标签,策略中用exchange.GetLabel()获取。平台不保存meta中的密钥,而是直接转发给托管者,所以用这种写法创建的实盘,每次重启时都必须重新传入settings。
通用协议交易所的写法:{"eid": "Exchange", "label": "test", "pair": "BTC_USDT", "meta": {"AccessKey": "...", "SecretKey": "...", "Front": "http://127.0.0.1:6666/test"}},Front为通用协议服务的地址。
GetAccount
GetAccount方法用于获取请求中的API KEY对应的发明者量化交易平台账号的账户信息。
返回值
json
{
"code":0,
"data":{
"result":{
"balance":22944702436,
"concurrent":0,
"consumed":211092719653,
"email":"[email protected]",
"openai":false,
"settings":null,
"sns":{"wechat":true},
"uid":"105ea6e51bcc177926a10fdbb7e2a1d6",
"username":"abc"
},
"error":null
}
}
- balance: 账户余额,单位为USD。为了控制精度使用整数表示,除以1e8(10的8次方)得到实际数值,示例中为229.44702436。
- consumed: 累计消费金额,单位与换算方式同
balance。
参数
无参数
GetNodeList
GetNodeList方法用于获取请求中的API KEY对应的平台账号可以使用的托管者列表,包括自己的托管者和平台的公共托管者。
返回值
json
{
"code": 0,
"data": {
"result": {
"all": 1,
"nodes": [{
"build": "3.7",
"city": "...",
"created": "2024-11-08 09:21:08",
"date": "2024-11-08 16:37:16",
"forward": "...",
"guid": "...",
"host": "node.fmz.com:9902",
"id": 123,
"ip": "...",
"is_owner": true,
"loaded": 0,
"name": "MacBook-Pro-2.local",
"online": true,
"os": "darwin/amd64",
"peer": "...",
"public": 0,
"region": "...",
"tunnel": false,
"version": "...",
"wd": 0
}]
},
"error": null
}
}
返回值字段说明(字面意思较明显的不再赘述):
- all: 托管者总数(包括公共托管者)。
- nodes: 记录托管者节点详细信息。
- build: 版本号。
- city: 所在城市。
- is_owner: true表示是私有托管者,false表示是公共托管者。
- loaded: 负载,搭载策略实例的个数。
- public: 0表示私有托管者,1表示公共托管者。
- region: 地理位置。
- version: 托管者详细版本信息。
- wd: 是否开启离线报警,0表示未开启。
一键部署的托管者包含一些额外信息,字段以ecs_、unit_前缀开头,记录了一键部署托管者服务器的相关信息(运营商名称、配置、状态等),计费周期、价格等信息,不再赘述。
参数
| 名称 | 类型 | 必填 | 描述 |
offset | number | 否 | 分页偏移,默认为0。 |
limit | number | 否 | 每页数量;不传或小于等于0时返回全部。 |
DeleteNode
DeleteNode方法用于删除请求中API KEY对应的发明者量化交易平台账号下的托管者节点,删除的托管者节点ID为nid参数指定的托管者ID。
返回值
json
{
"code":0,
"data":{
"result":true,
"error":null
}
}
- result: 是否成功删除关联的托管者程序。
参数
| 名称 | 类型 | 必填 | 描述 |
nid | number | 是 |
|
GetExchangeList
GetExchangeList方法用于获取FMZ量化交易平台支持的交易所列表及其配置信息。
返回值
isSummary参数为false时,返回的数据:
json
{
"code": 0,
"data": {
"result": {
"exchanges": [{
"category": "加密货币||Crypto",
"eid": "Futures_Binance",
"id": 74,
"logo": "/upload/asset/d8d84b23e573e9326b99.svg",
"meta": "[{\"desc\": \"Access Key\", \"qr\":\"apiKey\",\"required\": true, \"type\": \"string\", \"name\": \"AccessKey\", \"label\": \"Access Key\"}, {\"encrypt\": true, \"qr\":\"secretKey\",\"name\": \"SecretKey\", \"required\": true, \"label\": \"Secret Key\", \"type\": \"password\", \"desc\": \"Secret Key\"}]",
"name": "币安期货|Futures_Binance",
"priority": 200,
"stocks": "BTC_USDT,ETH_USDT,ETH_USD",
"website": "https://accounts.binance.com/zh-TC/register?ref=45110270"
}]
},
"error": null
}
}
isSummary参数为true时,返回的数据:
json
{
"code": 0,
"data": {
"result": {
"exchanges": [{
"category": "加密货币||Crypto",
"eid": "Futures_Binance",
"id": 74,
"logo": "/upload/asset/d8d84b23e573e9326b99.svg",
"name": "币安期货|Futures_Binance",
"priority": 200,
"website": "https://accounts.binance.com/zh-TC/register?ref=45110270"
}]
},
"error": null
}
}
- meta: 交易所配置元数据。
参数
| 名称 | 类型 | 必填 | 描述 |
isSummary | bool | 是 |
|
GetPlatformList
GetPlatformList方法用于获取请求中的API KEY对应的发明者量化交易平台账号下的已添加的交易所列表。
返回值
json
{
"code": 0,
"data": {
"result": {
"all": 2,
"platforms": [{
"category": "加密货币||Crypto",
"date": "2023-12-07 13:44:52",
"eid": "Binance",
"id": 123,
"label": "币安",
"logo": "...",
"name": "币安现货|Binance",
"stocks": ["BTC_USDT", "LTC_USDT", "ETH_USDT", "ETC_USDT", "BTC_TUSD", "ETH_TUSD", "BNB_TUSD"],
"website": "..."
}, {
"category": "通用协议|Custom Protocol",
"date": "2020-11-09 11:23:48",
"eid": "Exchange",
"id": 123,
"label": "XX交易所REST协议",
"logo": "...",
"name": "通用协议|Custom Protocol",
"stocks": ["BTC_USDT", "ETH_USDT"],
"website": ""
}]
},
"error": null
}
}
- all: 已添加/配置的交易所对象个数。
- platforms: 交易所相关信息。
- eid: 在发明者量化交易平台上交易所的Id,一些配置、参数中会使用到
eid。
- eid: 在发明者量化交易平台上交易所的Id,一些配置、参数中会使用到
参数
| 名称 | 类型 | 必填 | 描述 |
offset | number | 否 | 分页偏移,默认为0。 |
limit | number | 否 | 每页数量;不传或小于等于0时返回全部。 |
GetStrategyList
GetStrategyList方法用于获取平台策略信息。
返回值
json
{
"code": 0,
"data": {
"result": {
"all": 123,
"strategies": [{
"category": 9,
"date": "2024-11-10 20:40:04",
"description": "",
"forked": 0,
"hits": 0,
"id": 123,
"is_buy": false,
"is_owner": false,
"language": 0,
"last_modified": "2024-11-11 17:23:52",
"name": "HedgeGridStrategy",
"profile": {
"avatar": "...",
"nickname": "abc",
"uid": "4ed225440db1eda23fe05ed10184113e"
},
"public": 0,
"tags": "",
"uid": "4ed225440db1eda23fe05ed10184113e",
"username": "abc"
}]
},
"error": null
}
}
- all: 筛选查询出的策略总数。
- strategies: 查询出的具体策略信息,其中
category、language的取值同上面的参数说明。
参数
| 名称 | 类型 | 必填 | 描述 |
offset | number | 是 | 分页偏移。 |
length | number | 是 | 每页数量;小于等于0时返回全部。 |
strategyType | number | 是 | 查询范围:
|
category | number | 是 | 策略类型:
|
language | number | 是 | 策略的编程语言:
|
kw | string | 是 | 按策略名称模糊匹配的关键字,多个词用空格分隔;空字符串表示不筛选。以 |
groupId | number | 否 | 策略分组: |
orderBy | string | 否 | 排序字段: |
备注
参数中没有needArgs。按旧版文档在category之后多传一个参数,会使后面的参数错位,请按上面的顺序传参,或按参数名传值:
plaintext
api('GetStrategyList', 0, 10, -3, -1, -1, '') # 自己的前10个策略
api('GetStrategyList', strategyType=-3, language=7) # 自己的全部Rust策略
GetRobotGroupList
GetRobotGroupList方法用于获取请求中的API KEY对应的发明者量化交易平台账号下的实盘分组列表。
返回值
json
{
"code": 0,
"data": {
"result": {
"items": [{
"id": 3417,
"name": "测试"
}, {
"id": 3608,
"name": "实盘演示"
}]
},
"error": null
}
}
- items: 实盘分组信息。
- id: 实盘分组Id。
- name: 实盘分组名称。
items字段只记录创建的新分组,「默认」分组不在items中。
参数
无参数
GetRobotList
GetRobotList方法用于获取请求中的API KEY对应的平台账号下的实盘列表。参数都可以省略。
返回值
json
{
"code": 0,
"data": {
"result": {
"all": 1,
"concurrent": 0,
"robots": [{
"charge_time": 1731654846,
"date": "2024-11-12 14:05:29",
"end_time": "2024-11-15 14:56:32",
"fixed_id": 4509153,
"id": 591026,
"is_sandbox": 0,
"name": "测试",
"node_guid": "45891bcf3d57f99b08a43dff76ee1ea1",
"node_id": 4519153,
"node_public": 0,
"profit": 0,
"public": 0,
"refresh": 1731651257000,
"start_time": "2024-11-15 14:56:30",
"status": 3,
"strategy_id": 411670,
"strategy_isowner": true,
"strategy_language": 0,
"strategy_name": "测试",
"strategy_public": 0,
"uid": "105ed6e511cc977921610fdbb7e2a1d6",
"wd": 0
}]
},
"error": null
}
}
- all: 符合条件的实盘总数。
- robots: 实盘信息,
status为实盘状态码。- group_id: 实盘分组Id;如果策略实盘在默认分组中则没有
group_id字段。
- group_id: 实盘分组Id;如果策略实盘在默认分组中则没有
参数
| 名称 | 类型 | 必填 | 描述 |
offset | number | 否 | 分页偏移,默认为0。 |
length | number | 否 | 每页数量;小于等于0时返回全部(默认)。 |
customStatus | number | 否 | 按实盘状态码筛选,见 |
appId | string | 否 | 按实盘的自定义标签(创建时 |
kw | string | 否 | 按实盘名称模糊匹配的关键字,空字符串表示不筛选。 |
groupId | number | 否 | 实盘分组: |
orderBy | string | 否 | 排序字段: |
strategyId | number | 否 | 大于0时只返回该策略的实盘,默认为0(不筛选)。 |
备注
以签名验证页面Python示例中的api()为例:
api('GetRobotList'):获取全部实盘。api('GetRobotList', 'member2'):只传一个字符串时视为标签,获取标签为member2的全部实盘。api('GetRobotList', 0, 100, -1, 'member2', ''):按位置传参,从第0条开始最多获取100个标签为member2的实盘。api('GetRobotList', appId='member2', length=100):按参数名传值,效果同上。
GetRobotDetail
GetRobotDetail方法用于获取请求中的API KEY对应的发明者量化交易平台账号下的实盘详细信息,所要被获取详细信息的实盘Id为robotId参数指定的实盘Id。
返回值
json
{
"code": 0,
"data": {
"result": {
"robot": {
"charge_time": 1732246539,
"charged": 5850000,
"consumed": 5375000000,
"date": "2018-12-28 14:34:51",
"favorite": {
"added": false,
"type": "R"
},
"fixed_id": 123,
"hits": 1,
"id": 123,
"is_deleted": 0,
"is_manager": true,
"is_sandbox": 0,
"name": "测试",
"node_id": 123,
"pexchanges": {
"123": "Futures_OKX"
},
"phash": {
"123": "ca1aca74b9cf7d8624f2af2dac01e36d"
},
"plabels": {
"123": "OKX期货"
},
"priority": 0,
"profit": 0,
"public": 0,
"refresh": 1732244453000,
"robot_args": "[]",
"start_time": "2024-11-22 11:00:48",
"status": 1,
"strategy_args": "[]",
"strategy_exchange_pairs": "[60,[123],[\"ETH_USDT\"]]",
"strategy_id": 123,
"strategy_last_modified": "2024-11-21 16:49:25",
"strategy_name": "测试",
"strategy_public": "0",
"uid": "105ed6e51bcc17792a610fdbb7e2a1d6",
"username": "abc",
"wd": 0
}
},
"error": null
}
}
- charge_time: 下次扣费时间(Unix时间戳,秒),即当前已付费时段的截止时间。
- charged: 累计计费时长,单位为秒。
- consumed: 累计扣费金额,单位为USD,按1e8放大为整数,示例中5375000000即53.75 USD。
- date: 创建日期。
- fixed_id: 实盘运行时指派的托管者ID,如果是自动,该值为-1。
- is_manager: 是否有权限管理该实盘。
- is_sandbox: 是否是模拟盘。
- name: 实盘名称。
- node_id: 托管者ID。
- pexchanges: 实盘配置的交易所对象,123为pid,"Futures_OKX"为交易所Id(eid)。
- plabels: 实盘配置的交易所对象的标签信息。
- profit: 实盘收益数据。
- public: 实盘是否公开。
- refresh: 最近活跃时间。
- strategy_exchange_pairs: 配置的交易所对象,设置的交易对信息。
- wd: 是否开启离线报警。
参数
| 名称 | 类型 | 必填 | 描述 |
robotId | number | 是 |
|
备注
strategy_exchange_pairs属性说明,用以下数据为例:
plaintext
"[60,[44314,42960,15445,14703],[\"BTC_USDT\",\"BTC_USDT\",\"ETH_USDT\",\"ETH_USDT\"]]"
其中第一个数据60,代表实盘设置的默认K线周期为1分钟,即60秒。
[44314,42960,15445,14703]为实盘配置的交易所对象的pid(按添加顺序)。
[\"BTC_USDT\",\"BTC_USDT\",\"ETH_USDT\",\"ETH_USDT\"]为实盘配置的交易所对象设置的交易对(按添加顺序与pid一一对应)。
GetRobotLogs
GetRobotLogs方法用于获取请求中的API KEY对应的发明者量化交易平台账号下的实盘日志信息,所要被获取日志信息的实盘Id为robotId参数指定的实盘Id。
返回值
json
{
"code": 0,
"data": {
"result": {
"chart": "",
"chartTime": 0,
"logs": [{
"Total": 20,
"Max": 20,
"Min": 1,
"Arr": []
}, {
"Total": 0,
"Max": 0,
"Min": 0,
"Arr": []
}, {
"Total": 0,
"Max": 0,
"Min": 0,
"Arr": []
}],
"node_id": 123,
"online": true,
"refresh": 1732201544000,
"status": 4,
"summary": "...",
"updateTime": 1732201532636,
"wd": 0
},
"error": null
}
}
- logs: 日志信息;查询出的若干条日志数据在Arr字段中。
logs中第一个数据结构为实盘数据库中策略日志表中的日志记录。
logs中第二个数据结构为实盘数据库中收益日志表中的日志记录。
logs中第三个数据结构为实盘数据库中图表日志表中的日志记录。 - summary: 实盘状态栏数据。
参数
| 名称 | 类型 | 必填 | 描述 |
robotId | number | 是 |
|
logMinId | number | 是 |
|
logMaxId | number | 是 |
|
logOffset | number | 是 |
|
logLimit | number | 是 |
|
profitMinId | number | 是 |
|
profitMaxId | number | 是 |
|
profitOffset | number | 是 |
|
profitLimit | number | 是 |
|
chartMinId | number | 是 |
|
chartMaxId | number | 是 |
|
chartOffset | number | 是 |
|
chartLimit | number | 是 |
|
chartUpdateBaseId | number | 是 |
|
chartUpdateDate | number | 是 |
|
summaryLimit | number | 是 |
|
logExchange | string | 否 | 只返回该交易所对象(按标签)的日志,空字符串表示不筛选。 |
logKeyword | string | 否 | 只返回日志内容包含该关键字的日志,空字符串表示不筛选。 |
logTypes | string | 否 | 只返回这些类型的日志,日志类型号用逗号分隔,例如 |
备注
-
数据库中的策略日志表
返回数据中logs的属性值(数组结构)的第一个元素中(日志数据)Arr属性值描述如下:plaintext"Arr": [ [3977, 3, "Futures_OKX", "", 0, 0, "Sell(688.9, 2): 20016", 1526954372591, "", ""], [3976, 5, "", "", 0, 0, "this_week 仓位过多, 多: 2", 1526954372410, "", ""] ],id logType eid orderId price amount extra date contractType direction 3977 3 "Futures_OKX" "" 0 0 "Sell(688.9, 2): 20016" 1526954372591 "" "" 3976 5 "" "" 0 0 "this_week 仓位过多, 多: 2" 1526954372410 "" "" extra为打印的日志的附加消息。logType值具体代表的日志类型描述如下:logType: 0 1 2 3 4 5 6 logType意义: BUY SALE RETRACT ERROR PROFIT MESSAGE RESTART 中文意义 买单类型日志 卖单类型日志 撤销 错误 收益 日志 重启 -
数据库中的收益图表日志表
该图表日志表数据与策略日志表中的收益日志一致。plaintext"Arr": [ [202, 2515.44, 1575896700315], [201, 1415.44, 1575896341568] ]以其中一条日志数据为例:
plaintext[202, 2515.44, 1575896700315]202为日志Id,2515.44为收益数值,1575896700315为时间戳。 -
数据库中的图表日志表
plaintext"Arr": [ [23637, 0, "{\"close\":648,\"high\":650.5,\"low\":647,\"open\":650,\"x\":1575960300000}"], [23636, 5, "{\"x\":1575960300000,\"y\":3.0735}"] ]以其中一条日志数据为例:
plaintext[23637, 0, "{\"close\":648,\"high\":650.5,\"low\":647,\"open\":650,\"x\":1575960300000}"],23637为日志Id,0为图表数据系列索引,最后的数据"{\"close\":648,\"high\":650.5,\"low\":647,\"open\":650,\"x\":1575960300000}"为日志数据,这条数据为图表上的K线数据。
NewRobot
NewRobot方法用于在请求中的API KEY对应的平台账号下创建一个实盘并启动运行,与在网页上创建实盘一样会扣费。
返回值
json
{
"code":0,
"data":{
"result":591988,
"error":null
}
}
- result: 创建成功时为新实盘的Id;失败时为负数,含义同
实盘状态码中的异常代码(例如-2没有找到托管者,-5余额不足)。
参数
| 名称 | 类型 | 必填 | 描述 |
settings | JSON对象 | 是 | 实盘配置,字段见
|
备注
用eid方式直接传入交易所配置时,平台不保存meta中的密钥,之后每次用RestartRobot重启这个实盘都必须传入settings。
RestartRobot
RestartRobot方法用于启动(重启)请求中的API KEY对应的平台账号下的实盘,实盘Id由robotId参数指定。启动会扣费。
返回值
json
{
"code":0,
"data":{
"result":1,
"error":null
}
}
- result: 实盘状态码,1即运行中。
参数
| 名称 | 类型 | 必填 | 描述 |
robotId | number | 是 | 实盘Id,可以用 |
settings | JSON对象 | 否 | 实盘配置,字段见 |
备注
在平台页面创建、使用已添加交易所账户(pid)的实盘,可以只传robotId,按实盘当前的配置启动。用eid方式直接传入交易所配置的实盘(通常由扩展API接口创建),平台没有保存密钥,每次重启都必须传入settings。
StopRobot
StopRobot方法用于停止请求中API KEY对应的发明者量化交易平台账号下的实盘。停止运行的实盘Id由robotId参数指定。
返回值
json
{
"code":0,
"data":{
"result":2,
"error":null
}
}
- result: 实盘状态码,2表示停止中。
参数
| 名称 | 类型 | 必填 | 描述 |
robotId | number | 是 |
|
CommandRobot
CommandRobot方法用于向请求中的API KEY对应的发明者量化交易平台账号下的实盘发送交互命令,接收交互命令的实盘Id为robotId参数指定的实盘Id,交互命令由策略中调用的GetCommand()函数捕获返回。
返回值
json
{
"code":0,
"data":{
"result":true,
"error":null
}
}
- result: 交互指令是否发送成功;向一个没有运行的实盘发送指令,返回的数据中result为false。
参数
| 名称 | 类型 | 必填 | 描述 |
robotId | number | 是 |
|
cmd | string | 是 | 发送给实盘的交互命令,策略中用 |
备注
实盘策略,假设这个策略实盘处于运行中,实盘Id为123:
javascript
function main() {
while (true) {
var cmd = GetCommand()
if (cmd) {
Log(cmd)
}
Sleep(2000)
}
}
用签名验证页面Python示例中的api()调用api("CommandRobot", 123, "test command"),Id为123的实盘会收到交互指令:test command,然后通过Log函数输出打印出来。
DeleteRobot
DeleteRobot方法用于删除请求中的API KEY对应的平台账号下的实盘,实盘Id由robotId参数指定。运行中的实盘需要先停止才能删除。删除后不可恢复。
返回值
json
{
"code":0,
"data":{
"result":0,
"error":null
}
}
- result: 删除操作的结果。
- 0:删除成功。
- -1:没有删除:实盘不存在,或者仍在运行、启动中、停止中。
- -2:实盘已删除,但无法与实盘所在的托管者联系,日志数据没有删除;需要到托管者目录
logs/storage/<实盘Id>/下手动删除(例如123.db3)。
参数
| 名称 | 类型 | 必填 | 描述 |
robotId | number | 是 | 要删除的实盘Id,可以用 |
removeLog | bool | 否 | 是否同时删除托管者上的实盘日志数据,默认为 |
PluginRun
PluginRun方法在托管者上执行一段JavaScript代码并返回结果,与开发工具中的「调试工具」、交易终端插件使用同一种执行机制(见插件原理与编写)。执行时不创建实盘、不计费,单次执行最长5分钟。
返回值
json
{
"code": 0,
"data": {
"result": "{\"logs\":[{\"PlatformId\":\"\",\"OrderId\":\"0\",\"LogType\":5,\"Price\":0,\"Amount\":0,\"Extra\":\"Hello FMZ\",\"Currency\":\"\",\"Instrument\":\"\",\"Direction\":\"\",\"Time\":1732267473108}],\"result\":\"\"}",
"error": null
}
}
- result: 执行结果,是一个JSON字符串:
logs为代码中Log()输出的日志,result为main()返回值的JSON文本。
参数
| 名称 | 类型 | 必填 | 描述 |
settings | JSON对象 | 是 | 执行配置,例如:
|
备注
exchanges也可以不引用平台上的交易所账户,直接传入交易所配置,例如:
plaintext
{"eid": "Binance", "pair": "ETH_BTC", "meta": {"AccessKey": "...", "SecretKey": "..."}}
meta的字段名见GetExchangeList返回的meta。exchanges中通常只设置一个交易所对象(调试工具页面也只支持一个);设置两个不会报错,但代码中访问第二个交易所对象时会报错。
扩展API接口返回码
扩展API接口返回的结构如下:
json
{
"code": 0,
"data": {
"result": null,
"error": null
}
}
code是请求本身的状态码:
| 描述 | 代码 |
|---|---|
| 执行成功 | 0 |
错误的API KEY:AccessKey不存在或已禁用;直接验证时secret_key不正确 | 1 |
| 错误的签名 | 2 |
Nonce错误:nonce不大于上次请求的值,或与服务器时间相差超过1小时 | 3 |
| 方法不正确:方法不存在、不对外开放,或这把API KEY没有该方法的权限 | 4 |
参数不正确:args不是合法的JSON,或调用失败 | 5 |
| 内部未知错误 | 6 |
| 请求来源IP不在这把API KEY的IP白名单内 | 7 |
code为0只表示请求被受理。方法的结果在data.result中;方法执行出错时,data.error为错误信息(成功时为null)。例如参数个数不对:
json
{
"code": 0,
"data": {
"result": null,
"error": "Params number mismatch for StopRobot: expected 1, got 0"
}
}