策略源码
// @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)