Binance Sustainable Multicurrency Hedging Strategy (Do or Do Multi-Currency Index) 10 April Improved Bug, needs to be updated

Author: The grass, Date: 2020-04-03 11:12:31
Tags: Binance

This is important!

  • I'm sure you'll want to read this study first.https://www.fmz.com/digest-topic/5294■ Understand a range of issues such as strategy principles, risks, how to screen trades, how to set parameters, opening positions and the ratio of total capital.
  • The previous research report needs to be downloaded and uploaded to your own research environment. The actual modification runs again. If you have read this report, you have recently updated the latest week's data.
  • The strategy cannot be directly retested, it needs to be retested in the research environment.
  • The policy code and the default parameters are for research purposes only, and real-time operation requires caution.The risks
  • The strategy cannot be profitable every day, you can look back at the history, 1-2 weeks of crossovers and pullbacks are normal, and there is a possibility of a big pullback, which needs to be treated correctly.
  • The code is open, you can modify it yourself, if there are any problems, welcome feedback, it is best to join the Inventor Binance community (there is a method to join the research report) to get updates
  • The strategy needs to run in full-stock mode, without setting up bidirectional holdings, the strategy only supports binary options futures, the robot can be created with default trading pairs and K-line cycles, the strategy does not use K-line.
  • Tactics and other tactics, as well as manual operations, are in conflict and need to be taken into account.
  • In the test phase, you can rent Ali Cloud Hong Kong servers on the platform with one click, and rent them yourself by the month is cheaper ((the minimum configuration is available, deploy the tutorial:https://www.fmz.com/bbs-topic/2848 )
  • Binance futures and spot currency need to be added separately, Binance futures areFutures_Binance

The Principles of Strategy

The strategy is to spread the equivalent value as a basket of selected tokens, while the equivalent position as a bitcoin hedge, reducing risk and volatility. As the price fluctuates, constantly adjust the position to keep the value of the empty position constant and the multi-head position equivalent.Bitcoin price index is basically a time-lapse.The last two months' performance (leverage around 3x, data updated to 4.8) shows that the crypto has been up against bitcoin in the last week, so the loss, if you look at the multi-coin, can be set in the parameters to do nothing with bitcoin:

The default strategy is to do more bitcoins and do a dummy coin, you can also do the opposite (if you think the dummy is at the bottom) and decide for yourself.

img

Strategic logic

1. Updated market and account holdings 2. Update the value of each coin's short position to determine if the short position needs to be adjusted 3. update the position of the total empty position, determine the multi-head holding and decide whether to adjust the multi-head position 4. The order and quantity of the order will be determined by the Ice Mountain commission, according to the transaction price of the counterparty (buy and sell at the same price).The following order is immediately canceled (so you'll see a lot of unsuccessful canceled cells 400: {code:-2011,msg:Unknown order sent.}, normal phenomenon) 5.再次循环

Short_symbols, Long_symbols, and Long_symbols are used to determine the trade value of each currency in which more or less of the transaction pairs are traded, and the contract value of each currency in which less of the transaction pairs is the average of the hedge value.

If only empty BTC, plus TRX, DASH, ONT, QTUM, and Trade_value is 50, then TRX, DASH, ONT, and QTUM all have multiple positions of 50, and BTC holds 50*4 positions.

If there is only one BTC, empty TRX, DASH, ONT, QTUM, and trade_value is 50, then TRX, DASH, ONT, QTUM all have 50 empty positions, and BTC holds more than 50*4 positions.

Leverage in the status bar represents the collateral has been used proportionally, and should not be too high.

Policy parameters

img

  • Short_symbols: Empty coin, separated by a hyphen
  • Long_symbols: Multiple coins, can also be left blank, unhedged, straight blank.
  • Trade_value: The value of a single currency is unchanged. You also need to hedge multiple times, the total value = 2*Trade_value* is unchanged. Generally, leverage is used 3-5 times, i.e. total value = 3* account balance.
  • Adjust_value: The value of the contract (USDT pricing) is adjusted to the deviation value, too much adjustment is slower, too little processing fee is too high, as determined by Trade_value; it cannot be lower than 20, otherwise it will not reach the minimum transaction.
  • Ice_value: Iceberg delegated value, also cannot be less than 20, actually select the smaller of Adjust_value and Ice_value

Strategic risks

When the price of the empty coin rises, the value of the contract increases, at which point it is undervalued, and the profit is raised. This keeps the total contract value constant. It is very likely that the coin will come out of the independent market, and currently from a one-year cycle, the coin may be at the bottom, and it is likely to rise a lot from the bottom.


if(IsVirtual()){
    throw '不能回测,回测参考 https://www.fmz.com/digest-topic/5294 '
}
if(exchange.GetName() != 'Futures_Binance'){
    throw '只支持币安期货交易所,和现货交易所不同,需要单独添加,名称为Futures_Binance'
}

var short_symbols = Short_symbols.split(',')
var long_symbols = Long_symbols.split(',')

if(short_symbols.length == 1 && short_symbols[0] == ''){
    short_symbols = []
}
if(long_symbols.length == 1 && long_symbols[0] == ''){
    long_symbols = []
}
var symbols = []
for(var i=0; i<short_symbols.length; i++){
    if(short_symbols[i]){
        symbols.push(short_symbols[i])
    }
}
for(var i=0; i<long_symbols.length; i++){
    if(long_symbols[i]){
        symbols.push(long_symbols[i])
    }
}
var update_profit_time = 0
var assets = {}
var trade_info = {}
var exchange_info = HttpQuery('https://fapi.binance.com/fapi/v1/exchangeInfo')
if(!exchange_info){
    throw '无法连接币安网络,需要海外托管者'
}
exchange_info = JSON.parse(exchange_info)
for (var i=0; i<exchange_info.symbols.length; i++){
    if(symbols.indexOf(exchange_info.symbols[i].baseAsset) > -1){
       assets[exchange_info.symbols[i].baseAsset] = {amount:0, hold_price:0, value:0, bid_price:0, ask_price:0, realised_profit:0, margin:0, unrealised_profit:0}
       trade_info[exchange_info.symbols[i].baseAsset] = {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))))
                                                        }
    }
}
assets.USDT = {unrealised_profit:0, margin:0, margin_balance:0, total_balance:0, leverage:0}


function updateAccount(){
    var account = exchange.GetAccount()
    var pos = exchange.GetPosition()
    if (account == null || pos == null ){
        Log('update account time out')
        return
    }
    assets.USDT.update_time = Date.now()
    for(var i=0; i<symbols.length; i++){
        assets[symbols[i]].margin = 0
        assets[symbols[i]].unrealised_profit = 0
        assets[symbols[i]].hold_price = 0
        assets[symbols[i]].amount = 0
        assets[symbols[i]].unrealised_profit = 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(symbols.indexOf(coin) < 0){continue}
            assets[coin].margin = parseFloat(account.Info.positions[j].initialMargin) + parseFloat(account.Info.positions[j].maintMargin)
            assets[coin].unrealised_profit = parseFloat(account.Info.positions[j].unrealizedProfit)
        }
    }
    assets.USDT.margin = _N(parseFloat(account.Info.totalInitialMargin) + parseFloat(account.Info.totalMaintMargin),2)
    assets.USDT.margin_balance = _N(parseFloat(account.Info.totalMarginBalance),2)
    assets.USDT.total_balance = _N(parseFloat(account.Info.totalWalletBalance),2)
    assets.USDT.unrealised_profit = _N(parseFloat(account.Info.totalUnrealizedProfit),2)
    assets.USDT.leverage = _N(assets.USDT.margin/assets.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(symbols.indexOf(coin) < 0){continue}
            assets[coin].hold_price = parseFloat(pos[k].entryPrice)
            assets[coin].amount = parseFloat(pos[k].positionAmt)
            assets[coin].unrealised_profit = parseFloat(pos[k].unRealizedProfit)
        }
    }
}

function updateTick(){
    var ticker = HttpQuery('https://fapi.binance.com/fapi/v1/ticker/bookTicker')
    if(ticker == null){
        Log('get ticker time out')
        return
    }
    ticker = JSON.parse(ticker)
    for(var i=0; i<ticker.length; i++){
        var pair = ticker[i].symbol 
        var coin = pair.slice(0,pair.length-4)
        if(symbols.indexOf(coin) < 0){continue}
        assets[coin].ask_price = parseFloat(ticker[i].askPrice)
        assets[coin].bid_price = parseFloat(ticker[i].bidPrice)
        assets[coin].ask_value = _N(assets[coin].amount*assets[coin].ask_price, 2)
        assets[coin].bid_value = _N(assets[coin].amount*assets[coin].bid_price, 2)
    }
}

function trade(symbol, dirction, value){
    if(Date.now()-assets.USDT.update_time > 10*1000){
        Log('更新账户延时,不交易')
        return
    }
    var price = dirction == 'sell' ? assets[symbol].bid_price : assets[symbol].ask_price
    var amount = _N(Math.min(value,Ice_value)/price, trade_info[symbol].amountSize)
    if(amount < trade_info[symbol].minQty){
        Log(symbol, '合约调整偏离价值或冰山委托订单设置过小,达不到最小成交, 至少需要: ', _N(trade_info[symbol].minQty*price,0))
        return
    }
    exchange.IO("currency", symbol+'_'+'USDT')
    exchange.SetContractType('swap')
    exchange.SetDirection(dirction)
    var f = dirction == 'buy' ? 'Buy' : 'Sell'
    var id = exchange[f](price, amount, symbol)
    if(id){
        exchange.CancelOrder(id) //订单会立即撤销
    }
}



function updateStatus(){
        var table = {type: 'table', title: '交易对信息', 
             cols: ['币种', '数量', '持仓价格', '当前价格', '持仓价值', '保证金', '未实现盈亏'],
             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)
        var value = _N((assets[symbols[i]].ask_value + assets[symbols[i]].bid_value)/2, 2)
        var infoList = [symbols[i], assets[symbols[i]].amount, assets[symbols[i]].hold_price, price, value,_N(assets[symbols[i]].margin,3), _N(assets[symbols[i]].unrealised_profit,3)]
        table.rows.push(infoList)
    }
    var logString = _D() + '  ' + JSON.stringify(assets.USDT) + '\n'
    LogStatus(logString + '`' + JSON.stringify(table) + '`')
    
    if(Date.now()-update_profit_time > Log_profit_interval*1000){
        LogProfit(_N(assets.USDT.margin_balance,3))
        update_profit_time = Date.now()
    }
    
}

function onTick(){
    var short_value = Trade_value
    if(short_symbols.length<long_symbols.length){
        short_value = _N(long_symbols.length*Trade_value/short_symbols.length,0)
    }
    var long_value = Trade_value
    if(short_symbols.length>long_symbols.length){
        long_value = _N(short_symbols.length*Trade_value/long_symbols.length,0)
    }
    var symbol = ''
    for(var i=0; i<short_symbols.length; i++){
        symbol = short_symbols[i]
        if(assets[symbol].ask_price == 0){ continue }
        if(assets[symbol].bid_value + short_value > Adjust_value){
            trade(symbol, 'sell', assets[symbol].bid_value + short_value)
        }
        if(assets[symbol].ask_value + short_value < -Adjust_value){
            trade(symbol, 'buy', -(assets[symbol].ask_value + short_value))
        }
    }
    for(var i=0; i<long_symbols.length; i++){
        symbol = long_symbols[i]
        if(assets[symbol].ask_price == 0){ continue }
        if(assets[symbol].bid_value - long_value > Adjust_value){
            trade(symbol, 'sell', assets[symbol].bid_value-long_value)
        }
        if(assets[symbol].ask_value - long_value < -Adjust_value){
            trade(symbol, 'buy', long_value-assets[symbol].ask_value)
        }
    }   
}

function main() {
    while(true){
        updateAccount()
        updateTick()
        onTick()
        updateStatus()
        Sleep(Interval*1000)
    }
}

Related

More

Oh, my God.Is it a flat rate or a market price?

wfwfaf1updateAccount (()) is required if ((pair.slice ((pair.length-4, pair.length) == "USDT")) Since there is a busd contract, it is necessary to decide whether the position is a target contract when updating the holding information. Otherwise, multiple positions will be confused, leading to unlimited orders.