구매 가격과 판매 가격을 미리 설정하면 전략은 이 두 가격 사이를 연결하여 구매 후 판매, 판매 후 청구서를 연결하여 수익을 계속 순환합니다.
/*backtest start: 2020-05-18 00:00:00 end: 2020-06-16 23:59:00 period: 1h basePeriod: 1h exchanges: [{"eid":"Binance","currency":"BTC_USDT","stocks":0}] */ var order = {buy_price:0,buy_amount:0,buy_id:0,sell_price:0,sell_amount:0,sell_id:0} var account = null var last = 0 var symbol = '' var status = 0 //0:开始挂买单,1:买单成交挂卖单;2:卖单成交挂买单 var log_profit_time = 0 var update_status_time = 0 var update_alpha_time = Date.now() if(exchange.GetName().slice(0,7) == 'Futures'){ throw '此策略只支持现货' } if(_G('symbol')){ symbol = _G('symbol') }else{ symbol = exchange.GetCurrency() _G('symbol', symbol) } if(exchange.GetCurrency() != symbol){ throw '不可更换币种,需要重新建立新机器人' } function GetPrecision(){ if(IsVirtual()){ return {price:6, amount:6} } var precision = {price:0, amount:0} var depth = exchange.GetDepth() if(!depth){ throw '无法连接交易所行情,需要海外托管者' } for(var i=0;i<depth.Asks.length;i++){ var amountPrecision = depth.Asks[i].Amount.toString().indexOf('.') > -1 ? depth.Asks[i].Amount.toString().split('.')[1].length : 0 precision.amount = Math.max(precision.amount,amountPrecision) var pricePrecision = depth.Asks[i].Price.toString().indexOf('.') > -1 ? depth.Asks[i].Price.toString().split('.')[1].length : 0 precision.price = Math.max(precision.price,pricePrecision) } return precision } function updateAccount() { var acc = exchange.GetAccount() if(acc){ if(account && _N(acc.Stocks + acc.FrozenStocks,6) != _N(account.Stocks + account.FrozenStocks,6)){ if(acc.Stocks + acc.FrozenStocks > account.Stocks + account.FrozenStocks){ Log('买单成交:',_N(acc.Stocks + acc.FrozenStocks-account.Stocks - account.FrozenStocks,6), ' 数量变动:', _N(account.Stocks + account.FrozenStocks,6), ' -> ', _N(acc.Stocks + acc.FrozenStocks,6)) } if(acc.Stocks + acc.FrozenStocks < account.Stocks + account.FrozenStocks){ Log('卖单成交:',_N(account.Stocks + account.FrozenStocks - acc.Stocks - acc.FrozenStocks,6),' 数量变动:', _N(account.Stocks + account.FrozenStocks,6), ' -> ', _N(acc.Stocks + acc.FrozenStocks,6)) } } account = acc }else{ Log('获取账户信息出错') } } function updateTicker(){ var ticker = exchange.GetTicker() if(ticker){ last = ticker.Last }else{ Log('获取行情出错') } } function cancelAll(){ Log('撤销所有订单') var orders = exchange.GetOrders() if(!orders){ Log('获取订单失败') } for(var j=0; j<orders.length; j++){ exchange.CancelOrder(orders[j].Id) Sleep(10) } } cancelAll() last = exchange.GetTicker().Last updateAccount() var precision = GetPrecision() var init_value = 0 var init_account = {balance:0, amount:0} if(_G('init_value')){ init_value = _G('init_value') init_account = _G('init_account') }else{ init_value = _N(account.Balance+account.FrozenBalance+(account.Stocks+account.FrozenStocks)*last, 6) init_account = {balance:account.Balance+account.FrozenBalance, amount:account.Stocks+account.FrozenStocks} Log('第一次启动策略, 始总价值为: ', init_value) _G('init_value', init_value) _G('init_account', init_account) } function trade(direction, price, value, msg){ if(price <= 0){return} var amount = _N(value/price, precision.amount) var new_order = true order[direction+'_price'] = price if(new_order){ if(order[direction+'_id']){ exchange.CancelOrder(order[direction+'_id']) order[direction+'_price'] = 0 order[direction+'_id'] = 0 } var id =null if(direction == 'buy'){ if(account.Balance < 1*value){ Log('资金不足, 无法挂买单, 等待卖出') }else{ id = exchange.Buy(price, amount, msg) } } if(direction == 'sell'){ if(account.Stocks < 1*amount){ Log('余币不足, 无法挂卖单,等待买入') }else{ id = exchange.Sell(price, amount, msg) } } order[direction+'_id'] = id order[direction+'_price'] = price } } function updateStatus(){ if(Date.now()-update_status_time < 4000){ return } update_status_time = Date.now() var now_value = (account.Stocks+account.FrozenStocks)*last + account.Balance+account.FrozenBalance var profit = _N( now_value - init_account.amount*last - init_account.balance, 6) var table = { type: 'table', title: '账户信息', cols: ['初始币', '初始资金', '当前币', '当前资金', '买单价格', '卖单价格', '现价', '初始市值', '当前市值', '收益'], rows: [[_N(init_account.amount,6), _N(init_account.balance,6), _N(account.Stocks+account.FrozenStocks,6), _N(account.Balance+account.FrozenBalance,6), order.buy_price, order.sell_price, _N(last,6), _N(init_value,6), _N(now_value,6), _N(profit,6)]] } var logString = _D()+' 策略代码最后更新时间6月10日 14:00\n' LogStatus(logString + '`' + JSON.stringify(table) + '`'+'\n') var log_profit_intervel = IsVirtual() ? 12*60*60*1000 : Log_profit if(Date.now()-log_profit_time > log_profit_intervel){ LogProfit(_N((account.Stocks+account.FrozenStocks)*last + account.Balance+account.FrozenBalance - init_account.amount*last - init_account.balance, 6)) log_profit_time = Date.now() } } function onTick(){ if(last == 0){return} //0:开始挂买单,1:买单成交挂卖单;2:卖单成交挂买单 var buy_price = _N(Buy_price, precision.price) var sell_price = _N(Sell_price, precision.price) if(status == 0 && !order.buy_id){ trade('buy', buy_price, Amount*buy_price, '挂买单') } if(order.buy_id && status == 0 ){ var buy_order = exchange.GetOrder(order.buy_id) if(buy_order && buy_order.Status == ORDER_STATE_CLOSED){ status = 1 order.buy_id = 0 order.buy_price = 0 } } if(status == 1 && !order.sell_id){ trade('sell', sell_price, Amount*sell_price, '买单成交挂卖单') } if(status == 1 && order.sell_id){ var sell_order = exchange.GetOrder(order.sell_id) if(sell_order && sell_order.Status == ORDER_STATE_CLOSED){ status = 0 order.sell_id = 0 order.sell_price = 0 } } } function onexit(){ cancelAll() } function main() { while(true){ updateTicker() updateAccount() onTick() updateStatus() if(!IsVirtual()){ Sleep(Intervel) } } }