Установите лимит капитала для инвестирования, например, 10000 юаней. Установите соотношение стоимости капитала и биткойна, например, 50:50.
Например, если начальный капитал составляет 10000 долларов США, то соотношение средств к биткоину должно быть 30:70, а при первой сделке купить 7000 долларов США (предположим, что цена монеты 1000 долларов США, купить 7 монет), а остаток - 3000 долларов США, соотношение должно быть 30:70.
В следующем цикле торговли, предположим, цена монеты изменится до 1500 юаней, и общая стоимость изменится до 1500 юаней.7 + 3000 = 13500, и вы должны сохранить 13500.0.3 = 4050 юаней, то следует продать 4050 - 3000 = 1050 биткойнов, количество проданных - 1050/1500 = 0.7, оставшиеся в руке биткоины - 7-0.7 = 6.3, стоимость монеты - 6.3 * 1500 = 9450;; соотношение средств к стоимости биткойнов - 4050:9450 = 30:70;;
В то же время, когда цена падает, покупатели покупают, чтобы сохранить пропорциональность.
var initAccount = null; var initPrice = 0; var stockHold = 0; var moneyHold = 0; var lastOrderID = null; var prices = []; function AdjustFloat(v) { return Math.floor(v * 1000) / 1000; } function GetAccount() { var account = null; while (!(account = exchange.GetAccount())) { Log('Get Account Error'); Sleep(ErrorInterval); } return account; } function GetCurrentPrice() { var ticker = null; while (!(ticker = exchange.GetTicker())) { Log('Get Ticker Error'); Sleep(ErrorInterval); } return AdjustFloat(ticker.Last); } function GetOrders() { var orders = null; while (!(orders = exchange.GetOrders())) { Log('Get Orders Error'); Sleep(ErrorInterval); } return orders; } function CancelPendingOrders() { while (true) { var orders = GetOrders(); if (orders.length === 0) { return; } for (var i = 0; i < orders.length; i++) { exchange.CancelOrder(orders[i].Id); if (i < (orders.length - 1)) { Sleep(ErrorInterval); } } } } function GetStatus() { var price = GetCurrentPrice(); var initStockValue = InitStock + InitMoney / initPrice; var initMoneyValue = InitMoney + InitStock * initPrice; var stockValueNow = stockHold + moneyHold / price; var moneyValueNow = stockHold * price + moneyHold; var stockEarned = stockValueNow - initStockValue; var moneyEarned = moneyValueNow - initMoneyValue; var averagePrice = 0; var alpha = (stockHold - InitStock) * (price - initPrice); var beta = moneyEarned - alpha; var sum = 0; if (prices.length > 0) { for (var i = prices.length - 1; i >= 0; i--) { sum += prices[i]; } averagePrice = sum / prices.length; } var logString = 'Stock Holding:' + AdjustFloat(stockHold) + '\n'; logString += 'Money Holding:' + AdjustFloat(moneyHold) + '\n'; logString += 'Stock Earned:' + AdjustFloat(stockEarned) + '\n'; logString += 'Money Earned:' + AdjustFloat(moneyEarned) + '\n'; logString += 'History Average price:' + averagePrice + '\n'; logString += 'Current Price:' + price + '\n'; logString += 'Alpha:' + alpha + '\n'; logString += 'Beta:' + beta; LogProfit(moneyEarned); return logString; } function CaculateHoldings() { CancelPendingOrders(); if (lastOrderID) { var order = exchange.GetOrder(lastOrderID); Log('last order:', order); if (order.Status === ORDER_STATE_CLOSED) { if (order.Type === ORDER_TYPE_BUY) { //Buy stockHold += order.DealAmount; moneyHold -= order.DealAmount * order.Price; Log("Order Buy. stockHold +=:", order.DealAmount, ',Money -=:', order.DealAmount * order.Price); } else { //Sell stockHold -= order.DealAmount; moneyHold += order.DealAmount * order.Price; Log("Order Sell. stockHold -=:", order.DealAmount, ',Money +=:', order.DealAmount * order.Price); } } } } function OnTick() { var currentPrice = GetCurrentPrice(); prices.push(currentPrice); //Log('History prices:',prices); var stockValue = 0; var totalValue = 0; var ratio = 0; stockValue = stockHold * currentPrice; totalValue = stockValue + moneyHold; ratio = stockValue / totalValue; Log('Current Price:', currentPrice); Log('stockHold:', stockHold); Log('moneyHold:', moneyHold); Log('stockValue:', stockValue); Log('Current Ratio:', ratio); if (ratio > StockRatio) { //Sell Log('Current ratio > StockRatio'); var sellAmt = (stockValue - totalValue * StockRatio) / (currentPrice - SlidePrice); lastOrderID = exchange.Sell(currentPrice - SlidePrice, sellAmt); } else { //Buy Log('Current ratio < StockRatio'); var buyAmt = (totalValue * StockRatio - stockValue) / (currentPrice + SlidePrice); lastOrderID = exchange.Buy(currentPrice + SlidePrice, buyAmt); } Log('Order ID:', lastOrderID); CaculateHoldings(); } function main() { if (InitStock < 0) { Log('Stock less than zero.'); return; } if (InitMoney < 0) { Log('Money less than zero.'); } //if(InvestInterval < 0){ // Log('InvestInterval less than zero.'); //} if (ErrorInterval < 0) { Log('ErrorInterval less than zero.'); } if (StockRatio < 0 || StockRatio > 1) { Log('StockRatio should be a number from 0 to 1.'); } EnableLogLocal(true); SetFailover(true); exchange.IO("websocket"); Log(exchange.GetName(), exchange.GetCurrency()); initAccount = _G('InitAccount'); if (initAccount === null) { initAccount = GetAccount(); _G('InitAccount', initAccount); } Log('InitAccount', initAccount); initPrice = _G('InitPrice'); if (initPrice === null) { initPrice = GetCurrentPrice(); _G('InitPrice', initPrice); } Log('InitPrice', initPrice); if (UseAccount) { InitMoney = initAccount.Balance + initAccount.FrozenBalance; InitStock = initAccount.Stocks + initAccount.FrozenStocks; } Log('InitMoney:', InitMoney); Log('InitStock:', InitStock); stockHold = _G('StockHold'); if (stockHold === null) { stockHold = InitStock; Log('Set Stock Hold', stockHold); } moneyHold = _G('MoneyHold'); if (moneyHold === null) { moneyHold = InitMoney; Log('Set Money Hold', moneyHold); } if (_G('Prices') !== null) { prices = _G('Prices'); } while (true) { OnTick(); LogStatus(GetStatus()); Sleep(InvestInterval * 1000 * 60); } } function onexit() { _G('StockHold', stockHold); _G('MoneyHold', moneyHold); //_G('Prices',prices); Log('Set Stock Hold', stockHold); Log('Set Money Hold', moneyHold); Log('Set prices:', prices); Log('Robot Stopped!#ff0000@'); }