优宽量化交易平台的回测系统支持自定义数据源,回测系统使用GET
方法请求自定义的URL(可公开可访问的网址)来获取外部数据源进行回测,附加的请求参数如下:
参数 | 意义 | 说明 |
---|---|---|
symbol | 品种名 | 如: FUTURES_CNY.MA501 |
eid | 交易所 | 如: Futures_CTP |
round | 数据精度 | 为true,表示由自定义数据源反馈的数据中定义具体精度。优宽量化交易平台回测系统向自定义数据源发送的请求固定为:round=true |
period | K线数据的周期(毫秒) | 例如:60000 为1分钟周期 |
depth | 深度档数 | 1-20 |
trades | 是否需要分笔数据 | 真(1)/假(0) |
from | 开始时间 | unix时间戳 |
to | 结束时间 | unix时间 |
detail | 请求数据的品种详细信息 | 为true,表示需要由自定义数据源提供。优宽量化交易平台回测系统向自定义数据源发送的请求固定为:detail=true |
custom | – | 可以忽略该参数 |
交易所对象的数据源设置为自定义数据源(feeder)时回测系统向自定义数据源服务发送请求的例子:
// 模拟级Tick
http://customserver:9090/data?custom=0&depth=20&detail=true&eid=Futures_CTP&from=1719745260&period=60000&round=true&symbol=FUTURES_CNY.MA501&to=1720281600&trades=0
// 实盘级Tick
http://customserver:9090/data?custom=0&depth=20&detail=true&eid=Futures_CTP&from=1719763200&period=1000&round=true&symbol=FUTURES_CNY.MA501&to=1720281600&trades=0
返回的格式必须为以下两种格式其中之一(系统自动识别):
模拟级 Tick,以下是JSON数据范例: 普通的Bar级别回测,以下是数据范例:
{
"detail": {
"alias": "MA501",
"baseCurrency": "FUTURES",
"basePrecision": 1,
"contractType": "MA501",
"eid": "Futures_CTP",
"info": {
"CombinationType": 48,
"CreateDate": 20240116,
"DeliveryMonth": 1,
"DeliveryYear": 1501,
"EndDelivDate": 20250114,
"ExchangeID": "CZCE",
"ExchangeInstID": "MA501",
"ExpireDate": 20250114,
"InstLifePhase": 49,
"InstrumentID": "MA501",
"InstrumentName": "甲醇1月",
"IsTrading": 1,
"LongMarginRatio": 0.08,
"MaxLimitOrderVolume": 1000,
"MaxMarginSideAlgorithm": 48,
"MaxMarketOrderVolume": 200,
"MinLimitOrderVolume": 1,
"MinMarketOrderVolume": 1,
"OpenDate": 20240116,
"OptionsType": 0,
"PositionDateType": 50,
"PositionType": 50,
"PriceTick": 1,
"ProductClass": 49,
"ProductID": "MA",
"ShortMarginRatio": 0.08,
"StartDelivDate": 0,
"StrikePrice": 0,
"UnderlyingInstrID": "",
"UnderlyingMultiple": 1,
"VolumeMultiple": 10
},
"marginCurrency": "CNY",
"marginLevel": 12,
"maxNotional": 10000000,
"maxQty": 1000,
"minNotional": 1,
"minQty": 1,
"priceTick": 1,
"quoteCurrency": "CNY",
"quotePrecision": 0,
"symbol": "MA501",
"volumeTick": 1
},
"schema": ["time", "open", "high", "low", "close", "vol", "position"],
"data": [
[1719795600000, 2632, 2633, 2621, 2625, 13070, 1720510], // 2024-07-01 09:00:00
[1719795660000, 2625, 2625, 2621, 2623, 4280, 1720940], // 2024-07-01 09:01:00
[1719795720000, 2623, 2626, 2622, 2622, 5320, 1722310], // 2024-07-01 09:02:00
[1719795780000, 2622, 2625, 2620, 2625, 3480, 1722160],
[1719795840000, 2624, 2624, 2622, 2623, 2220, 1723150],
[1719795900000, 2623, 2624, 2620, 2620, 3080, 1722840],
[1719795960000, 2621, 2622, 2620, 2620, 3090, 1723850]
]
}
实盘级 Tick,以下是JSON数据范例:
Tick级回测的数据(包含盘口深度信息,深度格式为[价格, 量]
的数组。可有多级深度,asks
为价格升序,bids
为价格倒序)。
// 不含分笔数据
{
"detail": {
"alias": "MA501",
"baseCurrency": "FUTURES",
"basePrecision": 1,
"contractType": "MA501",
"eid": "Futures_CTP",
"info": {
"CombinationType": 48,
"CreateDate": 20240116,
"DeliveryMonth": 1,
"DeliveryYear": 1501,
"EndDelivDate": 20250114,
"ExchangeID": "CZCE",
"ExchangeInstID": "MA501",
"ExpireDate": 20250114,
"InstLifePhase": 49,
"InstrumentID": "MA501",
"InstrumentName": "甲醇1月",
"IsTrading": 1,
"LongMarginRatio": 0.08,
"MaxLimitOrderVolume": 1000,
"MaxMarginSideAlgorithm": 48,
"MaxMarketOrderVolume": 200,
"MinLimitOrderVolume": 1,
"MinMarketOrderVolume": 1,
"OpenDate": 20240116,
"OptionsType": 0,
"PositionDateType": 50,
"PositionType": 50,
"PriceTick": 1,
"ProductClass": 49,
"ProductID": "MA",
"ShortMarginRatio": 0.08,
"StartDelivDate": 0,
"StrikePrice": 0,
"UnderlyingInstrID": "",
"UnderlyingMultiple": 1,
"VolumeMultiple": 10
},
"marginCurrency": "CNY",
"marginLevel": 12,
"maxNotional": 10000000,
"maxQty": 1000,
"minNotional": 1,
"minQty": 1,
"priceTick": 1,
"quoteCurrency": "CNY",
"quotePrecision": 0,
"symbol": "MA501",
"volumeTick": 1
},
"schema": ["time", "asks", "bids", "close", "vol", "position"],
"data": [
[1719795601778, [[2633, 50]], [[2631, 50]], 2632, 110410, 1718490],
[1719795602192, [[2632, 120]], [[2631, 50]], 2632, 110410, 1718490],
[1719795603873, [[2631, 20]], [[2630, 600]], 2631, 110780, 1718790],
[1719795604769, [[2633, 120]], [[2630, 490]], 2631, 111300, 1718860],
[1719795605661, [[2632, 200]], [[2631, 30]], 2632, 111750, 1718880]
]
}
字段 | 说明 |
---|---|
schema | 指定data数组里列的属性,区分大小写, 仅限于 time, open, high, low, close, vol, asks, bids, trades |
data | 一个按schema指一列保存数据的数组 |
detail | 商品期货的品种需要提供的属性 |
detail字段
字段 | 说明 | 例子 |
---|---|---|
alias | 合约代码 | rb2501 |
baseCurrency | 交易品种 | FUTURES |
basePrecision | 交易品种精度 | 1 |
contractType | 合约代码 | rb2501 |
eid | 交易所对象Id | Futures_CTP |
info | 合约详细信息 | 其中记录了合约的上市日期、交割日期、合约乘数、价格一跳等信息。 |
marginCurrency | 保证金币种 | CNY |
marginLevel | 杠杆倍数 | 该数据和合约具体的保证金率有关,一般不可修改 |
maxNotional | 单笔最大下单金额 | 10000000 |
maxQty | 单笔最大下单数量 | 1000 |
minNotional | 单笔最小下单金额 | 1 |
minQty | 单笔最小下单数量 | 1 |
priceTick | 价格一跳 | – |
quoteCurrency | 计价货币 | CNY |
quotePrecision | 计价货币精度 | 0 |
symbol | 合约代码 | rb2501 |
volumeTick | 下单量最小变动幅度 | 1 |
特殊的列属性asks
、bids
、trades
:
字段 | 说明 | 备注 |
---|---|---|
asks / bids | [[价格, 数量], …] | 例如实盘级 Tick 数据范例中的数据:[[9531300, 10]] |
trades | [[时间, 方向(0:买,1:卖), 价格, 数量], …] | 例如实盘级 Tick 数据范例中的数据:[[1564315200000, 0, 9531300, 10]] |
detail字段中info
字段值内容与exchange.SetContractType()函数返回的数据Info字段一致。
detail字段中timeLine
字段说明:
当策略代码中设置的合约代码为主力连续合约(例如:MA888
)、指数合约(例如:MA000
)时,自定义数据源应答的数据的detail中还需要增加一个timeLine字段。
// timeLine字段值
[
{
"begin": 1451836800000,
"end": 1460013300000,
"symbol": "MA605"
}, {
"begin": 1460034000000,
"end": 1470640500000,
"symbol": "MA609"
}
// ...
]
指定数据源地址,例如:http://120.24.2.20:9090/data
。自定义数据源服务程序使用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
// r.URL: /data?custom=0&depth=20&detail=true&eid=Futures_CTP&from=1719745260&period=60000&round=true&symbol=FUTURES_CNY.MA501&to=1720281600&trades=0
fmt.Println("request:", r)
// response
defer func() {
// response data
/* e.g. data
{
"detail": {
"alias": "MA501",
"baseCurrency": "FUTURES",
"basePrecision": 1,
"contractType": "MA501",
"eid": "Futures_CTP",
"info": {
"CombinationType": 48,
"CreateDate": 20240116,
"DeliveryMonth": 1,
"DeliveryYear": 1501,
"EndDelivDate": 20250114,
"ExchangeID": "CZCE",
"ExchangeInstID": "MA501",
"ExpireDate": 20250114,
"InstLifePhase": 49,
"InstrumentID": "MA501",
"InstrumentName": "甲醇1月",
"IsTrading": 1,
"LongMarginRatio": 0.08,
"MaxLimitOrderVolume": 1000,
"MaxMarginSideAlgorithm": 48,
"MaxMarketOrderVolume": 200,
"MinLimitOrderVolume": 1,
"MinMarketOrderVolume": 1,
"OpenDate": 20240116,
"OptionsType": 0,
"PositionDateType": 50,
"PositionType": 50,
"PriceTick": 1,
"ProductClass": 49,
"ProductID": "MA",
"ShortMarginRatio": 0.08,
"StartDelivDate": 0,
"StrikePrice": 0,
"UnderlyingInstrID": "",
"UnderlyingMultiple": 1,
"VolumeMultiple": 10
},
"marginCurrency": "CNY",
"marginLevel": 12,
"maxNotional": 10000000,
"maxQty": 1000,
"minNotional": 1,
"minQty": 1,
"priceTick": 1,
"quoteCurrency": "CNY",
"quotePrecision": 0,
"symbol": "MA501",
"volumeTick": 1
},
"schema": ["time", "open", "high", "low", "close", "vol", "position"],
"data": [
[1719795600000, 2632, 2633, 2621, 2625, 13070, 1720510], // 2024-07-01 09:00:00
[1719795660000, 2625, 2625, 2621, 2623, 4280, 1720940], // 2024-07-01 09:01:00
[1719795720000, 2623, 2626, 2622, 2622, 5320, 1722310], // 2024-07-01 09:02:00
[1719795780000, 2622, 2625, 2620, 2625, 3480, 1722160],
[1719795840000, 2624, 2624, 2622, 2623, 2220, 1723150],
[1719795900000, 2623, 2624, 2620, 2620, 3080, 1722840],
[1719795960000, 2621, 2622, 2620, 2620, 3090, 1723850]
]
}
*/
// /* 模拟级Tick
ret := map[string]interface{}{
"detail": map[string]interface{}{
"alias": "MA501",
"baseCurrency": "FUTURES",
"basePrecision": 1,
"contractType": "MA501",
"eid": "Futures_CTP",
"info": map[string]interface{}{
"CombinationType": 48,
"CreateDate": 20240116,
"DeliveryMonth": 1,
"DeliveryYear": 1501,
"EndDelivDate": 20250114,
"ExchangeID": "CZCE",
"ExchangeInstID": "MA501",
"ExpireDate": 20250114,
"InstLifePhase": 49,
"InstrumentID": "MA501",
"InstrumentName": "甲醇1月",
"IsTrading": 1,
"LongMarginRatio": 0.08,
"MaxLimitOrderVolume": 1000,
"MaxMarginSideAlgorithm": 48,
"MaxMarketOrderVolume": 200,
"MinLimitOrderVolume": 1,
"MinMarketOrderVolume": 1,
"OpenDate": 20240116,
"OptionsType": 0,
"PositionDateType": 50,
"PositionType": 50,
"PriceTick": 1,
"ProductClass": 49,
"ProductID": "MA",
"ShortMarginRatio": 0.08,
"StartDelivDate": 0,
"StrikePrice": 0,
"UnderlyingInstrID": "",
"UnderlyingMultiple": 1,
"VolumeMultiple": 10,
},
"marginCurrency": "CNY",
"marginLevel": 12,
"maxNotional": 10000000,
"maxQty": 1000,
"minNotional": 1,
"minQty": 1,
"priceTick": 1,
"quoteCurrency": "CNY",
"quotePrecision": 0,
"symbol": "MA501",
"volumeTick": 1,
},
"schema": []string{"time", "open", "high", "low", "close", "vol", "position"},
"data": []interface{}{
[]int64{1719795600000, 2632, 2633, 2621, 2625, 13070, 1720510},
[]int64{1719795660000, 2625, 2625, 2621, 2623, 4280, 1720940},
[]int64{1719795720000, 2623, 2626, 2622, 2622, 5320, 1722310},
[]int64{1719795780000, 2622, 2625, 2620, 2625, 3480, 1722160},
[]int64{1719795840000, 2624, 2624, 2622, 2623, 2220, 1723150},
[]int64{1719795900000, 2623, 2624, 2620, 2620, 3080, 1722840},
[]int64{1719795960000, 2621, 2622, 2620, 2620, 3090, 1723850},
},
}
// */
/* 实盘级Tick
ret := map[string]interface{}{
"detail": map[string]interface{}{
"alias": "MA501",
"baseCurrency": "FUTURES",
"basePrecision": 1,
"contractType": "MA501",
"eid": "Futures_CTP",
"info": map[string]interface{}{
"CombinationType": 48,
"CreateDate": 20240116,
"DeliveryMonth": 1,
"DeliveryYear": 1501,
"EndDelivDate": 20250114,
"ExchangeID": "CZCE",
"ExchangeInstID": "MA501",
"ExpireDate": 20250114,
"InstLifePhase": 49,
"InstrumentID": "MA501",
"InstrumentName": "甲醇1月",
"IsTrading": 1,
"LongMarginRatio": 0.08,
"MaxLimitOrderVolume": 1000,
"MaxMarginSideAlgorithm": 48,
"MaxMarketOrderVolume": 200,
"MinLimitOrderVolume": 1,
"MinMarketOrderVolume": 1,
"OpenDate": 20240116,
"OptionsType": 0,
"PositionDateType": 50,
"PositionType": 50,
"PriceTick": 1,
"ProductClass": 49,
"ProductID": "MA",
"ShortMarginRatio": 0.08,
"StartDelivDate": 0,
"StrikePrice": 0,
"UnderlyingInstrID": "",
"UnderlyingMultiple": 1,
"VolumeMultiple": 10,
},
"marginCurrency": "CNY",
"marginLevel": 12,
"maxNotional": 10000000,
"maxQty": 1000,
"minNotional": 1,
"minQty": 1,
"priceTick": 1,
"quoteCurrency": "CNY",
"quotePrecision": 0,
"symbol": "MA501",
"volumeTick": 1,
},
"schema": []string{"time", "asks", "bids", "close", "vol", "position"},
"data": []interface{}{
[]interface{}{1719795601778, []interface{}{[]int64{2633, 50}}, []interface{}{[]int64{2631, 50}}, 2632, 110410, 1718490},
[]interface{}{1719795602192, []interface{}{[]int64{2632, 120}}, []interface{}{[]int64{2631, 50}}, 2632, 110410, 1718490},
[]interface{}{1719795603873, []interface{}{[]int64{2631, 20}}, []interface{}{[]int64{2630, 600}}, 2631, 110780, 1718790},
[]interface{}{1719795604769, []interface{}{[]int64{2633, 120}}, []interface{}{[]int64{2630, 490}}, 2631, 111300, 1718860},
[]interface{}{1719795605661, []interface{}{[]int64{2632, 200}}, []interface{}{[]int64{2631, 30}}, 2632, 111750, 1718880},
},
}
*/
b, _ := json.Marshal(ret)
w.Write(b)
}()
}
func main () {
fmt.Println("listen http://localhost:9090")
http.HandleFunc("/data", Handle)
http.ListenAndServe(":9090", nil)
}
测试策略,JavaScript
范例:
/*backtest
start: 2024-07-01 00:00:00
end: 2024-07-07 00:00:00
period: 1m
basePeriod: 1m
exchanges: [{"eid":"Futures_CTP","currency":"FUTURES","feeder":"http://120.24.2.20:9090/data"}]
*/
function main() {
// 对于测试代码,我们通过判断exchange.IO("status")函数,连接成功之后执行测试代码,区别于商品期货策略一般架构
while (!exchange.IO("status")) {
Sleep(1000)
}
// 设置合约为MA501
exchange.SetContractType("MA501")
// 获取ticker数据
var ticker = exchange.GetTicker()
// 获取records数据,即K线数据
var records = exchange.GetRecords()
// 打印数据
Log(ticker)
Log(records)
}
保存回测设置
本地回测引擎