商品期货套利 - 多品种网格对冲模型 注释版

  • #### 代码:
// 商品期货套利 - 多品种网格对冲模型 注释版
function Hedge(q, e, positions, symbolA, symbolB, hedgeSpread) { // 对冲对象 生成函数, 参数q 为最开始调用 商品期货交易类库模板 的 导出函数 生成的 交易队列控制对象, 参数e 为交易所对象,positions 为初始仓位// symbolA 为第一个合约类型,  symbolB 为第二个合约类型, hedgeSpread 为对冲 交易量控制表 字符串。var self = {}                                                // 声明一个 空对象 用于给空对象 初始化 后返回 (即对冲对象)self.q = q                                                   // 给对冲对象 添加 属性 q ,并用参数的q 初始赋值。self.symbolA = symbolA                                       // 给对冲对象self 添加属性 symbolA ,储存 第一个合约类型self.symbolB = symbolB                                       // ...self.name = symbolA + " & " + symbolB                        // 对冲对象的 名称 即对冲组合self.e = e                                                   // 对冲对象 中储存交易所对象 的引用 self.isBusy = false                                          // 繁忙 标记 初始为 不繁忙。self.diffA = 0                                               // 差价A ,  即 symbolA买一 - symbolB卖一 self.diffB = 0                                               // 差价B ,  即 symbolB卖一 - symbolA买一self.update = _D()                                           // 记录 更新时间var arr = hedgeSpread.split(';')                             // 把传入的  交易量控制表 字符串 按照 ';' 字符 分割。self.dic = []                                                // 网格节点 对象 数组var n = 0                                                    // var coefficient = 1                                          // 系数 初始1for (var i = 0; i < positions.length; i++) {                 // 遍历持仓信息。if (positions[i].ContractType == symbolA) {              // 如果遍历当前的 持仓信息 的合约类型 和 当前对冲对象的 第一个合约类型 相同n += positions[i].Amount                             // 累计 类型为 symbolA 的合约的持仓量if (positions[i].Type == PD_LONG || positions[i].Type == PD_LONG_YD) {   // 如果 持仓类型是 多仓 , coefficient 赋值为 -1 ,即 代表 反对冲: 多 symbolA  空 symbolBcoefficient = -1}}}_.each(arr, function(pair) {                                 // 把 控制表字符串 数组的  每一个单元  迭代传递到 匿名函数 作为参数 pairvar tmp = pair.split(':');                               // 把每个 网格节点的 单元 按照':'字符 分割成 参数 数组 tmpif (tmp.length != 3) {                                   // 由于 格式 是  30:15:1  即   开仓差价: 平仓差价: 下单量    ,所以 用 ':' 分割后 tmp长度 不是3的 即 格式错误throw "开仓表不正确";                                  // 抛出异常  格式错误}var st = {                                               // 每次迭代的时候 构造一个对象 open: Number(tmp[0]),                                // 开仓  把 tmp[0]  即 30:15:1 按 ':' 分割后 生成的数组中的 第一个元素  30 , 通过 Number 函数 转换为数值cover: Number(tmp[1]),                               // 平仓..amount: Number(tmp[2]),                              // 量..hold: 0                                              // 持仓 初始为0}if (n > 0) {                                             // 如果 n 大于0  ,即 开始的时候 有持仓。var m = Math.min(n, st.amount)                       // 取 当前合约组合中 symbolA的 持仓量   和  网格节点 中的开仓量  二者的 最小值 赋值给 m 变量n -= m                                               // 在持仓累计数量  n  中 减去 mst.hold = m * coefficient                            // 正对冲 coefficient 这个系数 为1  ,  如果 symbolA 为 合约的持仓 类型为  多仓, 则是反对冲 那么 coefficient 在之前 就会被赋值为 -1// 在迭代过程中  n 被 分散到各个 网格节点  恢复网格 持仓数据。Log("恢复", self.name, st)                            // 输出本次的恢复信息。}self.dic.push(st)                                        // 把恢复好的节点 压入 dic数组 。});if (n > 0) {                                                 // 如果 迭代完成后  n 值 依然大于0  即 还有仓位没有分配恢复 , 抛出错误throw "恢复失败, 有多余仓位 " + n;}self.poll = function() {                                     // 给 self 对冲对象  添加 属性poll  并用一个 匿名函数 初始化 赋值if (self.isBusy || (!$.IsTrading(self.symbolA))) {       // 如果 self 对象的属性 isBusy 为true 即繁忙 ,或者 合约类型 symbolA 不在交易时间内 (通过调用$.IsTrading这个模板导出函数获取) ,则调用return返回return}var insDetailA = exchange.SetContractType(self.symbolA)  // 设置 合约类型 symbolA if (!insDetailA) {                                       // 返回 null 则 调用 return 返回 return}var tickerA = exchange.GetTicker()                       // 获取 symbolA 合约的行情信息if (!tickerA) {                                          // 获取失败 调用returnreturn}var insDetailB = exchange.SetContractType(self.symbolB)  // 设置 合约类型 symbolB if (!insDetailB) {return}var tickerB = exchange.GetTicker()                       // 获取 symbolB 合约的行情信息if (!tickerB) {return}self.update = _D(tickerA.Time)                           // 更新时间var action = null                                        // 动作变量var diffA = _N(tickerA.Buy - tickerB.Sell)               // A合约的 买一  减去  B合约的 卖一var diffB = _N(tickerA.Sell - tickerB.Buy)               // A合约的 卖一  减去  B合约的 买一self.diffA = diffA                                       // 赋值 给 对象 的 成员diffAself.diffB = diffB                                       // 赋值 ..for (var i = 0; i < self.dic.length && !action; i++) {   // 遍历 网格的  节点 ,直到 遍历结束  或者  有action 执行。if (self.dic[i].hold == 0) {                         // 如果 网格 节点的持仓量 为 0if (self.dic[i].open <= diffA) {                 // 如果 网格 节点的开仓价 小于等于 差价A (即 A合约买一 减去 B合约的卖一 的差价 突破 网格节点的 开仓价)action = [i, "sell", "buy", self.dic[i].amount]    // action 记录下 网格节点   索引 、symbolA sell ,symbolB buy ,操作量 。} else if (self.dic[i].open <= -diffB) {               // -diffB 实际就是  tickerB.Buy - tickerA.Sell ,也就是 B合约买一 减去 A合约的卖一 的差价 突破 网格节点的 开仓价action = [i, "buy", "sell", -self.dic[i].amount]   // action 记录..}} else {                                                   // 网格节点的 持仓量 不为0if (self.dic[i].hold > 0 && self.dic[i].cover >= diffB) {             // 如果 节点的持仓量 大于0  即 正对冲 持仓 A合约持空,B合约持多。 并且 平仓差价(合约A sell ,合约B buy)小于平仓线action = [i, "closesell", "closebuy", self.dic[i].hold]           // action 记录下 网格节点  索引 , 合约A 平空仓 , 合约B 平多仓, 按照节点持仓量 平。} else if (self.dic[i].hold < 0 && self.dic[i].cover >= -diffA) {     // 如果持仓量 小于0 , 并且 -diffA 即 tickerB.Sell - tickerA.Buy ,小于平仓线action = [i, "closebuy", "closesell", self.dic[i].hold]           // action 记录下 ..}}}if (!action) {                                                                // 如果 action  为初始赋值的 null ,即没有 被 赋值操作。 调用 return 返回return}Log("A卖B买: " + _N(diffA) + ", A买B卖: " + _N(diffB), ", Action: " + JSON.stringify(action))  // 如果 action 有值 ,输出信息 差价A  差价B 和  action 储存的数据。self.isBusy = true                                                                            // 有操作 即 锁定, 为繁忙状态, 处理完成前 在该函数开始处都会触发 return self.q.pushTask(self.e, self.symbolA, action[1], self.dic[action[0]].amount, function(task, ret) {     // 调用 交易队列对象q 的成员函数 把 具体操作 参数传入 , 压任务进队列 等待处理。if (!ret) {                                                                                        // 回调函数, 如果完成的 返回值 ret 为false 即 操作失败, self.isBusy = false                                                                            // 重新把 isBusy 赋值为 false ,解除锁定return                                                                                         // 返回}self.q.pushTask(self.e, self.symbolB, action[2], self.dic[action[0]].amount, function(task, ret) { // A 合约 操作 成功 则,压入B合约的 操作任务  进 任务队列 等待处理。if (!ret) {                                                                                    // 如果 A合约操作完成 B 合约 操作失败 则 抛出异常throw "开仓失败..."}self.isBusy = false                                                                            // 解除锁定if (task.action != "buy" && task.action != "sell") {                                           // 如果 调用该回调函数的 任务 不是开仓 操作self.dic[action[0]].hold = 0;                                                              // 当前 操作的网格 节点 的持仓量 重新赋值为 0} else {                                                                                       // 如果是 开仓操作self.dic[action[0]].hold = action[3];                                                      // 把 当前任务 的下单量 参数 赋值给 当前网格节点的持仓量}})})}return self                                                                                                // 该函数 返回一个 对冲组合 对象
}// 注释版
function main() { SetErrorFilter("ready|login|timeout")       // 过滤常规错误Log("正在与交易服务器连接...")                 while (!exchange.IO("status")) Sleep(1000); // 一个循环 直到 IO函数返回 true 连接上服务器后 跳出Log("与交易服务器连接成功")                    // 显示与服务器连接 var mode = exchange.IO("mode", 0);          // 调整行情获取模式。立即返回模式。if (typeof(mode) !== 'number') {            // 调整行情模式函数 如果返回的不是数值类型throw "切换模式失败, 请更新到最新托管者!";   // 抛出错误异常} else {Log("已切换到适合多品种价格查询的立即模式");}if (CoverAll) {                             // 如果 开启平掉初始仓位的功能 CoverAll  启动时平掉所有仓位(界面上的参数)Log("开始平掉所有残余仓位...");            // 显示信息  平掉所有初始仓位 $.NewPositionManager().CoverAll();      // 调用商品期货模板的导出函数生成一个对象,并调用该对象的CoverAll方法,平掉所有初始仓位。Log("操作完成");                         // CoverAll函数执行完 打印 日志信息,显示操作完成。}LogStatus("尝试获取持仓状态")                 // 状态栏 显示尝试获取持仓状态的信息var positions = _C(exchange.GetPosition)   // 获取所有持仓信息。LogStatus("Ready")if (positions.length > 0 && !AutoRestore) { // 如果持仓信息 数组 positions 长度大于0 并且界面参数没有开启自动恢复throw "发现持仓, 请勾选自动恢复"            // 抛出错误异常}var pairs = []                              // 声明一个数组, 用来储存 处理对冲组合的对象。var q = $.NewTaskQueue(function(task, ret) { // 调用商品期货模板导出函数,生成一个 队列对象,用来处理并发的交易操作Log(task.desc, ret ? "成功" : "失败")     // 匿名函数(回调) 在队列中的任务完成后打印 显示任务的描述,返回状态。 })var arr = HedgeTable.split('(');            // 处理 界面参数 交易参考表, 按照 '('符号 分割字符串,初步 把多种合约控制表混合的字符串分割成 每一个组合为一个元素的字符串数组。var tbl = {                                 // 声明一个  tbl 对象 用来记录 显示在状态栏的数据type: 'table',                          // 调用LogStatus 时 ,让状态栏显示为表格,详见API , 此处类型需要设置为 tabletitle: 'Runtime',                       // 状态栏表格的 标题cols: ['Pair', 'Open', 'Cover', 'Hold', 'DiffA', 'DiffB', 'Time'], // 表格的每列的表头。rows: []                                                           // 表格的每行数据,初始时是一个空数组。};_.each(arr, function(item) {                                           // 一个JS 库的迭代 函数, 把arr中的每个元素  作为 (第二个参数) 匿名函数的参数 ,迭代执行匿名函数。if (item != '') {                                                  // 忽略 item 为空字符串的 情况。item 即为 每个合约组合 以及他们的 开仓控制表。var tmp = item.split(')');                                     // 根据 ')' 字符 分割 合约组合  和  控制表 。var pair = tmp[0].replace('(', '').split('&');                 // 合约组合字符串中存在 '('字符替换为'' 空字符, 再进行按 '&' 字符分割为 字符串数组。分别储存 合约类型。var symbolDetail = _C(exchange.SetContractType, pair[0])       // 使用 第一个 合约类型 设置合约类型,然后Log 显示 该合约的一些信息。Log("合约", symbolDetail.InstrumentName, "一手", symbolDetail.VolumeMultiple, "份, 最大下单量", symbolDetail.MaxLimitOrderVolume, "保证金率:", _N(symbolDetail.LongMarginRatio), _N(symbolDetail.ShortMarginRatio), "交割日期", symbolDetail.StartDelivDate);symbolDetail = _C(exchange.SetContractType, pair[1])           // 使用 第二个 合约类型 设置合约类型,然后Log 显示 该合约的一些信息。Log("合约", symbolDetail.InstrumentName, "一手", symbolDetail.VolumeMultiple, "份, 最大下单量", symbolDetail.MaxLimitOrderVolume, "保证金率:", _N(symbolDetail.LongMarginRatio), _N(symbolDetail.ShortMarginRatio), "交割日期", symbolDetail.StartDelivDate);pairs.push(Hedge(q, exchanges[0], positions, pair[0], pair[1], tmp[1]))  // 用以上处理好的数据:q处理交易对象,exchanges[0]交易所对象,当前迭代的 合约组合中的第一个合约类型,第二个类型,交易控制表 这几个变量作为参数 传入 Hedge 函数 ,Hedge函数返回一个对象 ,//把该对象压入pairs数组}});var ts = 0var lastUpdate = 0while (true) {                                                                 // 策略 主循环if (!exchange.IO("status")) {                                              // 如果 连接服务器状态 为false 则 程序进入睡眠1秒 跳过一下代码,重复主循环。Sleep(1000)continue}var now = new Date().getTime()                                             // 获取当前时间戳if (now - ts > (CalcPeriod * 60000)) {                                     // 如果 当前时间 距离上次 账户权益统计 的时间 大于 账户权益统计周期(分) 参数设定的值,执行 if 内代码。var account = exchange.GetAccount()                                    // 获取账户信息if (account) {                                                         // 如果正常获取 account 数据 var obj = JSON.parse(exchange.GetRawJSON())                        // 调用 GetRawJSON API  获取account 的详细信息JSON 格式 用parse 函数解析为 JS 对象。返回一个 对象给 obj$.PlotLine('账户权益', obj['Balance'] + obj['PositionProfit']);     // 调用 画线模板的导出函数 $.PlotLine 画账户权益曲线, 数值为: obj的Balance属性 加 PositionProfit 属性ts = now                                                           // 把本次更新 账户权益 的时间戳 记录在ts 变量 用于比较。}}// IO("wait") 会一直等待收到任何一个品种的行情推送信息, 返回收到行情的真实时间var n = exchange.IO("wait")                                                // IO("wait") 函数 返回的也是一个纳秒级的 时间戳。// 计算行情信息传到策略层花费的时间var idle = UnixNano() - n                                                  // 最新托管者 增加的内置函数,获取纳秒 时间if (now - lastUpdate > 5000) {                                             // 当前的时间戳如果 比上次记录的更新时间(lastUpdate)值大 超过5000(5秒) 则执行 if 分支代码tbl.rows = []                                                          // tbl 对象 的行设置 为空数组,即清空。_.each(pairs, function(t) {                                            // 储存对冲对象的数组 内的元素迭代 传递到匿名函数 作为参数t。for (var i = 0; i < t.dic.length; i++) {                           // 遍历当前对冲对象 的 交易量 控制数组 dic tbl.rows.push([t.name, t.dic[i].open, t.dic[i].cover, t.dic[i].hold, t.diffA, t.diffB, t.update])   // 把每一个 差价的 开平仓 值  持仓、当前的差价值 等信息 压入到表格 行数组中}});LogStatus('`' + JSON.stringify(tbl) + '`\nUpdate: ' + _D() + ', Idle: ' + (idle/1000000) + ' ms')           // 把更新过的表格显示在  状态栏。显示上更新时间。lastUpdate = now                                                                                            // 把当前的时间戳(毫秒) 更新给lastUpdate 变量 用于下一次比较。}_.each(pairs, function(t) {                                                                                     // 迭代 对冲对象 作为 匿名函数的参数 t ,迭代执行。t.poll()                                                                                                    // 执行当前的 对冲对象的 成员函数  poll()});q.poll()                                                                                                        // 调用模板生成的  交易队列控制对象 q 的成员函数 poll() 模拟并发执行交易任务}
}
  • 策略地址

    商品期货套利 - 多品种网格对冲模型

可以复制到自己的编辑器里面方便 查找变量名,如果有解释不对的地方、理解错误、BUG 等 ,欢迎留言,QQ单M我,不胜感谢! ^_^

商品期货套利 - 多品种网格对冲模型 注释版相关推荐

  1. 商品期货策略 之 Python 精简多品种 MACD 趋势策略框架(注释版)

    Python 精简多品种 MACD 趋势策略框架(注释版) Python超级精简的多品种MACD趋势策略框架, 代码超级精简, 注释超级详细啰嗦. >_<! 需要引用 python版CTP ...

  2. 网格交易模型 股票网格交易 期货网格交易 策略开发

    网格交易模型 主要逻辑: 包括两个类: 1.new_block创建新的网格,其中有网格中线值(start)参数,(add)按绝对值创建网格,(times)按小数比例创建网格,(quantity)网格中 ...

  3. 商品期货中各种品种之间的关系研究

    商品期货中各种品种之间的关系研究 作者:来源:时间:2018-12-01 14:01:14 在产品期货买卖中,许多种类之间会出现着不同程度的相关联系,有时分是由于同种原因导致的,比方说,社会全体需求增 ...

  4. 使用PyTorch构建神经网络(详细步骤讲解+注释版) 01-建立分类器类

    文章目录 1 数据准备 2 数据预览 3 简单神经网络创建 3.1 设计网络结构 3.2 损失函数相关设置 3.3 向网络传递信息 3.4 定义训练函数train 4 函数汇总 1 数据准备 神经网络 ...

  5. 使用PyTorch构建GAN生成对抗网络源码(详细步骤讲解+注释版)02 人脸识别 下

    文章目录 1 测试鉴别器 2 建立生成器 3 测试生成器 4 训练生成器 5 使用生成器 6 内存查看 上一节,我们已经建立好了模型所必需的鉴别器类与Dataset类. 使用PyTorch构建GAN生 ...

  6. 使用PyTorch构建GAN生成对抗网络源码(详细步骤讲解+注释版)02 人脸识别 上

    文章目录 1 数据集描述 2 GPU设置 3 设置Dataset类 4 设置辨别器类 5 辅助函数与辅助类 1 数据集描述 此项目使用的是著名的celebA(CelebFaces Attribute) ...

  7. 使用PyTorch构建卷积GAN源码(详细步骤讲解+注释版) 02人脸图片生成 上

    阅读提示:本篇文章的代码为在普通GAN代码上实现人脸图片生成的修改,文章内容仅包含修改内容,全部代码讲解需结合下面的文章阅读. 相关资料链接为:使用PyTorch构建GAN生成对抗 本次训练代码使用了 ...

  8. 手撕Alexnet卷积神经网络-pytorch-详细注释版(可以直接替换自己数据集)-直接放置自己的数据集就能直接跑。跑的代码有问题的可以在评论区指出,看到了会回复。训练代码和预测代码均有。

    Alexnet网络详解代码:手撕Alexnet卷积神经网络-pytorch-详细注释版(可以直接替换自己数据集)-直接放置自己的数据集就能直接跑.跑的代码有问题的可以在评论区指出,看到了会回复.训练代 ...

  9. 手撕VGG卷积神经网络-pytorch-详细注释版(可以直接替换自己数据集)-直接放置自己的数据集就能直接跑。跑的代码有问题的可以在评论区指出,看到了会回复。训练代码和预测代码均有。

    Alexnet网络详解代码:手撕Alexnet卷积神经网络-pytorch-详细注释版(可以直接替换自己数据集)-直接放置自己的数据集就能直接跑.跑的代码有问题的可以在评论区指出,看到了会回复.训练代 ...

最新文章

  1. Linear Regression(一)——
  2. php读取txt并写入数据库,php读取txt文件组成SQL并插入数据库的方法
  3. Redis 集群规范
  4. fedora14编译安装skyeye-1.3.2
  5. 一键部署VS插件:让.NET开发者更幸福
  6. python灰色关联度分析代码_灰色关联分析法步骤 - osc_uwnmtz9n的个人空间 - OSCHINA - 中文开源技术交流社区...
  7. python求度分布的程序
  8. 关于router-link包含dom元素会出现Warnings while compiling.警告的问题!
  9. Flex3——编译器错误代码列表
  10. shelve模块使用说明
  11. GOM引擎ItemShow代码在NPC对话框中显示装备图片及属性
  12. 关于在tomcat9中配置server.xml中URIEncoding=UTF-8无效的解决方法
  13. Cfree-5各种抽风解决办法
  14. mysql 美元符号_坑爹的PostgreSQL的美元符号(有时需要替换成单引号)
  15. 巨象指纹浏览器的反追踪技术原理
  16. 超级表格全新升级,这些功能你不可能在其他软件上看到
  17. 什么是 Web 3.0?|互联网的下一波浪潮解释
  18. ASP.NET MVC中的身份验证
  19. 计算机网络到底该怎么学?
  20. Excel VBA高级编程 - 根据关键词实时筛选,自动生成下拉菜单

热门文章

  1. 【稀饭】react native 实战系列教程之首页列表UI实现
  2. 哈佛凌晨四点半——生活感悟
  3. .NET Core发送HTTP Post和Get
  4. 什么是RAID 0?什么是RAID 1?了解硬盘阵列的作用
  5. Java——多态与接口
  6. 使用Java代码生成RSA公私钥的.pem文件
  7. 机器学习之支持向量机: Support Vector Machines (SVM)
  8. 二叉搜索树、平衡二叉搜索树和红黑树
  9. 微信小程序点击事件(bindtap)传递参数
  10. Kotin学习手记——类、接口、扩展方法、空类型