- Square
- 币安永续(双账户单币种对冲)(YN)(RUN)
币安永续(双账户单币种对冲)(YN)(RUN)
Author:
高吸低抛, Date: 2020-05-31 22:18:16
Tags:
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);
}
}
template: strategy.tpl:40:21: executing "strategy.tpl" at <.api.GetStrategyListByName>: wrong number of args for GetStrategyListByName: want 7 got 6