楼主: littleDreamX
5053 1

[源码分享] CTP商品期货多品种海龟交易法策略源码分享 [推广有奖]

  • 0关注
  • 4粉丝

本科生

2%

还不是VIP/贵宾

-

威望
0
论坛币
125 个
通用积分
0
学术水平
10 点
热心指数
15 点
信用等级
5 点
经验
701 点
帖子
36
精华
0
在线时间
34 小时
注册时间
2016-4-11
最后登录
2018-5-22

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币
BotVS的 CTP商品期货多品种海龟交易法源码分享
  1. /* 参数
  2. Instruments               合约列表                             字符串(string)
  3. LoopInterval              轮询周期(秒)                         数字型(number)        3
  4. RiskRatio                 % Risk Per N ( 0 - 100)            数字型(number)        1
  5. ATRLength                 ATR计算周期                         数字型(number)        20
  6. EnterPeriodA              系统一入市周期                       数字型(number)        20
  7. LeavePeriodA              系统一离市周期                       数字型(number)        10
  8. EnterPeriodB              系统二入市周期                       数字型(number)        55
  9. LeavePeriodB              系统二离市周期                       数字型(number)        20
  10. UseEnterFilter            使用入市过滤                         布尔型(true/false)    true
  11. IncSpace                  加仓间隔(N的倍数)                     数字型(number)        0.5
  12. StopLossRatio             止损系数(N的倍数)                     数字型(number)        2
  13. MaxLots                   单品种加仓次数                        数字型(number)        4
  14. RMode                     进度恢复模式                         下拉框(selected)      自动|手动
  15. VMStatus@RMode==1         手动恢复字符串                        字符串(string)        {}
  16. WXPush                    推送交易信息                         布尔型(true/false)     true
  17. */
  18. var _bot = $.NewPositionManager();//  声明一个全局变量, 值由 $.NewPositionManager 这个导出函数 返回, 返回的是一个 对象

  19. var TTManager = {//  一个对象,全局对象, 生成器。
  20.     New: function(needRestore, symbol, riskRatio, atrLen, enterPeriodA, leavePeriodA, enterPeriodB, leavePeriodB, useFilter,
  21.         multiplierN, multiplierS, maxLots) {//构造函数
  22.         //New函数参数:【needRestore】需要重启 ,symbol【合约编号】,riskRatio【风险比率】,atrLen【art指标长度】,enterPeriodA【入市期A】,leavePeriodA【离市期A】,
  23.         //enterPeriodB【入市期B】,leavePeriodB【离市期B】,useFilter【使用过滤】,multiplierN【乘数N】,multiplierS【乘数S】,maxLots【单品种加仓次数】
  24.         // subscribe
  25.         var symbolDetail = _C(exchange.SetContractType, symbol);//根据合约编号设置合约类型,回去返回的合约信息,symbolDetail
  26.         if (symbolDetail.VolumeMultiple == 0 || symbolDetail.MaxLimitOrderVolume == 0 || symbolDetail.MinLimitOrderVolume == 0 || symbolDetail.LongMarginRatio == 0 || symbolDetail.ShortMarginRatio == 0) {
  27.             //合约一首 份数 == 0    或者   最大下单量 == 0    或者   最小下单量 == 0 或者 多头仓保证金率 == 0 或者  空头仓保证金率 == 0
  28.             Log(symbolDetail);//输出  合约详细信息。
  29.             throw "合约信息异常";//抛出 合约 异常错误,策略停止。
  30.         } else {
  31.             Log("合约", symbolDetail.InstrumentName, "一手", symbolDetail.VolumeMultiple, "份, 最大下单量", symbolDetail.MaxLimitOrderVolume, "保证金率:", _N(symbolDetail.LongMarginRatio), _N(symbolDetail.ShortMarginRatio), "交割日期", symbolDetail.StartDelivDate);
  32.             //显示合约一部分信息。
  33.         }

  34.         var obj = {//在New 函数内声明的对象,该对象在New函数最后会作为返回值返回。以下还会声明 obj对象的成员函数、成员属性。
  35.             symbol: symbol, // 把New 函数准备构造对象 传进来的参数 symbol ,初始化给 obj 对象的成员 symbol,合约代码
  36.             riskRatio: riskRatio,//风险比率
  37.             atrLen: atrLen,//ATR指标长度
  38.             enterPeriodA: enterPeriodA,// 入市 、 离市 周期
  39.             leavePeriodA: leavePeriodA,
  40.             enterPeriodB: enterPeriodB,
  41.             leavePeriodB: leavePeriodB,//
  42.             useFilter: useFilter,// 使用过滤
  43.             multiplierN: multiplierN, // 乘数N
  44.             multiplierS: multiplierS  // 乘数S
  45.         };
  46.         obj.maxLots = maxLots; // 为什么不在obj 内声明、 初始化   单品种加仓次数
  47.         obj.lastPrice = 0; //最后价格 初始化0
  48.         obj.symbolDetail = symbolDetail; //合约的详细信息
  49.         obj.status = { //obj对象的状态,  status 也是个 对象
  50.             symbol: symbol,//合约代码
  51.             recordsLen: 0, //K线长度
  52.             vm: [], //一个数组 ,用来保存 marketPosition ,openPrice , N , leavePeriod , preBreakoutFailure
  53.             open: 0, //开仓次数
  54.             cover: 0,//平仓次数
  55.             st: 0, //
  56.             marketPosition: 0, //
  57.             lastPrice: 0, //最后价格
  58.             holdPrice: 0, //持仓价格
  59.             holdAmount: 0, //持仓数量
  60.             holdProfit: 0, //持仓盈亏
  61.             N: 0, //N值
  62.             upLine: 0, //上线
  63.             downLine: 0, //下线
  64.             symbolDetail: symbolDetail, //合约的详细信息
  65.             lastErr: "", // 最近错误
  66.             lastErrTime: "" // 最近错误时间
  67.         };

  68.         obj.setLastError = function(err) {//设置 最后一次出错
  69.             if (typeof(err) === 'undefined' || err === '') {//如果 err 参数没有传入, 火车 err 为空字符串,执行以下
  70.                 obj.status.lastErr = ""; //给 obj.status.lastErr 赋值 空字符串
  71.                 obj.status.lastErrTime = ""; // 同样也赋值 空字符串
  72.                 return; //返回
  73.             }
  74.             var t = new Date(); // 获取当前时间
  75.             obj.status.lastErr = err; // 把错误信息 赋值给 obj.status.lastErr
  76.             obj.status.lastErrTime = t.toLocaleString(); // 调用了 Date 对象的方法,toLocaleString() 方法可根据本地时间把 Date 对象转换为字符串,并返回结果。
  77.             // 赋值给 obj.status.lasrErrTime
  78.         };
  79.         obj.reset = function(marketPosition, openPrice, N, leavePeriod, preBreakoutFailure) { //重启函数
  80.                                 //               最后一次加仓价  , N值 , 离市周期 , 前一次失败跳出
  81.             if (typeof(marketPosition) !== 'undefined') { //如果 marketPosition 不等于  未定义,即 在函数调用的时候 ,全部传入参数
  82.                 obj.marketPosition = marketPosition; // 把 参数传进来的 marketPosition 赋值给 obj相应的 成员
  83.                 obj.openPrice = openPrice; // 创建obj.openPrice 参数赋值给 obj对象的相应的成员 ,最后一次加仓价
  84.                 obj.preBreakoutFailure = preBreakoutFailure; // 创建了 obj 对象的成员 preBreakoutFailure ,并且有 函数参数初始化, 上次突破(布尔值)
  85.                 obj.N = N;  // 创建obj.N, 给obj.N 赋值
  86.                 obj.leavePeriod = leavePeriod; // 创建了 obj对象的成员 leavePeriod 离市周期 , 函数传入参数 给其赋值
  87.                 var pos = _bot.GetPosition(obj.symbol, marketPosition > 0 ? PD_LONG : PD_SHORT); //调用商品期货交易类库 这个模板生成的 对象_bot 的成员函数
  88.                 // GetPosition ,传入 reset 自身对象obj 的成员symbol(这个对象管理的合约代码),根据marketPosition 选择 方向 PD_LONG 多仓, PD_SHORT 空仓,获取该
  89.                 //合约的 一个方向的持仓信息
  90.                 if (pos) {// 如果 返回的持仓信息 pos 不是 null ,即 有持仓信息
  91.                     obj.holdPrice = pos.Price; //给obj.holdPrice 赋值 持仓均价
  92.                     obj.holdAmount = pos.Amount; //给 obj.holdAmount 赋值 持仓数量
  93.                     Log(obj.symbol, "仓位", pos); // 在日志打印 合约代码 , 持仓信息。
  94.                 } else {//如果 pos 是null
  95.                     throw "恢复" + obj.symbol + "的持仓状态出错, 没有找到仓位信息";//抛出错误 , 恢复 symbol 这个合约的 时候 持仓状态出错,没有找到持仓信息。
  96.                 }
  97.                 Log("恢复", obj.symbol, "加仓次数", obj.marketPosition, "持仓均价:", obj.holdPrice, "持仓数量:", obj.holdAmount, "最后一次加仓价", obj.openPrice, "N值", obj.N, "离市周期:", leavePeriod, "上次突破:", obj.preBreakoutFailure ? "失败" : "成功");
  98.                 //在日志打印, 合约代码 ,  加仓次数 ,持仓均价 ,持仓数量 ,最后一次加仓价
  99.                 obj.status.open = 1;//恢复开仓次数 1
  100.                 obj.status.vm = [obj.marketPosition, obj.openPrice, obj.N, obj.leavePeriod, obj.preBreakoutFailure]; //给obj.status.vm 赋值
  101.             } else {// marketPosition === 'undefined' 即 在调用该函数时 ,没有传入任何参数。
  102.                 obj.marketPosition = 0;// 加仓次数 为0
  103.                 obj.holdPrice = 0;// 持仓均价 0
  104.                 obj.openPrice = 0; // 最后一次加仓价格 0
  105.                 obj.holdAmount = 0; // 持仓量  0
  106.                 obj.holdProfit = 0; // 持仓 盈亏 0
  107.                 obj.preBreakoutFailure = true; // test system A   //上次突破是否失败, true即真
  108.                 obj.N = 0; // N值  0
  109.                 obj.leavePeriod = leavePeriodA; // 系统A 的离市周期(界面参数) 赋值给 leavePeriod  
  110.             }
  111.             obj.holdProfit = 0; // 主要用于 if条件触发
  112.             obj.lastErr = ""; // if  和  else  操作 都会执行该语句
  113.             obj.lastErrTime = ""; // 同上
  114.         };

  115.         obj.Status = function() {// 更新obj 对象的 Status 属性
  116.             obj.status.N = obj.N; // 用obj对象相应的属性去赋值 (status属性中相应的 成员) N值
  117.             obj.status.marketPosition = obj.marketPosition; //加仓次数 (也是持仓方向 +  -  代表方向, 数值代表 操作的次数,一个方向 直到 平仓)
  118.             obj.status.holdPrice = obj.holdPrice;
  119.             obj.status.holdAmount = obj.holdAmount;
  120.             obj.status.lastPrice = obj.lastPrice;
  121.             if (obj.lastPrice > 0 && obj.holdAmount > 0 && obj.marketPosition !== 0) {
  122.                 obj.status.holdProfit = _N((obj.lastPrice - obj.holdPrice) * obj.holdAmount * symbolDetail.VolumeMultiple, 4) * (obj.marketPosition > 0 ? 1 : -1);
  123.             } else {
  124.                 obj.status.holdProfit = 0;
  125.             }
  126.             return obj.status;
  127.         };
  128.         obj.Poll = function() {
  129.             var suffix = WXPush ? '@' : '';
  130.             // switch symbol
  131.             _C(exchange.SetContractType, obj.symbol);
  132.             var records = exchange.GetRecords();
  133.             if (!records) {
  134.                 obj.setLastError("获取K线失败");
  135.                 return;
  136.             }
  137.             obj.status.recordsLen = records.length;
  138.             if (records.length < obj.atrLen) {
  139.                 obj.setLastError("K线长度小于 " + obj.atrLen);
  140.                 return;
  141.             }
  142.             var opCode = 0; // 0: IDLE, 1: LONG, 2: SHORT, 3: CoverALL
  143.             var lastPrice = records[records.length - 1].Close;
  144.             obj.lastPrice = lastPrice;
  145.             if (obj.marketPosition === 0) {
  146.                 obj.status.upLine = 0;
  147.                 obj.status.downLine = 0;
  148.                 for (var i = 0; i < 2; i++) {
  149.                     if (i == 0 && obj.useFilter && !obj.preBreakoutFailure) {
  150.                         continue;
  151.                     }
  152.                     var enterPeriod = i == 0 ? obj.enterPeriodA : obj.enterPeriodB;
  153.                     if (records.length < (enterPeriod + 1)) {
  154.                         continue;
  155.                     }
  156.                     var highest = TA.Highest(records, enterPeriod, 'High');
  157.                     var lowest = TA.Lowest(records, enterPeriod, 'Low');
  158.                     obj.status.upLine = obj.status.upLine == 0 ? highest : Math.min(obj.status.upLine, highest);
  159.                     obj.status.downLine = obj.status.downLine == 0 ? lowest : Math.max(obj.status.downLine, lowest);
  160.                     if (lastPrice > highest) {
  161.                         opCode = 1;
  162.                     } else if (lastPrice < lowest) {
  163.                         opCode = 2;
  164.                     }
  165.                     obj.leavePeriod = (enterPeriod == obj.enterPeriodA) ? obj.leavePeriodA : obj.leavePeriodB;
  166.                 }
  167.             } else {
  168.                 var spread = obj.marketPosition > 0 ? (obj.openPrice - lastPrice) : (lastPrice - obj.openPrice);
  169.                 if (spread > (obj.N * 2)) {
  170.                     opCode = 3;
  171.                     obj.preBreakoutFailure = true;
  172.                     Log(obj.symbolDetail.InstrumentName, "止损平仓", suffix);
  173.                     obj.status.st++;
  174.                 } else if (-spread > (0.5 * obj.N)) {
  175.                     opCode = obj.marketPosition > 0 ? 1 : 2;
  176.                 } else if (records.length > obj.leavePeriod) {
  177.                     if ((obj.marketPosition > 0 && lastPrice < TA.Lowest(records, obj.leavePeriod, 'Low')) ||
  178.                         (obj.marketPosition < 0 && lastPrice > TA.Highest(records, obj.leavePeriod, 'High'))) {
  179.                         obj.preBreakoutFailure = false;
  180.                         Log(obj.symbolDetail.InstrumentName, "正常平仓", suffix);
  181.                         opCode = 3;
  182.                         obj.status.cover++;
  183.                     }
  184.                 }
  185.             }

  186.             if (opCode == 0) {
  187.                 return;
  188.             }
  189.             if (opCode == 3) {
  190.                 _bot.Cover(obj.symbol);
  191.                 obj.reset();
  192.                 _G(obj.symbol, null);
  193.                 return;
  194.             }
  195.             // Open
  196.             if (Math.abs(obj.marketPosition) >= obj.maxLots) {
  197.                 obj.setLastError("禁止开仓, 超过最大持仓 " + obj.maxLots);
  198.                 return;
  199.             }
  200.             var atrs = TA.ATR(records, atrLen);
  201.             var N = _N(atrs[atrs.length - 1], 4);

  202.             var account = _bot.GetAccount();
  203.             var unit = parseInt(account.Balance * (obj.riskRatio / 100) / N / obj.symbolDetail.VolumeMultiple);
  204.             var canOpen = parseInt(account.Balance / (opCode == 1 ? obj.symbolDetail.LongMarginRatio : obj.symbolDetail.ShortMarginRatio) / (lastPrice * 1.2) / obj.symbolDetail.VolumeMultiple);
  205.             unit = Math.min(unit, canOpen);
  206.             if (unit < obj.symbolDetail.MinLimitOrderVolume) {
  207.                 obj.setLastError("可开 " + unit + " 手 过小无法开仓");
  208.                 return;
  209.             }
复制代码

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:商品期货 海龟交易 CTP 交易法 Instruments 商品期货 海龟交易法

沙发
littleDreamX 发表于 2016-8-10 16:45:19 |只看作者 |坛友微信交流群
  1. var ret = null;
  2. if (opCode == 1) {
  3. ret = _bot.OpenLong(obj.symbol, unit);
  4. } else {
  5. ret = _bot.OpenShort(obj.symbol, unit);
  6. }
  7. if (!ret) {
  8. obj.setLastError("下单失败");
  9. return;
  10. }

  11. Log(obj.symbolDetail.InstrumentName, obj.marketPosition == 0 ? "开仓" : "加仓", "离市周期", obj.leavePeriod, suffix);
  12. obj.N = N;
  13. obj.openPrice = ret.price;
  14. obj.holdPrice = ret.position.Price;
  15. if (obj.marketPosition == 0) {
  16. obj.status.open++;
  17. }
  18. obj.holdAmount = ret.position.Amount;
  19. obj.marketPosition += opCode == 1 ? 1 : -1;
  20. obj.status.vm = [obj.marketPosition, obj.openPrice, N, obj.leavePeriod, obj.preBreakoutFailure];
  21. _G(obj.symbol, obj.status.vm);

  22. };
  23. var vm = null;
  24. if (RMode === 0) {
  25. vm = _G(obj.symbol);
  26. } else {
  27. vm = JSON.parse(VMStatus)[obj.symbol];
  28. }
  29. if (vm) {
  30. Log("准备恢复进度, 当前合约状态为", vm);
  31. obj.reset(vm[0], vm[1], vm[2], vm[3], vm[4]);
  32. } else {
  33. if (needRestore) {
  34. throw "没有找到" + obj.symbol + "的进度恢复信息";
  35. }
  36. obj.reset();
  37. }
  38. return obj;
  39. }
  40. };

  41. function onexit() {
  42. Log("已退出策略...");
  43. }

  44. function main() {
  45. if (exchange.GetName().indexOf('CTP') == -1) {
  46. throw "只支持商品期货CTP";
  47. }
  48. SetErrorFilter("login|ready|流控|连接失败|初始|Timeout");
  49. var mode = exchange.IO("mode", 0);
  50. if (typeof(mode) !== 'number') {
  51. throw "切换模式失败, 请更新到最新托管者!";
  52. }
  53. while (!exchange.IO("status")) {
  54. Sleep(3000);
  55. LogStatus("正在等待与交易服务器连接, " + new Date());
  56. }
  57. var positions = _C(exchange.GetPosition);
  58. if (positions.length > 0) {
  59. Log("检测到当前持有仓位, 系统将开始尝试恢复进度...");
  60. }
  61. Log("风险系数:", RiskRatio, "N值周期:", ATRLength, "系统1: 入市周期", EnterPeriodA, "离市周期", LeavePeriodA, "系统二: 入市周期", EnterPeriodB, "离市周期", LeavePeriodB, "加仓系数:", IncSpace, "止损系数:", StopLossRatio, "单品种最多开仓:", MaxLots, "次");
  62. var tts = [];
  63. var filter = [];
  64. var arr = Instruments.split(',');
  65. for (var i = 0; i < arr.length; i++) {
  66. var symbol = arr[i].replace(/^\s+/g, "").replace(/\s+$/g, "");
  67. if (typeof(filter[symbol]) !== 'undefined') {
  68. Log(symbol, "已经存在, 系统已自动过滤");
  69. continue;
  70. }
  71. filter[symbol] = true;
  72. var hasPosition = false;
  73. for (var j = 0; j < positions.length; j++) {
  74. if (positions[j].ContractType == symbol) {
  75. hasPosition = true;
  76. break;
  77. }
  78. }
  79. var obj = TTManager.New(hasPosition, symbol, RiskRatio, ATRLength, EnterPeriodA, LeavePeriodA, EnterPeriodB, LeavePeriodB, UseEnterFilter, IncSpace, StopLossRatio, MaxLots);
  80. tts.push(obj);
  81. }
  82. var initAccount = _bot.GetAccount();
  83. Log("资产信息", initAccount);

  84. var preTotalHold = -1;
  85. var lastStatus = '';
  86. while (true) {
  87. while (!exchange.IO("status")) {
  88. Sleep(3000);
  89. LogStatus("正在等待与交易服务器连接, " + new Date() + "\n" + lastStatus);
  90. }
  91. var tblStatus = {
  92. type: "table",
  93. title: "持仓信息",
  94. cols: ["合约名称", "持仓方向", "持仓均价", "持仓数量", "持仓盈亏", "加仓次数", "开仓次数", "止损次数", "成功次数", "当前价格", "N"],
  95. rows: []
  96. };
  97. var tblMarket = {
  98. type: "table",
  99. title: "数据信息",
  100. cols: ["合约名称", "合约乘数", "保证金率", "柱线长度", "上线", "下线", "异常描述", "发生时间"],
  101. rows: []
  102. };
  103. var totalHold = 0;
  104. var vmStatus = {};
  105. var ts = new Date().getTime();
  106. for (var i = 0; i < tts.length; i++) {
  107. tts[i].Poll();
  108. var d = tts[i].Status();
  109. if (d.holdAmount > 0) {
  110. vmStatus[d.symbol] = d.vm;
  111. }
  112. tblStatus.rows.push([d.symbolDetail.InstrumentName, d.holdAmount == 0 ? '--' : (d.marketPosition > 0 ? '多' : '空'), d.holdPrice, d.holdAmount, d.holdProfit, Math.abs(d.marketPosition), d.open, d.st, d.cover, d.lastPrice, d.N]);
  113. tblMarket.rows.push([d.symbolDetail.InstrumentName, d.symbolDetail.VolumeMultiple, _N(d.symbolDetail.LongMarginRatio, 4) + '/' + _N(d.symbolDetail.ShortMarginRatio, 4), d.recordsLen, d.upLine, d.downLine, d.lastErr, d.lastErrTime]);
  114. totalHold += Math.abs(d.holdAmount);
  115. }
  116. var now = new Date();
  117. var elapsed = now.getTime() - ts;
  118. var tblAssets = _bot.GetAccount(true);
  119. var nowAccount = _bot.Account();
  120. if (tblAssets.rows.length > 10) {
  121. // replace AccountId
  122. tblAssets.rows[0] = ["InitAccount", "初始资产", initAccount];
  123. } else {
  124. tblAssets.rows.unshift(["NowAccount", "当前可用", nowAccount], ["InitAccount", "初始资产", initAccount]);
  125. }
  126. lastStatus = '`' + JSON.stringify([tblStatus, tblMarket, tblAssets]) + '`\n轮询耗时: ' + elapsed + ' 毫秒, 当前时间: ' + now.toLocaleString();
  127. if (totalHold > 0) {
  128. lastStatus += "\n手动恢复字符串: " + JSON.stringify(vmStatus);
  129. }
  130. LogStatus(lastStatus);
  131. if (preTotalHold > 0 && totalHold == 0) {
  132. LogProfit(nowAccount.Balance - initAccount.Balance);
  133. }
  134. preTotalHold = totalHold;
  135. Sleep(LoopInterval * 1000);
  136. }
  137. }
复制代码
已有 1 人评分经验 论坛币 收起 理由
fantuanxiaot + 22 + 22 精彩帖子

总评分: 经验 + 22  论坛币 + 22   查看全部评分

使用道具

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注jr
拉您进交流群

京ICP备16021002-2号 京B2-20170662号 京公网安备 11010802022788号 论坛法律顾问:王进律师 知识产权保护声明   免责及隐私声明

GMT+8, 2024-4-25 04:49