TradingView策略信号下单机器人-欧易版

Author: 高频量化, Date: 2022-08-22 22:09:44
Tags:


/*
- 交互命令字符串格式
  action:amount
  action: buy , sell , long , short , cover_long , cover_short, spk , bpk
- 交易所类型
  eType变量取值: 0 spot , 1 futures

- TV文档链接
  https://www.tradingview.com/pine-script-docs/en/v4/Quickstart_guide.html
  https://cn.tradingview.com/chart/8xfTuX7F/

- TV webhook 发送请求
  https://www.fmz.com/api/v1?access_key=xxx&secret_key=yyyy&method=CommandRobot&args=[186515,"action:amount"]

- 引用类库
  引用数字货币交易类库
*/

// 参数
//var IsMarketOrder = true 
var QuotePrecision = 3
var BasePrecision = 3

// 期货参数
var Ct = "swap"
//exchange.SetContractType("swap")        // 设置为永续合约
//exchange.SetCurrency("BTC_USDT")

// 全局变量
var BUY = "buy"
var SELL = "sell"
var LONG = "long"
var SHORT = "short"
var COVER_LONG = "cover_long"
var COVER_SHORT = "cover_short"
var SPK = "spk"
var BPK = "bpk"


//------------------- 添加
const accountInformation = { //账号信息
    type: 'table',
    title: '账号信息',
    cols: ['初始余额', '钱包余额 ', '保证金余额', '可用保证金', '已用保证金', '总收益', '收益率'], //列表头
    rows: null //列表数组   
};

const binanceFundingRate = { //持仓单数组
    type: 'table',
    title: 'OKexU本位持仓单',
    cols: ['交易对', '交易方向 ', '开仓量', '开仓价格', '持仓价值', '杠杆', '占用保证金', '持仓盈利'], //列表头
    rows: null //列表数组
};


initialPrincipalUsdt = null //初始本金/usdt
revenueUsdt = 0 //曲线


//--------------------------------------
//账号信息
//--------------------------------------
function accountInformationfunction() {
    exchange.SetContractType("swap"); // 设置为永续合约 swap / quarter/
    var Currency = exchange.GetCurrency()
    exchange.SetCurrency(Currency) //切换产品访问的是U本位的账号信息
    var account = _C(exchange.GetAccount)

    _CDelay(2000 * 60)
    if (!account) {
        Log("没有获取资产")
        return
    }
    
    if (initialPrincipalUsdt==null ) {
        initialPrincipalUsdt = account.Info.data[0].totalEq //获取加载的时候,净值记录为开始余额
        _G("initialPrincipalUsdt", initialPrincipalUsdt) //获取保存的数据
        if (initialPrincipalUsdt == 0) {
            Log("USDT合约中没有资产")
            return
        }
    }
    /*API okx
uTime	String	账户信息的更新时间,Unix时间戳的毫秒数格式,如 1597026383085
totalEq	String	美金层面权益
isoEq	String	美金层面逐仓仓位权益
适用于单币种保证金模式和跨币种保证金模式和组合保证金模式
adjEq	String	美金层面有效保证金
适用于跨币种保证金模式和组合保证金模式
ordFroz	String	美金层面全仓挂单占用保证金
适用于跨币种保证金模式和组合保证金模式
imr	String	美金层面占用保证金
适用于跨币种保证金模式和组合保证金模式
mmr	String	美金层面维持保证金
适用于跨币种保证金模式和组合保证金模式
mgnRatio	String	美金层面保证金率
适用于跨币种保证金模式 和组合保证金模式
notionalUsd	String	以美金价值为单位的持仓数量,即仓位美金价值
适用于跨币种保证金模式和组合保证金模式
    */

    InitialBalance = Number(initialPrincipalUsdt)
    WalletBalance = account.Info.data[0].totalEq
    marginBalance = account.Info.data[0].isoEq
    FreeMargin = account.Info.data[0].isoEq
    UsedMargin = account.Info.data[0].isoEq
   
    TotalRevenue = Number(WalletBalance) - Number(InitialBalance)
    Yield1 = TotalRevenue / InitialBalance
    yield1 = Number(Yield1)
    Yield = (yield1 * 100).toFixed(2) + "%"
    //封装在数组中
    revenueUsdt = Number(TotalRevenue)

    accountInformation.rows = [] //置空
                                 //'初始余额',  '钱包余额 ',  '保证金余额', '可用保证金', '已用保证金', '总收益', '收益率'
    accountInformation.rows[0] = [InitialBalance, WalletBalance, marginBalance, FreeMargin, UsedMargin, TotalRevenue, Yield]

}

//--------------------------------------
//持仓单数组
//--------------------------------------
function binanceFundingRatefunction() { //持仓单数组
    binanceFundingRate.rows = []
    exchange.SetContractType("swap"); // 设置为永续合约,注意币本位和USDT本位都存在永续
    var y = 0 //判断没有改产品也可以

    for (var i = 0; i < exchanges.length; i++) {
        exchange.SetCurrency(exchanges[i].GetCurrency()) //切换产品
        //-------------------------------------------------------
        var position = _C(exchange.GetPosition) //获取账号持仓情况
       // Log("position", position)
        _CDelay(1000 * 2 * 60)
        //币本位不一样的跨期合约放在一个数组。永续与之不一样
        if (position) {
            for (var iii = 0; iii < position.length; iii++) {
                if (exchange.GetContractType() == position[iii].ContractType) { //为什么要判断,因为跨期合约的持仓,都放在一起了
                //   ['交易对', '交易方向 ', '开仓量', '开仓价格', '持仓价值', '杠杆', '占用保证金', '持仓盈利'], //列表头
                    binanceFundingRate.rows[y] = [position[iii].Info.instId, position[iii].Type == 0 ? "BUY" : "SELL", position[iii].Amount,
                                                  position[iii].Price, position[iii].Amount * position[iii].Price,
                                                  position[iii].MarginLevel, position[iii].Margin, position[iii].Profit
                                                  ]
                                                   y++
                }
            }
        }

    }

}


//--------------------------------------
//主函数
//--------------------------------------

function main() {
    // 清空日志,如不需要,可以删除
    //LogReset(1)

    // 设置精度
    exchange.SetPrecision(QuotePrecision, BasePrecision)

    // 识别期货还是现货
    var eType = 0
    var eName = exchange.GetName() //交易所名称 如:Futures_Binance
    var patt = /Futures_/
    if (patt.test(eName)) { //判断是否带有Futures_     期货交易的话设置合约为永续  Ct = "swap"
        Log("添加的交易所为期货交易所:", eName, "#FF0000")
        eType = 1
        if (Ct == "") {
            throw "Ct 合约设置为空"
        } else {
            Log(exchange.SetContractType(Ct), "设置合约:", Ct, "#FF0000")
        }
    } else {
        Log("添加的交易所为现货交易所:", eName, "#32CD32")
    }


    //测试持仓函数
    var position3 = exchange.GetPosition()
    if (position3.length == 0) {
        Log("机器人首次启动,正在对交易所进行全面检查", "#33CD33")
        Log(exchange.GetLabel(), "账户信息初始化完成:交易所没有持仓单子,一切正常", "#0000FF")
        Log("机器人已就绪! !等待信号! !", "#0000FF")
    }
    if (position3.length > 0) {
        Log("机器人首次启动,正在对交易所进行全面检查", "#33CD33")
        Log(exchange.GetLabel(), "账户信息初始化完成:交易所检查异常,有单子持仓, 请确认! ! !,", "持有仓位种类", position3.length, "(种)", "持仓数量:", position3[0].Amount, "(张/币)", "持仓方向:", position3[0].Type, "(0代表多单/1代表空单)", "#0000FF")
        Log("机器人已就绪! ! 等待信号中! ! !", "#0000FF")
    }

    var lastMsg = ""
    var position = _C(exchange.GetPosition)
    var acc = _C(exchange.GetAccount)
    //LogProfit(acc.Balance)
    //LogProfit(acc.Balance, '&')
    //LogProfit(acc.Stocks)
    //var acc = exchange.GetAccount
    Log(acc);

    var count = 0 //记录循环次数
    if(initialPrincipalUsdt==null){
       initialPrincipalUsdt = _G("initialPrincipalUsdt") //获取保存的数据
    }


    while (true) {
        var cmd = GetCommand()

        if (!cmd) {
            //Log("没有接收到cmd命令:", cmd, "#FF0000")
            //continue
        }

        if (cmd) {
            // 检测交互命令
            Log("接收到来自TradingView的警报信号", cmd, "#32CD32")
            Log("开始执行本次信号循环处理!", "#32CD32")

            lastMsg = "命令:" + cmd + "时间:" + _D()
            var arr = cmd.split(":")
            if (arr.length != 2) {
                Log("cmd信息有误:", cmd, "(请确认开仓或平仓的命令是否正确)", "#FF0000")
                continue
            }

            var action = arr[0]
            var amount = parseFloat(arr[1])
            //var amount = 0.01 //等号后面合约张数的数量
            //Log(action, amount)
            //Log("电报群共享的为FMZ第一版本的机器人代码,仅供学习用,如需完美对接电报群里播报信号的TradingView策略或想要更多优质TV策略的请联系群主18664029094", "#0000FF")
            //Log("微信 tian-qi-666 或电报群 //t.me/tq16889 或Bilbil视频上搜索:收益14500%策略详细使用方法或500U账户如何用复利下单全自动交易", "#FF0000")
            //Log("TradingView策略如何对接到发明者(FMZ)量化机器人的?发明者如何依据TV的信号对币安或OKEX等交易所进行全自动开仓平仓做单的? ", "#0000FF")
            //现货处理逻辑
            if (eType == 0) {
                if (action == BUY) {
                    var buyInfo = IsMarketOrder ? exchange.Buy(-1, amount) : $.Buy(amount)
                    Log("buyInfo:", buyInfo)
                } else if (action == SELL) {
                    var sellInfo = IsMarketOrder ? exchange.Sell(-1, amount) : $.Sell(amount)
                    Log("sellInfo:", sellInfo)
                } else {
                    Log("现货交易所不支持!", "#FF0000")
                }
                //期货处理逻辑
            } else if (eType == 1) {
                var tradeInfo = null
                var ticker = _C(exchange.GetTicker)

                if (action == LONG) {
                    Log("开多:", amount, "#32CD32")
                    //如果发过来的是long:0.01指令,那就平空,同时执行开多命令
                    //exchange.SetDirection("closesell")
                    //var tradeInfo1 = IsMarketOrder ? exchange.Buy(-1, amount) : exchange.Buy(ticker.Sell, amount)
                    //exchange.SetDirection("buy")
                    //var tradeInfo2 = IsMarketOrder ? exchange.Buy(-1, amount) : exchange.Buy(ticker.Sell, amount)
                    //tradeInfo = [tradeInfo1, tradeInfo2]                    
                    exchange.SetDirection("buy")
                    tradeInfo = IsMarketOrder ? exchange.Buy(-1, amount) : exchange.Buy(ticker.Sell, amount)
                    Log("本次信号处理完毕!!! 等待接受新的信号!!!", "#0000FF")

                } else if (action == SHORT) {
                    Log("开空:", amount, "#32CD32")
                    //如果发过来的是short:0.01指令,那就平多,同时执行做空命令
                    //exchange.SetDirection("closebuy")
                    //var tradeInfo1 = IsMarketOrder ? exchange.Sell(-1, amount) : exchange.Sell(ticker.Buy, amount)
                    //exchange.SetDirection("sell")
                    //var tradeInfo2 = IsMarketOrder ? exchange.Sell(-1, amount) : exchange.Sell(ticker.Buy, amount)
                    //tradeInfo = [tradeInfo1, tradeInfo2]                    
                    exchange.SetDirection("sell")
                    tradeInfo = IsMarketOrder ? exchange.Sell(-1, amount) : exchange.Sell(ticker.Buy, amount)
                    Log("本次信号处理完毕!!! 等待接受新的信号!!!", "#0000FF")

                } else if (action == COVER_LONG) {
                    Log("平多单:", amount, "#32CD32")

                    //增加是否有持仓情况判断
                    // 依次取回数据获取的结果
                    var account = _C(exchange.GetAccount)
                    if (!ticker || !account) {
                        Log(exchange.GetLabel(), ":获取交易数据异常,先不下单,跳过。", "@")
                        continue
                    }
                    // 获取持仓情况
                    var position = exchange.GetPosition()
                    // if (position_size != 0)
                    // Log(exchanges[i].GetLabel(), "的持仓数量为:", position_size)
                    if (position.length == 0) {
                        Log(exchange.GetLabel(), ":没有持仓,不做平仓.")
                        Log("本次信号处理完毕!!! 等待接受新的信号!!!", "#0000FF")
                        continue

                    }

                    //如果发过来的是cover_long:2指令,那就平多,同时平空
                    //exchange.SetDirection("closebuy")
                    //var tradeInfo1 = IsMarketOrder ? exchange.Sell(-1, amount) : exchange.Sell(ticker.Buy, amount)
                    //exchange.SetDirection("closesell")
                    //var tradeInfo2 = IsMarketOrder ? exchange.Buy(-1, amount) : exchange.Buy(ticker.Sell, amount)
                    //tradeInfo = [tradeInfo1, tradeInfo2]                    
                    exchange.SetDirection("closebuy")
                    tradeInfo = IsMarketOrder ? exchange.Sell(-1, amount) : exchange.Sell(ticker.Buy, amount)
                    Log("本次信号处理完毕!!! 等待接受新的信号!!!", "#0000FF")

                } else if (action == COVER_SHORT) {
                    Log("平空单:", amount, "#32CD32")

                    //增加是否有持仓情况判断
                    // 依次取回数据获取的结果
                    var account1 = _C(exchange.GetAccount)
                    if (!ticker || !account1) {
                        Log(exchange.GetLabel(), ":获取交易数据异常,先不下单,跳过。", "@")
                        continue
                    }
                    // 获取持仓情况
                    var position1 = exchange.GetPosition()
                    // if (position_size != 0)
                    // Log(exchanges[i].GetLabel(), "的持仓数量为:", position_size)
                    if (position1.length == 0) {
                        Log(exchange.GetLabel(), ":没有持仓,不做平仓.")
                        Log("本次信号处理完毕!!! 等待接受新的信号!!!", "#0000FF")
                        continue
                    }

                    //如果发过来的是cover_short:0.01指令,那就平多,同时平空
                    //exchange.SetDirection("closebuy")
                    //var tradeInfo1 = IsMarketOrder ? exchange.Sell(-1, amount) : exchange.Sell(ticker.Buy, amount)
                    //exchange.SetDirection("closesell")
                    //var tradeInfo2 = IsMarketOrder ? exchange.Buy(-1, amount) : exchange.Buy(ticker.Sell, amount)
                    //tradeInfo = [tradeInfo1, tradeInfo2]                    
                    exchange.SetDirection("closesell")
                    tradeInfo = IsMarketOrder ? exchange.Buy(-1, amount) : exchange.Buy(ticker.Sell, amount)
                    Log("本次信号处理完毕!!! 等待接受新的信号!!!", "#0000FF")

                } else if (action == SPK) { // 卖出平多仓,卖出开空仓
                    exchange.SetDirection("closebuy")
                    var tradeInfo1 = IsMarketOrder ? exchange.Sell(-1, amount) : exchange.Sell(ticker.Buy, amount)
                    exchange.SetDirection("sell")
                    var tradeInfo2 = IsMarketOrder ? exchange.Sell(-1, amount) : exchange.Sell(ticker.Buy, amount)
                    tradeInfo = [tradeInfo1, tradeInfo2]

                } else if (action == BPK) { // 买入平空仓,买入开多仓
                    exchange.SetDirection("closesell")
                    var tradeInfo1 = IsMarketOrder ? exchange.Buy(-1, amount) : exchange.Buy(ticker.Sell, amount)
                    exchange.SetDirection("buy")
                    var tradeInfo2 = IsMarketOrder ? exchange.Buy(-1, amount) : exchange.Buy(ticker.Sell, amount)
                    tradeInfo = [tradeInfo1, tradeInfo2]

                } else {
                    Log("期货交易所不支持!", "#FF0000")
                }
                if (tradeInfo) {
                    Log("tradeInfo:", tradeInfo)
                }
            } else {
                throw "eType error, eType:" + eType
            }
            acc = _C(exchange.GetAccount)
        }

        /*   //原来有
        var tbl = {
            type: "table",
            title: "状态信息",
            cols: ["数据"],
            rows: []
        }
        tbl.rows.push([JSON.stringify(acc)])
        LogStatus(_D(), eName, "上次接收到的命令:", lastMsg, "\n", "`" + JSON.stringify(tbl) + "`")
       */

        if (count % 100 == 0) {
            //展示持仓与挂单信息
            // binanceOrderRate()
            // FirmOfferIncome()
            accountInformationfunction() //账号信息
            binanceFundingRatefunction() //持仓单数组

            //一小时才记录一次    
            if (count % 600 == 0) {
                LogProfit(revenueUsdt, '&') //资金曲线
            }
        }


        LogStatus("上次接收到的命令:", lastMsg, "\n",
            '\n`' + JSON.stringify("最后更新时间:" + _D()) + '`\n' +
            '\n`' + JSON.stringify([accountInformation]) + '`\n' +
            '\n`' + JSON.stringify([binanceFundingRate]) + '`\n'
        ); //栏目框展示


        count++
        _G("initialPrincipalUsdt", initialPrincipalUsdt) //获取保存的数据
        Sleep(1000)
    }
}

More