Bybit 算法接针 - VWAP (BTC)

Author: 扁豆子, Date: 2020-01-26 18:51:44
Tags:

在这里开始分享Bybit原始版本的接针策略~ 主要原因是什么呢/// img

这就很气了不是… 你说好好的开源, 都没有不知道情况下被卖生气… 希望小老哥别在这样了~ 在这里直接开源, 本身也不是什么牛逼的策略…

大家随意玩耍叭~ 不要花钱买我的辣鸡源码了~ 咱直接用!! 走起!!

顺便广告一发~ 更多亏钱攻略请关注公众号 “扁豆子的量化日志” WX: wangxiaoba

(●’◡’●)


// 判断uid权限 (UID list + getAccount uid 校验)
function user_auth() {
    user_list = [775536, 783571, 789086, 819490, 1265698, 1294567, 1299150]
    user_id = account.Info.result[0].user_id
    //Log(user_id)
    if (user_list.indexOf(user_id) == -1) {
        throw new Error('用户认证错误, 请联系微信: wangxiaoba')
    }
}

// 计算获取VWAP及上下边界 Bybit
function VWAP() {
    // 定义K线, 计算VWAP
    if (records.length > 1440) {
        records.splice(0, 1);
    }
    var n = records.length - 1
    //Log(n)
    var total_sum = 0.0
    var volume_sum = 0
    vwap_arr = []
    vwap_up_arr = []
    vwap_dw_arr = []
    for (var i = 0; i < n + 1; i++) {
        var high_price = records[i].High
        //Log("log high_price " + high_price)
        var low_price = records[i].Low
        var close_price = records[i].Close
        //Log("log low_price " + low_price)
        var price = (high_price + low_price + close_price) / 3
        //Log("price", price)
        var volume = records[i].Volume
        //Log("log volume " + volume)
        total_sum += price * volume
        //Log("log total_sum " + total_sum)
        volume_sum += volume
        //Log("log volume_sum " + volume_sum)
        var re = total_sum / volume_sum
        var re_up = re * (1 + long_vwap_offset / 100)
        var re_dw = re * (1 - short_vwap_offset / 100)
        vwap_arr.push(re)
        vwap_up_arr.push(re_up)
        vwap_dw_arr.push(re_dw)
        //return total_sum / volume_sum
    }
    if (vwap_arr.length > 2000) {
        vwap_arr.splice(0, 1);
    }
    if (vwap_up_arr.length > 2000) {
        vwap_up_arr.splice(0, 1);
    }
    if (vwap_dw_arr.length > 2000) {
        vwap_dw_arr.splice(0, 1);
    }
    vwap = vwap_arr[vwap_arr.length - 1]
    vwap_up = vwap_up_arr[vwap_arr.length - 1]
    vwap_dw = vwap_dw_arr[vwap_arr.length - 1]
    //Log("log vwap " + vwap, "log vwap_up " + vwap_up, "log vwap_dw " + vwap_dw)
}

// 画线
function PlotMA_Kline(records, isFirst) {
    $.PlotRecords(records, "K")
    if (isFirst) {
        for (var i = records.length - 1; i >= 0; i--) {
            if (vwap_arr[i] !== null) {
                $.PlotLine("vwap", vwap_arr[i], records[i].Time)
                $.PlotLine("vwap_up", vwap_up_arr[i], records[i].Time)
                $.PlotLine("vwap_dw", vwap_dw_arr[i], records[i].Time)
            }
        }
        PreBarTime = records[records.length - 1].Time
    } else {
        if (PreBarTime !== records[records.length - 1].Time) {
            $.PlotLine("vwap", vwap_arr[vwap_arr.length - 2], records[records.length - 2].Time)
            $.PlotLine("vwap_up", vwap_up_arr[vwap_up_arr.length - 2], records[records.length - 2].Time)
            $.PlotLine("vwap_dw", vwap_dw_arr[vwap_dw_arr.length - 2], records[records.length - 2].Time)
            PreBarTime = records[records.length - 1].Time
        }
        $.PlotLine("vwap", vwap_arr[vwap_arr.length - 1], records[records.length - 1].Time)
        $.PlotLine("vwap_up", vwap_up_arr[vwap_up_arr.length - 1], records[records.length - 1].Time)
        $.PlotLine("vwap_dw", vwap_dw_arr[vwap_dw_arr.length - 1], records[records.length - 1].Time)
    }
}

// 封装下单, 多, 空 Bybit
// 定义Buy
function buy(Price, Amount, dec) {
    exchange.SetDirection("buy");
    var orderId = null;
    orderId = exchange.Buy(Price, Amount, dec, '@');
    while (!orderId && typeof(orderId) != "undefined" && orderId != 0) {
        Log(orderId);
        Sleep(100);
        orderId = exchange.Buy(Price, Amount, dec, '@');

    }
    return orderId;
}

// 定义Sell
function sell(Price, Amount, dec) {
    exchange.SetDirection("sell");
    var orderId = null;
    orderId = exchange.Sell(Price, Amount, dec, '@');
    while (!orderId && typeof(orderId) != "undefined" && orderId != 0) {
        Log(orderId);
        Sleep(100);
        orderId = exchange.Sell(Price, Amount, dec, '@');

    }
    return orderId;
}

// 账户信息
function AccountInfo() {
    // 资产信息表
    var AccountTab = {
        type: "table",
        title: "资产信息",
        cols: ["仓位", "持仓方向", "持仓均价", "当前价格", "爆仓点位", "杠杆倍数", "仓位盈亏", "起始资产值", "总资产", "净资产", "总盈亏"],
        rows: [],
    }
    AccountTab.rows.push([account.Info.result[0].size, CW, account.Info.result[0].entry_price, ticker.Last, account.Info.result[0].liq_price, account.Info.result[0].leverage, account.Info.result[0].unrealised_pnl, start_balance, account.Info.result[0].wallet_balance, jzc, pt])
    LogStatus(_D() + '   STATUS: ' + CW + '\n' +
        '总计可下单量(*杠杆): ' + yue + '\n' +
        'index: ' + index + '\n' +
        'VWAP: ' + vwap + '\n' +
        'VWAP_UP: ' + vwap_up + '\n' +
        'VWAP_DW: ' + vwap_dw + '\n' +
        'N: ' + records.length + '\n' +
        'WX: wangxiaoba' + '\n' +
        '`' + JSON.stringify([AccountTab]) + '`' + '\n');
}

// 状态判断
function Status() {
    if (account.Info.result[0].side === "Buy") {
        status = PD_LONG;
        CW = "LONG";
    } else if (account.Info.result[0].side === "Sell") {
        status = PD_SHORT;
        CW = "SHORT";
    } else {
        status = idle;
        CW = "IDLE";
    }
}

// 追踪止盈 初始%, 追踪U
function TP() {
    var TP_first_long = account.Info.result[0].entry_price + take_profit
    var TP_trailing_long = TP_HH - trailing_profit
    var TP_first_short = account.Info.result[0].entry_price - take_profit
    var TP_trailing_short = TP_LL + trailing_profit
    // 当多仓时, 现价大于开仓+初始止赢价 -> 触发追踪止盈 
    if ((status === PD_LONG) && (ticker.Last > TP_first_long)) {
        // Log('当多仓时, 现价大于开仓+初始止赢价 -> 触发追踪止盈', TP_HH)
        TP_status = true
        // 触发追踪止盈, 未初始化开仓最大价格 -> 开仓后最大价格更新为现价
        if (TP_status === true && TP_HH == 0) {
            Log('触发追踪止盈, 未初始化开仓最大价格 -> 开仓后最大价格更新为现价', TP_HH)
            TP_HH = ticker.Last
        }
        // 触发追踪止盈, 已有开仓后最大价格, 现价大于开仓后最大价格 -> 开仓后最大价格更新为现价
        else if (TP_status === true && TP_HH != 0 && ticker.Last > TP_HH) {
            Log('触发追踪止盈, 已有开仓后最大价格, 现价大于开仓后最大价格 -> 开仓后最大价格更新为现价', TP_HH)
            TP_HH = ticker.Last
        }
        // 触发追踪止盈, 已有开仓后最大价格, 现价小于 (开仓后最大价格减 - 回撤USD) -> 开空平仓止盈
        else if (TP_status === true && TP_HH != 0 && ticker.Last < TP_trailing_long) {
            Log('触发追踪止盈, 已有开仓后最大价格, 现价小于 (开仓后最大价格减 - 回撤USD) -> 开空平仓止盈', TP_HH)
            sell(-1, account.Info.result[0].size, "在" + ticker.Last + "止赢平多仓!! 开仓价格: " + account.Info.result[0].entry_price + "数量: " + account.Info.result[0].size)
            status = idle
            $.PlotFlag(new Date().getTime(), 'Close_Long', 'PT_L')
            TP_status = false
            TP_HH = 0
            LogProfit(pt, pt * ticker.Last)
        }
    }
    // 当空仓时, 现价小于开仓-初始止赢价 -> 触发追踪止盈
    else if ((status === PD_SHORT) && (ticker.Last < TP_first_short)) {
        // Log('当空仓时, 现价小于开仓-初始止赢价 -> 触发追踪止盈', TP_LL)
        TP_status = true
        // 触发追踪止盈, 未初始化开仓最大价格 -> 开仓后最小价格更新为现价
        if (TP_status === true && TP_LL == 0) {
            Log('触发追踪止盈, 未初始化开仓最大价格 -> 开仓后最小价格更新为现价', TP_LL)
            TP_LL = ticker.Last
        }
        // 触发追踪止盈, 已有开仓后最小价格, 现价小于开仓后最小价格 -> 开仓后最小价格更新为现价
        else if (TP_status === true && TP_LL != 0 && ticker.Last < TP_LL) {
            Log('触发追踪止盈, 已有开仓后最小价格, 现价小于开仓后最小价格 -> 开仓后最小价格更新为现价', TP_LL)
            TP_LL = ticker.Last
        }
        // 触发追踪止盈, 已有开仓后最小价格, 现价大于 (开仓后最小价格减 + 回撤USD) -> 开多平仓止盈
        else if (TP_status === true && TP_LL != 0 && ticker.Last > TP_trailing_short) {
            Log('触发追踪止盈, 已有开仓后最小价格, 现价大于 (开仓后最小价格减 + 回撤USD) -> 开多平仓止盈', TP_LL)
            buy(-1, account.Info.result[0].size, "在" + ticker.Last + "止赢平空仓!! 开仓价格: " + account.Info.result[0].entry_price + "数量: " + account.Info.result[0].size)
            status = idle
            $.PlotFlag(new Date().getTime(), 'Close_Short', 'PT_S')
            TP_status = false
            TP_LL = 0
            LogProfit(pt, pt * ticker.Last)
        }
    }
}

// 止损 %
function Stoploss() {
    // 当多仓时, 现价小于开仓-止损价, 做空平多
    if ((status === PD_LONG) && (ticker.Last < account.Info.result[0].entry_price - (ticker.Last * stop_loss / 100))) {
        Log('当多仓时, 现价小于开仓-止损价, 做空平多')
        sell(-1, account.Info.result[0].size, "在" + ticker.Last + "止损平多仓!! 开仓价格: " + account.Info.result[0].entry_price + " 数量: " + account.Info.result[0].size)
        status = idle
        isstoploss = true
        $.PlotFlag(new Date().getTime(), 'Close_Long', 'ST_L')
        LogProfit(pt, pt * ticker.Last)
    }
    // 当空仓时, 现价大于开仓+止损价, 做多平空
    else if ((status === PD_SHORT) && (ticker.Last > account.Info.result[0].entry_price + (ticker.Last * stop_loss / 100))) {
        Log('当空仓时, 现价大于开仓+止损价, 做多平空')
        buy(-1, account.Info.result[0].size, "在" + ticker.Last + "止损平空仓!! 开仓价格: " + account.Info.result[0].entry_price + " 数量: " + account.Info.result[0].size)
        status = idle
        isstoploss = true
        $.PlotFlag(new Date().getTime(), 'Close_Short', 'ST_S')
        LogProfit(pt, pt * ticker.Last)
    }
}

function AtrIndex() {
    if (records && records.length > 14) {
        var atr = TA.ATR(records, 14)
    }
    if (atr && atr.length > 20) {
        var eamatr = TA.EMA(atr, 20)
        // Log(eamatr[eamatr.length - 1])
    }
    if (eamatr){
        var temp = 0
        for(var i=0; i<eamatr.length; i++){
            temp += atr[atr.length - 1]/eamatr[eamatr.length - 1]
        }
    }
    index = _N((temp/eamatr.length), 4)
}


// 计算收益
function PT_log() {
    time = new Date().getTime();
    if (time >= (timep + 7200000)) {
        LogProfit(pt, pt * ticker.Last);
        timep = time;
    }
}


function main() {
    // 初始化参数 
    PreBarTime = 0
    isFirst = true
    exchange.SetMarginLevel(GG)
    exchange.SetContractType('swap');
    _CDelay(100);
    idle = -1;
    status = idle;
    CW = 0;
    timep = 0;
    TP_status = false // 是否触发追踪止盈 
    TP_HH = 0
    TP_LL = 0
    isstoploss = false
    index = 0
    // WS 配置
    var param = {
        "op": "subscribe",
        "args": "liquidation"
    }
    var client = Dial("wss://www.bitmex.com/realtime|reconnect=true&payload=" + JSON.stringify(param), 3800)
    client.write('{"op": "subscribe", "args": "liquidation"}')
    while (1) {
        // 定义基本信息
        account = _C(exchange.GetAccount)
        records_5m = _C(exchange.GetRecords, PERIOD_M5)
        records = _C(exchange.GetRecords, PERIOD_M1)
        ticker = _C(exchange.GetTicker)
        yue = account.Info.result[0].wallet_balance * ticker.Last * GG; // 总可开仓量 (钱包币 x 最新价格 x 杠杆倍数)
        jzc = account.Info.result[0].wallet_balance + account.Info.result[0].unrealised_pnl; // 净资产量 (总资产 - 未结盈亏)
        pt = jzc - start_balance; // 盈利 (净资产 - 初始币量)
        //Log('初始化')
        // 状态判断
        Status()
        //Log('状态判断')
        // 权限验证
        // user_auth()
        //Log('权限验证')
        // 封装指标, 并画K线
        AtrIndex()
        VWAP()
        //Log('指标封装')
        if (records) {
            PlotMA_Kline(records_5m, isFirst)
            //Log('画线')
            isFirst = false
        }
        // 读取WS消息
        bitmexData = client.read(-1)
        obj = null
        //Log('读取WS消息')
        if (bitmexData) {
            obj = JSON.parse(bitmexData)
            //Log('bitmex liquidation Data ', obj)
        }
        //Log('读取WS消息完毕')
        // 下单逻辑!
        // 判断交易对, 及清算值 (BTC>100000, ETH>7500 , EOS?? , XRP??) {"table":"liquidation","action":"insert","data":[{"orderID":"77e987c5-03c2-814e-0fb3-5632f9438f31","symbol":"XBTUSD","side":"Buy","price":9938,"leavesQty":32618}]}
        // 交易对
        if (obj) {
            if (obj.table == "liquidation" && obj.action == "insert" && obj.data[0].symbol == "XBTUSD") {
                // Log('判断交易对')
                // 方向和大小
                // 当清算方向为Buy, 清算量大于10W, 最新价格大于vwap上界时, 小于最大开仓量!! 做空
                if (obj.data[0].side == "Buy" && obj.data[0].leavesQty > 250000 && ticker.Last > vwap_up && account.Info.result[0].size < maxPosition) {
                    Log('判断大小方向, 空')
                    sell(-1, short_qty, "在" + ticker.Last + "- 做空 " + short_qty + "|")
                    $.PlotFlag(new Date().getTime(), 'Sell', 'SK')
                }
                // 当清算方向为Sell, 清算量大于10W, 最新价格小于vwap下界时, 小于最大开仓量!! 做多
                else if (obj.data[0].side == "Sell" && obj.data[0].leavesQty > 250000 && ticker.Last < vwap_dw && account.Info.result[0].size < maxPosition) {
                    Log('判断大小方向, 多')
                    buy(-1, long_qty, "在" + ticker.Last + "- 做多 " + long_qty + "|")
                    $.PlotFlag(new Date().getTime(), 'Buy', 'BK')
                }
            }
        }
        // 止损 
        Stoploss()
        if (isstoploss === true) {
            Log("触发止损, 止损后暂停!! " + stop_step + "s!!!")
            AccountInfo()
            Sleep(stop_step * 1000)
            isstoploss = false
        }
        //Log('止损')
        // 追踪止盈
        TP()
        //Log('追踪止盈')
        // 账户信息更新
        AccountInfo()
        // 间隔时间
        //Log('间隔时间')
        Sleep(600);
    }
}

More

韬奋量化 豆子牛逼

haohao 亏钱策略哈哈

rootme 豆神牛逼

fmzero 豆神牛逼!

中本姜 谢谢豆神!

扁豆子 (^U^)ノ~YO

扁豆子 谢谢二哥!