JS 查看三角套利(币币交易)是否有赚头

本贴最后更新于 2530 天前,其中的信息可能已经事过境迁

概念

币币交易

用一种数字资产去直接换取另一种数字资产,中间不涉及任何法币结算,就是我们所说的币币交易。如 OKEX 币币交易 或者 火币币币交易

三角套利

用两个市场(比如 MANA/USDT,BTC/USDT)的价格相除计算出 MANA/BTC 价格,如果该价格和实际的 MANA/BTC 价格不一致,那么就可以从中赚取差价。

案例

注:由于人民币无法直接兑换为数字货币,因此我们选用价格稳定的 USDT 替代 CNY。使用 MANA、BTC、USDT(MANA/USDT,BTC/USDT,BTC/MANA)来进行进行演示。

假设 BTC/USDT = 15872.0400,MANA/USDT = 0.1320,MANA/BTC = 0.000009,此时计算出的 MANA/BTC(.000008317)价格小于实际价格 0.000009

  1. 使用 13.2 个 USDT 买入 100 个 MANA,手续费 0.0132 USDT
  2. 使用 100 个 MANA 买入 0.0009 个 BTC,手续费 0.1 MANA
  3. 使用 0.0009 个 BTC 买入 14.284836 个 USDT,手续费 0.0000009 BTC

整个过程中,BTC 和 MANA 的数量不变,而增加的 1.084836 - (0.0132 * 2 + 0.014284836) = 1.072720836 个 USDT 就是我们的盈利

当然如果实际计算出的价格大于实际价格时,我们只要方向操作也时可以盈利的

假设 BTC/USDT = 15872.0400,MANA/USDT = 0.1320,MANA/BTC = 0.000008,此时计算出的 MANA/BTC(.000008317)价格大于实际价格 0.000008

  1. 使用 12.697632 个 USDT 买入 0.0008 个 BTC,手续费 0.0000008 BTC
  2. 使用 0.0008 个 BTC 买入 100 个 MANA,手续费 0.1 MANA
  3. 使用 100 个 MANA 买入 13.2 个 USDT,手续费 0.0132 USDT

整个过程中,BTC 和 MANA 的数量不变,而增加的 0.502368 - (0.012697632 * 2 + 0.0132) = 0.463772736 个 USDT 就是我们的盈利

使用方式

准备

  1. F12/option+cmd+i 打开开发者工具,选择 Sources -> Snippets,点击 +New snippet 分别创建 math,okex,huobi 三个 snippet。如下图所示

1B10D44A-E639-4C33-B42B-2E7CBE40FBF0.png

  1. 在 snippet 中对应贴入文章末尾代码,然后 ctrl+s/cmd+s 进行保存

  2. 打开 https://www.okex.com/api/v1/depth.do?symbol=mana_btc 页面。右键点击 math,选择运行;然后在右键点击 okex,选择运行即可出 OKEX 币币交易盈利结果

CFA0FCBA-1587-4DD3-96A9-65C096A35B06.png

  1. 同理右键点击 huobi,选择运行,即可出现 huobi 币币交易盈利结果

代码

okex

var getATicker = async function(sm) {
    const response = await fetch(`https://www.okex.com/api/v1/depth.do?symbol=${sm}&size=2`).then(function (response){return response.text();})
    const responseJSON = JSON.parse(response)
    if (responseJSON.error_code) {
        console.error(`Error Code: ${responseJSON.error_code}, URL: https://www.okex.com/api/v1/depth.do?symbol=${sm}&step=1; Info: https://www.okex.com/rest_request.html`)
        return null
    }
    return {
        ask: responseJSON.asks.pop(),
        bid: responseJSON.bids[0]
    }
}

var hasBenefit = async function(coin, mainCoin) {
    const mainCoin2usdt = await getATicker(`${mainCoin}_usdt`)
    if (!mainCoin2usdt) {
        return
    }
    const coin2usdt = await getATicker(`${coin}_usdt`)
    if (!coin2usdt) {
        return
    }
    const coin2mainCoin = await getATicker(`${coin}_${mainCoin}`)
    if (!coin2mainCoin) {
        return
    }

    let putCount = Math.min(coin2usdt.ask[1], coin2mainCoin.bid[1])
    if (mainCoin2usdt.bid[1] < math.eval(`${putCount} * ${coin2mainCoin.bid[0]}`)) {
        putCount = math.eval(`${mainCoin2usdt.bid[1]} / ${coin2mainCoin.bid[0]}`)
    }
    if (putCount >= 0.01) {
        const moreUsdt = math.eval(`${mainCoin2usdt.bid[0]} * ${coin2mainCoin.bid[0]} * ${putCount} - ${coin2usdt.ask[0]} * ${putCount}`)
        const serviceCharge = math.eval(`(${coin2usdt.ask[0]} * 2 + ${coin2mainCoin.bid[0]} * ${mainCoin2usdt.bid[0]}) * ${putCount} * 0.001`)
        if (moreUsdt > serviceCharge) {
            // MANA/BTC 市场卖出一定数量 Q3 的 MANA,同时在 MANA/USDT 市场买入数量为 Q3 的 MANA,在 BTC/USDT 市场卖出数量为 P3 * Q3 的 BTC
            // Trade(`${coin}_${mainCoin}`, 'sell', coin2mainCoin.bid[0], putCount) 
            // Trade(`${coin}_usdt`, 'buy', coin2usdt.ask[0], putCount) 
            // Trade(`${mainCoin}_usdt`, 'sell', mainCoin2usdt.bid[0], math.eval(`${putCount} * ${coin2mainCoin.bid[0]}`)) 
            console.log(`${coin}-${mainCoin}:需 ${putCount} USDT,赚:`, math.eval(`${moreUsdt} - ${serviceCharge}`) + ' USDT,百分比:', math.eval(`(${moreUsdt} - ${serviceCharge}) / ${putCount} * 100`))
            console.log(Math.min(coin2usdt.ask[1], coin2mainCoin.bid[1]), putCount)
            return
        }
    }

    let putCount1 = Math.min(coin2usdt.bid[1], coin2mainCoin.ask[1])
    if (mainCoin2usdt.ask[1] < math.eval(`${putCount1} * ${coin2mainCoin.ask[0]}`)) {
        putCount1 = math.eval(`${mainCoin2usdt.ask[1]} / ${coin2mainCoin.ask[0]}`)
    }
    if (putCount1 < 0.01) {
        return
    }
    const moreUsdt1 = math.eval(`${coin2usdt.bid[0]} * ${putCount1} - ${mainCoin2usdt.ask[0]} * ${coin2mainCoin.ask[0]} * ${putCount1}`)
    const serviceCharge1 = math.eval(`(${coin2usdt.bid[0]} + ${coin2mainCoin.ask[0]} * ${mainCoin2usdt.ask[0]} * 2) * ${putCount1} * 0.001`)
    if (moreUsdt1 > serviceCharge1) {
        // 就在 MANA/BTC 市场买入一定数量 Q3 的 MANA,同时在 MANA/USDT 市场卖出数量为 Q3 的 MANA,在 BTC/USDT 市场买入数量为 P3 * Q3 的 BTC
        // Trade(`${coin}_${mainCoin}`, 'buy', coin2mainCoin.ask[0], putCount1) 
        // Trade(`${coin}_usdt`, 'sell', coin2usdt.bid[0], putCount1) 
        // Trade(`${mainCoin}_usdt`, 'buy', mainCoin2usdt.ask[0], math.eval(`${putCount1} * ${coin2mainCoin.ask[0]}`)) 
        console.log(`反向 ${coin}-${mainCoin}:需 ${putCount1} USDT,赚:`, math.eval(`${moreUsdt1} - ${serviceCharge1}`) + ' USDT,百分比:', math.eval(`(${moreUsdt1} - ${serviceCharge1}) / ${putCount1} * 100`))
        console.log(Math.min(coin2usdt.bid[1], coin2mainCoin.ask[1]), putCount1)
    }
}

var coins = ["ltc", "avt", "cmt", "edo", "san", "pro", "itc", "nuls", "lrc", "mco", "dgd", "gnt", "storj", "snt", "pay", "act", "eos", "omg", "dash", "xrp", "zec", "neo", "gas", "hsr", "qtum", "iota", "xuc", "etc", "ctr", "link", "salt", "1st", "wtc", "sngls", "snm", "zrx", "bnt", "cvc", "mana", "vee"]
// coins = ['avt']
for (var i = 0, iMax = coins.length; i < iMax; i++) {
    hasBenefit(coins[i], 'btc')
    hasBenefit(coins[i], 'eth')
}

var getCoins = function() {
    var coins = [];
    $('#ethCurrencyPair li').each(function() {
        coins.push(this.getAttribute('data-symbol').replace('_eth', ''))
    })
    return coins;
}

huobi

var getATicker = async function(sm) {
    const response = await fetch(`https://api.huobi.pro/market/detail/merged?symbol=${sm}`).then(function (response){return response.text();})
    const responseJSON = JSON.parse(response)
    if (responseJSON.status === 'error') {
        console.error(`Error Code: ${responseJSON.err_msg}, URL: https://api.huobi.pro/market/detail/merged?symbol=${sm}`)
        return null
    }
    return {
        ask: responseJSON.tick.ask,
        bid: responseJSON.tick.bid
    }
}

var hasBenefit = async function(coin, mainCoin) {
    const mainCoin2usdt = await getATicker(`${mainCoin}usdt`)
    if (!mainCoin2usdt) {
        return
    }
    const coin2usdt = await getATicker(`${coin}usdt`)
    if (!coin2usdt) {
        return
    }
    const coin2mainCoin = await getATicker(`${coin}${mainCoin}`)
    if (!coin2mainCoin) {
        return
    }
    const putCount = Math.min(mainCoin2usdt.bid[1], coin2usdt.ask[1], coin2mainCoin.bid[1])
    const moreUsdt = math.eval(`${mainCoin2usdt.bid[0]} * ${coin2mainCoin.bid[0]} * ${putCount} - ${coin2usdt.ask[0]} * ${putCount}`)
    const serviceCharge = math.eval(`(${coin2usdt.ask[0]} * 2 + ${coin2mainCoin.bid[0]} * ${mainCoin2usdt.bid[0]}) * ${putCount} * 0.004`)
    if (moreUsdt > serviceCharge) {
        // MANA/BTC 市场卖出一定数量 Q3 的 MANA,同时在 MANA/USDT 市场买入数量为 Q3 的 MANA,在 BTC/USDT 市场卖出数量为 P3 * Q3 的 BTC
        console.log(`${coin}-${mainCoin}:需 ${putCount} USDT,赚:`, math.eval(`${moreUsdt} - ${serviceCharge}`) + ' USDT,百分比:', math.eval(`(${moreUsdt} - ${serviceCharge}) / ${putCount} * 100`))
    } else {
        console.warn(`${coin}-${mainCoin}:需 ${putCount} USDT,亏:`, math.eval(`${moreUsdt} - ${serviceCharge}`) + ' USDT,百分比:', math.eval(`(${moreUsdt} - ${serviceCharge}) / ${putCount} * 100`))
    }

    const putCount1 = Math.min(mainCoin2usdt.ask[1], coin2usdt.bid[1], coin2mainCoin.ask[1])
    const moreUsdt1 = math.eval(`${coin2usdt.bid[0]} * ${putCount1} - ${mainCoin2usdt.ask[0]} * ${coin2mainCoin.ask[0]} * ${putCount1}`)
    const serviceCharge1 = math.eval(`(${coin2usdt.bid[0]} + ${coin2mainCoin.ask[0]} * ${mainCoin2usdt.ask[0]} * 2) * ${putCount1} * 0.004`)
    if (moreUsdt1 > serviceCharge1) {
        // 就在 MANA/BTC 市场买入一定数量 Q3 的 MANA,同时在 MANA/USDT 市场卖出数量为 Q3 的 MANA,在 BTC/USDT 市场买入数量为 P3 * Q3 的 BTC
        console.log(`反向 ${coin}-${mainCoin}:需 ${putCount1} USDT,赚:`, math.eval(`${moreUsdt1} - ${serviceCharge1}`) + ' USDT,百分比:', math.eval(`(${moreUsdt1} - ${serviceCharge1}) / ${putCount1} * 100`))
    } else {
        console.warn(`反向 ${coin}-${mainCoin}:需 ${putCount1} USDT,亏:`, math.eval(`${moreUsdt1} - ${serviceCharge1}`) + ' USDT,百分比:', math.eval(`(${moreUsdt1} - ${serviceCharge1}) / ${putCount1} * 100`))
    }
}

var coins = ['eos', 'bcc', 'eth', 'xrp', 'ltc', 'dash', 'etc', 'eos', 'omg', 'zec', 'qtum']
// coins = ['eos', 'bcc', 'eth', 'xrp', 'ltc', 'dash', 'etc', 'eos', 'omg', 'zec']
for (var i = 0, iMax = coins.length; i < iMax; i++) {
    hasBenefit(coins[i], 'btc')
    // hasBenefit(coins[i], 'eth')
}

math

https://cdnjs.cloudflare.com/ajax/libs/mathjs/3.18.0/math.min.js

总结

以上仅供参考娱乐。想要用于实际赚钱,除了手续费以外我们还需要考虑更多的实际情况,诸如挂单失败、挂单无法交易、货币不足等等。

  • 套利
    4 引用 • 19 回帖
  • 数字货币
    1 引用 • 19 回帖
  • JavaScript

    JavaScript 一种动态类型、弱类型、基于原型的直译式脚本语言,内置支持类型。它的解释器被称为 JavaScript 引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在 HTML 网页上使用,用来给 HTML 网页增加动态功能。

    729 引用 • 1327 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • flhuoshan

    算法还有问题的感觉,以火币为例,正向和反向出来都是亏,不是应该一亏一赚么

    1 回复
  • 其他回帖
  • errorlife

    战略 Mark(夫妻炒币党啊 hhhh)

    1 回复
  • alanfans

    看不懂
    aaaa.png

    1 回复
  • flhuoshan

    好像是,手续费远大于三角搬砖所得貌似

    2 回复
  • 查看全部回帖