三角套利监控 - 自动搜索


创建日期: 2025-05-09 01:21:04 最后修改: 2025-05-09 01:21:10
复制: 0 点击次数: 79
avatar of 算法007 算法007
3
关注
1
关注者
策略源码
// @version=6
indicator("现货三角套利监控 - 自动搜索", overlay=true)

// 交易所选择
var string BINANCE = "BINANCE"
var string OKX = "OKX"
var string BYBIT = "BYBIT"

exchange = input.string(BINANCE, "选择交易所", options=[BINANCE, OKX, BYBIT])

// 基础货币选择
base_currency = input.string("USDT", "基础货币", options=["USDT", "BUSD", "USD"])

// 手续费设置
fee_maker = input.float(0.001, "Maker手续费率", minval=0.0, maxval=0.01, step=0.0001)
fee_taker = input.float(0.002, "Taker手续费率", minval=0.0, maxval=0.01, step=0.0001)
slippage = input.float(0.001, "滑点率", minval=0.0, maxval=0.01, step=0.0001)
min_profit = input.float(0.002, "最小收益率", minval=0.0, maxval=0.01, step=0.0001)

// 创建数组
var string[] all_pairs = array.new_string()
var string[] base_pairs = array.new_string()  // 以基础货币计价的交易对
var string[] cross_pairs = array.new_string() // 币币交易对

// 创建信号数组
var float[] profits = array.new_float()  // 存储所有套利组合的收益率
var string[] paths = array.new_string()  // 存储所有套利组合的路径

// 创建单一表格用于显示信息
var info_table = table.new(position.top_right, 4, 6, color.new(color.gray, 90), 
                         border_width=1, border_color=color.gray)

// 初始化交易对数组
if barstate.isfirst
    // 根据交易所选择添加常见交易对
    if exchange == "BINANCE"
        // 添加基础货币交易对
        array.push(base_pairs, "BTCUSDT")
        array.push(base_pairs, "ETHUSDT")
        array.push(base_pairs, "BNBUSDT")
        array.push(base_pairs, "ADAUSDT")
        
        // 添加币币交易对
        array.push(cross_pairs, "ETHBTC")
        array.push(cross_pairs, "BNBBTC")
        array.push(cross_pairs, "ADABTC")
        
    else if exchange == "OKX"
        array.push(base_pairs, "BTCUSDT")
        array.push(base_pairs, "ETHUSDT")
        array.push(cross_pairs, "ETHBTC")
        
    else if exchange == "BYBIT"
        array.push(base_pairs, "BTCUSDT")
        array.push(base_pairs, "ETHUSDT")
        array.push(cross_pairs, "ETHBTC")

// 用于存储最佳套利机会
var float best_profit1 = 0.0
var float best_profit2 = 0.0
var string best_path1 = ""
var string best_path2 = ""

if barstate.islast
    // 遍历所有基础货币交易对组合
    for i = 0 to array.size(base_pairs) - 1
        coin1_pair = array.get(base_pairs, i)
        coin1 = str.replace(coin1_pair, base_currency, "")
        
        for j = i + 1 to array.size(base_pairs) - 1
            coin2_pair = array.get(base_pairs, j)
            coin2 = str.replace(coin2_pair, base_currency, "")
            
            // 查找对应的币币交易对
            cross_pair = coin2 + coin1
            if array.includes(cross_pairs, cross_pair)
                // 构建三角套利组合
                pair1 = exchange + ":" + coin1_pair
                pair2 = exchange + ":" + coin2_pair
                pair3 = exchange + ":" + cross_pair
                
                // 获取价格
                price1 = request.security(pair1, timeframe.period, close)
                price2 = request.security(pair2, timeframe.period, close)
                price3 = request.security(pair3, timeframe.period, close)
                
                // 计算套利机会
                path1_profit = ((1 / price1) * (1 / price3) * price2) - 1
                path2_profit = ((1 / price2) * price3 * price1) - 1
                
                // 更新最佳套利机会
                if path1_profit > best_profit1
                    best_profit1 := path1_profit
                    best_path1 := base_currency + " -> " + coin1 + " -> " + coin2 + " -> " + base_currency
                
                if path2_profit > best_profit2
                    best_profit2 := path2_profit
                    best_path2 := base_currency + " -> " + coin2 + " -> " + coin1 + " -> " + base_currency

    // 更新表格显示
    if barstate.islast
        // 表头
        table.cell(info_table, 0, 0, "套利路径", text_color=color.white)
        table.cell(info_table, 1, 0, "收益率(%)", text_color=color.white)
        table.cell(info_table, 2, 0, "手续费(%)", text_color=color.white)
        table.cell(info_table, 3, 0, "净收益(%)", text_color=color.white)
        
        // 显示最佳正向套利
        net_profit1 = best_profit1 - (fee_maker + fee_taker) * 3 - slippage
        table.cell(info_table, 0, 1, best_path1, 
                   text_color=net_profit1 > min_profit ? color.green : color.gray)
        table.cell(info_table, 1, 1, str.tostring(best_profit1 * 100, "#.###") + "%",
                   text_color=net_profit1 > min_profit ? color.green : color.gray)
        table.cell(info_table, 2, 1, str.tostring((fee_maker + fee_taker) * 3 * 100, "#.###") + "%",
                   text_color=color.white)
        table.cell(info_table, 3, 1, str.tostring(net_profit1 * 100, "#.###") + "%",
                   text_color=net_profit1 > min_profit ? color.green : color.gray)
        
        // 显示最佳反向套利
        net_profit2 = best_profit2 - (fee_maker + fee_taker) * 3 - slippage
        table.cell(info_table, 0, 2, best_path2,
                   text_color=net_profit2 > min_profit ? color.green : color.gray)
        table.cell(info_table, 1, 2, str.tostring(best_profit2 * 100, "#.###") + "%",
                   text_color=net_profit2 > min_profit ? color.green : color.gray)
        table.cell(info_table, 2, 2, str.tostring((fee_maker + fee_taker) * 3 * 100, "#.###") + "%",
                   text_color=color.white)
        table.cell(info_table, 3, 2, str.tostring(net_profit2 * 100, "#.###") + "%",
                   text_color=net_profit2 > min_profit ? color.green : color.gray)

// 在全局作用域绘制套利信号
plotshape(best_profit1 > min_profit, "最佳正向套利", style=shape.triangleup, 
         location=location.belowbar, color=color.new(color.green, 0), size=size.small)
plotshape(best_profit2 > min_profit, "最佳反向套利", style=shape.triangledown,
         location=location.abovebar, color=color.new(color.red, 0), size=size.small)

// 设置报警条件
if best_profit1 > min_profit
    alert("发现最佳正向三角套利机会\n" + best_path1 + 
          "\n收益率: " + str.tostring(best_profit1 * 100, "#.###") + "%", 
          alert.freq_once_per_bar)

if best_profit2 > min_profit
    alert("发现最佳反向三角套利机会\n" + best_path2 + 
          "\n收益率: " + str.tostring(best_profit2 * 100, "#.###") + "%", 
          alert.freq_once_per_bar)