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

概念

币币交易

用一种数字资产去直接换取另一种数字资产,中间不涉及任何法币结算,就是我们所说的币币交易。如 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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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

总结

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