量化对冲网格模型基于发明者平台的比特币OKCoin期货交易策略

 

比特币.okcoin

OKCoin期货跨期对冲策略,季度、当周、次周

1、 季度-当周

2、 季度-次周

3、 当周-次周

4、在周五交割前5分钟会自动 平仓, 锁定15分钟 后再正常运行。

作者本人呢 是菜鸟程序猿一个, 平时没什么爱好,就喜欢写代码。最近一年在发明者量化上学到了不少新知识, 模仿Zero 大神的商品期货对冲网格策略,写了一个 电子货币 (BTC期货) 的对冲网格策略。回测一下还行(当然回测只是最初步的检测,不代表任何结论!)

以下代码不能直接运行,需要配置参数(在发明者量化平台)。代码连接: https://www.botvs.com/strategy/34878

对冲网格策略

对冲网格策略

var checkTime = 0; var residualTime = 0; var checkPreTime = 0; var JGDate = [];                                     // 交割模拟。 ["BTC1129", "BTC1229", "BTC0316"]; var JGDateIndex = 0;                                 // 模拟交割索引。 var JGHoursCorrect = 8;                              // 检测交割剩余小时,在实盘中需要修正 8小时。 模拟时该值设置为0 var idA = null; var idB = null; var A = 1; var B = 2; var PRE = 3; var PLUS = 4; var MINUS = 5; var FREE = 6;  function init(){     if(istry){         JGHoursCorrect = 0;                          // 模拟中 该值修改为0         Log("启用模拟 交割,初始化交割日期列表。");         UpdateJGDate();     } }  function UpdateJGDate(){                                  // 循环31次 遍历出 当前月份的所有 星期5的 日期, 取时间戳, 对比当前时间戳,小于当前的 丢弃,大于当前的第一个即是      // 在用时间戳恢复日期,拿到 字符串     var array_JG_stamp = [];     var date = new Date();     var nowStamp = date.getTime();     var nowMonth = date.getmonth();     var nextJG_Stamp = 0;     date.setHours(16);                     // 0~23     date.setMinutes(0);                    // 0~59     date.setSeconds(0);                    // 0~59     for(var i = 1 ; i <= 31; i++){         date.setDate(i);         var EveryDay = date.getDay();        // 1~6         if(EveryDay === 5 && nowMonth == date.getMonth()){             var fridayStamp = date.getTime();             array_JG_stamp.push(fridayStamp);         }     }     for(var j = 0 ; j < array_JG_stamp.length ; j++){         if(nowStamp <= array_JG_stamp[j]){             nextJG_Stamp = array_JG_stamp[j];             break;         }         if(j == array_JG_stamp.length - 1){                  nextJG_Stamp = array_JG_stamp[j] + 1000 * 7 * 24 * 60 * 60;                }     }     array_JG_stamp = [];     for(var n = 1 ; n <= 100; n++){  // 生成 100 个 模拟交割日期。         if(n == 1){             array_JG_stamp.push(nextJG_Stamp);         }else{             nextJG_Stamp += 1000 * 7 * 24 * 60 * 60;             array_JG_stamp.push(nextJG_Stamp);         }     }     var date2 = new Date();     for(var m = 0 ; m < array_JG_stamp.length ; m++){         date2.setTime(array_JG_stamp[m]);         var strMonth = date2.getMonth() + 1;         var strDate = date2.getDate();         if(strMonth < 10){             strMonth = '0' + strMonth;         }         if(strDate < 10){             strDate = '0' + strDate;         }         JGDate.push("BTC" + strMonth + strDate);     }     Log("模拟生成的交割日期:", JGDate); }  function CheckDelivery(nowTime, symbol, task) {     var contractInfo = null;     if(checkTime <= 0){         var contractName = "";         var ContractIndex = 0;         if(Symbol === "this_week"){             ContractIndex = 0;         }else if(Symbol === "next_week"){             ContractIndex = 1;         }else if(Symbol === "quarter"){             ContractIndex = 2;         }         if(istry === true){                          // 判断是不是 模拟测试             try{                 contractName = JGDate[JGDateIndex];  // 模拟测试 交割日期                 JGDateIndex++;             } catch(e){                 Log("回测模式,更新交割日期错误", e);                 JGDateIndex--;             }         }         while (contractName == "") {             //var contractInfo = HttpQuery("https://www.okcoin.com/api/v1/future_hold_amount.do?symbol=btc_usd&contract_type=this_week"); //只是检测this_week ,避免重复调用提高效率             switch(ContractIndex){                 case 0: contractInfo = HttpQuery("https://www.okcoin.com/api/v1/future_hold_amount.do?symbol=btc_usd&contract_type=this_week");                         break;                 case 1: contractInfo = HttpQuery("https://www.okcoin.com/api/v1/future_hold_amount.do?symbol=btc_usd&contract_type=next_week");                         break;                 case 2: contractInfo = HttpQuery("https://www.okcoin.com/api/v1/future_hold_amount.do?symbol=btc_usd&contract_type=quarter");                         break;                 default: Log("contractInfo:", contractInfo);                           //throw "switch NumContractType ERROR!";             }            //根据 contractType 类型 选择读取合约交割日期             if (!contractInfo || contractInfo.length === 0) {                 Sleep(100);                 continue;             }             try {                 contractName = (JSON.parse(contractInfo))[0].contract_name;             } catch (e) {                 Log("CheckDelivery Error",contractInfo, e);                 return 0;             }         }         var nowDateTime = new Date();         contractName = contractName.split("BTC")[1]; //抽取BTC后的字符串 重新赋值         var strMonth = contractName[0] + contractName[1];         var strDay = contractName[2] + contractName[3];         var strYear = nowDateTime.getFullYear() + ""; //获取 年份字符串                  // 处理跨年问题         var nowMonth = nowDateTime.getMonth(); // 获取月份         if(strMonth < nowMonth){             strYear = (strYear - 0) + 1;             strYear = strYear + "";         }                  var strDate = strYear + '-' + strMonth + '-' + strDay + ' ' + "16:00:00";         var deliveryTime = (new Date(strDate)).getTime();             // + 16 * 60 * 60 * 1000;         nowTime = nowDateTime.getTime();         residualTime = (deliveryTime - nowTime) / 1000 / 60 / 60 - JGHoursCorrect; //单位是小时         checkTime = (deliveryTime - nowTime) - JGHoursCorrect * 1000 * 60 * 60;    //还差多少毫秒交割         checkPreTime = nowTime;                                       //记录开始的时间         Log("合约", Symbol, "交割日期获取:", strDate);      }else{         checkTime -= nowTime - checkPreTime;                          //减去消耗的时间         checkPreTime = nowTime;         residualTime = checkTime / 1000 / 60 / 60;                    // 计算距离交割多少小时     }     if(residualTime < 24){                                            //交割小于24小时         MSG_String = "  " + Symbol + " 交割时间剩余:" + residualTime + "小时!!#FF0000";         if((checkTime / 1000 / 60) <= 5 && task.isFrozen == false){   // 每次交割前5分钟 锁定。             Log("距离交割剩余5分钟,平掉所有仓位!#FF0000");             for(var index = 0; index < task.dic.length; index++){                 if(task.dic[index].hold > 0){                                                 // 平空A 平多B                     task.action = [index, "closesell", "closebuy", task.dic[index].hold];                     Log(JSON.stringify(task.action));                     Hedge_Open_Cover(task);                     $.PlotFlag(nowTime, "C", "closesell-closebuy", "circlepin");                 }else if(task.dic[index].hold < 0){                                           // 平多A 平空B                     task.action = [index, "closebuy", "closesell", task.dic[index].hold];                     Log(JSON.stringify(task.action));                     Hedge_Open_Cover(task);                     $.PlotFlag(nowTime, "C", "closebuy-closesell", "circlepin");                 }             }             task.nowAccount = _C(task.e.GetAccount);             var Positions = _C(task.e.GetPosition);             UpdatePosition(task, Positions);             Log("全部仓位已平,检查持仓:", Positions, "程序冻结15分钟!#FF0000");             task.isFrozen = true;             task.FrozenStartTime = new Date().getTime();         }     }else{         MSG_String = "  " + Symbol + " 交割时间剩余:" + residualTime + "小时!!";     }     return _N(residualTime, 3); }   function OpenPriceToActual(Price, Piece){     var OnePieceequivalentCoin = 100 / Price;     var OpenFee = Piece * (OnePieceEquivalentCoin) * (0.03 * 0.01);     var Actual = Price + (OpenFee * Price) / (OnePieceEquivalentCoin * Piece);     return Actual;     //Log("Actual:", Actual, "OpenFee:", OpenFee, "OnePieceEquivalentCoin:", OnePieceEquivalentCoin, "保证金:", OpenFee / 0.01 / 0.03 / 10); // 测试     //var Actual = Price + ((0.03 * 0.01) * Price); }  function CreateHedgeList(Begin, End, Size, Step, AmountOfPoint, SymbolA, SymbolB){     // "(this_week&quarter)100:90:1;110:100:1;120:110:1;130:120:1;140:130:1;150:140:1;160:150:1;170:160:1;180:170:1;190:180:1";     if((SymbolA !== "this_week" && SymbolA !== "next_week" && SymbolA !== "quarter") || (SymbolB !== "this_week" && SymbolB !== "next_week" && SymbolB !== "quarter")){         throw "合约代码错误: SymbolA " + SymbolA + " SymbolB " + SymbolB;     }     var BodyString = "";     var HeadString = '(' + SymbolA + '&' + SymbolB + ')';     for(var i = Begin ; i <= End ; i += Step){         if(i + Step > End){             BodyString += (i + ':') + (i - Size) + (':' + AmountOfPoint);         }else{             BodyString += (i + ':') + (i - Size) + (':' + AmountOfPoint) + ';';         }     }     var HL = HeadString + BodyString;     Log("按参数生成对冲列表:", HL);     return HL; }  function UpdatePosition(task, Positions, onlyAorBorPRE){     if(Positions.length > 2){         Log(Positions, "Positions 长度大于2!#FF0000");         throw "同类型合约不能同时持有多仓空仓。";     }     if(onlyAorBorPRE == PRE){         task.Pre_APositions = task.APositions;         task.Pre_BPositions = task.BPositions;     }     for(var i = 0; i < Positions.length; i++){         if(Positions[i].ContractType == task.symbolA && onlyAorBorPRE !== B){             task.APositions = Positions[i];         }         if(Positions[i].ContractType == task.symbolB && onlyAorBorPRE !== A){             task.BPositions = Positions[i];         }     }     if(Positions.length == 0){         if(onlyAorBorPRE !== B){             task.APositions = {MarginLevel: 0, Amount: 0, FrozenAmount: 0, Price: 0, Profit: 0, Type: 0, ContractType: ""};         }         if(onlyAorBorPRE !== A){             task.BPositions = {MarginLevel: 0, Amount: 0, FrozenAmount: 0, Price: 0, Profit: 0, Type: 0, ContractType: ""};         }         if(onlyAorBorPRE !== A && onlyAorBorPRE !== B){             task.APositions = {MarginLevel: 0, Amount: 0, FrozenAmount: 0, Price: 0, Profit: 0, Type: 0, ContractType: ""};              task.BPositions = {MarginLevel: 0, Amount: 0, FrozenAmount: 0, Price: 0, Profit: 0, Type: 0, ContractType: ""};         }     } }  function DealAction(task, AorB, amount){     if(amount <= 0){         throw "错误: DealAction 的 amount 参数为:" + amount;     }     if(AorB == A){         task.e.SetContractType(task.symbolA);         task.e.SetDirection(task.action[1]);         if(task.action[1] == "buy" || task.action[1] == "closesell"){             idA = task.e.Buy(-1, typeof(amount) == "undefined" ? Math.abs(task.action[3]) : amount, task.symbolA);         }else if(task.action[1] == "sell" || task.action[1] == "closebuy"){             idA = task.e.Sell(-1, typeof(amount) == "undefined" ? Math.abs(task.action[3]) : amount, task.symbolA);         }     }     if(AorB == B){         task.e.SetContractType(task.symbolB);         task.e.SetDirection(task.action[2]);         if(task.action[2] == "buy" || task.action[2] == "closesell"){             idB = task.e.Buy(-1, typeof(amount) == "undefined" ? Math.abs(task.action[3]) : amount, task.symbolB);         }else if(task.action[2] == "sell" || task.action[2] == "closebuy"){             idB = task.e.Sell(-1, typeof(amount) == "undefined" ? Math.abs(task.action[3]) : amount, task.symbolB);         }     } }  function DealActionlimit(task, AorB, Piece, isAgain){     var tradeInfo  = null;     var Price = 0;     var Piece = Math.abs(Piece);     if(isAgain){         while(true){             task.e.SetContractType(task.symbolA);             var Adepth = task.e.GetDepth();             task.e.SetContractType(task.symbolB);             var Bdepth = task.e.GetDepth();                          if(!Adepth || !Bdepth || Adepth.Asks.length === 0 || Adepth.Bids.length === 0 || Bdepth.Asks.length === 0 || Bdepth.Bids.length === 0){                 //Log("获取深度信息异常!", Adepth, Bdepth);                 Sleep(Interval);                 continue;             }                          task.Adepth = Adepth;             task.Bdepth = Bdepth;                          task.Adiff = _N(Adepth.Bids[0].Price - Bdepth.Asks[0].Price);             task.Bdiff = _N(Adepth.Asks[0].Price - Bdepth.Bids[0].Price);             break;         }     }     task.e.SetContractType(AorB == A ? task.symbolA : task.symbolB);     task.e.SetDirection(task.action[AorB]);     if(task.action[AorB] == "buy"){         Price = AorB == A ? task.Adepth.Asks[0].Price : task.Bdepth.Asks[0].Price;         tradeInfo = task.P.OpenLong(AorB == A ? task.symbolA : task.symbolB, Piece, Price);     }else if(task.action[AorB] == "sell"){         Price = AorB == A ? task.Adepth.Bids[0].Price : task.Bdepth.Bids[0].Price;         tradeInfo = task.P.OpenShort(AorB == A ? task.symbolA : task.symbolB, Piece, Price);     }else if(task.action[AorB] == "closebuy"){         Price = AorB == A ? task.Adepth.Bids[0].Price : task.Bdepth.Bids[0].Price;         tradeInfo = task.P.Cover(AorB == A ? task.symbolA : task.symbolB, Price, Piece, PD_LONG); // task.action[AorB]      }else if(task.action[AorB] == "closesell"){         Price = AorB == A ? task.Adepth.Asks[0].Price : task.Bdepth.Asks[0].Price;         tradeInfo = task.P.Cover(AorB == A ? task.symbolA : task.symbolB, Price, Piece, PD_SHORT); // task.action[AorB]     }     if((task.action[AorB] == "buy" || task.action[AorB] == "sell") && tradeInfo.amount === 0){         return false;     }else if((task.action[AorB] == "closebuy" || task.action[AorB] == "closesell") && tradeInfo == 0){         return false;     }     return tradeInfo; }  function CalcActualPrice(task){     if(task.action[0] == 0){         var A_Pv = task.APositions.Price;         var B_Pv = task.BPositions.Price;          task.dic[task.action[0]].ActualPrice = A_Pv - B_Pv;         Log(task.symbolA, A_Pv, task.symbolB, B_Pv, "#FF0000");     }else if(task.APositions.Amount == 1 && task.BPositions.Amount == 1){         var A_Pv = task.APositions.Price;         var B_Pv = task.BPositions.Price;          task.dic[task.action[0]].ActualPrice = A_Pv - B_Pv;         Log(task.symbolA, A_Pv, task.symbolB, B_Pv, "#FF0000");     }else{         var A_Pv = task.APositions.Price;         var A_P1 = task.Pre_APositions.Price;         var A_m = task.APositions.Amount - task.Pre_APositions.Amount;         var A_n = task.Pre_APositions.Amount;          var B_Pv = task.BPositions.Price;          var B_P1 = task.Pre_BPositions.Price;         var B_m = task.BPositions.Amount - task.Pre_BPositions.Amount;         var B_n = task.Pre_BPositions.Amount;          var A_P2 = A_Pv * A_P1 * A_m / ((A_m + A_n) * A_P1 - A_n * A_Pv);         var B_P2 = B_Pv * B_P1 * B_m / ((B_m + B_n) * B_P1 - B_n * B_Pv);          task.dic[task.action[0]].ActualPrice = A_P2 - B_P2;         Log(task.symbolA, A_P2, task.symbolB, B_P2, "#FF0000");     } }  function Hedge_Open_Cover(task){     if(task.isUseMarketorder === false){       // 限价单         if((task.action[1] === "buy" && task.action[2] === "sell") || (task.action[1] === "sell" && task.action[2] === "buy")){ // open             var tradeInfo_A = DealActionLimit(task, A, task.action[3]);             var dealAmount_A = Math.abs(task.action[3]);             while(tradeInfo_A == false || (dealAmount_A -= tradeInfo_A.amount) !== 0){                 Log("合约:" + task.symbolA + "已对冲" + (tradeInfo_A == false ? 0 : tradeInfo_A.amount), "剩余,重试!张数:" + dealAmount_A);                 tradeInfo_A = DealActionLimit(task, A, dealAmount_A, true);                 Sleep(Interval);             }              var tradeInfo_B = DealActionLimit(task, B, task.action[3]);             var dealAmount_B = Math.abs(task.action[3]);             while(tradeInfo_B == false || (dealAmount_B -= tradeInfo_B.amount) !== 0){                 Log("合约:" + task.symbolB + "已对冲" + (tradeInfo_B == false ? 0 : tradeInfo_B.amount), "剩余,重试!张数:" + dealAmount_B);                 tradeInfo_B = DealActionLimit(task, B, dealAmount_B, true);                 Sleep(Interval);             }              task.dic[task.action[0]].hold = task.action[3];             // task.dic[task.action[0]].ActualPrice = _N(orderA.AvgPrice - orderB.AvgPrice);         }else if((task.action[1] === "closesell" && task.action[2] === "closebuy") || (task.action[1] === "closebuy" && task.action[2] === "closesell")){ // cover             var tradeInfo_A_Piece = DealActionLimit(task, A, task.action[3]);             var dealAmount_A = Math.abs(task.action[3]);             while(tradeInfo_A_Piece == false || (dealAmount_A -= tradeInfo_A_Piece) !== 0){                 Log("合约:" + task.symbolA + "已对冲" + (tradeInfo_A == false ? 0 : tradeInfo_A_Piece), "剩余,重试!张数:" + dealAmount_A);                 tradeInfo_A_Piece = DealActionLimit(task, A, dealAmount_A, true);                 Sleep(Interval);             }                          var tradeInfo_B_Piece = DealActionLimit(task, B, task.action[3]);             var dealAmount_B = Math.abs(task.action[3]);             while(tradeInfo_B_Piece == false || (dealAmount_B -= tradeInfo_B_Piece) !== 0){                 Log("合约:" + task.symbolB + "已对冲" + (tradeInfo_B == false ? 0 : tradeInfo_B_Piece), "剩余,重试!张数:" + dealAmount_B);                 tradeInfo_B_Piece = DealActionLimit(task, B, dealAmount_B, true);                 Sleep(Interval);             }              task.dic[task.action[0]].hold = 0;             task.dic[task.action[0]].ActualPrice = 0;             task.dic[task.action[0]].CoverTimes += 1;         }         Sleep(100);     }else if(task.isUseMarketOrder === true){  // 市价单         var orderA = null;         var orderB = null;         if((task.action[1] === "buy" && task.action[2] === "sell") || (task.action[1] === "sell" && task.action[2] === "buy")){ // open             DealAction(task, A);             DealAction(task, B);              while(!idA || !idB){                 if(!idA){                     DealAction(task, A);                 }                 if(!idB){                     DealAction(task, B);                 }             }                          while(true){                 if(!orderA || orderA.Status !== ORDER_STATE_CLOSED){                     orderA = task.e.GetOrder(idA);                 }                 if(!orderB || orderB.Status !== ORDER_STATE_CLOSED){                     orderB = task.e.GetOrder(idB);                 }                 if(orderA && orderB && orderA.Status == ORDER_STATE_CLOSED && orderB.Status == ORDER_STATE_CLOSED){                     break;                 }                 Sleep(Interval);             }              //Log("Open symbolA:", orderA, "symbolB:", orderB);             task.dic[task.action[0]].hold = task.action[3];             task.dic[task.action[0]].ActualPrice = _N(orderA.AvgPrice - orderB.AvgPrice);         }else if((task.action[1] === "closesell" && task.action[2] === "closebuy") || (task.action[1] === "closebuy" && task.action[2] === "closesell")){ // cover             DealAction(task, A);             DealAction(task, B);              while(!idA || !idB){                 if(!idA){                     DealAction(task, A);                 }                 if(!idB){                     DealAction(task, B);                 }             }              while(true){                 if(!orderA || orderA.Status !== ORDER_STATE_CLOSED){                     orderA = task.e.GetOrder(idA);                 }                 if(!orderB || orderB.Status !== ORDER_STATE_CLOSED){                     orderB = task.e.GetOrder(idB);                 }                 if(orderA && orderB && orderA.Status == ORDER_STATE_CLOSED && orderB.Status == ORDER_STATE_CLOSED){                     break;                 }                 Sleep(Interval);             }              //Log("Cover symbolA:", orderA, "symbolB:", orderB);             task.dic[task.action[0]].hold = 0;             task.dic[task.action[0]].ActualPrice = 0;             task.dic[task.action[0]].CoverTimes += 1;         }         Sleep(100); // 避免访问过于频繁。     } }  function Taskscontroller(){ // 任务控制器 构造函数     // 构造用于返回的 控制器对象     var self = {};     self.tasks = []; // 控制器的任务数组。      self.AddTask = function(e, symbolA, symbolB, HedgeList){ // 添加对冲 任务, 函数中进行 构造, 部分参数变量未初始化。在main 函数开始 根据界面参数列表,确定task 个数 进行构造。         var task = {             // 任务的参数变量             e : e,             symbolA : symbolA,             symbolB : symbolB,             HedgeList : HedgeList,             dic : [],             Adepth : null,             Bdepth : null,             Adiff : 0,             Bdiff : 0,             action : null,             lastUpdateLineTime : 0,             MarginLevel : MarginLevel,             isUseMarketOrder : true,             // 账户信息             initAccount : _C(e.GetAccount),             nowAccount : null,             isFrozen : false,             FrozenStartTime : 0,             APositions : null,             BPositions : null,             Pre_APositions : null,             Pre_BPositions : null,             PositionsLastUpdateTime : 0,             isLogProfit : false,             taskProfit : 0,             State : FREE,         };         self.tasks.push(task);     }          self.InitTask = function(){ // 初始化 任务,设置合约 杠杆等         _.each(self.tasks, function(task){             var arr = task.HedgeList.split(';');             var hedgeDirection = 1;             // 可扩展 恢复持仓,读取当前持仓。             _.each(arr, function(pair){                 var tmp = pair.split(':');                               // 把每个 网格节点的 单元 按照':'字符 分割成 参数 数组 tmp                 if (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                     ActualPrice: 0,                     PointProfit : 0,                                     // 但个仓位累计差价。                            CoverTimes : 0,                                      // 平仓次数                       };                 task.dic.push(st);             });             // 处理其它 初始化工作             task.P = $.NewPositionManager(task.e);             task.isUseMarketOrder = isUseMarketOrder;                    // 初始是否使用市价单             task.e.SetMarginLevel(task.MarginLevel);                     // 设置杠杆             task.nowAccount = _C(task.e.GetAccount);                     // 初始化 当前账户信息             // 检查, 启用的网格 是否会 耗尽资金             if((task.dic[0].open < 0 && isCreateHedgeList) || (task.dic[0].cover < 0 && isCreateHedgeList)){                       // throw "自动网格生成错误:第一个节点开仓值、平仓值 小于0,会引起产生重复部分。" +JSON.stringify(task.dic);                     }             var dic_length = task.dic.length;             var sumPiece = 0;             for(var i = 0; i < dic_length; i++){                 sumPiece += task.dic[i].amount;             }             sumPiece = sumPiece * 2;             task.e.SetContractType(task.symbolA);             var tickerA = _C(task.e.GetTicker);             task.e.SetContractType(task.symbolB);             var tickerB = _C(task.e.GetTicker);             var Margin = sumPiece * 100 * OK_Rate / ((tickerA.Last + tickerB.Last) / 2) / task.MarginLevel;             if(MarginRatio * task.initAccount.Stocks < Margin){                 if(istry == false || Isvirtual()){                     throw "满仓所需保证金:" + Margin + " 超出 限制比例: " + MarginRatio;                 }else{                     Log("注意,实盘测试模式开启!#FF0000");                 }             }              Log("按照当前初始化,满仓将开" + sumPiece + "张合约,共需要 保证金:" + Margin + "BTC");         });     }      self.DealTask = function(nowTime){         // 处理task 任务         tbls = []; // 每次初始清空         _.each(self.tasks, function(task){             // 迭代处理 task              task.e.SetContractType(task.symbolA);             var Adepth = task.e.GetDepth();             task.e.SetContractType(task.symbolB);             var Bdepth = task.e.GetDepth();                          if(!Adepth || !Bdepth || Adepth.Asks.length === 0 || Adepth.Bids.length === 0 || Bdepth.Asks.length === 0 || Bdepth.Bids.length === 0){                 return;             }                          task.Adepth = Adepth;             task.Bdepth = Bdepth;                          task.Adiff = _N(Adepth.Bids[0].Price - Bdepth.Asks[0].Price);             task.Bdiff = _N(Adepth.Asks[0].Price - Bdepth.Bids[0].Price);                          if(nowTime - task.lastUpdateLineTime > 1000 * 60){                 $.PlotLine("plus", task.Adiff);                 $.PlotLine("minus", task.Bdiff);                 task.lastUpdateLineTime = nowTime;             }              // 判断解除冻结             if(nowTime - task.FrozenStartTime > 1000 * 15 * 60 && task.isFrozen == true){                 task.isFrozen = false;                 if(For_USD == false){                     var lastRate = OK_Rate;                     OK_Rate = task.e.GetUSDCNY();                     task.e.SetRate(OK_Rate);                 }                 Log("冻结解除!", For_USD == false ? "并且更新汇率,上次汇率:" + lastRate + "更新后汇率:" + OK_Rate + "#FF0000" : "#FF0000");             }              // 交易逻辑             var SumHold = task.dic.length;             for(var index = 0; index < task.dic.length && task.isFrozen == false; index++){                 if(task.dic[index].hold === 0){                     if(task.dic[index].open <= task.Adiff && task.State !== MINUS){                            // 正对冲 空A 多B                         task.action = [index, "sell", "buy", task.dic[index].amount];                         Log(JSON.stringify(task.action));                         Hedge_Open_Cover(task);                          $.PlotFlag(nowTime, "O", "sell-buy", "flag", "red");                         task.isLogProfit = false;                         task.nowAccount = _C(task.e.GetAccount);                                 var Positions = _C(task.e.GetPosition);  // 获取持仓信息。                         UpdatePosition(task, Positions, PRE);                         Log("Open symbolA:", task.APositions, "symbolB:", task.BPositions);                         CalcActualPrice(task);                         task.State = PLUS;                     }else if(task.dic[index].open <= -task.Bdiff && task.State !== PLUS){                     // 反对冲 多A 空B                         task.action = [index, "buy", "sell", -task.dic[index].amount];                         Log(JSON.stringify(task.action));                         Hedge_Open_Cover(task);                          $.PlotFlag(nowTime, "O", "buy-sell", "flag", "red");                         task.isLogProfit = false;                         task.nowAccount = _C(task.e.GetAccount);                                 var Positions = _C(task.e.GetPosition);  // 获取持仓信息。                         UpdatePosition(task, Positions, PRE);                         Log("Open symbolA:", task.APositions, "symbolB:", task.BPositions);                         CalcActualPrice(task);                         task.State = MINUS;                     }else{                         SumHold--;                     }                 }else{                     if(task.dic[index].hold > 0 && task.dic[index].cover >= task.Bdiff){  // 平空A 平多B                         task.action = [index, "closesell", "closebuy", task.dic[index].hold];                         Log(JSON.stringify(task.action));                         // Buy_SymbolA_Sell_SymbolB(task);                         Hedge_Open_Cover(task);                         $.PlotFlag(nowTime, "C", "closesell-closebuy", "circlepin");                         task.nowAccount = _C(task.e.GetAccount);                         var Positions = _C(task.e.GetPosition);  // 获取持仓信息。                         UpdatePosition(task, Positions);                         Log("Cover symbolA:", task.APositions, "symbolB:", task.BPositions);                     }else if(task.dic[index].hold < 0 && task.dic[index].cover >= -task.Adiff){  // 平多A 平空B                         task.action = [index, "closebuy", "closesell", task.dic[index].hold];                         Log(JSON.stringify(task.action));                         // Sell_SymbolA_Buy_SymbolB(task);                         Hedge_Open_Cover(task);                         $.PlotFlag(nowTime, "C", "closebuy-closesell", "circlepin");                         task.nowAccount = _C(task.e.GetAccount);                         var Positions = _C(task.e.GetPosition);  // 获取持仓信息。                         UpdatePosition(task, Positions);                         Log("Cover symbolA:", task.APositions, "symbolB:", task.BPositions);                     }                 }             }              if(SumHold != 0 && nowTime - task.PositionsLastUpdateTime > 1000 * 30){                 var Positions = _C(task.e.GetPosition);  // 获取持仓信息。                 UpdatePosition(task, Positions);                 task.PositionsLastUpdateTime = nowTime;             }else if(SumHold == 0 && task.isLogProfit == false){                 sumProfit = 0;                 task.State = FREE;                 for(var a = 0 ; a < TC.tasks.length; a++){                     sumProfit += TC.tasks[a].taskProfit;                 }                 LogProfit(sumProfit, "当前:", task.nowAccount, "初始:", task.initAccount);                 task.taskProfit = task.nowAccount.Stocks - task.initAccount.Stocks;                 task.isLogProfit = true;             }              // 检测交割剩余时间、发送 交割前平仓命令             CheckDelivery(nowTime, "this_week", task);  // 检测 当周交割。 必须在当周交割前平仓。              // 测试 将数据现在状态栏             var tbl = {                 type : "table",                 title : task.symbolA + "&" + task.symbolB,                 cols : ["key", "value"],                 rows : []             };             for(var key in task){                 value = task[key];                 if(key === "dic" || key === "Adepth" || key === "Bdepth" || key === "initAccount" || key === "nowAccount" || key === "isFrozen" ||                      key === "FrozenStartTime" || key === "P" || key === "Pre_APositions" || key === "Pre_BPositions"){ // 过滤显示                     continue;                 }                 if(key === "e"){                     value = "初始: " + JSON.stringify(task.initAccount) + " 当前: " + JSON.stringify(task.nowAccount);                     key = task[key].GetName();                 }                 tbl.rows.push([key, value]);             }             // 判断下网格方向             if(task.dic[0].hold < 0){                 for(var j = 0; j < task.dic.length; j++){                     var task_dic = JSON.stringify(task.dic[j]);                     if(task.dic[j].hold > 0){                         task_dic += "#FF0000";                     }else if(task.dic[j].hold < 0){                         task_dic += "#32CD32";                     }                     tbl.rows.push([j, task_dic]);                 }             }else if(task.dic[0].hold > 0){                 for(var j = task.dic.length - 1; j >= 0; j--){                     var task_dic = JSON.stringify(task.dic[j]);                     if(task.dic[j].hold > 0){                         task_dic += "#FF0000";                     }else if(task.dic[j].hold < 0){                         task_dic += "#32CD32";                     }                     tbl.rows.push([j, task_dic]);                 }             }else{                 for(var j = 0; j < task.dic.length; j++){                     var task_dic = JSON.stringify(task.dic[j]);                     if(task.dic[j].hold > 0){                         task_dic += "#FF0000";                     }else if(task.dic[j].hold < 0){                         task_dic += "#32CD32";                     }                     tbl.rows.push([j, task_dic]);                 }             }             tbls.push(tbl);         });         if(tbls.length === 0){ // 容错模式,或者实盘中 可能有原因导致 _.each 迭代中 返回,tbls 为  [] ,处理此种情况。             return;         }         LogStatus("轮询耗时:" + StrLoopTime + " 当前时间:" + _D() + MSG_String + 'n`' + JSON.stringify(tbls) + '`'); // 输出到状态栏     }      // 返回对象     return self; }  var TC = null; // TasksController 对象 var tbls = []; var MSG_String = "  "; var StrLoopTime = ""; var OK_Rate = 0; var SumUseTime = 0; var times = 0; var sumTimes = 0; var sumProfit = 0; function main(){     // 测试代码 模拟界面参数     if(isFilter){         Log("启用过滤常规错误信息。");         SetErrorFilter("502:|503:|tcp|character|unexpected|network|timeout|WSARecv|Connect|GetAddr|no such|reset|http|received|EOF|reused");     }      var Positions = [];     for(var j = 0 ; j < exchanges.length ; j++){         var position = _C(exchanges[j].GetPosition);         if(position.length !== 0){             Positions.push(position);         }     }     if(AutoRecoveryState == false && Positions.length == 0){  // 没有持仓,并且关闭了自动恢复         if(isCreateHedgeList == true){             HedgeTable = CreateHedgeList(begin, end, size, step, amountOfPoint, symbolA, symbolB);         }          // 输出对冲控制表,并检查。         Log("对冲控制表", HedgeTable);         if(HedgeTable == "(this_week&quarter)30:15:1"){             Log("注意!对冲控制表 当前为 默认值!可能引起亏损。");         }              // 创建控制器对象         TC = TasksController();              var exchangesNum = 0;         var e_index = 0;         for(var i = 0; i < exchanges.length; i++){ // 遍历交易所对象数组             exchangesNum++;         }          var arr = HedgeTable.split('(');          _.each(arr, function(item) {             if (item != '') {                 var tmp = item.split(')');                 var pair = tmp[0].replace('(', '').split('&');                 // Log("pair:", pair, "tmp:", tmp); // 测试 显示 处理后的 控制表字符串                 TC.AddTask(exchanges[e_index], pair[0], pair[1], tmp[1]);                 if(For_USD){                                                     // 设置汇率                     OK_Rate = 1;                     exchanges[e_index].SetRate(1);                     Log("使用的价格为美元计价,汇率:", OK_Rate, ",请注意 ”对冲 控制表“ 是否为美元差价#FF0000"); // 币种提示                 }else{                     OK_Rate = exchanges[e_index].GetUSDCNY();                     exchanges[e_index].SetRate(OK_Rate);                     Log("使用的价格为RMB计价,汇率:", OK_Rate, ",请注意 ”对冲 控制表“ 是否为RMB差价#FF0000");  // 币种提示                 }                 if(--exchangesNum < 0){                     throw "添加的交易所 和 对冲控制表 不匹配!交易所个数:" + exchanges.length + " arr:" + arr;                 }else if(exchangesNum !== 0){                     e_index++;                 }             }         });              Log("交易所对象最大索引 e_index:", e_index, "关联后剩余交易所数量: exchangesNum:", exchangesNum); // 测试              // 调用控制器对象的初始化函数         TC.InitTask();     }else if(AutoRecoveryState == false && Positions.length !== 0){                    // 未开启恢复,有持仓         throw "未开启自动恢复,检测到有持仓信息:" + JSON.stringify(Positions);     }else if(AutoRecoveryState == true && Positions.length == 0 && (istry == false || IsVirtual())){    // 开启自动恢复, 无持仓信息         throw "未检测到持仓信息,无法恢复!";     }else{                                                                             // 恢复持仓         Log("恢复持仓!");         if(isCreateHedgeList == true){             HedgeTable = CreateHedgeList(begin, end, size, step, amountOfPoint, symbolA, symbolB);         }          // 输出对冲控制表,并检查。         Log("对冲控制表", HedgeTable);         if(HedgeTable == "(this_week&quarter)30:15:1"){             Log("注意!对冲控制表 当前为 默认值!可能引起亏损。");         }              // 创建控制器对象         TC = TasksController();              var exchangesNum = 0;         var e_index = 0;         for(var i = 0; i < exchanges.length; i++){ // 遍历交易所对象数组             exchangesNum++;         }          var arr = HedgeTable.split('(');          _.each(arr, function(item) {             if (item != '') {                 var tmp = item.split(')');                 var pair = tmp[0].replace('(', '').split('&');                 // Log("pair:", pair, "tmp:", tmp); // 测试 显示 处理后的 控制表字符串                 TC.AddTask(exchanges[e_index], pair[0], pair[1], tmp[1]);                 if(For_USD){                                                     // 设置汇率                     OK_Rate = 1;                     exchanges[e_index].SetRate(1);                     Log("使用的价格为美元计价,汇率:", OK_Rate, ",请注意 ”对冲 控制表“ 是否为美元差价#FF0000"); // 币种提示                 }else{                     OK_Rate = exchanges[e_index].GetUSDCNY();                     exchanges[e_index].SetRate(OK_Rate);                     Log("使用的价格为RMB计价,汇率:", OK_Rate, ",请注意 ”对冲 控制表“ 是否为RMB差价#FF0000");  // 币种提示                 }                 if(--exchangesNum < 0){                     throw "添加的交易所 和 对冲控制表 不匹配!交易所个数:" + exchanges.length + " arr:" + arr;                 }else if(exchangesNum !== 0){                     e_index++;                 }             }         });              Log("交易所对象最大索引 e_index:", e_index, "关联后剩余交易所数量: exchangesNum:", exchangesNum); // 测试              // 调用控制器对象的初始化函数         TC.InitTask();         var PreTC = _G("TC");         for(var index = 0; index < TC.tasks.length ; index++){             for(var key in TC.tasks[index]){                 if(key == "e" || key == "Adepth" || key == "Bdepth" || key == "P"){                     continue;                 }                 TC.tasks[index][key] = PreTC.tasks[index][key];             }         }     }      while(true){         var nowTime = new Date().getTime();         TC.DealTask(nowTime);         Sleep(Interval);         var endTime = new Date().getTime();         if(times < 100000){             SumUseTime += (endTime - nowTime);             times++;         }else{             SumUseTime = 0;             times = 0;             SumUseTime += (endTime - nowTime);             times++;         }         sumTimes++;         var avgUseTime = _N(SumUseTime / times);         StrLoopTime = (endTime - nowTime) + " ms " + "平均耗时:" + avgUseTime + "循环次数:" + sumTimes;     } }  function onexit(){     Log("退出策略,自动保存状态。");     _G("TC", TC); } 

原文:https://www.quantinfo.com/Article/View/39

相关阅读

超详细比特币暴跌史!这次暴跌之后还会暴涨吗?

作者 | 孙副社

不奖励比特币的矿机都是耍流氓 猫盘挖矿版使用体验

随着PoW矿机成本急剧升高、挖矿回本周期日渐拉长,很多PoW矿工/矿场都想转型PoS挖矿。与此同时,市面上出现了众多的区块链产品。这些

如何才可以挖掘到比特币?

可能有很多朋友很好奇,我们如何才可以挖掘到比特币呢?这里为大家介绍一个比较常用的挖矿方法。随着现在比特币的流行,越来越多的人加

HTC推出Exodus 1s区块链手机 可运行完整的比特币节点

A5创业网(公众号:iadmin5)10月20日报道,近日HTC发布了最新款的区块链手机Exodus 1s,这是Exodus 1的继任者,可以兼作硬件分类帐,并且新机

1块比特币价值130000元人民币?

17年到18年年中什么最火呢?要数数字货币了。数字货币的始祖-比特币也是一个传奇的存在。在经历2年多的低谷后,在17年顺势而上达到人

发表评论