资源加载中... loading...

商品期货API文档(旧文档)

Author: 雨幕(youquant), Created: 2021-10-20 19:26:38, Updated: 2024-06-20 16:13:22

Name`。

如果创建使用通用协议插件支持交易所的实盘,在配置Settings这个参数时,对于exchanges属性可以使用如下设置:

  {"eid": "Exchange", "label" : "test", "pair": "xxx", "meta" :{ ... , "Front" : "http://127.0.0.1:6666/XXX"}}
  
- 测试用策略:
  - 策略参数
    ```Interval```

  - ```JavaScript```策略代码
    ```javascript
    function main(){
        Sleep(6000)
        Log(exchange.GetAccount())
        Log("Interval:", Interval)
    }
    ```

- 返回值:

// 成功创建实盘 { “code”: 0, “data”: { “result”: 74260, “error”: null } }


#### PluginRun

```PluginRun```,参数:```Settings```。使用扩展API接口调用**调试工具**功能。

调试工具页面地址:https://www.youquant.com/m/debug

- 参数
  ```Settings```为```JSON```对象类型,即调试工具中的设置(```Settings```配置中包括了测试代码写在```source```属性中)。

- 测试代码
  ```Python```范例:
  ```python
  #!/usr/bin/python
  # -*- coding: utf-8 -*-
  import time
  import json
  import ssl
  ssl._create_default_https_context = ssl._create_unverified_context  

  try:
      import md5
      import urllib2
      from urllib import urlencode
  except:
      import hashlib as md5
      import urllib.request as urllib2
      from urllib.parse import urlencode  

  # API KEY已经打码,可用自己的API KEY测试
  accessKey = 'f77XXXXXXXXXXXXXXX757'
  # API KEY已经打码,可用自己的API KEY测试
  secretKey = 'd8XXXXXXXXXXXXXXXX41ca97ea15'  

  def api(method, *args):
      d = {
          'version': '1.0',
          'access_key': accessKey,
          'method': method,
          'args': json.dumps(list(args)),
          'nonce': int(time.time() * 1000),
          }  

      d['sign'] = md5.md5(('%s|%s|%s|%d|%s' % (d['version'], d['method'], d['args'], d['nonce'], secretKey)).encode('utf-8')).hexdigest()
      # 注意: urllib2.urlopen 函数,超时问题,可以设置超时时间,urllib2.urlopen('https://www.youquant.com/api/v1', urlencode(d).encode('utf-8'), timeout=10) 设置超时 10秒
      return json.loads(urllib2.urlopen('https://www.youquant.com/api/v1', urlencode(d).encode('utf-8')).read().decode('utf-8'))  

  # 返回托管者列表  

  code = '''
  function main() {
      Sleep(6000)
      Log(exchange.GetAccount())      
      return exchanges[0].GetPosition()
  }
  '''  

  settings = { 
      # K线周期参数,60即为60秒
      "period": 60,                                 
      "source": code, 
      # 托管者ID,可以指定在哪个托管者上运行实盘,如果该值为-1,代表自动分配
      "node" : 12345,                               
      "exchanges": [
          {"pid": 1234, "pair": "FUTURES"},
          {"pid": 1223, "pair": "FUTURES"}
      ]
  }  

  print(api('PluginRun', settings))

注意: {"pid": 1234, "pair": "FUTURES"} {"pid": 1223, "pair": "FUTURES"} 对于settings中的exchanges属性来说,在调用PluginRun接口时只用设置一个(在调试工具页面使用时也只支持一个交易所对象)。在settings里设置2个交易所对象不会引起报错,但是在代码中如果访问第二个交易所对象就会报错。

  • 返回值 api("PluginRun", settings)返回结果:
    
    {
      'code': 0, 
      'data': {
          'result': '
              {
                  "logs":[
                      {...}            // Log(exchange.GetAccount())
                  ],
                  "result":"[]"        // return exchanges[0].GetPosition()
              }', 
          'error': None
      }
    }
    

GetRobotLogs


- 参数
  |参数名|类型|备注|
  |-|-|-|
  |robotId|为int类型|实盘ID|
  
  **table Log**,查询数据库表Log的数据:

  |参数名|类型|备注|
  |-|-|-|
  |logMinId|为int类型|Log日志的最小ID|
  |logMaxId|为int类型|Log日志的最大ID|
  |logOffset|为int类型|由logMinId和logMaxId确定范围后,根据logOffset偏移(跳过多少条记录),开始作为获取数据的起始位置。|
  |logLimit|为int类型|确定起始位置后,选取的数据记录条数。|
   
  **table Profit**,查询数据库表Profit的数据:

  |参数名|类型|备注|
  |-|-|-|      
  |profitMinId|为int类型|记录最小ID|
  |profitMaxId|为int类型|记录最大ID|
  |profitOffset|为int类型|偏移(跳过多少条记录),作为起始位置|
  |profitLimit|为int类型|确定起始位置后,选取的数据记录条数。|
  
  **table Chart**,查询数据表Chart的数据:

  |参数名|类型|备注|
  |-|-|-|      
  |chartMinId|为int类型|记录的最小ID|
  |chartMaxId|为int类型|记录的最大ID|
  |chartOffset|为int类型|偏移|
  |chartLimit|为int类型|需要获取的记录条数|
  |chartUpdateBaseId|为int类型|查询的更新后的基础ID|
  |chartUpdateDate|为int类型|数据记录更新时间戳,会筛选出比这个时间戳大的记录|
  
  **summaryLimit**,查询状态栏数据:

  查询实盘的状态栏数据,该参数类型为整型,设置0表示不需要查询状态栏信息,设置为非0表示需要查询的状态栏信息字节数(该接口不限制数据量,可以指定一个较大的```summaryLimit```参数来获取所有状态栏信息)。状态栏数据储存在返回的数据的```summary```中。

  ```Python```范例:
  ```python
  api('GetRobotLogs', 63024, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)    # 具体代码,参看以上内容:4、简单的例子,此处不再赘述,只写GetRobotLogs的调用和参数传入
  • 返回值 返回数据:

    {
      'code': 0, 
      'data': {
          'result': {
              'chart': '', 
              'chartTime': 0, 
              'logs': [
                  {
                      'Total': 4, 
                      'Max': 12, 
                      'Min': 9, 
                      'Arr': [
                          [12, 5, '', '', 0, 0, '[]', 1635495362912, '', ''], 
                          [11, 3, 'Futures_Futu', '', 0, 0, 'Buy(1826.08, 1000): TrdMarket_CN: 缺少必要的参数: secMarket', 1635495362904, '', '']
                      ]
                  }, 
                  {'Total': 0, 'Max': 0, 'Min': 0, 'Arr': []}, 
                  {'Total': 0, 'Max': 0, 'Min': 0, 'Arr': []}
              ], 
              'node_id': 507885, 
              'online': True, 
              'refresh': 0, 
              'status': 3, 
              'updateTime': 1635495362919, 
              'wd': 0
          }, 
          'error': None
      }
    }
    
  • 数据库中的策略日志表

查询的日志截图:

以上返回结果数据中Arr属性值描述:

  'Arr': [
      [12, 5, '', '', 0, 0, '[]', 1635495362912, '', ''], 
      [11, 3, 'Futures_Futu', '', 0, 0, 'Buy(1826.08, 1000): TrdMarket_CN: 缺少必要的参数: secMarket', 1635495362904, '', '']
  ]

|id|logType|eid|orderId|price|amount|extra|date|contractType|direction| |-|-|-|-|-|-|-|-|-|-| |12|5|“|”|0|0|‘[]’|1635495362912|“|”| |11|3|‘Futures_Futu’|“|0|0|‘Buy(1826.08, 1000): TrdMarket_CN: 缺少必要的参数: secMarket’|1635495362904|”|“|


  ```logType```值具体代表的日志类型:
  
  |logType:|0|1|2|3|4|5|6|
  |-|-|-|-|-|-|-|-|
  |logType意义:|BUY|SALE|RETRACT|ERROR|PROFIT|MESSAGE|RESTART|
  |中文意义|买单类型日志|卖单类型日志|撤销|错误|收益|日志|重启|

- 数据库中的收益图表日志表
  该图表日志表数据与策略日志表中的收益日志一致。

“Arr”: [ [202, 2515.44, 1575896700315], [201, 1415.44, 1575896341568] ]

  
  以其中一条日志数据为例:

[202, 2515.44, 1575896700315]

  ```202```为日志```ID```,```2515.44```为收益数值,```1575896700315```为时间戳。

- 数据库中的图表日志表

“Arr”: [ [23637, 0, “{\“close\”:648,\“high\”:650.5,\“low\”:647,\“open\”:650,\“x\”:1575960300000}“], [23636, 5, “{\“x\”:1575960300000,\“y\”:3.0735}“] ]


  以其中一条日志数据为例:

[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线数据。

# 交易插件

### 简介
 
为了完善交易终端功能、更好的方便手动交易,推出了交易插件功能,位置如下:

![商品期货API文档(旧文档)](/upload/asset/1783fdaa5063f7e6410b9.png) 
 
### 插件原理
 
原理和调试工具相同,发送一段代码到交易终端页面的托管者执行,并且支持返回图表和表格(调试工具目前也升级支持)。和**调试工具**功能相同只能执行3分钟,不收取费用。可实现一些简单的小功能,复杂的策略还是需要运行实盘。

### 插件编写

在新建策略页面,设置策略类型为:```交易插件```,交易插件支持```JavaScript```、```Python```、```C++```、```My语言```。

![商品期货API文档(旧文档)](/upload/asset/1784cc694b2122814b1da.png) 
  
### 插件用途
 
插件可以执行代码一段时间,可执行一些简单的操作。例如**冰山委托**、**挂单**、**撤单**、**计算**等任务,和**调试工具**一样使用```return```返回结果,也可以直接返回图表和表格。下面举几个例子,其他功能可以自行探索。

- 返回深度的快照
  ```js
  // 返回深度的快照
  function main() {
      var tbl = { 
          type: 'table', 
          title: '深度快照 @ ' + _D(), 
          cols: ['#', 'Amount', 'Ask', 'Bid', 'Amount'], 
          rows: []
      }
      var d = exchange.GetDepth()
      for (var i = 0; i < Math.min(Math.min(d.Asks.length, d.Bids.length), 15); i++) {
          tbl.rows.push([i, d.Asks[i].Amount, d.Asks[i].Price+'#ff0000', d.Bids[i].Price+'#0000ff', d.Bids[i].Amount])
      }
      return tbl
  }
  def main():
      tbl = {
          "type": "table",
          "title": "深度快照 @ " + _D(),
          "cols": ["#", "Amount", "Ask", "Bid", "Amount"],
          "rows": []
      }
      d = exchange.GetDepth()
      for i in range(min(min(len(d["Asks"]), len(d["Bids"])), 15)):
          tbl["rows"].append([i, d["Asks"][i]["Amount"], str(d["Asks"][i]["Price"]) + "#FF0000", str(d["Bids"][i]["Price"]) + "#0000FF", d["Bids"][i]["Amount"]])
      return tbl
  void main() {
      json tbl = R"({
          "type": "table",
          "title": "abc",
          "cols": ["#", "Amount", "Ask", "Bid", "Amount"],
          "rows": []   
      })"_json;
      
      tbl["title"] = "深度快照 @" + _D(); 
      auto d = exchange.GetDepth();
      for(int i = 0; i < 5; i++) {
          tbl["rows"].push_back({format("%d", i), format("%f", d.Asks[i].Amount), format("%f #FF0000", d.Asks[i].Price), format("%f #0000FF", d.Bids[i].Price), format("%f", d.Bids[i].Amount)});
      }
      
      LogStatus("`" + tbl.dump() + "`");
      // C++ 不支持return json 显示表格,可以创建实盘显示状态栏表格
  }

商品期货API文档(旧文档)

  • 画跨期差价 “`js // 画跨期差价 var chart = { __isStock: true,
    title : { text : ‘差价分析图’},
    xAxis: { type: ‘datetime’},
    yAxis : {
    title: {text: ‘差价’},
    opposite: false
    }, series : [
    {name : “diff”, data : []} ] }

function main() { exchange.SetContractType(‘rb2205’) // 实际使用时,需要自行修改需要的合约代码 var recordsA = exchange.GetRecords(PERIOD_M5) exchange.SetContractType(‘rb2201’) // 实际使用时,需要自行修改需要的合约代码 var recordsB = exchange.GetRecords(PERIOD_M5)

  for(var i = 0; i < Math.min(recordsA.length, recordsB.length); i++){
      var diff = recordsA[recordsA.length - Math.min(recordsA.length, recordsB.length) + i].Close - recordsB[recordsB.length - Math.min(recordsA.length, recordsB.length) + i].Close
      chart.series[0].data.push([recordsA[recordsA.length - Math.min(recordsA.length, recordsB.length) + i].Time, diff])
  }
  return chart

}

  
  ```python
  chart = {
      "__isStock": True,
      "title": {"text": "差价分析图"},
      "xAxis": {"type": "datetime"},
      "yAxis": {
          "title": {"text": "差价"}, 
          "opposite": False
      }, 
      "series": [
          {"name": "diff", "data": []}
      ]
  }  
  
  def main():
      exchange.SetContractType("rb2205")
      recordsA = exchange.GetRecords(PERIOD_M5)
      exchange.SetContractType("rb2201")
      recordsB = exchange.GetRecords(PERIOD_M5)  

      for i in range(min(len(recordsA), len(recordsB))):
          diff = recordsA[len(recordsA) - min(len(recordsA), len(recordsB)) + i].Close - recordsB[len(recordsB) - min(len(recordsA), len(recordsB)) + i].Close
          chart["series"][0]["data"].append([recordsA[len(recordsA) - min(len(recordsA), len(recordsB)) + i]["Time"], diff])
      return chart
  // C++ 不支持 return json 结构画图

商品期货API文档(旧文档)

策略广场中还有其它范例。

使用方式

  • 添加交易终端插件模块 如图所示,在交易终端页面打开模块添加菜单,当前优宽账号策略库中的交易终端插件会自动在列表中显示,找到需要添加的插件点击添加。

商品期货API文档(旧文档)

  • 运行插件 点击「执行」,交易终端插件就开始运行。插件不会显示出日志,但是可以返回显示表格。

商品期货API文档(旧文档)

  • 插件运行时间 交易终端插件运行时长最长为3分钟,超过3分钟自动停止运行。

Alpha因子分析工具

简介

分析公式参考了worldquant公开的alpha101http://q.youquant.com/chart/doc/101_Formulaic_Alphas.pdf 中行情计算的方法,基本兼容了其语法(未实现的有说明),并进行了增强。 用于快速对时间序列进行运算,验证想法,使用地址

页面简介:

商品期货API文档(旧文档)

函数和操作符

下面的“{}”代表占位符,所有表达式大小写不敏感,x代表数据时间序列

  • abs(x), log(x), sign(x)字面意思,分别是绝对值、对数、符号函数。

以下操作符+, -, *, /, >, <也符合其标准的含义,==:是否相等,||:逻辑或,x ? y : z:三目运算符。

  • rank(x) :横截面的排序,返回所在百分比。需要指定侯选多个标的池,用于单个行情无法计算,将直接返回原结果。
  • delay(x, d) : 序列d周期前的值。
  • sma(x, d) : 序列d周期的简单均线。
  • correlation(x, y, d):时间序列x和y过去d周期的相关系数。
  • covariance(x, y, d) :时间序列x和y过去d周期的协方差。
  • scale(x, a) :归一化数据,使sum(abs(x))=a(a默认为1)。
  • delta(x, d) :时间序列x的现在值减去d周期前的值。
  • signedpower(x, a)x^a
  • decay_linear(x, d) :时间序列x带权重的d周期移动平均值,权重为d,d-1,d-2….1(经过归一化处理)。
  • indneutralize(x, g) : 针对行业分类g进行中性处理,目前不支持。
  • ts_{O}(x, d) : 对时间序列x过去d个周期进行O操作(O可具体代表min、max等,接下来有介绍),d会转为整数。
  • ts_min(x, d) : 过去d周期最小值。
  • ts_max(x, d) : 过去d周期最大值。
  • ts_argmax(x, d)ts_max(x, d)位置。
  • ts_argmin(x, d)ts_min(x, d)位置。
  • ts_rank(x, d) : 过去d个周期时间序列x值的排序(百分比排序)。
  • min(x, d)ts_min(x, d)
  • max(x, d)ts_max(x, d)
  • sum(x, d) :过去d周期的和。
  • product(x, d) :过去d周期的积。
  • stddev(x, d) :过去d周期的标准差。

输入数据

输入数据的大小写不敏感,默认的数据是网页上的选择品种,也可以直接指定例如MA888.close

  • returns :收盘价收益率。
  • open, close, high, low, volume :周期内开盘价、收盘价、最高价、最低价、成交量。
  • vwap :成交量加权成交价,未实现,当前为收盘价。
  • cap :总市值,未实现。
  • IndClass :行业分类,未实现。

其它

支持一次输出多个结果,用列表表示。例如[sma(close, 10), sma(high, 30)]将会在图中画两条线。除了输入时间序列数据外,也可以当成一个简单的计算器。

其它

交易终端

优宽量化交易平台提供模块化、定制化的交易终端页面。可以自由添加各种数据模块、交易功能模块,甚至可以自己编写代码开发模块(交易终端插件)。凭借着高度灵活自由的使用方式也极大方便了手动交易、半程序化交易的用户。 交易终端页面上的各种模块均可以拖动、缩放,可以修改模块绑定的交易对、交易所等设置,可以添加多个同类型的模块。

商品期货API文档(旧文档)

调试工具

调试工具页面提供了一个快速实盘测试代码的环境,目前仅支持JavaScript语言。

商品期货API文档(旧文档)

远程编辑

支持本地编辑器远程同步策略代码到优宽量化交易平台,支持Sublime Text/Atom/Vim/VSCode编辑器。在策略编辑页面点击「远程编辑」展开插件下载地址按钮,显示当前策略的远程同步密钥(token)。

商品期货API文档(旧文档)

点击「更新密钥」可以刷新当前密钥显示,点击「删除密钥」可以删除当前策略的密钥(token)。

商品期货API文档(旧文档)

不同编辑器的插件安装方式略有差别,可以点击下载按钮跳转到具体的远程同步插件项目。

商品期货API文档(旧文档)

实盘参数导入导出

商品期货API文档(旧文档)

运行实盘时需要保存实盘配置的参数数据可以点击「导出参数」按钮。导出的策略参数将以json文件保存,导出的策略参数配置也可以再次导入实盘,点击「导入参数」按钮即可把保存的策略实盘参数导入到当前实盘,导入后点击「更新参数」保存。

策略导入导出文件

商品期货API文档(旧文档)

  • 下载源码 导出策略源码,导出的文件类型基于策略的编程语言。JavaScript策略导出扩展名为js的文件;python策略导出扩展名为py的文件;c++策略导出扩展名为cpp的文件;麦语言策略导出扩展名为txt的文件。注意只导出策略源码,不包含策略参数、模板引用等信息。

  • 导出策略 导出完整策略,包含策略源码、参数设计等策略所有信息,导出的文件为xml文件。

  • 导入策略 使用「导出策略」功能导出的xml文件,在策略编辑页面点击「导入策略」按钮选中需要导入的xml文件即可导入完整策略。导入后需要点击「保存」按钮保存策略。

多国语言支持

策略名称,策略参数的描述,都可以用中文|英文的形式书写,让网页自动识别语言显示。

商品期货API文档(旧文档)

商品期货API文档(旧文档)

其它地方,例如:策略描述使用说明等这些Markdown格式的文本,用[trans]中文|英文[/trans]或者[trans]中文||英文[/trans]也可以达到自动识别的效果,以上例子的效果如下图所示:

  • 中文页面显示: 商品期货API文档(旧文档)

  • 英文页面显示: 商品期货API文档(旧文档)

切换语言后,刷新网页后生效。

在策略代码中可以写入字符串的函数也支持语言切换,例如Log函数、LogStatus函数等。

function main() {
    Log("[trans]日志|log[/trans]")
    var table = {
        type: "table", 
        title: "[trans]操作|option[/trans]", 
        cols: ["[trans]列1|col1[/trans]", "[trans]列2|col2[/trans]", "[trans]操作|option[/trans]"],
        rows: [ 
            ["[trans]螺纹钢主力合约|rb888[/trans]", "[trans]甲醇主力合约|MA888[/trans]", {"type": "button", "cmd": "coverAll", "name": "平仓|cover", "description": "描述|description"}]  // 注意:按钮中不用加[trans]标签
        ]
    }
    LogStatus("[trans]信息|message[/trans]", "\n`" + JSON.stringify(table) + "`")
    throw "[trans]错误|error[/trans]"
}
import json
def main():
    Log("[trans]日志|log[/trans]")
    table = {
        "type": "table", 
        "title": "[trans]操作|option[/trans]", 
        "cols": ["[trans]列1|col1[/trans]", "[trans]列2|col2[/trans]", "[trans]操作|option[/trans]"],
        "rows": [ 
            ["[trans]螺纹钢主力合约|rb888[/trans]", "[trans]甲醇主力合约|MA888[/trans]", {"type": "button", "cmd": "coverAll", "name": "平仓|cover", "description": "描述|description"}]
        ]
    }
    LogStatus("[trans]信息|message[/trans]", "\n`" + json.dumps(table) + "`")
    raise Exception("[trans]错误|error[/trans]")
void main() {
    Log("[trans]日志|log[/trans]");
    json table = R"({
        "type": "table", 
        "title": "[trans]操作|option[/trans]", 
        "cols": ["[trans]列1|col1[/trans]", "[trans]列2|col2[/trans]", "[trans]操作|option[/trans]"],
        "rows": [ 
            ["[trans]螺纹钢主力合约|rb888[/trans]", "[trans]甲醇主力合约|MA888[/trans]", {"type": "button", "cmd": "coverAll", "name": "平仓|cover", "description": "描述|description"}]
        ]
    })"_json;
    LogStatus("[trans]信息|message[/trans]", "\n`" + table.dump() + "`");
    Panic("[trans]错误|error[/trans]");
}

托管者程序参数

下载托管者软件之后,解压缩后的可执行文件,文件名robot即为托管者程序,在部署托管者时可以给托管者程序指定参数。

  • -v:查看当前托管者程序的版本、编译时间等信息。 完整的执行命令以苹果电脑Mac系统为例:./robot -v
  • -s:运行托管者程序时指定的和优宽量化交易平台通信的地址。 完整的执行命令以苹果电脑Mac系统为例:./robot -s node.youquant.com/xxxxxxxxxxxxxx部分为每个优宽量化交易平台账号唯一的识别ID,命令执行后会提示要求输入对应的优宽量化交易平台账号的密码。
  • -p:可以直接在运行命令中指定参数输入密码,不建议这样做,因为会留下密码参数在当前系统记录中。假设地址node.youquant.com/xxxxxxx对应的账号密码为:abc123456。 完整的执行命令以苹果电脑Mac系统为例:./robot -s node.youquant.com/xxxxxxx -p abc123456
  • -n:给运行的托管者程序附加标签信息。 完整的执行命令以苹果电脑Mac系统为例:./robot -n macTest -s node.youquant.com/xxxxxxx。在平台托管者管理页面的托管者信息中会有macTest文本标记。
  • -l:打印当前托管者支持的交易所列表。 完整的执行命令以苹果电脑Mac系统为例:./robot -l。即可输出所支持的交易所名称。

实盘报错、异常退出的常见原因

  • 策略静态语法错误(此类错误比较明显,通常在策略编辑页面可以看到错误标记), 在回测时可以发现纠正。
  • 策略运行时错误, 最常见的例如对函数返回值不做合法判断直接使用。
  • 在全局变量里保存过多不能垃圾回收的内容, 导致占用内存过大。
  • 使用异步exchange.Go函数,操作时没有合理wait等待协程结束,导致协程数量过大。
  • 函数递归调用层数过多导致超出协程堆栈大小。
  • 接口业务错误、网络请求错误等,此类报错会显示相关的交易所对象名称、函数名称、错误相关的消息和原因等信息,此类错误不会导致实盘异常停止(此类报错通常是起因,但是并非是直接原因,直接原因通常是没有对接口返回值判断合法性直接使用引起的程序异常)。
  • 平台底层报错,常见的有Decrypt: Secret key decrypt failed错误,该错误会导致实盘无法启动。错误原因是修改了优宽量化交易平台的账号密码导致所有配置的API KEY失效,需要重新配置API KEY,重启托管者即可。
  • Python策略出租时由于平台给策略加密的Python和策略运行时的Python版本不兼容导致的报错:ValueError: bad marshal data (unknown type code),将策略运行的Python环境升级或者安装为:Python 2.7Python 3.5Python 3.6其中之一的策略支持的版本即可。
  • interrupt错误,该错误是由于程序在执行某个操作(例如访问交易所接口)时,用户点击了实盘页面上的停止实盘按钮,实盘停止中断了当前的操作打印的报错信息。该报错并没有什么影响,仅仅是一个日志记录。

实盘、策略分组

在优宽量化交易平台「实盘」页面、「策略库」页面可以点击右侧分组管理按钮,用来给策略、实盘分组管理。例如对于策略的分组管理时可以把模板类库分为一组、JavaScript语言的策略分为一组、测试用策略分为一组。

子账号、实盘围观

子账号 登录平台后,点击「控制中心」、「账号设置」跳转到优宽账户管理页面。点击「子账户组」可以看到子账户创建页面,操作权限控件内选择所创建子账号可以访问的实盘,用户信息控件内设置子账号用户名子账号登录密码。点击「创建子账户」按钮即可创建一个子账号。创建后的子账号会在当前页面显示、并且可以「修改」、「锁定/解锁」、「删除」。

子账号只有有限权限,只能看到操作权限设置中授权的实盘。对于授权的实盘拥有修改参数、停止实盘、重启实盘的权限,但是无法修改实盘配置的交易所对象。子账号的使用场景通常为: - A.量化团队管理多个实盘策略时方便登录、管理。 - B.策略租用时的调试。

实盘围观 在优宽平台实盘页面的实盘列表中点击「公开」按钮即可公开展示当前行的实盘。实盘围观目前有两种方式: - 1、在优宽平台公开的实盘围观页面展示实盘。当点击「公开」按钮后选择公开分享即可。 - 2、创建围观私链。 当点击「公开」按钮后选择内部分享,设置有效期后即可生成一个私有链接用来登录该策略实盘的私有围观页面。

策略分享、出租

策略库页面,策略右侧的「操作项」按钮点击后弹出的菜单中有分享、出租操作选项。

策略分享 - 公开分享 点击「分享」按钮后会弹出对话框,可以选择「公开分享」。策略即完整的分享在平台的策略广场,任何用户都可以复制该策略。

  • 内部分享 点击「分享」按钮后会弹出对话框,可以选择「内部分享」。选择分享有效期、分享次数之后会生成该策略的复制页面地址复制码。可以分发给指定的优宽平台用户,需求该策略的用户只需使用复制页面地址链接,登录复制页面后输入复制码即可获取该策略,获取后策略自动会在策略库中出现。

策略出租 - 公开出售 点击「出租」按钮后会弹出对话框,可以选择「公开出售」。策略即可申请上架(需要通过审核)。

  • 内部出售 点击「出租」按钮后会弹出对话框,可以选择「内部出售」。选择使用天数、最多并发、注册码个数之后会生成该策略的注册页面地址注册码。可以分发给指定的优宽平台用户,需求该策略的用户只需使用注册页面地址链接,登录注册页面后输入注册码即可获取策略的使用权。策略也会出现在策略库中,不过只有回测、实盘使用权,看不到策略源码等信息。

重要提示,在创建、分发策略注册码时请务必仔细确认是「注册码」还是「复制码」。以免误将策略分享出去。

回测系统夏普算法

function returnAnalyze(totalAssets, profits, ts, te, period, yearDays) {
    // force by days
    period = 86400000
    if (profits.length == 0) {
        return null
    }
    var freeProfit = 0.03 // 0.04
    var yearRange = yearDays * 86400000
    var totalReturns = profits[profits.length - 1][1] / totalAssets
    var annualizedReturns = (totalReturns * yearRange) / (te - ts)

    // MaxDrawDown
    var maxDrawdown = 0
    var maxAssets = totalAssets
    var maxAssetsTime = 0
    var maxDrawdownTime = 0
    var maxDrawdownStartTime = 0
    var winningRate = 0
    var winningResult = 0
    for (var i = 0; i < profits.length; i++) {
        if (i == 0) {
            if (profits[i][1] > 0) {
                winningResult++
            }
        } else {
            if (profits[i][1] > profits[i - 1][1]) {
                winningResult++
            }
        }
        if ((profits[i][1] + totalAssets) > maxAssets) {
            maxAssets = profits[i][1] + totalAssets
            maxAssetsTime = profits[i][0]
        }
        if (maxAssets > 0) {
            var drawDown = 1 - (profits[i][1] + totalAssets) / maxAssets
            if (drawDown > maxDrawdown) {
                maxDrawdown = drawDown
                maxDrawdownTime = profits[i][0]
                maxDrawdownStartTime = maxAssetsTime
            }
        }
    }
    if (profits.length > 0) {
        winningRate = winningResult / profits.length
    }
    // trim profits
    var i = 0
    var datas = []
    var sum = 0
    var preProfit = 0
    var perRatio = 0
    var rangeEnd = te
    if ((te - ts) % period > 0) {
        rangeEnd = (parseInt(te / period) + 1) * period
    }
    for (var n = ts; n < rangeEnd; n += period) {
        var dayProfit = 0.0
        var cut = n + period
        while (i < profits.length && profits[i][0] < cut) {
            dayProfit += (profits[i][1] - preProfit)
            preProfit = profits[i][1]
            i++
        }
        perRatio = ((dayProfit / totalAssets) * yearRange) / period
        sum += perRatio
        datas.push(perRatio)
    }

    var sharpeRatio = 0
    var volatility = 0
    if (datas.length > 0) {
        var avg = sum / datas.length;
        var std = 0;
        for (i = 0; i < datas.length; i++) {
            std += Math.pow(datas[i] - avg, 2);
        }
        volatility = Math.sqrt(std / datas.length);
        if (volatility !== 0) {
            sharpeRatio = (annualizedReturns - freeProfit) / volatility
        }
    }

    return {
        totalAssets: totalAssets,
        yearDays: yearDays,
        totalReturns: totalReturns,
        annualizedReturns: annualizedReturns,
        sharpeRatio: sharpeRatio,
        volatility: volatility,
        maxDrawdown: maxDrawdown,
        maxDrawdownTime: maxDrawdownTime,
        maxAssetsTime: maxAssetsTime,
        maxDrawdownStartTime: maxDrawdownStartTime,
        winningRate: winningRate
    }
}

更多内容

henryp1 怎么不显示目录?

雨幕(youquant) 哪个目录 ?