var Stop_loss = 0.8; //var MarginLevel =100; var NO_TRADE = false var Interval =1 var Log_profit_interval = 60; var update_profit_time = 0; var update_base_price_time = Date.now(); var assets = {}; //var init_prices = {}; var trade_info = {}; var Version = '0.1.3'; var Success = '#5cb85c'; //成功颜色 var Danger = '#ff0000'; //危险颜色 var Warning = '#f0ad4e'; //警告颜色 var accountAssets_0 = []; //保存资产 var accountAssets_1 = []; //保存资产 var Funding_0 = 0; var Funding_1 = 0; var Trade_ex = 0; var exLabel_0 = exchanges[0].GetLabel() var exLabel_1 = exchanges[1].GetLabel() var baseApiURL = "" //baseApiURL = "https://testnet.binancefuture.com" baseApiURL = "https://fapi.binance.com" function init() { if (Reset) { LogReset() LogProfitReset() _G('init_balance', null) _G("WinRateData", null) _G('init_prices', null); _G("StartTime", null); //重置开始时间 _G("initialAccount_" + exchange.GetLabel(), null); //重置开始资金 _G("tradeNumber", null); //重置交易次数 _G("tradeVolume", null); //重置交易量 _G("buyNumber", null); //重置做多次数 _G("sellNumber", null); //重置做空次数 _G("totalProfit", null); //重置打印次数 _G("profitNumber", null); //重置盈利次数 _G("initialAccount_" + exLabel_0 , null); _G("initialAccount_" + exLabel_1 , null); } //设置 BTC_USDT exchanges[0].IO("currency", 'BTC_USDT') exchanges[1].IO("currency", 'BTC_USDT') exchanges[0].SetMarginLevel(MarginLevel) exchanges[1].SetMarginLevel(MarginLevel) exchanges[0].SetContractType('swap') exchanges[1].SetContractType('swap') //设置为 单向 changeToDualSidePosition(false,exchanges[0]) changeToDualSidePosition(false,exchanges[1]) //设置为 逐仓模式 changeMarginTypeToCROSSED(false,"BTCUSDT",exchanges[0]) changeMarginTypeToCROSSED(false,"BTCUSDT",exchanges[1]) assets[exLabel_0]={} assets[exLabel_0].USDT = { unrealised_profit: 0, margin: 0, margin_balance: 0, total_balance: 0, leverage: 0, update_time: 0, margin_ratio: 0, init_balance: 0, stop_balance: 0, short_value: 0, long_value: 0, profit: 0 }; assets[exLabel_0]["BTC"] = { amount: 0, hold_price: 0, value: 0, bid_price: 0, ask_price: 0, btc_price: 0, btc_change: 1, btc_diff: 0, realised_profit: 0, margin: 0, unrealised_profit: 0, leverage: 20, positionInitialMargin: 0, liquidationPrice: 0 }; updateAccount(exchanges[0]) assets[exLabel_1]={} assets[exLabel_1].USDT = { unrealised_profit: 0, margin: 0, margin_balance: 0, total_balance: 0, leverage: 0, update_time: 0, margin_ratio: 0, init_balance: 0, stop_balance: 0, short_value: 0, long_value: 0, profit: 0 }; assets[exLabel_1]["BTC"] = { amount: 0, hold_price: 0, value: 0, bid_price: 0, ask_price: 0, btc_price: 0, btc_change: 1, btc_diff: 0, realised_profit: 0, margin: 0, unrealised_profit: 0, leverage: 20, positionInitialMargin: 0, liquidationPrice: 0 }; updateAccount(exchanges[1]) getExchangeInfo() // Log(assets) } function getExchangeInfo(){ var exchange_info = HttpQuery(baseApiURL + '/fapi/v1/exchangeInfo'); if (!exchange_info) { throw '无法连接币安网络,需要海外托管者'; } exchange_info = JSON.parse(exchange_info); for (var i = 0; i < exchange_info.symbols.length; i++) { if (exchange_info.symbols[i].baseAsset =="BTC") { trade_info["BTC"] = { minQty: parseFloat(exchange_info.symbols[i].filters[1].minQty), priceSize: parseInt((Math.log10(1.1 / parseFloat(exchange_info.symbols[i].filters[0].tickSize)))), amountSize: parseInt((Math.log10(1.1 / parseFloat(exchange_info.symbols[i].filters[1].stepSize)))) }; } } } function onexit() { updateAccount(exchanges[0]) updateAccount(exchanges[1]); //更新账户和持仓 updateTick(); //行情 //stopLoss(); //止损 //onTick(); //策略逻辑部分 updateStatus(); //输出状态栏信息 //cancelCloseAll() if(CloseAllOnExit){ cancelAll("BTC",exchanges[0]) cancelAll("BTC",exchanges[1]) closeAll("BTC",exchanges[0]) closeAll("BTC",exchanges[1]) } Log('exit') } function isEmpty(v) { //same with _.isEmpty() let type = typeof v; if (type === 'undefined') { return true; } if (type === 'boolean') { return !v; } if (v === null) { return true; } if (v === undefined) { return true; } if (v instanceof Array) { if (v.length < 1) { return true; } } else if (type === 'string') { if (v.length < 1) { return true; } if (v === '0') { return true; } } else if (type === 'object') { if (Object.keys(v).length < 1) { return true; } } else if (type === 'number') { if (v === 0) { return true; } } return false; } function changeToDualSidePosition(param = "true",ex = exchange) { try { if(param == false||param == true) params = "dualSidePosition="+param var msg = ex.IO('api', 'GET', '/fapi/v1/positionSide/dual'); if (!msg) return msg if (msg.dualSidePosition != param){ msg = ex.IO('api', 'POST', '/fapi/v1/positionSide/dual', params); if (!msg) return msg if (msg.code == -4059) return msg if (msg.code != 200) { Sleep(10) msg = changeToDualSidePosition(param,ex) } } return msg } catch (err) { Log('changeToDualSidePosition error:' + err); } } function changeMarginTypeToCROSSED(cross = false,param = "BTCUSDT",ex = exchange) { try { if(cross == true){ params = "marginType=CROSSED&symbol=" + param }else if(cross == false){ params = "marginType=ISOLATED&symbol=" + param } var msg = ex.IO('api', 'POST', '/fapi/v1/marginType', params); if (!msg) return msg if (msg.code == -4046) return msg if (msg.code != 200) { Sleep(10) msg = changeMarginTypeToCROSSED(cross,param,ex) } return msg } catch (err) { Log('changeMarginTypeToCROSSED error:' + err); } } function getPostion(symbol = "BTC",exchange = exchanges[0]) { //更新账户和持仓 try { var exLabel=exchange.GetLabel() var params ="" if(!isEmpty(symbol)) params = "symbol="+symbol+"USDT" else params = "symbol=BTCUSDT" var pos = exchange.IO('api', 'GET', '/fapi/v2/positionRisk',params); if (isEmpty(pos)) return; //var asset = assets[exLabel] /* var account = exchange.GetAccount(); var pos = exchange.GetPosition(); if (account == null || pos == null) { Log(115,exchange.GetLabel(),' update account time out'); return; } if(exLabel==exLabel_0) accountAssets_0 = account.Info.assets; else accountAssets_1 = account.Info.assets; assets[exLabel].USDT.update_time = Date.now(); //for (var i = 0; i < trade_symbols.length; i++) { assets[exLabel]["BTC"].margin = 0; assets[exLabel]["BTC"].unrealised_profit = 0; assets[exLabel]["BTC"].hold_price = 0; assets[exLabel]["BTC"].amount = 0; //} for (var j = 0; j < account.Info.positions.length; j++) { if (account.Info.positions[j].positionSide == 'BOTH') { var pair = account.Info.positions[j].symbol; var coin = pair.slice(0, pair.length - 4); if ("BTC" != coin) { continue; } assets[exLabel][coin].margin = parseFloat(account.Info.positions[j].initialMargin) + parseFloat(account.Info.positions[j].maintMargin); assets[exLabel][coin].unrealised_profit = parseFloat(account.Info.positions[j].unrealizedProfit); assets[exLabel][coin].positionInitialMargin = parseFloat(account.Info.positions[j].positionInitialMargin);//持仓起始保证金 assets[exLabel][coin].leverage = account.Info.positions[j].leverage; } } assets[exLabel].USDT.margin = _N(parseFloat(account.Info.totalInitialMargin) + parseFloat(account.Info.totalMaintMargin), 2); //起始保证金总额(存在逐仓请忽略)+ 维持保证金总额 assets[exLabel].USDT.margin_balance = _N(parseFloat(account.Info.totalMarginBalance), 2); //保证金总余额 (不含占用的保证金)= 钱包账户总余额 + 未实现盈亏 assets[exLabel].USDT.total_balance = _N(parseFloat(account.Info.totalWalletBalance), 2);//账户总余额 (不含未实现盈亏) //assets[exLabel].USDT.total_balance = _N(parseFloat(account.Info.totalWalletBalance), 2);//账户总余额 assets[exLabel].USDT.unrealised_profit = _N(parseFloat(account.Info.totalUnrealizedProfit), 2); //持仓未实现盈亏总额 assets[exLabel].USDT.margin_ratio = (account.Info.totalMaintMargin / account.Info.totalMarginBalance * 100);// 维持保证金总额/保证金总余额 if(exLabel==exLabel_0) assets[exLabel].USDT.init_balance = parseFloat(FirstAccount(exchanges[0]).Info.totalWalletBalance); else assets[exLabel].USDT.init_balance = parseFloat(FirstAccount(exchanges[1]).Info.totalWalletBalance); assets[exLabel].USDT.profit = _N(assets[exLabel].USDT.margin_balance - assets[exLabel].USDT.init_balance, 2);//保证金总余额 - 最初 账户总余额 assets[exLabel].USDT.stop_balance = _N(Stop_loss * assets[exLabel].USDT.init_balance, 2); assets[exLabel].USDT.leverage = _N(assets[exLabel].USDT.margin / assets[exLabel].USDT.total_balance, 2);// (起始保证金总额(存在逐仓请忽略)+ 维持保证金总额)/账户总余额 pos = JSON.parse(exchange.GetRawJSON()); */ if (pos.length > 0) { for (var k = 0; k < pos.length; k++) { var pair = pos[k].symbol; var coin = pair.slice(0, pair.length - 4); if (symbol != coin) { continue; } if (pos[k].positionSide != 'BOTH') { continue; } assets[exLabel][coin].hold_price = parseFloat(pos[k].entryPrice); assets[exLabel][coin].amount = parseFloat(pos[k].positionAmt); assets[exLabel][coin].unrealised_profit = parseFloat(pos[k].unRealizedProfit); assets[exLabel][coin].liquidationPrice = parseFloat(pos[k].liquidationPrice); //zyn add assets[exLabel][coin].markPrice = parseFloat(pos[k].markPrice); assets[exLabel][coin].leverage = parseFloat(pos[k].leverage); assets[exLabel][coin].positionSide = pos[k].positionSide; //zyn add end assets[exLabel][coin].marginType = pos[k].marginType; } } //return assets[exLabel]; } catch (err) { Log('getPostion error:' + err); } } function updateAccount(exchange = exchanges[0]) { //更新账户和持仓 try { var exLabel=exchange.GetLabel() //var asset = assets[exLabel] var account = exchange.GetAccount(); var pos = exchange.GetPosition(); //zyn add //if(isEmpty(pos)) getPostion() //zyn add end if (account == null || pos == null) { Log(115,exchange.GetLabel(),' update account time out'); return; } if(exLabel==exLabel_0) accountAssets_0 = account.Info.assets; else accountAssets_1 = account.Info.assets; assets[exLabel].USDT.update_time = Date.now(); /* for (var i = 0; i < trade_symbols.length; i++) { assets[exLabel]["BTC"].margin = 0; assets[exLabel]["BTC"].unrealised_profit = 0; assets[exLabel]["BTC"].hold_price = 0; assets[exLabel]["BTC"].amount = 0; } */ for (var j = 0; j < account.Info.positions.length; j++) { if (account.Info.positions[j].positionSide == 'BOTH') { var pair = account.Info.positions[j].symbol; var coin = pair.slice(0, pair.length - 4); if ("BTC" != coin) { continue; } assets[exLabel][coin].margin = parseFloat(account.Info.positions[j].initialMargin) + parseFloat(account.Info.positions[j].maintMargin); assets[exLabel][coin].unrealised_profit = parseFloat(account.Info.positions[j].unrealizedProfit); assets[exLabel][coin].positionInitialMargin = parseFloat(account.Info.positions[j].positionInitialMargin);//持仓起始保证金 assets[exLabel][coin].leverage = account.Info.positions[j].leverage; //zyn add assets[exLabel][coin].hold_price = account.Info.positions[j].entryPrice; assets[exLabel][coin].positionSide = account.Info.positions[j].positionSide; //zyn add end } } assets[exLabel].USDT.margin = _N(parseFloat(account.Info.totalInitialMargin) + parseFloat(account.Info.totalMaintMargin), 2); //起始保证金总额(存在逐仓请忽略)+ 维持保证金总额 assets[exLabel].USDT.margin_balance = _N(parseFloat(account.Info.totalMarginBalance), 2); //保证金总余额 (不含占用的保证金)= 钱包账户总余额 + 未实现盈亏 assets[exLabel].USDT.total_balance = _N(parseFloat(account.Info.totalWalletBalance), 2);//账户总余额 (不含未实现盈亏) //assets[exLabel].USDT.total_balance = _N(parseFloat(account.Info.totalWalletBalance), 2);//账户总余额 assets[exLabel].USDT.unrealised_profit = _N(parseFloat(account.Info.totalUnrealizedProfit), 2); //持仓未实现盈亏总额 assets[exLabel].USDT.margin_ratio = (account.Info.totalMaintMargin / account.Info.totalMarginBalance * 100);// 维持保证金总额/保证金总余额 /* if (assets[exLabel].USDT.init_balance == 0) { if (_G('init_balance')) { assets[exLabel].USDT.init_balance = _N(_G('init_balance'), 2); } else { assets[exLabel].USDT.init_balance = assets[exLabel].USDT.total_balance; // 账户总余额 _G('init_balance', assets[exLabel].USDT.init_balance); } } */ if(exLabel==exLabel_0) assets[exLabel].USDT.init_balance = parseFloat(FirstAccount(exchanges[0]).Info.totalWalletBalance); else assets[exLabel].USDT.init_balance = parseFloat(FirstAccount(exchanges[1]).Info.totalWalletBalance); assets[exLabel].USDT.profit = _N(assets[exLabel].USDT.margin_balance - assets[exLabel].USDT.init_balance, 2);//保证金总余额 - 最初 账户总余额 assets[exLabel].USDT.stop_balance = _N(Stop_loss * assets[exLabel].USDT.init_balance, 2); assets[exLabel].USDT.leverage = _N(assets[exLabel].USDT.margin / assets[exLabel].USDT.total_balance, 2);// (起始保证金总额(存在逐仓请忽略)+ 维持保证金总额)/账户总余额 pos = JSON.parse(exchange.GetRawJSON()); if (pos.length > 0) { for (var k = 0; k < pos.length; k++) { var pair = pos[k].symbol; var coin = pair.slice(0, pair.length - 4); if ("BTC" != coin) { continue; } if (pos[k].positionSide != 'BOTH') { continue; } assets[exLabel][coin].hold_price = parseFloat(pos[k].entryPrice); assets[exLabel][coin].amount = parseFloat(pos[k].positionAmt); assets[exLabel][coin].unrealised_profit = parseFloat(pos[k].unRealizedProfit); assets[exLabel][coin].liquidationPrice = parseFloat(pos[k].liquidationPrice); //zyn add assets[exLabel][coin].markPrice = parseFloat(pos[k].markPrice); assets[exLabel][coin].leverage = parseFloat(pos[k].leverage); assets[exLabel][coin].positionSide = pos[k].positionSide; //zyn add end assets[exLabel][coin].marginType = pos[k].marginType; } } //return assets[exLabel]; } catch (err) { Log('updateAccount error:' + err); } } function updateTick() { //更新行情 var ticker = HttpQuery(baseApiURL + '/fapi/v1/ticker/bookTicker'); try { ticker = JSON.parse(ticker); } catch (e) { Log('get ticker time out'); return; } //assets.USDT.short_value = 0; //assets.USDT.long_value = 0; for (var i = 0; i < ticker.length; i++) { var pair = ticker[i].symbol; var coin = pair.slice(0, pair.length - 4); if (coin !="BTC") { continue; } trade_info[coin].ask_price = parseFloat(ticker[i].askPrice); trade_info[coin].bid_price = parseFloat(ticker[i].bidPrice); assets[exLabel_0][coin].ask_price = parseFloat(ticker[i].askPrice); assets[exLabel_0][coin].bid_price = parseFloat(ticker[i].bidPrice); assets[exLabel_0][coin].ask_value = _N(assets[exLabel_0][coin].amount * assets[exLabel_0][coin].ask_price, 2); assets[exLabel_0][coin].bid_value = _N(assets[exLabel_0][coin].amount * assets[exLabel_0][coin].bid_price, 2); assets[exLabel_1][coin].ask_price = parseFloat(ticker[i].askPrice); assets[exLabel_1][coin].bid_price = parseFloat(ticker[i].bidPrice); assets[exLabel_1][coin].ask_value = _N(assets[exLabel_1][coin].amount * assets[exLabel_1][coin].ask_price, 2); assets[exLabel_1][coin].bid_value = _N(assets[exLabel_1][coin].amount * assets[exLabel_1][coin].bid_price, 2); //trade_info[coin].ask_value = _N(assets[coin].amount * trade_info[coin].ask_price, 2); //trade_info[coin].bid_value = _N(assets[coin].amount * trade_info[coin].bid_price, 2); //if (trade_symbols.indexOf(coin) < 0) { // continue; //} //if (assets[coin].amount < 0) { // assets.USDT.short_value += Math.abs((assets[coin].ask_value + assets[coin].bid_value) / 2); //} else { // assets.USDT.long_value += Math.abs((assets[coin].ask_value + assets[coin].bid_value) / 2); //} //assets.USDT.short_value = _N(assets.USDT.short_value, 0); //assets.USDT.long_value = _N(assets.USDT.long_value, 0); } //updateIndex(); //for (var i = 0; i < trade_symbols.length; i++) { // assets[trade_symbols[i]].btc_diff = _N(assets[trade_symbols[i]].btc_change - index, 4); //zyn add //btcDiffIndex.push(assets[trade_symbols[i]].btc_diff) //zyn add end //} //zyn add //btcDiffIndex.sort((a,b)=>b-a) //Log(295," btcDiffIndex=",btcDiffIndex) //zyn add end } function cancelAll(symbol,exchange = exchanges[0]) { try { //updateAccount(); //updateTick(); var orders = _C(exchange.GetOrders); for (var i = 0; i < orders.length; i++) { if(orders[i].Info.symbol!=symbol+"USDT") continue; exchange.CancelOrder(orders[i].Id) Log(502,exchange.GetLabel()," 取消所有",symbol,"订单 orderId: ", orders[i].Id); } } catch (err) { Log('closeAll error:' + err); } } function cancelAllOrders(symbol,exchange = exchanges[0]) { try { //updateAccount(); //updateTick(); return exchange.IO('api', 'DELETE', '/fapi/v1/allOpenOrders', 'symbol=' + symbol) } catch (err) { Log('cancelAllOrders error:' + err); } } function closeAll(symbol,exchange = exchanges[0]) { try { updateAccount(exchange); updateTick(); //var f = assets[symbol].amount < 0 ? 'Buy' : 'Sell'; if(assets[exchange.GetLabel()][symbol].amount!=0){ var dirction = assets[exchange.GetLabel()][symbol].amount < 0 ? 'buy' : 'sell'; var f = dirction == 'buy' ? 'Buy' : 'Sell'; exchange.IO("currency", symbol + '_' + 'USDT'); exchange.SetContractType('swap'); exchange.SetDirection(dirction); exchange.SetMarginLevel(MarginLevel) var id=exchange[f](-1, Math.abs(assets[exchange.GetLabel()][symbol].amount), symbol); if (id) { exchange.CancelOrder(id); //订单会立即撤销 Log(502,exchange.GetLabel()," ",symbol," 仓位已市价平仓(orderId:",id,")") } } if((assets[exchange.GetLabel()][symbol].amount!=0 && id) || assets[exchange.GetLabel()][symbol].amount==0){ var orders = _C(exchange.GetOrders); for (var i = 0; i < orders.length; i++) { if(orders[i].Info.symbol!=symbol+"USDT") continue; exchange.CancelOrder(orders[i].Id) Log(502,exchange.GetLabel()," 取消所有",symbol,"止损止盈单 orderId: ", orders[i].Id); } } } catch (err) { Log('closeAll error:' + err); } } function makeOrder(Order = [],exchange = exchanges=[0]) { //输入 list 或者 数组 try { exchange.SetContractType('swap') /* var Order = {"symbol":"BTCUSDT", "side":"BUY" , "positionSide":"LONG" , "type":"MARKET", "quantity":0.001} */ var marketOrder = false if (Array.isArray(Order)) { Order = Order[0] } if (Object.keys(Order).length < 4) return Log("makeOrder函数下订单,订单内参数量最小为4,不能为 ", Object.keys(Order).length) if (Order.type == "MARKET") marketOrder = true //Log("Order=",Order) var theOrder = {} theOrder = exchange.IO('api', 'POST', '/fapi/v1/order', "", JSON.stringify(Order)); //返回 list 对象,而非数组 Log(400,"makeOrder Order=",Order," => orderId:",theOrder.orderId) if (Object.keys(theOrder).length == 0) return {} /* var params = [] if(!Array.isArray(Order)) { params.push(Order) Order = params params = [] } if(Order.length!=1) return Log("makeOrder函数下订单量最大为1,不能为 ",Order.length) for(var key in Order[0]) { if(key=="type"&&Order[0][key]=="MARKET"){ //symbol = Order[0].symbol marketOrder =true } params.push(key+"="+Order[0][key]); } params = params.join("&") //Log(params) var theOrder = exchange.IO('api', 'POST', '/fapi/v1/order',params); //返回 list 对象,而非数组 */ if (marketOrder) { Log(389," theOrder=",theOrder) theOrder = waitOrder(theOrder) } return theOrder //返回 list 对象 而非数组 } catch (err) { Log('makeOrder error:' + err); } } function waitOrder(theOrder = "",exchange = exchanges[0]) { //输入 List or ID //不必须传入 symbol 交易对 //只等待状态改变,不重新下单 try { if (!theOrder) return Log("waitOrder函数参数属性必须包含Id,不能为 ", theOrder) if (Array.isArray(theOrder)) theOrder = theOrder[0] if (typeof theOrder == "string" || typeof theOrder == "number") { theOrder = exchange.GetOrder(theOrder) //返回 List theOrder = theOrder.Info } var j = 11 while (--j) { if (theOrder.status != "NEW") break; //Log((11-j)," Wait 100ms for OrderID:",theOrder.orderId ," status=",theOrders[i].status) Sleep(100) //theOrder = GetOrder(theOrder.orderId) //theOrder = theOrder.Info theOrder = getAllOrders("symbol=" + theOrder.symbol + "&limit=1&orderId=" + theOrder.orderId) //返回数组 theOrder = theOrder[0] Log(420, " ", (11 - j), " waitOrder= OrderId:", theOrder.orderId, " (", theOrder.status, ")", " (", theOrder.timeInForce, ")") //Log("theOrder=",theOrder," !theOrder=",!theOrder) if (!theOrder) break; //return theOrder } return theOrder //输出 List } catch (err) { Log(429,'waitOrder error:' + err); } } function FirstAccount(exchange = exchanges[0]) { var key = "initialAccount_" + exchange.GetLabel(); var initialAccount = _G(key); if (initialAccount == null) { initialAccount = exchange.GetAccount(); _G(key, initialAccount); } return initialAccount; } function StartTime() { var StartTime = _G("StartTime"); if (StartTime == null) { StartTime = _D(); _G("StartTime", StartTime); } return StartTime; } function RuningTime() { var ret = {}; var dateBegin = new Date(StartTime()); var dateEnd = new Date(_D()); var dateDiff = dateEnd.getTime() - dateBegin.getTime(); var dayDiff = Math.floor(dateDiff / (24 * 3600 * 1000)); var leave1 = dateDiff % (24 * 3600 * 1000); var hours = Math.floor(leave1 / (3600 * 1000)); var leave2 = leave1 % (3600 * 1000); var minutes = Math.floor(leave2 / (60 * 1000)); ret.dayDiff = dayDiff; ret.hours = hours; ret.minutes = minutes; ret.str = "运行时间: " + dayDiff + " 天 " + hours + " 小时 " + minutes + " 分钟"; return ret; } function AppendedStatus() { var accountTable = { type: "table", title: "盈利统计", cols: ["交易所", "初始资金", "现有资金", "保证金余额", "已用保证金", "保证金比率", "止损", "总收益", "预计年化", "预计月化", "平均日化"], rows: [] }; var feeTable = { type: 'table', title: '交易统计', cols: ["策略指数", '交易次数', '做多次数', '做空次数', '预估胜率', '预估成交额', '预估手续费', "未实现盈利", '持仓总值', '做多总值', '做空总值'], rows: [] }; var runday = RunTime.dayDiff; if (runday == 0) { runday = 1; } if (Funding_0 == 0) { Funding_0 = parseFloat(FirstAccount(exchanges[0]).Info.totalWalletBalance); // 初始 账户总余额 } if (Funding_1 == 0) { Funding_1 = parseFloat(FirstAccount(exchanges[1]).Info.totalWalletBalance); // 初始 账户总余额 } var profitColors_0 = Danger; var profitColors_1 = Danger; var totalProfit_0 = assets[exLabel_0].USDT.total_balance - Funding_0; //总盈利 var totalProfit_1 = assets[exLabel_1].USDT.total_balance - Funding_1; //总盈利 if (totalProfit_0 > 0) { profitColors_0 = Success; } if (totalProfit_1 > 0) { profitColors_1 = Success; } var dayProfit_0 = totalProfit_0 / runday; //天盈利 var dayProfit_1 = totalProfit_1 / runday; //天盈利 var dayRate_0 = dayProfit_0 / Funding_0 * 100; var dayRate_1 = dayProfit_1 / Funding_0 * 100; accountTable.rows.push([ exLabel_0, '$' + _N(Funding_0, 2), // 初始 账户总余额 '$' + assets[exLabel_0].USDT.total_balance, // 账户总余额 '$' + assets[exLabel_0].USDT.margin_balance,//保证金总余额 '$' + assets[exLabel_0].USDT.margin,//起始保证金总额(存在逐仓请忽略)+ 维持保证金总额 _N(assets[exLabel_0].USDT.margin_ratio, 2) + '%',// 维持保证金总额/保证金总余额 _N(assets[exLabel_0].USDT.stop_balance, 2) + Danger, _N(totalProfit_0 / Funding_0 * 100, 2) + "% = $" + _N(totalProfit_0, 2) + (profitColors_0), _N(dayRate_0 * 365, 2) + "% = $" + _N(dayProfit_0 * 365, 2) + (profitColors_0), _N(dayRate_0 * 30, 2) + "% = $" + _N(dayProfit_0 * 30, 2) + (profitColors_0), _N(dayRate_0, 2) + "% = $" + _N(dayProfit_0, 2) + (profitColors_0) ]); accountTable.rows.push([ exLabel_1, '$' + _N(Funding_1, 2), // 初始 账户总余额 '$' + assets[exLabel_1].USDT.total_balance, // 账户总余额 '$' + assets[exLabel_1].USDT.margin_balance,//保证金总余额 '$' + assets[exLabel_1].USDT.margin,//起始保证金总额(存在逐仓请忽略)+ 维持保证金总额 _N(assets[exLabel_1].USDT.margin_ratio, 2) + '%',// 维持保证金总额/保证金总余额 _N(assets[exLabel_1].USDT.stop_balance, 2) + Danger, _N(totalProfit_1 / Funding_1 * 100, 2) + "% = $" + _N(totalProfit_1, 2) + (profitColors_1), _N(dayRate_1 * 365, 2) + "% = $" + _N(dayProfit_1 * 365, 2) + (profitColors_1), _N(dayRate_1 * 30, 2) + "% = $" + _N(dayProfit_1 * 30, 2) + (profitColors_1), _N(dayRate_1, 2) + "% = $" + _N(dayProfit_1, 2) + (profitColors_1) ]); /* var vloume = _G("tradeVolume") ? _G("tradeVolume") : 0; feeTable.rows.push([ exLabel_0, //指数 _G("tradeNumber") ? _G("tradeNumber") : 0, //交易次数 _G("buyNumber") ? _G("buyNumber") : 0, //做多次数 _G("sellNumber") ? _G("sellNumber") : 0, //做空次数 _N(_G("profitNumber") / _G("totalProfit") * 100, 2) + '%', //胜率 '$' + _N(vloume, 2) + ' ≈ ฿' + _N(vloume / ((assets.BTC.bid_price + assets.BTC.ask_price) / 2), 6), //成交金额 '$' + _N(vloume * (SelfFee / 100), 4), //手续费 '$' + _N(assets.USDT.unrealised_profit, 2) + (assets.USDT.unrealised_profit >= 0 ? Success : Danger),//持仓未实现盈亏总额 account.Info.totalUnrealizedProfit '$' + _N(TotalLong + Math.abs(TotalShort), 2), //持仓总价值 '$' + _N(TotalLong, 2) + Success, //做多总值 '$' + _N(Math.abs(TotalShort), 2) + Danger, //做空总值 ]); */ var assetTable = { type: 'table', title: '账户资产信息', cols: ['交易所', '资产名', '起始保证金', '维持保证金', '保证金余额', '最大可提款金额', '挂单起始保证金', '持仓起始保证金', '持仓未实现盈亏', '账户余额'], rows: [] }; for (var i = 0; i < accountAssets_0.length; i++) { var acc = accountAssets_0[i]; assetTable.rows.push([ exLabel_0, acc.asset, acc.initialMargin,// 起始保证金 acc.maintMargin,// 维持保证金 acc.marginBalance,//保证金余额 acc.maxWithdrawAmount,//最大可提款金额 acc.openOrderInitialMargin,//挂单起始保证金 acc.positionInitialMargin,//持仓起始保证金 acc.unrealizedProfit,//持仓未实现盈亏 acc.walletBalance //账户余额 ]); } for (var i = 0; i < accountAssets_1.length; i++) { var acc = accountAssets_1[i]; assetTable.rows.push([ exLabel_1, acc.asset, acc.initialMargin,// 起始保证金 acc.maintMargin,// 维持保证金 acc.marginBalance,//保证金余额 acc.maxWithdrawAmount,//最大可提款金额 acc.openOrderInitialMargin,//挂单起始保证金 acc.positionInitialMargin,//持仓起始保证金 acc.unrealizedProfit,//持仓未实现盈亏 acc.walletBalance //账户余额 ]); } /* var indexTable = { type: 'table', title: '币指数信息', cols: ['编号','最小额', '币种', '当前价', 'BTC计价', '初始BTC计价', 'BTC计价变化(%)','币群','群号', '偏离平均(%)','Max(%)', '交易次数', '做空次数', '做多次数', '预估胜率'], rows: [] }; for (var i = 0; i < symbols.length; i++) { var price = _N((assets[symbols[i]].ask_price + assets[symbols[i]].bid_price) / 2, trade_info[symbols[i]].priceSize); if (symbols.indexOf(symbols[i]) < 0) { indexTable.rows.push([i + 1, symbols[i], price, assets[symbols[i]].btc_price,0, _N((assets[symbols[i]].btc_change-1) * 100), _N(100 * assets[symbols[i]].btc_diff,2), 0, 0, 0, '0%']); } else { var rateData = _G("WinRateData"); //zyn add init_prices = _G('init_prices'); var symbolText="" var symbolNum=0 if(symbols[i] in highIndex){ // if(i==highIndex[symbols[i]]){ //symbolText= "[High]"+"-"+highIndex[symbols[i]]+Danger symbolText= "[High]"+Danger symbolNum=highIndex[symbols[i]] // } }else if(symbols[i] in midIndex){ // if(i==midIndex[symbols[i]]){ //symbolText= "[Mid]"+"-"+midIndex[symbols[i]]+Success symbolText= "[Mid]"+Success symbolNum=midIndex[symbols[i]] // } }else if(symbols[i] in lowIndex){ // if(i==lowIndex[symbols[i]]){ //symbolText= "[Low]"+"-"+lowIndex[symbols[i]]+Danger symbolText= "[Low]"+Danger symbolNum=lowIndex[symbols[i]] // } }else if(symbols[i] in nullIndex){ symbolText= "[NULL]" symbolNum=nullIndex[symbols[i]] }else{ symbolText= "[Other]" } //zyn add end var winRate = _N(rateData[symbols[i]].profitNumber / rateData[symbols[i]].totalProfit * 100, 2); indexTable.rows.push([ (i + 1), //'编号' _N(trade_info[symbols[i]].minQty * price,2),//最小交易额 symbols[i] + Warning, //币种信息 price, //当前价 _N(assets[symbols[i]].btc_price, 6), //BTC计价 //zyn add _N(init_prices[symbols[i]],6), //初始BTC计价 _N((assets[symbols[i]].btc_change-1) * 100),//BTC计价变化(%) //zyn add end //_N((1 - assets[symbols[i]].btc_change) * 100),//BTC计价变化(%) symbolText, symbolNum, _N(100 * assets[symbols[i]].btc_diff,2) + (assets[symbols[i]].btc_diff >= 0 ? Success : Danger),//偏离平均(%) 100*maxDiff[symbols[i]]+"/"+100*minDiff[symbols[i]], rateData[symbols[i]].tradeNumber,//交易次数 rateData[symbols[i]].sellNumber,//做空次数 rateData[symbols[i]].buyNumber,//做多次数 (rateData[symbols[i]].profitNumber > 0 && rateData[symbols[i]].totalProfit > 0 ? winRate : '0') + '%' + (winRate >= 50 ? Success : Danger), //胜率 ]); } } */ var retData = {}; //retData.upTable = RunTime.str + '\n' + "最后更新: " + _D() + '\n' + 'Version:' + Version + '\n' + '`' + JSON.stringify([accountTable, assetTable]) + '`\n' + '`' + JSON.stringify(feeTable) + '`\n'; retData.upTable = RunTime.str + '\n' + "最后更新: " + _D() + '\n' + 'Version:' + Version + '\n' + '`' + JSON.stringify([accountTable, assetTable]) + '`\n' ; //retData.indexTable = indexTable; return retData; } function updateStatus() { //状态栏信息 //updateFundingRate() var table = { type: 'table', title: '交易对信息', //cols: ['编号', '[模式][倍数]','费率%', '币种','币群','群号','偏离平均(%)','Max(%)', '方向', '数量', '持仓价', '当前价', '强平价', '强平尚需', '持仓价值', '保证金', '未实现盈亏', '投降'], cols: ['交易所', '[模式][倍数]', '币种', '方向', '数量', '持仓价', '当前价', '强平价', '强平尚需', '持仓价值', '保证金', '未实现盈亏', '投降'], rows: [] }; //TotalLong = 0; //TotalShort = 0; //for (var i = 0; i < symbols.length; i++) { var symbol ="BTC" var direction = '空仓'; var margin = direction; if (assets[exLabel_0][symbol].amount != 0) { direction = assets[exLabel_0][symbol].amount > 0 ? '做多' + Success : '做空' + Danger; margin = (assets[exLabel_0][symbol].marginType == 'cross' ? '全仓' : '逐仓'); } var price = _N((assets[exLabel_0][symbol].ask_price + assets[exLabel_0][symbol].bid_price) / 2, trade_info[symbol].priceSize); var value = _N((assets[exLabel_0][symbol].ask_value + assets[exLabel_0][symbol].bid_value) / 2, 2); /* if (value != 0) { if (value > 0) { TotalLong += value; } else { TotalShort += value; } } */ // var rateData = _G("WinRateData"); //zyn add /* var symbolText="" var symbolNum=0 if(symbol in highIndex){ // if(i==highIndex[symbol]){ //symbolText= "[High]"+"-"+highIndex[symbol]+Danger symbolText= "[High]"+Danger symbolNum=highIndex[symbol] // } }else if(symbol in midIndex){ // if(i==midIndex[symbol]){ //symbolText= "[Mid]"+"-"+midIndex[symbol]+Success symbolText= "[Mid]"+Success symbolNum=midIndex[symbol] // } }else if(symbol in lowIndex){ // if(i==lowIndex[symbol]){ //symbolText= "[Low]"+"-"+lowIndex[symbol]+Danger symbolText= "[Low]"+Danger symbolNum=lowIndex[symbol] // } }else if(symbol in nullIndex){ symbolText= "[NULL]" symbolNum=nullIndex[symbol] }else{ symbolText= "[Other]" } */ //强平价差 liquidationToMarkPrice = 0 if(assets[exLabel_0][symbol].amount < 0) liquidationToMarkPrice = assets[exLabel_0][symbol].liquidationPrice == 0 ? '0' : "↑" + _N(assets[exLabel_0][symbol].liquidationPrice - assets[exLabel_0][symbol].markPrice, trade_info[symbol].priceSize) + '$' + ' ≈ ' + _N((assets[exLabel_0][symbol].liquidationPrice - assets[exLabel_0][symbol].markPrice) / assets[exLabel_0][symbol].markPrice * 100, 2) + '%' + Warning //强平价差 if(assets[exLabel_0][symbol].amount > 0) liquidationToMarkPrice = assets[exLabel_0][symbol].liquidationPrice == 0 ? '0' : "↓" + _N(assets[exLabel_0][symbol].markPrice - assets[exLabel_0][symbol].liquidationPrice, trade_info[symbol].priceSize) + '$' + ' ≈ ' + _N((assets[exLabel_0][symbol].markPrice - assets[exLabel_0][symbol].liquidationPrice) / assets[exLabel_0][symbol].markPrice * 100, 2) + '%' + Warning //强平价差 //zyn add end var infoList = [ exLabel_0, "[" + margin + "] [" + assets[exLabel_0][symbol].leverage + 'x] ', //_N(100 * assets[exLabel_0][symbol].fundingRate,3), //费率% symbol, //symbolText, //symbolNum, //_N(100 * assets[exLabel_0][symbol].btc_diff,2) + (assets[exLabel_0][symbol].btc_diff >= 0 ? Success : Danger),//偏离平均(%) //100*maxDiff[symbol]+"/"+100*minDiff[symbol], direction, Math.abs(assets[exLabel_0][symbol].amount), assets[exLabel_0][symbol].hold_price, price, assets[exLabel_0][symbol].liquidationPrice, //强平价格 //assets[exLabel_0][symbol].liquidationPrice == 0 ? '0' : '$' + _N(assets[exLabel_0][symbol].liquidationPrice - price, 5) + ' ≈ ' + _N(assets[exLabel_0][symbol].liquidationPrice / price * 100, 2) + '%' + Warning, //强平价格 liquidationToMarkPrice,//强平价差 Math.abs(value), _N(assets[exLabel_0][symbol].positionInitialMargin, 2), // assets[exLabel_0][symbol].btc_diff, _N(assets[exLabel_0][symbol].unrealised_profit, 3) + (assets[exLabel_0][symbol].unrealised_profit >= 0 ? Success : Danger),//未实现盈亏 // (rateData[symbol].profitNumber > 0 && rateData[symbol].totalProfit > 0 ? _N(rateData[symbol].profitNumber / rateData[symbol].totalProfit * 100, 2) : '0') + '%', //胜率 { 'type': 'button', 'cmd': '说好的没有撤退可言呢???:' + symbol + ':' + assets[exLabel_0][symbol].amount + ':'+ 0 + ':', 'name': symbol + ' 投降' } ]; table.rows.push(infoList); direction = '空仓'; margin = direction; if (assets[exLabel_1][symbol].amount != 0) { direction = assets[exLabel_1][symbol].amount > 0 ? '做多' + Success : '做空' + Danger; margin = (assets[exLabel_1][symbol].marginType == 'cross' ? '全仓' : '逐仓'); } price = _N((assets[exLabel_1][symbol].ask_price + assets[exLabel_1][symbol].bid_price) / 2, trade_info[symbol].priceSize); value = _N((assets[exLabel_1][symbol].ask_value + assets[exLabel_1][symbol].bid_value) / 2, 2); //强平价差 liquidationToMarkPrice = 0 if(assets[exLabel_1][symbol].amount < 0) liquidationToMarkPrice = assets[exLabel_1][symbol].liquidationPrice == 0 ? '0' : "↑" + _N(assets[exLabel_1][symbol].liquidationPrice - assets[exLabel_1][symbol].markPrice, trade_info[symbol].priceSize) + '$' + ' ≈ ' + _N((assets[exLabel_1][symbol].liquidationPrice - assets[exLabel_1][symbol].markPrice) / assets[exLabel_1][symbol].markPrice * 100, 2) + '%' + Warning //强平价差 if(assets[exLabel_1][symbol].amount > 0) liquidationToMarkPrice = assets[exLabel_1][symbol].liquidationPrice == 0 ? '0' : "↓" + _N(assets[exLabel_1][symbol].markPrice - assets[exLabel_1][symbol].liquidationPrice, trade_info[symbol].priceSize) + '$' + ' ≈ ' + _N((assets[exLabel_1][symbol].markPrice - assets[exLabel_1][symbol].liquidationPrice) / assets[exLabel_1][symbol].markPrice * 100, 2) + '%' + Warning //强平价差 infoList = [ exLabel_1, "[" + margin + "] [" + assets[exLabel_1][symbol].leverage + 'x] ', //_N(100 * assets[exLabel_1][symbol].fundingRate,3), //费率% symbol, //symbolText, //symbolNum, //_N(100 * assets[exLabel_1][symbol].btc_diff,2) + (assets[exLabel_1][symbol].btc_diff >= 0 ? Success : Danger),//偏离平均(%) //100*maxDiff[symbol]+"/"+100*minDiff[symbol], direction, Math.abs(assets[exLabel_1][symbol].amount), assets[exLabel_1][symbol].hold_price, price, assets[exLabel_1][symbol].liquidationPrice, //强平价格 //assets[exLabel_1][symbol].liquidationPrice == 0 ? '0' : '$' + _N(assets[exLabel_1][symbol].liquidationPrice - price, 5) + ' ≈ ' + _N(assets[exLabel_1][symbol].liquidationPrice / price * 100, 2) + '%' + Warning, //强平价格 liquidationToMarkPrice,//强平价差 Math.abs(value), _N(assets[exLabel_1][symbol].positionInitialMargin, 2), // assets[exLabel_1][symbol].btc_diff, _N(assets[exLabel_1][symbol].unrealised_profit, 3) + (assets[exLabel_1][symbol].unrealised_profit >= 0 ? Success : Danger),//未实现盈亏 // (rateData[symbol].profitNumber > 0 && rateData[symbol].totalProfit > 0 ? _N(rateData[symbol].profitNumber / rateData[symbol].totalProfit * 100, 2) : '0') + '%', //胜率 { 'type': 'button', 'cmd': '说好的没有撤退可言呢???:' + symbol + ':' + assets[exLabel_1][symbol].amount + ':' + 1 + ':', 'name': symbol + ' 投降' } ]; table.rows.push(infoList); //} //delete assets.USDT.update_time; //时间戳没什么用,不要了 var logString = JSON.stringify(assets[exLabel_0].USDT) + '\n'; logString = logString + JSON.stringify(assets[exLabel_1].USDT) + '\n'; var StatusData = AppendedStatus(); //LogStatus(StatusData.upTable + '`' + JSON.stringify([table, StatusData.indexTable]) + '`\n' + logString); LogStatus(StatusData.upTable + '`' + JSON.stringify([table]) + '`\n' + logString); if (Date.now() - update_profit_time > Log_profit_interval * 1000) { var balance = assets[exLabel_0].USDT.margin_balance + assets[exLabel_1].USDT.margin_balance; /* if (Show) { balance = assets.USDT.margin_balance - Funding; } */ LogProfit(_N(balance, 3), '&'); update_profit_time = Date.now(); /* if (UpProfit != 0 && (_N(balance, 0) != UpProfit)) { //第一次不计算,并且小数点面的不进行胜率计算 tradingCounter("totalProfit", 1); //统计打印次数, 胜率=盈利次数/打印次数*100 if (_N(balance, 0) > UpProfit) { tradingCounter("profitNumber", 1); //盈利次数 } WinRate(); } UpProfit = _N(balance, 0); */ } } function onTick() { //策略逻辑部分 var symbol = "BTC"; if (trade_info[symbol].ask_price == 0 || trade_info[symbol].bid_price ==0) { return; } //检查 持仓是否已经被 止盈止损单 清仓 //全0持仓 //对冲结束 if(assets[exLabel_0][symbol].amount == 0 && assets[exLabel_1][symbol].amount == 0 && ( //assets[exLabel_1].USDT.total_balance <1 || //assets[exLabel_0].USDT.total_balance <1 || assets[exLabel_0].USDT.total_balance * MarginLevel < trade_info[symbol].minQty * trade_info[symbol].bid_price || assets[exLabel_1].USDT.total_balance * MarginLevel < trade_info[symbol].minQty * trade_info[symbol].bid_price ) ){ // Log(assets[exLabel_0].USDT.total_balance,"<",trade_info[symbol].minQty * trade_info[symbol].bid_price) // Log(assets[exLabel_1].USDT.total_balance,"<",trade_info[symbol].minQty * trade_info[symbol].bid_price) onexit(); throw '1082 对冲结束,如果需要重新运行策略,需要重新设置参数账户'; } if ( Math.abs(assets[exLabel_0][symbol].amount) <= trade_info[symbol].minQty && Math.abs(assets[exLabel_1][symbol].amount) <= trade_info[symbol].minQty && assets[exLabel_0].USDT.total_balance * MarginLevel >= trade_info[symbol].minQty * trade_info[symbol].bid_price && assets[exLabel_1].USDT.total_balance * MarginLevel >= trade_info[symbol].minQty * trade_info[symbol].bid_price ) { //持仓全几乎为0,且账户余额全不为0 exchanges[0].IO("currency", symbol + '_' + 'USDT'); exchanges[0].SetContractType('swap'); exchanges[0].SetMarginLevel(MarginLevel) exchanges[1].IO("currency", symbol + '_' + 'USDT'); exchanges[1].SetContractType('swap'); exchanges[1].SetMarginLevel(MarginLevel) var amount =0 if(assets[exLabel_1].USDT.total_balance > assets[exLabel_0].USDT.total_balance ){ // USDT.total_balance 小的 全量下单 Trade_ex = 0 //设置为 全仓模式 //changeMarginTypeToCROSSED(true,"BTCUSDT",exchanges[0]) //changeMarginTypeToCROSSED(false,"BTCUSDT",exchanges[1]) }else{ Trade_ex = 1 //设置为 全仓模式 //changeMarginTypeToCROSSED(true,"BTCUSDT",exchanges[1]) //changeMarginTypeToCROSSED(false,"BTCUSDT",exchanges[0]) } if (NO_TRADE){ //Log(exchanges[Trade_ex].GetLabel()) //Log(assets[exchanges[Trade_ex].GetLabel()]) //Log(assets) // Log(assets[exchanges[Trade_ex].GetLabel()].USDT.total_balance) // Log(trade_info[symbol].ask_price) Log(353,"exchanges[",Trade_ex,"] buy",symbol," amount:",_N(assets[exchanges[Trade_ex].GetLabel()].USDT.total_balance * MarginLevel /trade_info[symbol].ask_price,trade_info[symbol].amountSize)," total_balance:",assets[exchanges[Trade_ex].GetLabel()].USDT.total_balance," ask_price:",trade_info[symbol].ask_price) Log(354,"exchanges[",1-Trade_ex,"] sell",symbol," amount:",_N(assets[exchanges[Trade_ex].GetLabel()].USDT.total_balance * MarginLevel /trade_info[symbol].bid_price,trade_info[symbol].amountSize)," total_balance:",assets[exchanges[Trade_ex].GetLabel()].USDT.total_balance," bid_price:",trade_info[symbol].bid_price) }else{ //设置为 全仓模式 changeMarginTypeToCROSSED(true,"BTCUSDT",exchanges[Trade_ex]) changeMarginTypeToCROSSED(false,"BTCUSDT",exchanges[1-Trade_ex]) cancelAll(symbol,exchanges[Trade_ex]) exchanges[Trade_ex].SetDirection('buy'); //var ticker = _C(exchange.GetTicker); //var spread = ticker.Sell - ticker.Buy; //(ticker.Sell + spread) var spread = trade_info[symbol].ask_price - trade_info[symbol].bid_price; amount = _N(assets[exchanges[Trade_ex].GetLabel()].USDT.total_balance * MarginLevel * 0.99 /(trade_info[symbol].ask_price+spread) ,trade_info[symbol].amountSize) //Log(1052,exchanges[Trade_ex].GetLabel()," buy ",symbol," value(",MarginLevel,"x):",_N(assets[exchanges[Trade_ex].GetLabel()].USDT.total_balance * MarginLevel,2)," amount:",amount," balance:",assets[exchanges[Trade_ex].GetLabel()].USDT.total_balance," ask_price:",trade_info[symbol].ask_price," ticker.Sell:",ticker.Sell ," spread:",spread) Log(1052,exchanges[Trade_ex].GetLabel()," buy ",symbol," value(",MarginLevel,"x):",_N(assets[exchanges[Trade_ex].GetLabel()].USDT.total_balance * MarginLevel,2)," amount:",amount," balance:",assets[exchanges[Trade_ex].GetLabel()].USDT.total_balance," ask_price:",trade_info[symbol].ask_price) var exOrderid_01=exchanges[Trade_ex].Buy(-1, amount, symbol); if(exOrderid_01){ //买同量的币,钱少的账户应该先买(不是卖),因为买,比卖花的钱多 cancelAll(symbol,exchanges[1-Trade_ex]) exchanges[1-Trade_ex].SetDirection('sell'); //amount = _N(assets[exchanges[Trade_ex].GetLabel()].USDT.total_balance * MarginLevel /trade_info[symbol].bid_price,trade_info[symbol].amountSize) Log(1094,exchanges[1-Trade_ex].GetLabel()," sell ",symbol," value(",MarginLevel,"x):",_N(assets[exchanges[Trade_ex].GetLabel()].USDT.total_balance * MarginLevel,2)," amount:",amount," balance:",assets[exchanges[Trade_ex].GetLabel()].USDT.total_balance," bid_price:",trade_info[symbol].bid_price) for (var i = 0; i < 10; i++) { var exOrderid_02=exchanges[1-Trade_ex].Sell(-1, amount, symbol); if(!isEmpty(exOrderid_02))break; Sleep(100) } if(isEmpty(exOrderid_02))return; //Sleep(1000) var theOrder = waitOrder(exOrderid_01,exchanges[Trade_ex]) //var theOrder = exchanges[Trade_ex].GetOrder(exOrderid_01); //if(!isEmpty(theOrder))theOrder=theOrder.Info; //Log(theOrder); Log(946,exchanges[Trade_ex].GetLabel()," buy ",symbol," OrderId:",theOrder.orderId ,"=>(",theOrder.status,")"," origQty:",theOrder.origQty,"=>(executed:",theOrder.executedQty,") avgPrice:",theOrder.avgPrice," USDT.balance: ",assets[exchanges[Trade_ex].GetLabel()].USDT.total_balance) if (theOrder.status != "NEW"){ //var theOrder2 = waitOrder(exOrderid_02,exchanges[1-Trade_ex]) updateAccount(exchanges[Trade_ex]) exchanges[Trade_ex].SetDirection('closebuy'); //exchanges[Trade_ex].Sell(_N( parseFloat(theOrder.avgPrice) * 1.0055,trade_info[symbol].priceSize ) , parseFloat(theOrder.executedQty), symbol); //止盈单 //amount = _N(assets[symbol].liquidationPrice * Stop_loss + assets[symbol].hold_price * (1 - Stop_loss), trade_info[symbol].priceSize) //assets[exchanges[Trade_ex].GetLabel()][symbol].liquidationPrice -10 if(isEmpty(assets[exchanges[Trade_ex].GetLabel()][symbol].liquidationPrice)){ getPostion(symbol,exchanges[Trade_ex]) } if(isEmpty(assets[exchanges[Trade_ex].GetLabel()][symbol].liquidationPrice)){ return } amount = assets[exchanges[Trade_ex].GetLabel()][symbol].liquidationPrice +10 /* if (theOrder2.status != "NEW"){ updateAccount(exchanges[1-Trade_ex]) if(isEmpty(assets[exchanges[1-Trade_ex].GetLabel()][symbol].liquidationPrice)){ getPostion(symbol,exchanges[1-Trade_ex]) } if(isEmpty(assets[exchanges[1-Trade_ex].GetLabel()][symbol].liquidationPrice)){ return } exchanges[Trade_ex].Sell(_N( parseFloat(assets[exchanges[1-Trade_ex].GetLabel()][symbol].liquidationPrice) ,trade_info[symbol].priceSize ) , parseFloat(theOrder.executedQty), symbol); //止盈单 }else{ exchanges[Trade_ex].Sell(_N( parseFloat(theOrder.avgPrice) * 1.0055,trade_info[symbol].priceSize ) , parseFloat(theOrder.executedQty), symbol); //止盈单 } */ var Order = [{ "symbol": symbol + "USDT", "side": "SELL", "positionSide": "BOTH", "type": "STOP", "stopPrice": _N( amount , trade_info[symbol].priceSize ), "workingType": "MARK_PRICE", "quantity": _N( parseFloat(theOrder.executedQty) , trade_info[symbol].amountSize ), "price": _N( amount -9 , trade_info[symbol].priceSize ), "timeInForce": "GTC", "reduceOnly": true }] //Log(995,Order) theOrder = makeOrder(Order,exchanges[Trade_ex]) amount = _N((1-amount / assets[exchanges[Trade_ex].GetLabel()][symbol].hold_price) * 100, 2) Log(533, " 挂止损单(损失率:", amount, "%) closebuy ", symbol, " (status:", theOrder.status, ") 订单 Id:", theOrder.orderId, " price:", theOrder.price, "(stopPrice:",_N( assets[exchanges[Trade_ex].GetLabel()][symbol].liquidationPrice +10 , trade_info[symbol].priceSize ),") liquidationPrice:", _N(assets[exchanges[Trade_ex].GetLabel()][symbol].liquidationPrice, trade_info[symbol].priceSize), " amount:", theOrder.origQty, " MarginLevel:", MarginLevel, " timeInForce=", theOrder.timeInForce, " @", _D()) } //Sleep(1000) theOrder = waitOrder(exOrderid_02,exchanges[1-Trade_ex]) //theOrder = theOrder2 //theOrder = exchanges[1-Trade_ex].GetOrder(exOrderid_02); //if(!isEmpty(theOrder))theOrder=theOrder.Info; Log(987,exchanges[1-Trade_ex].GetLabel()," sell ",symbol," OrderId:",theOrder.orderId ,"=>(",theOrder.status,")"," origQty:",theOrder.origQty,"=>(executed:",theOrder.executedQty,") avgPrice:",theOrder.avgPrice," USDT.balance: ",assets[exchanges[1-Trade_ex].GetLabel()].USDT.total_balance) if (theOrder.status != "NEW"){ updateAccount(exchanges[1-Trade_ex]) //exchanges[1-Trade_ex].SetDirection('closesell'); //exchanges[1-Trade_ex].Buy(_N( parseFloat(theOrder.avgPrice) * 0.9944,trade_info[symbol].priceSize ) , parseFloat(theOrder.executedQty), symbol); //止盈单 if(isEmpty(assets[exchanges[1-Trade_ex].GetLabel()][symbol].liquidationPrice)){ getPostion(symbol,exchanges[1-Trade_ex]) } if(isEmpty(assets[exchanges[1-Trade_ex].GetLabel()][symbol].liquidationPrice)){ return } amount = assets[exchanges[1-Trade_ex].GetLabel()][symbol].liquidationPrice -10 exchanges[Trade_ex].SetDirection('closebuy'); exchanges[Trade_ex].Sell(_N( parseFloat(assets[exchanges[1-Trade_ex].GetLabel()][symbol].liquidationPrice) ,trade_info[symbol].priceSize ) ,_N( parseFloat(Math.abs(assets[exchanges[Trade_ex].GetLabel()][symbol].amount)), trade_info[symbol].amountSize), symbol); //止盈单 exchanges[1-Trade_ex].SetDirection('closesell'); exchanges[1-Trade_ex].Buy(_N( parseFloat(assets[exchanges[Trade_ex].GetLabel()][symbol].liquidationPrice),trade_info[symbol].priceSize ) , _N( parseFloat(Math.abs(assets[exchanges[1-Trade_ex].GetLabel()][symbol].amount)), trade_info[symbol].amountSize), symbol); //止盈单 var Order = [{ "symbol": symbol + "USDT", "side": "BUY", "positionSide": "BOTH", "type": "STOP", "stopPrice": _N( amount , trade_info[symbol].priceSize ), "workingType": "MARK_PRICE", "quantity": _N(parseFloat(theOrder.executedQty), trade_info[symbol].amountSize), "price": _N( amount +9 , trade_info[symbol].priceSize ), "timeInForce": "GTC", "reduceOnly": true }] theOrder = makeOrder(Order,exchanges[1-Trade_ex]) amount = _N((amount / assets[exchanges[1-Trade_ex].GetLabel()][symbol].hold_price -1) * 100, 2) Log(571, " 挂止损单(损失率:", amount, "%) closesell ", symbol, " (status:", theOrder.status, ") 订单 Id:", theOrder.orderId, " price:", theOrder.price, "(stopPrice:",_N( assets[exchanges[1-Trade_ex].GetLabel()][symbol].liquidationPrice -10 , trade_info[symbol].priceSize ),") liquidationPrice:", _N(assets[exchanges[1-Trade_ex].GetLabel()][symbol].liquidationPrice, trade_info[symbol].priceSize), " amount:", theOrder.origQty, " MarginLevel:", MarginLevel, " timeInForce=", theOrder.timeInForce, " @", _D()) } }//end order_01 }//end NO_TRADE } //单一持仓 if ((Math.abs(assets[exLabel_0][symbol].amount) >= trade_info[symbol].minQty && Math.abs(assets[exLabel_1][symbol].amount) <= trade_info[symbol].minQty )|| (Math.abs(assets[exLabel_0][symbol].amount) <= trade_info[symbol].minQty && Math.abs(assets[exLabel_1][symbol].amount) >= trade_info[symbol].minQty )) { //任一为0另一不为0 if(assets[exLabel_0][symbol].amount != 0){ cancelAll(symbol,exchanges[0]) cancelAll(symbol,exchanges[1]) closeAll(symbol,exchanges[0]) Log(1022,exLabel_0," 已平仓(因另一交易所已平仓)! exLabel_0_Amount:",assets[exLabel_0][symbol].amount,"exLabel_1_Amount:",assets[exLabel_1][symbol].amount) } if(assets[exLabel_1][symbol].amount != 0){ cancelAll(symbol,exchanges[0]) cancelAll(symbol,exchanges[1]) closeAll(symbol,exchanges[1]) Log(1026,exLabel_1," 已平仓(因另一交易所已平仓)! exLabel_0_Amount:",assets[exLabel_0][symbol].amount,"exLabel_1_Amount:",assets[exLabel_1][symbol].amount) } onexit(); throw '1317 对冲结束,请检查仓位,委托单是否已经清除,并重启'; } //止盈//止损 if ( Math.abs(assets[exLabel_0][symbol].amount) >= trade_info[symbol].minQty && Math.abs(assets[exLabel_1][symbol].amount) >= trade_info[symbol].minQty ){ //持仓都不为0 if(assets[exchanges[Trade_ex].GetLabel()][symbol].markPrice <= assets[exchanges[Trade_ex].GetLabel()][symbol].liquidationPrice +10 || assets[exchanges[1-Trade_ex].GetLabel()][symbol].markPrice >= assets[exchanges[1-Trade_ex].GetLabel()][symbol].liquidationPrice -10 ){ //止损 if(assets[exchanges[Trade_ex].GetLabel()][symbol].markPrice <= assets[exchanges[Trade_ex].GetLabel()][symbol].liquidationPrice +10) Log(1224,exchanges[Trade_ex].GetLabel(),"止损,并平仓另一交易所 markPrice",assets[exchanges[Trade_ex].GetLabel()][symbol].markPrice,"<=",assets[exchanges[Trade_ex].GetLabel()][symbol].liquidationPrice +10) if(assets[exchanges[1-Trade_ex].GetLabel()][symbol].markPrice >= assets[exchanges[1-Trade_ex].GetLabel()][symbol].liquidationPrice -10) Log(1225,exchanges[1-Trade_ex].GetLabel(),"止损,并平仓另一交易所 markPrice",assets[exchanges[1-Trade_ex].GetLabel()][symbol].markPrice,">=",assets[exchanges[1-Trade_ex].GetLabel()][symbol].liquidationPrice -10) cancelAll(symbol,exchanges[Trade_ex]) cancelAll(symbol,exchanges[1-Trade_ex]) closeAll(symbol,exchanges[Trade_ex]) closeAll(symbol,exchanges[1-Trade_ex]) } } } function RunCommand() { var str_cmd = GetCommand(); if (str_cmd) { var arrCmd = str_cmd.split(':'); var symbol = arrCmd[1]; var amount = parseFloat(arrCmd[2]); var ex = arrCmd[3]; var exchange=exchanges[ex] if (amount == 0) { Log('亲,你还记得大明湖畔的乔碧萝吗?' + Danger); return; } var f = amount < 0 ? 'Buy' : 'Sell'; var dirction = amount < 0 ? 'buy' : 'sell'; exchange.IO("currency", symbol + '_' + 'USDT'); exchange.SetContractType('swap'); exchange.SetDirection(dirction); exchange.SetMarginLevel(MarginLevel) exchange[f](-1, Math.abs(amount), symbol); Log(737,exchange.GetLabel(),dirction,symbol," 投降 amount=",amount) } } function main() { while (true) { RunTime = RuningTime(); RunCommand(); //捕获交互命令 updateAccount(exchanges[0]) updateAccount(exchanges[1]); //更新账户和持仓 updateTick(); //行情 //stopLoss(); //止损 onTick(); //策略逻辑部分 updateStatus(); //输出状态栏信息 Sleep(Interval * 1000); } }
Jenny LiHi, ich bin sehr an dieser Strategie interessiert, aber es ist sehr schwierig, sie umzusetzen.