输入/搜索内容
欢迎使用发明者量化交易平台
编程语言
JavaScript
TypeScript
Python
C++
My语言(麦语言)
PINE语言
Blockly可视化
Workflow工作流
密钥安全性
实盘
策略库
托管者
部署托管者
一键租用托管者
手动部署托管者
托管者操作注意事项
全局指定IP地址
命令行版本托管者程序的参数
实盘数据迁移
托管者监控
交易所
策略编辑器
回测系统
策略入口函数
策略框架与API函数
模板类库
策略参数
交互控件
期权交易
C++策略编写说明
JavaScript策略编写说明
Web3
内置库
扩展API接口
MCP 服务
交易终端
数据探索
Alpha因子分析工具
通用协议
调试工具
远程编辑
完整策略的导入与导出
多语言支持
实盘、策略分组
实盘展示
策略分享与出租
实盘消息推送
实盘报错、异常退出的常见原因
交易所特殊说明

发明者量化交易平台的回测系统支持自定义数据源,回测系统使用GET方法请求自定义的URL(可公开访问的网址)来获取外部数据源进行回测,附加的请求参数如下:

参数意义说明
symbol品种名称现货行情数据示例:BTC_USDT,期货行情数据示例:BTC_USDT.swap,期货永续合约资金费率数据示例:BTC_USDT.funding,期货永续合约价格指数数据示例:BTC_USDT.index
eid交易所例如:OKX、Futures_OKX
round数据精度为true时,表示由自定义数据源返回的数据中定义具体精度。发明者量化交易平台回测系统向自定义数据源发送的请求固定为:round=true
periodK线数据的周期(毫秒)例如:60000表示1分钟周期
depth深度档数1-20
trades是否需要逐笔成交数据真(1)/假(0)
from开始时间unix时间戳
to结束时间unix时间戳
detail请求品种的详细信息为true时,表示需要由自定义数据源提供。发明者量化交易平台回测系统向自定义数据源发送的请求固定为:detail=true
custom--可忽略此参数

现货交易所、期货交易所对象的数据源设置为自定义数据源(feeder)时,回测系统向自定义数据源服务发送请求的示例:

url
http://customserver:9090/data?custom=0&depth=20&detail=true&eid=Bitget&from=1351641600&period=86400000&round=true&symbol=BTC_USDT&to=1611244800&trades=1 http://customserver:9090/data?custom=0&depth=20&detail=true&eid=Futures_OKX&from=1351641600&period=86400000&round=true&symbol=BTC_USDT.swap&to=1611244800&trades=1

返回的格式必须为以下两种格式之一(系统自动识别):

  • 模拟级Tick,以下是JSON数据示例:
    json
    { "detail": { "eid": "Binance", "symbol": "BTC_USDT", "alias": "BTCUSDT", "baseCurrency": "BTC", "quoteCurrency": "USDT", "marginCurrency": "USDT", "basePrecision": 5, "quotePrecision": 2, "minQty": 0.00001, "maxQty": 9000, "minNotional": 5, "maxNotional": 9000000, "priceTick": 0.01, "volumeTick": 0.00001, "marginLevel": 10 }, "schema":["time", "open", "high", "low", "close", "vol"], "data":[ [1564315200000, 9531300, 9531300, 9497060, 9497060, 787], [1564316100000, 9495160, 9495160, 9474260, 9489460, 338] ] }
  • 实盘级Tick,以下是JSON数据示例:
    Tick级回测数据(包含盘口深度信息,深度格式为[价格, 数量]的数组。可包含多级深度,asks按价格升序排列,bids按价格降序排列)。
    json
    { "detail": { "eid": "Binance", "symbol": "BTC_USDT", "alias": "BTCUSDT", "baseCurrency": "BTC", "quoteCurrency": "USDT", "marginCurrency": "USDT", "basePrecision": 5, "quotePrecision": 2, "minQty": 0.00001, "maxQty": 9000, "minNotional": 5, "maxNotional": 9000000, "priceTick": 0.01, "volumeTick": 0.00001, "marginLevel": 10 }, "schema":["time", "asks", "bids", "trades", "close", "vol"], "data":[ [1564315200000, [[9531300, 10]], [[9531300, 10]], [[1564315200000, 0, 9531300, 10]], 9497060, 787], [1564316100000, [[9531300, 10]], [[9531300, 10]], [[1564316100000, 0, 9531300, 10]], 9497060, 787] ] }
字段说明
detail请求数据的品种详细信息,包含计价币名称、交易币名称、精度、最小下单量等
schema指定data数组中列的属性,区分大小写。仅限于 time, open, high, low, close, vol, asks, bids, trades
data按照schema设置的列结构记录的数据

detail字段

字段说明
eid交易所ID,注意同一交易所的现货与期货使用不同的eid
symbol交易品种代码
alias当前交易品种代码在交易所中对应的symbol
baseCurrency交易币种
quoteCurrency计价币种
marginCurrency保证金币种
basePrecision交易币种精度
quotePrecision计价币种精度
minQty最小下单量
maxQty最大下单量
minNotional最小下单金额
maxNotional最大下单金额
priceTick价格最小变动单位
volumeTick下单量最小变动单位
marginLevel期货杠杆倍数
contractType对于永续合约设置为:swap,回测系统将继续发送资金费率、价格指数请求

特殊列属性asksbidstrades说明:

字段说明备注
asks / bids[[价格, 数量], ...]例如实盘级 Tick数据示例中的数据:[[9531300, 10]]
trades[[时间, 方向(0:买,1:卖), 价格, 数量], ...]例如实盘级 Tick数据示例中的数据:[[1564315200000, 0, 9531300, 10]]

期货交易所的永续合约回测时,自定义数据源还需要提供额外的资金费率数据和价格指数数据。只有当请求的行情数据返回时,返回结构中的detail字段包含"contractType": "swap"键值对,回测系统才会继续发送资金费率请求。
当回测系统收到资金费率数据后,才会继续发送价格指数数据请求。

资金费率数据结构如下:

json
{ "detail": { "eid": "Futures_Binance", "symbol": "BTC_USDT.funding", "alias": "BTC_USDT.funding", "baseCurrency": "BTC", "quoteCurrency": "USDT", "marginCurrency": "", "basePrecision": 8, "quotePrecision": 8, "minQty": 1, "maxQty": 10000, "minNotional": 1, "maxNotional": 100000000, "priceTick": 1e-8, "volumeTick": 1e-8, "marginLevel": 10 }, "schema": [ "time", "open", "high", "low", "close", "vol" ], "data": [ [ 1584921600000, -16795, -16795, -16795, -16795, 0 ], [ 1584950400000, -16294, -16294, -16294, -16294, 0 ] // ... ] }
  • 相邻周期间隔为8小时
  • 例如币安资金费率每8小时更新一次,资金费率数据为何是 -16795?
    这是因为与K线数据一样,为避免网络传输过程中浮点数精度丢失,数据采用整型表示;资金费率数据也可能为负值。

回测系统发出的资金费率数据请求示例:

url
http://customserver:9090/data?custom=0&depth=20&detail=true&eid=Futures_Binance&from=1351641600&period=86400000&round=true&symbol=BTC_USDT.funding&to=1611244800&trades=0

价格指数数据结构如下:

json
{ "detail": { "eid": "Futures_Binance", "symbol": "BTC_USDT.index", "alias": "BTCUSDT", "baseCurrency": "BTC", "quoteCurrency": "USDT", "contractType": "index", "marginCurrency": "USDT", "basePrecision": 3, "quotePrecision": 1, "minQty": 0.001, "maxQty": 1000, "minNotional": 0, "maxNotional": 1.7976931348623157e+308, "priceTick": 0.1, "volumeTick": 0.001, "marginLevel": 10, "volumeMultiple": 1 }, "schema": [ "time", "open", "high", "low", "close", "vol" ], "data": [ [1584921600000, 58172, 59167, 56902, 58962, 0], [1584922500000, 58975, 59428, 58581, 59154, 0], // ... ] }

回测系统发出的价格指数数据请求示例:

url
http://customserver:9090/data?custom=0&depth=20&detail=true&eid=Futures_Binance&from=1351641600&period=86400000&round=true&symbol=BTC_USDT.index&to=1611244800&trades=0

指定数据源地址,例如:http://120.24.2.20:9090/data。自定义数据源服务程序使用Golang编写:

golang
package main import ( "fmt" "net/http" "encoding/json" ) func Handle (w http.ResponseWriter, r *http.Request) { // e.g. set on backtest DataSourse: http://xxx.xx.x.xx:9090/data // request: GET http://xxx.xx.x.xx:9090/data?custom=0&depth=20&detail=true&eid=OKX&from=1584921600&period=86400000&round=true&symbol=BTC_USDT&to=1611244800&trades=1 // http://xxx.xx.x.xx:9090/data?custom=0&depth=20&detail=true&eid=Futures_Binance&from=1599958800&period=3600000&round=true&symbol=BTC_USDT.swap&to=1611244800&trades=0 fmt.Println("request:", r) // response defer func() { // response data /* e.g. data { "detail": { "eid": "Binance", "symbol": "BTC_USDT", "alias": "BTCUSDT", "baseCurrency": "BTC", "quoteCurrency": "USDT", "marginCurrency": "USDT", "basePrecision": 5, "quotePrecision": 2, "minQty": 0.00001, "maxQty": 9000, "minNotional": 5, "maxNotional": 9000000, "priceTick": 0.01, "volumeTick": 0.00001, "marginLevel": 10 }, "schema": [ "time", "open", "high", "low", "close", "vol" ], "data": [ [1610755200000, 3673743, 3795000, 3535780, 3599498, 8634843151], [1610841600000, 3599498, 3685250, 3385000, 3582861, 8015772738], [1610928000000, 3582499, 3746983, 3480000, 3663127, 7069811875], [1611014400000, 3662246, 3785000, 3584406, 3589149, 7961130777], [1611100800000, 3590194, 3641531, 3340000, 3546823, 8936842292], [1611187200000, 3546823, 3560000, 3007100, 3085013, 13500407666], [1611273600000, 3085199, 3382653, 2885000, 3294517, 14297168405], [1611360000000, 3295000, 3345600, 3139016, 3207800, 6459528768], [1611446400000, 3207800, 3307100, 3090000, 3225990, 5797803797], [1611532800000, 3225945, 3487500, 3191000, 3225420, 8849922692] ] } */ // /* 模拟级Tick ret := map[string]interface{}{ "detail": map[string]interface{}{ "eid": "Binance", "symbol": "BTC_USDT", "alias": "BTCUSDT", "baseCurrency": "BTC", "quoteCurrency": "USDT", "marginCurrency": "USDT", "basePrecision": 5, "quotePrecision": 2, "minQty": 0.00001, "maxQty": 9000, "minNotional": 5, "maxNotional": 9000000, "priceTick": 0.01, "volumeTick": 0.00001, "marginLevel": 10, }, "schema": []string{"time","open","high","low","close","vol"}, "data": []interface{}{ []int64{1610755200000, 3673743, 3795000, 3535780, 3599498, 8634843151}, // 1610755200000 : 2021-01-16 08:00:00 []int64{1610841600000, 3599498, 3685250, 3385000, 3582861, 8015772738}, // 1610841600000 : 2021-01-17 08:00:00 []int64{1610928000000, 3582499, 3746983, 3480000, 3663127, 7069811875}, []int64{1611014400000, 3662246, 3785000, 3584406, 3589149, 7961130777}, []int64{1611100800000, 3590194, 3641531, 3340000, 3546823, 8936842292}, []int64{1611187200000, 3546823, 3560000, 3007100, 3085013, 13500407666}, []int64{1611273600000, 3085199, 3382653, 2885000, 3294517, 14297168405}, []int64{1611360000000, 3295000, 3345600, 3139016, 3207800, 6459528768}, []int64{1611446400000, 3207800, 3307100, 3090000, 3225990, 5797803797}, []int64{1611532800000, 3225945, 3487500, 3191000, 3225420, 8849922692}, }, } // */ /* 实盘级Tick ret := map[string]interface{}{ "detail": map[string]interface{}{ "eid": "Binance", "symbol": "BTC_USDT", "alias": "BTCUSDT", "baseCurrency": "BTC", "quoteCurrency": "USDT", "marginCurrency": "USDT", "basePrecision": 5, "quotePrecision": 2, "minQty": 0.00001, "maxQty": 9000, "minNotional": 5, "maxNotional": 9000000, "priceTick": 0.01, "volumeTick": 0.00001, "marginLevel": 10, }, "schema": []string{"time", "asks", "bids", "trades", "close", "vol"}, "data": []interface{}{ []interface{}{1610755200000, []interface{}{[]int64{9531300, 10}}, []interface{}{[]int64{9531300, 10}}, []interface{}{[]int64{1610755200000, 0, 9531300, 10}}, 9497060, 787}, []interface{}{1610841600000, []interface{}{[]int64{9531300, 15}}, []interface{}{[]int64{9531300, 15}}, []interface{}{[]int64{1610841600000, 0, 9531300, 11}}, 9497061, 789}, }, } */ b, _ := json.Marshal(ret) w.Write(b) }() } func main () { fmt.Println("listen http://localhost:9090") http.HandleFunc("/data", Handle) http.ListenAndServe(":9090", nil) }

测试策略,JavaScript示例:

javascript
/*backtest start: 2021-01-16 08:00:00 end: 2021-01-22 00:00:00 period: 1d basePeriod: 1d exchanges: [{"eid":"OKX","currency":"BTC_USDT","feeder":"http://120.24.2.20:9090/data"}] args: [["number",2]] */ function main() { var ticker = exchange.GetTicker() var records = exchange.GetRecords() Log(exchange.GetName(), exchange.GetCurrency()) Log(ticker) Log(records) }