Two platforms hedging-JS

Author: 7meter, Date: 2017-10-18 11:15:58
Tags: Hedge


function cancelAll(){
    var ref = false;
    for(var e in exchanges){
        while(true){
            var n = 0;
            var my_orders = _C(exchanges[e].GetOrders);
            for(var order1 in my_orders){
                ref = true;
                e.CancelOrder(my_orders[order1].Id);
                n += 1;
            }
            if(n==0){
                break;
            }
        }
    }
    return ref;
}

function main(){
    if(exchanges.length != 2){
        throw("Only two exchanges are supported");
    }

    LogReset();
    LogProfitReset();
    cancelAll();

    var initStocks = 0.0;
    var initBalance = 0.0;
    var minAmount = 0.1;
    var lastTradeTime = 0;
    var lastTradeErrExchange = '';
    var accountsCache = [];
    var hedgeNum = [0, 0];
    var names = [];
    var baseCurrency = exchange.GetCurrency();
    for(var e in exchanges){
        if(exchanges[e].GetCurrency() != baseCurrency){
            throw("It has to be the same currency to hedge:"+baseCurrency);
        }
        names.push(exchanges[e].GetName());
        var account = _C(exchanges[e].GetAccount);
        accountsCache.push(account);
        initStocks += account.Stocks;
        initBalance += account.Balance;
    }
    if(baseCurrency == "BTC"){
        minAmount = 0.01
    } else {
        minAmount = 0.1
    }
    
    Log("all balance:", _N(initBalance), "all stocks", _N(initStocks))
    while(true){
        if(accountsCache.length <= 0){
            for(var e in exchanges){
                var account1 = _C(exchanges[e].GetAccount);
                accountsCache.push(account1);
            }
        }
        Sleep(LoopInterval);
        cmd = GetCommand();
        if(cmd){
            Log("CMD", cmd);
            var arr = cmd.split(":");
            if(arr[0]=="A->B"){
                MinSpreadA = parseFloat(arr[1]);
            } else if(arr[0]=="B->A"){
                MinSpreadB = parseFloat(arr[1]);
            }
        }
        var depthA = exchanges[0].GetDepth();
        if (!depthA){
            continue;
        }
        var depthB = exchanges[1].GetDepth();
        if (!depthB){
            continue;
        }
        var time = new Date();
        if(lastTradeTime > 0 && time.getTime() - lastTradeTime > BalanceTime){
            var needUpdate = cancelAll();
            if (!needUpdate){
                for(var account2 in accountsCache){
                    if(accountsCache[account2].FrozenBalance >= 0.1 || accountsCache[account2].FrozenStocks >= 0.001){
                        needUpdate = true;
                        break;
                    }
                }
            }
            if (needUpdate){
                for(var k in exchanges){
                    account3 = _C(exchanges[k].GetAccount);
                    accountsCache.push(account3);
                }
            }
            var nowStocks = 0.0;
            var nowBalance = 0.0;
            for(var account4 in accountsCache){
                nowBalance += accountsCache[account4].Balance;
                nowStocks += accountsCache[account4].Stocks;
            }
            var diff = _N(nowStocks-initStocks, 5);
            var isReverse;
            if(Math.abs(diff) < minAmount){
                LogProfit(_N(nowBalance-initBalance, 3), "all balance", _N(nowBalance), "all stocks", _N(nowStocks), "stock offset:", diff);
                lastTradeTime = 0;
            } else if(diff > minAmount){
                isReverse = depthA.Bids[0].Price < depthB.Bids[0].Price;
            } else if(-diff > minAmount){
                isReverse = depthA.Asks[0].Price > depthB.Asks[0].Price;
            }
            if(isReverse != null){
                var depths = [depthA, depthB];
                var opAmount;
                var kk;
                if(isReverse){
                    kk = [1, 0];
                } else{
                    kk = [0, 1];
                }
                for(var pos in kk){
                    if(diff > minAmount){
                        opAmount = Math.min(diff, accountsCache[pos].Stocks, depths[pos].Bids[0].Amount + depths[pos].Bids[1].Amount);
                        diff = -opAmount;
                        if(opAmount >= minAmount){
                            exchanges[pos].Sell(depths[pos].Bids[1].Price, opAmount);
                        }
                    } else if(-diff >= minAmount){
                        opAmount = Math.min(-diff, _N(accountsCache[pos].Balance / depths[pos].Asks[1].Price, 3), depths[pos].Asks[0].Amount + depths[pos].Asks[1].Amount);
                        diff += opAmount;
                        if (opAmount >= minAmount){
                            exchanges[pos].Buy(depths[pos].Asks[1].Price, opAmount);
                        }
                    }
                }
                if (opAmount != undefined){
                    var time1 = new Date();
                    lastTradeTime = time1.getTime();
                    accountsCache = [];
                }
            }
            continue;
        }
        var diffA = _N(depthA.Bids[0].Price - depthB.Asks[0].Price, 3)
        var diffB = _N(depthB.Bids[0].Price - depthA.Asks[0].Price, 3)
        LogStatus(JSON.stringify({type: 'table', title: 'status', cols: ['name', 'money', 'frozenmoney', 'stock', 'frozenstock', 'buyone', 'sellone', 'threshold', 'offset', 'num of times'], rows: [[names[0], accountsCache[0].Balance, accountsCache[0].FrozenBalance, accountsCache[0].Stocks, accountsCache[0].FrozenStocks, depthA.Bids[0].Price, depthA.Asks[0].Price, MinSpreadA, diffA, hedgeNum[0]], [names[1], accountsCache[1].Balance, accountsCache[1].FrozenBalance, accountsCache[1].Stocks, accountsCache[1].FrozenStocks, depthB.Bids[0].Price, depthB.Asks[0].Price, MinSpreadB, diffB, hedgeNum[0]]]}));
        HPos = 0;
        if (diffA >= MinSpreadA){
            orderH = depthA.Bids[0];
            orderL = depthB.Asks[0];
            exchangeH = 0;
            exchangeL = 1;
            accountH = accountsCache[0];
            accountL = accountsCache[1];
        }
        else if (diffB >= MinSpreadB){
            HPos = 1;
            orderH = depthB.Bids[0];
            orderL = depthA.Asks[0];
            exchangeH = 1;
            exchangeL = 0;
            accountH = accountsCache[1];
            accountL = accountsCache[0];
        }
        else{
            continue;
        }
        
        var opPrice = _N((orderH.Price + orderL.Price) / 2.0, 2);
        var opAmount = Math.min(MaxAmount, orderH.Amount, orderL.Amount, accountH.Stocks, _N(accountL.Balance / opPrice, 3));
        if(opAmount >= minAmount){
            var tasks = [[exchangeH, "H"], [exchangeL, "L"]];
            if(lastTradeErrExchange == "L"){
                tasks.reverse();
            }
            lastTradeErrExchange = "";
            for(var task in tasks){
                if(tasks[task][1] == "H"){
                    var id = exchanges[tasks[task][0]].Sell(opPrice, opAmount);
                    if(id == undefined){
                        lastTradeErrExchange = tasks[task][1];
                        break;
                    }
                }
                if(tasks[task][1] == "L"){
                    var id = exchanges[tasks[task][0]].Buy(opPrice, opAmount);
                    if(id == undefined){
                        lastTradeErrExchange = tasks[task][1];
                        break;
                    }
                }
            }
            
            var time = new Date();
            lastTradeTime = time.getTime();
            accountsCache = []
            hedgeNum[HPos] += 1
        }
    }
}

Related

More

dyhhuSo if this is unbalanced, is it going to be necessary to adjust the spread, tending to balance the spread?

bijiasuoIf the test is not effective, is the spread going to change?

7meterCorrected

m0606So the ref on line 17 is written as ret.