littlelittlexDream
Newbie
Offline
Activity: 2
Merit: 0
|
|
November 07, 2017, 05:50:47 AM |
|
I have some strategy on BotVS . In fact , I think the hedge strategy is the low risk strategy. Although the profit is few . Ok ! Talk is cheap, Show code to you ! Address: https://www.botvs.com/strategy/57var initState; var isBalance = true; var feeCache = new Array(); var feeTimeout = optFeeTimeout * 60000; var lastProfit = 0; var lastAvgPrice = 0; var lastSpread = 0; var lastOpAmount = 0; function adjustFloat(v) { return Math.floor(v*1000)/1000; }
function isPriceNormal(v) { return (v >= StopPriceL) && (v <= StopPriceH); }
function stripTicker(t) { return 'Buy: ' + adjustFloat(t.Buy) + ' Sell: ' + adjustFloat(t.Sell); }
function updateStatePrice(state) { var now = (new Date()).getTime(); for (var i = 0; i < state.details.length; i++) { var ticker = null; var key = state.details[i].exchange.GetName() + state.details[i].exchange.GetCurrency(); var fee = null; while (!(ticker = state.details[i].exchange.GetTicker())) { Sleep(Interval); }
if (key in feeCache) { var v = feeCache[key]; if ((now - v.time) > feeTimeout) { delete feeCache[key]; } else { fee = v.fee; } } if (!fee) { while (!(fee = state.details[i].exchange.GetFee())) { Sleep(Interval); } feeCache[key] = {fee: fee, time: now}; } // Buy-=fee Sell+=fee state.details[i].ticker = {Buy: ticker.Buy * (1-(fee.Sell/100)), Sell: ticker.Sell * (1+(fee.Buy/100))}; state.details[i].realTicker = ticker; state.details[i].fee = fee; } }
function getProfit(stateInit, stateNow, coinPrice) { var netNow = stateNow.allBalance + (stateNow.allStocks * coinPrice); var netInit = stateInit.allBalance + (stateInit.allStocks * coinPrice); return adjustFloat(netNow - netInit); }
function getExchangesState() { var allStocks = 0; var allBalance = 0; var minStock = 0; var details = []; for (var i = 0; i < exchanges.length; i++) { var account = null; while (!(account = exchanges[i].GetAccount())) { Sleep(Interval); } allStocks += account.Stocks + account.FrozenStocks; allBalance += account.Balance + account.FrozenBalance; minStock = Math.max(minStock, exchanges[i].GetMinStock()); details.push({exchange: exchanges[i], account: account}); } return {allStocks: adjustFloat(allStocks), allBalance: adjustFloat(allBalance), minStock: minStock, details: details}; }
function cancelAllOrders() { for (var i = 0; i < exchanges.length; i++) { while (true) { var orders = null; while (!(orders = exchanges[i].GetOrders())) { Sleep(Interval); }
if (orders.length == 0) { break; }
for (var j = 0; j < orders.length; j++) { exchanges[i].CancelOrder(orders[j].Id, orders[j]); } } } }
function balanceAccounts() { // already balance if (isBalance) { return; }
cancelAllOrders();
var state = getExchangesState(); var diff = state.allStocks - initState.allStocks; var adjustDiff = adjustFloat(Math.abs(diff)); if (adjustDiff < state.minStock) { isBalance = true; } else { Log('初始币总数量:', initState.allStocks, '现在币总数量: ', state.allStocks, '差额:', adjustDiff); // other ways, diff is 0.012, bug A only has 0.006 B only has 0.006, all less then minstock // we try to statistical orders count to recognition this situation updateStatePrice(state); var details = state.details; var ordersCount = 0; if (diff > 0) { var attr = 'Sell'; if (UseMarketOrder) { attr = 'Buy'; } // Sell adjustDiff, sort by price high to low details.sort(function(a, b) {return b.ticker[attr] - a.ticker[attr];}); for (var i = 0; i < details.length && adjustDiff >= state.minStock; i++) { if (isPriceNormal(details[i].ticker[attr]) && (details[i].account.Stocks >= state.minStock)) { var orderAmount = adjustFloat(Math.min(AmountOnce, adjustDiff, details[i].account.Stocks)); var orderPrice = details[i].realTicker[attr] - SlidePrice; if ((orderPrice * orderAmount) < details[i].exchange.GetMinPrice()) { continue; } ordersCount++; if (details[i].exchange.Sell(orderPrice, orderAmount, stripTicker(details[i].ticker))) { adjustDiff = adjustFloat(adjustDiff - orderAmount); } // only operate one platform break; } } } else { var attr = 'Buy'; if (UseMarketOrder) { attr = 'Sell'; } // Buy adjustDiff, sort by sell-price low to high details.sort(function(a, b) {return a.ticker[attr] - b.ticker[attr];}); for (var i = 0; i < details.length && adjustDiff >= state.minStock; i++) { if (isPriceNormal(details[i].ticker[attr])) { var canRealBuy = adjustFloat(details[i].account.Balance / (details[i].ticker[attr] + SlidePrice)); var needRealBuy = Math.min(AmountOnce, adjustDiff, canRealBuy); var orderAmount = adjustFloat(needRealBuy * (1+(details[i].fee.Buy/100))); var orderPrice = details[i].realTicker[attr] + SlidePrice; if ((orderAmount < details[i].exchange.GetMinStock()) || ((orderPrice * orderAmount) < details[i].exchange.GetMinPrice())) { continue; } ordersCount++; if (details[i].exchange.Buy(orderPrice, orderAmount, stripTicker(details[i].ticker))) { adjustDiff = adjustFloat(adjustDiff - needRealBuy); } // only operate one platform break; } } } isBalance = (ordersCount == 0); }
if (isBalance) { var currentProfit = getProfit(initState, state, lastAvgPrice); LogProfit(currentProfit, "Spread: ", adjustFloat((currentProfit - lastProfit) / lastOpAmount), "Balance: ", adjustFloat(state.allBalance), "Stocks: ", adjustFloat(state.allStocks));
if (StopWhenLoss && currentProfit < 0 && Math.abs(currentProfit) > MaxLoss) { Log('交易亏损超过最大限度, 程序取消所有订单后退出.'); cancelAllOrders(); if (SMSAPI.length > 10 && SMSAPI.indexOf('http') == 0) { HttpQuery(SMSAPI); Log('已经短信通知'); } throw '已停止'; } lastProfit = currentProfit; } }
function onTick() { if (!isBalance) { balanceAccounts(); return; }
var state = getExchangesState(); // We also need details of price updateStatePrice(state);
var details = state.details; var maxPair = null; var minPair = null; for (var i = 0; i < details.length; i++) { var sellOrderPrice = details[i].account.Stocks * (details[i].realTicker.Buy - SlidePrice); if (((!maxPair) || (details[i].ticker.Buy > maxPair.ticker.Buy)) && (details[i].account.Stocks >= state.minStock) && (sellOrderPrice > details[i].exchange.GetMinPrice())) { details[i].canSell = details[i].account.Stocks; maxPair = details[i]; }
var canBuy = adjustFloat(details[i].account.Balance / (details[i].realTicker.Sell + SlidePrice)); var buyOrderPrice = canBuy * (details[i].realTicker.Sell + SlidePrice); if (((!minPair) || (details[i].ticker.Sell < minPair.ticker.Sell)) && (canBuy >= state.minStock) && (buyOrderPrice > details[i].exchange.GetMinPrice())) { details[i].canBuy = canBuy; // how much coins we real got with fee details[i].realBuy = adjustFloat(details[i].account.Balance / (details[i].ticker.Sell + SlidePrice)); minPair = details[i]; } }
if ((!maxPair) || (!minPair) || ((maxPair.ticker.Buy - minPair.ticker.Sell) < MaxDiff) || !isPriceNormal(maxPair.ticker.Buy) || !isPriceNormal(minPair.ticker.Sell)) { return; }
// filter invalid price if (minPair.realTicker.Sell <= minPair.realTicker.Buy || maxPair.realTicker.Sell <= maxPair.realTicker.Buy) { return; }
// what a fuck... if (maxPair.exchange.GetName() == minPair.exchange.GetName()) { return; }
lastAvgPrice = adjustFloat((minPair.realTicker.Buy + maxPair.realTicker.Buy) / 2); lastSpread = adjustFloat((maxPair.realTicker.Sell - minPair.realTicker.Buy) / 2);
// compute amount var amount = Math.min(AmountOnce, maxPair.canSell, minPair.realBuy); lastOpAmount = amount; var hedgePrice = adjustFloat((maxPair.realTicker.Buy - minPair.realTicker.Sell) / Math.max(SlideRatio, 2)) if (minPair.exchange.Buy(minPair.realTicker.Sell + hedgePrice, amount * (1+(minPair.fee.Buy/100)), stripTicker(minPair.realTicker))) { maxPair.exchange.Sell(maxPair.realTicker.Buy - hedgePrice, amount, stripTicker(maxPair.realTicker)); }
isBalance = false; }
function main() { if (exchanges.length < 2) { throw "交易所数量最少得两个才能完成对冲"; }
TickInterval = Math.max(TickInterval, 50); Interval = Math.max(Interval, 50);
cancelAllOrders();
initState = getExchangesState(); if (initState.allStocks == 0) { throw "所有交易所货币数量总和为空, 必须先在任一交易所建仓才可以完成对冲"; } if (initState.allBalance == 0) { throw "所有交易所CNY数量总和为空, 无法继续对冲"; }
for (var i = 0; i < initState.details.length; i++) { var e = initState.details[i]; Log(e.exchange.GetName(), e.exchange.GetCurrency(), e.account); }
Log("ALL: Balance: ", initState.allBalance, "Stocks: ", initState.allStocks, "Ver:", Version());
while (true) { onTick(); Sleep(parseInt(TickInterval)); } } The another one is the Grid strategy: (Used in shocking market) address : https://www.botvs.com/strategy/629function hasOrder(orders, orderId) { for (var i = 0; i < orders.length; i++) { if (orders[i].Id == orderId) { return true; } } return false; }
function cancelPending() { var ret = false; while (true) { if (ret) { Sleep(Interval); } var orders = _C(exchange.GetOrders); if (orders.length == 0) { break; }
for (var j = 0; j < orders.length; j++) { exchange.CancelOrder(orders[j].Id, orders[j]); ret = true; } } return ret; }
function valuesToString(values, pos) { var result = ''; if (typeof(pos) === 'undefined') { pos = 0; } for (var i = pos; i < values.length; i++) { if (i > pos) { result += ' '; } if (values[i] === null) { result += 'null'; } else if (typeof(values[i]) == 'undefined') { result += 'undefined'; } else { switch (values[i].constructor.name) { case 'Date': case 'Number': case 'String': case 'Function': result += values[i].toString(); break; default: result += JSON.stringify(values[i]); break; } } } return result; }
function Trader() { var vId = 0; var orderBooks = []; var hisBooks = []; var orderBooksLen = 0; this.Buy = function(price, amount, extra) { if (typeof(extra) === 'undefined') { extra = ''; } else { extra = valuesToString(arguments, 2); } vId++; var orderId = "V" + vId; orderBooks[orderId] = { Type: ORDER_TYPE_BUY, Status: ORDER_STATE_PENDING, Id: 0, Price: price, Amount: amount, Extra: extra }; orderBooksLen++; return orderId; }; this.Sell = function(price, amount, extra) { if (typeof(extra) === 'undefined') { extra = ''; } else { extra = valuesToString(arguments, 2); } vId++; var orderId = "V" + vId; orderBooks[orderId] = { Type: ORDER_TYPE_SELL, Status: ORDER_STATE_PENDING, Id: 0, Price: price, Amount: amount, Extra: extra }; orderBooksLen++; return orderId; }; this.GetOrders = function() { var orders = _C(exchange.GetOrders); for (orderId in orderBooks) { var order = orderBooks[orderId]; if (order.Status !== ORDER_STATE_PENDING) { continue; } var found = false; for (var i = 0; i < orders.length; i++) { if (orders[i].Id == order.Id) { found = true; break; } } if (!found) { orders.push(orderBooks[orderId]); } } return orders; } this.GetOrder = function(orderId) { if (typeof(orderId) === 'number') { return exchange.GetOrder(orderId); } if (typeof(hisBooks[orderId]) !== 'undefined') { return hisBooks[orderId]; } if (typeof(orderBooks[orderId]) !== 'undefined') { return orderBooks[orderId]; } return null; }; this.Len = function() { return orderBooksLen; }; this.RealLen = function() { var n = 0; for (orderId in orderBooks) { if (orderBooks[orderId].Id > 0) { n++; } } return n; }; this.Poll = function(ticker, priceDiff) { var orders = _C(exchange.GetOrders); for (orderId in orderBooks) { var order = orderBooks[orderId]; if (order.Id > 0) { var found = false; for (var i = 0; i < orders.length; i++) { if (order.Id == orders[i].Id) { found = true; } } if (!found) { order.Status = ORDER_STATE_CLOSED; hisBooks[orderId] = order; delete(orderBooks[orderId]); orderBooksLen--; continue; } } var diff = _N(order.Type == ORDER_TYPE_BUY ? (ticker.Buy - order.Price) : (order.Price - ticker.Sell)); var pfn = order.Type == ORDER_TYPE_BUY ? exchange.Buy : exchange.Sell; if (order.Id == 0 && diff <= priceDiff) { var realId = pfn(order.Price, order.Amount, order.Extra + "(距离: " + diff + (order.Type == ORDER_TYPE_BUY ? (" 买一: " + ticker.Buy) : (" 卖一: " + ticker.Sell))+")"); if (typeof(realId) === 'number') { order.Id = realId; } } else if (order.Id > 0 && diff > (priceDiff + 1)) { var ok = true; do { ok = true; exchange.CancelOrder(order.Id, "不必要的" + (order.Type == ORDER_TYPE_BUY ? "买单" : "卖单"), "委托价:", order.Price, "量:", order.Amount, ", 距离:", diff, order.Type == ORDER_TYPE_BUY ? ("买一: " + ticker.Buy) : ("卖一: " + ticker.Sell)); Sleep(200); orders = _C(exchange.GetOrders); for (var i = 0; i < orders.length; i++) { if (orders[i].Id == order.Id) { ok = false; } } } while (!ok); order.Id = 0; } } }; }
function balanceAccount(orgAccount, initAccount) { cancelPending(); var nowAccount = _C(exchange.GetAccount); var slidePrice = 0.2; var ok = true; while (true) { var diff = _N(nowAccount.Stocks - initAccount.Stocks); if (Math.abs(diff) < exchange.GetMinStock()) { break; } var depth = _C(exchange.GetDepth); var books = diff > 0 ? depth.Bids : depth.Asks; var n = 0; var price = 0; for (var i = 0; i < books.length; i++) { n += books[i].Amount; if (n >= Math.abs(diff)) { price = books[i].Price; break; } } var pfn = diff > 0 ? exchange.Sell : exchange.Buy; var amount = Math.abs(diff); var price = diff > 0 ? (price - slidePrice) : (price + slidePrice); Log("开始平衡", (diff > 0 ? "卖出" : "买入"), amount, "个币"); if (diff > 0) { amount = Math.min(nowAccount.Stocks, amount); } else { amount = Math.min(nowAccount.Balance / price, amount); } if (amount < exchange.GetMinStock()) { Log("资金不足, 无法平衡到初始状态"); ok = false; break; } pfn(price, amount); Sleep(1000); cancelPending(); nowAccount = _C(exchange.GetAccount); } if (ok) { LogProfit(_N(nowAccount.Balance - orgAccount.Balance)); Log("平衡完成", nowAccount); } }
var STATE_WAIT_OPEN = 0; var STATE_WAIT_COVER = 1; var STATE_WAIT_CLOSE = 2; var ProfitCount = 0; var BuyFirst = true; var IsSupportGetOrder = true; var LastBusy = 0;
function setBusy() { LastBusy = new Date(); }
function isTimeout() { if (MaxIdle <= 0) { return false; } var now = new Date(); if (((now.getTime() - LastBusy.getTime()) / 1000) >= MaxIdle) { LastBusy = now; return true; } return false; }
function onexit() { if (CancelAllWS) { Log("正在退出, 尝试取消所有挂单"); cancelPending(); } Log("策略成功停止"); Log(_C(exchange.GetAccount)); }
function fishing(orgAccount, fishCount) { setBusy(); var account = _C(exchange.GetAccount); Log(account); var InitAccount = account; var ticker = _C(exchange.GetTicker); var amount = _N(AmountOnce); var amountB = [amount]; var amountS = [amount]; if (typeof(AmountType) !== 'undefined' && AmountType == 1) { for (var idx = 0; idx < AllNum; idx++) { amountB[idx] = BAmountOnce; amountS[idx] = SAmountOnce; } } else { for (var idx = 1; idx < AllNum; idx++) { switch (AmountCoefficient[0]) { case '+': amountB[idx] = amountB[idx - 1] + parseFloat(AmountCoefficient.substring(1)); break; case '-': amountB[idx] = amountB[idx - 1] - parseFloat(AmountCoefficient.substring(1)); break; case '*': amountB[idx] = amountB[idx - 1] * parseFloat(AmountCoefficient.substring(1)); break; case '/': amountB[idx] = amountB[idx - 1] / parseFloat(AmountCoefficient.substring(1)); break; } amountB[idx] = _N(amountB[idx], AmountDot); amountS[idx] = amountB[idx]; } } if (FirstPriceAuto) { FirstPrice = BuyFirst ? _N(ticker.Buy - PriceGrid, Precision) : _N(ticker.Sell + PriceGrid, Precision); } // Initialize fish table var fishTable = {}; var uuidTable = {}; var needStocks = 0; var needMoney = 0; var actualNeedMoney = 0; var actualNeedStocks = 0; var notEnough = false; var canNum = 0; for (var idx = 0; idx < AllNum; idx++) { var price = _N((BuyFirst ? FirstPrice - (idx * PriceGrid) : FirstPrice + (idx * PriceGrid)), Precision); needStocks += amountS[idx]; needMoney += price * amountB[idx]; if (BuyFirst) { if (_N(needMoney) <= _N(account.Balance)) { actualNeedMondy = needMoney; actualNeedStocks = needStocks; canNum++; } else { notEnough = true; } } else { if (_N(needStocks) <= _N(account.Stocks)) { actualNeedMondy = needMoney; actualNeedStocks = needStocks; canNum++; } else { notEnough = true; } } fishTable[idx] = STATE_WAIT_OPEN; uuidTable[idx] = -1; } if (!EnableAccountCheck && (canNum < AllNum)) { Log("警告, 当前资金只可做", canNum, "个网格, 全网共需", (BuyFirst ? needMoney : needStocks), "请保持资金充足"); canNum = AllNum; } if (BuyFirst) { if (EnableProtectDiff && (FirstPrice - ticker.Sell) > ProtectDiff) { throw "首次买入价比市场卖1价高" + _N(FirstPrice - ticker.Sell, Precision) + ' 元'; } else if (EnableAccountCheck && account.Balance < _N(needMoney)) { if (fishCount == 1) { throw "资金不足, 需要" + _N(needMoney) + "元"; } else { Log("资金不足, 需要", _N(needMoney), "元, 程序只做", canNum, "个网格 #ff0000"); } } else { Log('预计动用资金: ', _N(needMoney), "元"); } } else { if (EnableProtectDiff && (ticker.Buy - FirstPrice) > ProtectDiff) { throw "首次卖出价比市场买1价高 " + _N(ticker.Buy - FirstPrice, Precision) + ' 元'; } else if (EnableAccountCheck && account.Stocks < _N(needStocks)) { if (fishCount == 1) { throw "币数不足, 需要 " + _N(needStocks) + " 个币"; } else { Log("资金不足, 需要", _N(needStocks), "个币, 程序只做", canNum, "个网格 #ff0000"); } } else { Log('预计动用币数: ', _N(needStocks), "个, 约", _N(needMoney), "元"); } }
var trader = new Trader(); var OpenFunc = BuyFirst ? exchange.Buy : exchange.Sell; var CoverFunc = BuyFirst ? exchange.Sell : exchange.Buy; if (EnableDynamic) { OpenFunc = BuyFirst ? trader.Buy : trader.Sell; CoverFunc = BuyFirst ? trader.Sell : trader.Buy; } var ts = new Date(); var preMsg = ""; var profitMax = 0; while (true) { var now = new Date(); var table = null; if (now.getTime() - ts.getTime() > 5000) { if (typeof(GetCommand) == 'function' && GetCommand() == "收网") { Log("开始执行命令进行收网操作"); balanceAccount(orgAccount, InitAccount); return false; } ts = now; var nowAccount = _C(exchange.GetAccount); var ticker = _C(exchange.GetTicker); if (EnableDynamic) { trader.Poll(ticker, DynamicMax); } var amount_diff = (nowAccount.Stocks + nowAccount.FrozenStocks) - (InitAccount.Stocks + InitAccount.FrozenStocks); var money_diff = (nowAccount.Balance + nowAccount.FrozenBalance) - (InitAccount.Balance + InitAccount.FrozenBalance); var floatProfit = _N(money_diff + (amount_diff * ticker.Last)); var floatProfitAll = _N((nowAccount.Balance + nowAccount.FrozenBalance - orgAccount.Balance - orgAccount.FrozenBalance) + ((nowAccount.Stocks + nowAccount.FrozenStocks - orgAccount.Stocks - orgAccount.FrozenStocks) * ticker.Last)); var isHold = Math.abs(amount_diff) >= exchange.GetMinStock(); if (isHold) { setBusy(); }
profitMax = Math.max(floatProfit, profitMax); if (EnableAccountCheck && EnableStopLoss) { if ((profitMax - floatProfit) >= StopLoss) { Log("当前浮动盈亏", floatProfit, "利润最高点: ", profitMax, "开始止损"); balanceAccount(orgAccount, InitAccount); if (StopLossMode == 0) { throw "止损退出"; } else { return true; } } } if (EnableAccountCheck && EnableStopWin) { if (floatProfit > StopWin) { Log("当前浮动盈亏", floatProfit, "开始止盈"); balanceAccount(orgAccount, InitAccount); if (StopWinMode == 0) { throw "止盈退出"; } else { return true; } } } var distance = 0; if (EnableAccountCheck && AutoMove) { if (BuyFirst) { distance = ticker.Last - FirstPrice; } else { distance = FirstPrice - ticker.Last; } var refish = false; if (!isHold && isTimeout()) { Log("空仓过久, 开始移动网格"); refish = true; } if (distance > MaxDistance) { Log("价格超出网格区间过多, 开始移动网格, 当前距离: ", _N(distance, Precision), "当前价格:", ticker.Last); refish = true; } if (refish) { balanceAccount(orgAccount, InitAccount); return true; } }
var holdDirection, holdAmount = "--", holdPrice = "--"; if (isHold) { if (RestoreProfit && ProfitAsOrg) { if (BuyFirst) { money_diff += LastProfit; } else { money_diff -= LastProfit; } } holdAmount = amount_diff; holdPrice = (-money_diff) / amount_diff; if (!BuyFirst) { holdAmount = -amount_diff; holdPrice = (money_diff) / -amount_diff; } holdAmount = _N(holdAmount, 4); holdPrice = _N(holdPrice, Precision); holdDirection = BuyFirst ? "多" : "空"; } else { holdDirection = "--"; } table = { type: 'table', title: '运行状态', cols: ['动用资金', '持有仓位', '持仓大小', '持仓均价', '总浮动盈亏', '当前网格盈亏', '撒网次数', '网格偏移', '真实委托', '最新币价'], rows: [ [_N(actualNeedMondy, 4), holdDirection, holdAmount, holdPrice, _N(floatProfitAll, 4) + ' ( ' + _N(floatProfitAll * 100 / actualNeedMondy, 4) + ' % )', floatProfit, fishCount, (AutoMove && distance > 0) ? ((BuyFirst ? "向上" : "向下") + "偏离: " + _N(distance) + " 元") : "--", trader.RealLen(), ticker.Last] ] }; } var orders = _C(trader.GetOrders); if (table) { if (!EnableDynamic) { table.rows[0][8] = orders.length; } LogStatus('`' + JSON.stringify(table) + '`'); } for (var idx = 0; idx < canNum; idx++) { var openPrice = _N((BuyFirst ? FirstPrice - (idx * PriceGrid) : FirstPrice + (idx * PriceGrid)), Precision); var coverPrice = _N((BuyFirst ? openPrice + PriceDiff : openPrice - PriceDiff), Precision); var state = fishTable[idx]; var fishId = uuidTable[idx]; if (hasOrder(orders, fishId)) { continue; }
if (fishId != -1 && IsSupportGetOrder) { var order = trader.GetOrder(fishId); if (!order) { Log("获取订单信息失败, ID: ", fishId); continue; } if (order.Status == ORDER_STATE_PENDING) { //Log("订单状态为未完成, ID: ", fishId); continue; } }
if (state == STATE_WAIT_COVER) { var coverId = CoverFunc(coverPrice, (BuyFirst ? amountS[idx] : amountB[idx]), (BuyFirst ? '完成买单:' : '完成卖单:'), openPrice, '量:', (BuyFirst ? amountB[idx] : amountS[idx])); if (typeof(coverId) === 'number' || typeof(coverId) === 'string') { fishTable[idx] = STATE_WAIT_CLOSE; uuidTable[idx] = coverId; } } else if (state == STATE_WAIT_OPEN || state == STATE_WAIT_CLOSE) { var openId = OpenFunc(openPrice, BuyFirst ? amountB[idx] : amountS[idx]); if (typeof(openId) === 'number' || typeof(openId) === 'string') { fishTable[idx] = STATE_WAIT_COVER; uuidTable[idx] = openId; if (state == STATE_WAIT_CLOSE) { ProfitCount++; var account = _C(exchange.GetAccount); var ticker = _C(exchange.GetTicker); var initNet = _N(((InitAccount.Stocks + InitAccount.FrozenStocks) * ticker.Buy) + InitAccount.Balance + InitAccount.FrozenBalance, 8); var nowNet = _N(((account.Stocks + account.FrozenStocks) * ticker.Buy) + account.Balance + account.FrozenBalance, 8); var actualProfit = _N(((nowNet - initNet)) * 100 / initNet, 8); if (AmountType == 0) { var profit = _N((ProfitCount * amount * PriceDiff) + LastProfit, 8); Log((BuyFirst ? '完成卖单:' : '完成买单:'), coverPrice, '量:', (BuyFirst ? amountS[idx] : amountB[idx]), '平仓收益', profit); } else { Log((BuyFirst ? '完成卖单:' : '完成买单:'), coverPrice, '量:', (BuyFirst ? amountS[idx] : amountB[idx])); } } } } } Sleep(CheckInterval); } return true; }
function main() { if (ResetData) { LogProfitReset(); LogReset(); } exchange.SetMaxDigits(Precision) if (typeof(AmountType) === 'undefined') { AmountType = 0; } if (typeof(AmountDot) === 'undefined') { AmountDot = 3; } if (typeof(EnableDynamic) === 'undefined') { EnableDynamic = false; } if (typeof(AmountCoefficient) === 'undefined') { AmountCoefficient = "*1"; } if (typeof(EnableAccountCheck) === 'undefined') { EnableAccountCheck = true; } BuyFirst = (OpType == 0); IsSupportGetOrder = exchange.GetName().indexOf('itstamp') == -1; if (!IsSupportGetOrder) { Log(exchange.GetName(), "不支持GetOrder, 可能影响策略稳定性."); }
SetErrorFilter("502:|503:|S_U_001|unexpected|network|timeout|WSARecv|Connect|GetAddr|no such|reset|http|received|refused|EOF|When");
exchange.SetRate(1); Log('已经禁用汇率转换, 当前货币为', exchange.GetBaseCurrency());
if (!RestoreProfit) { LastProfit = 0; }
var orgAccount = _C(exchange.GetAccount); var fishCount = 1; while (true) { if (!fishing(orgAccount, fishCount)) { break; } fishCount++; Log("第", fishCount, "次重新撒网..."); FirstPriceAuto = true; Sleep(1000); } }
|