-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patharbitrage-pairs.js
123 lines (89 loc) · 4.08 KB
/
arbitrage-pairs.js
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
"use strict";
const ccxt = require ('../../ccxt.js')
const asTable = require ('as-table')
const log = require ('ololog').configure ({ locate: false })
require ('ansicolor').nice;
let printSupportedExchanges = function () {
log ('Supported exchanges:', ccxt.exchanges.join (', ').green)
}
let printUsage = function () {
log ('Usage: node', process.argv[1], 'id1'.green, 'id2'.yellow, 'id3'.blue, '...')
printSupportedExchanges ()
}
let printExchangeSymbolsAndMarkets = function (exchange) {
log (getExchangeSymbols (exchange))
log (getExchangeMarketsTable (exchange))
}
let getExchangeMarketsTable = (exchange) => {
return asTable.configure ({ delimiter: ' | ' }) (Object.values (markets))
}
let sleep = (ms) => new Promise (resolve => setTimeout (resolve, ms));
let proxies = [
'', // no proxy by default
'https://crossorigin.me/',
'https://cors-anywhere.herokuapp.com/',
]
;(async function main () {
if (process.argv.length > 3) {
let ids = process.argv.slice (2)
let exchanges = {}
log (ids.join (', ').yellow)
// load all markets from all exchanges
for (let id of ids) {
// instantiate the exchange by id
let exchange = new ccxt[id] ()
// save it in a dictionary under its id for future use
exchanges[id] = exchange
// load all markets from the exchange
let markets = await exchange.loadMarkets ()
// basic round-robin proxy scheduler
let currentProxy = 0
let maxRetries = proxies.length
for (let numRetries = 0; numRetries < maxRetries; numRetries++) {
try { // try to load exchange markets using current proxy
exchange.proxy = proxies[currentProxy]
await exchange.loadMarkets ()
} catch (e) { // rotate proxies in case of connectivity errors, catch all other exceptions
// swallow connectivity exceptions only
if (e instanceof ccxt.DDoSProtection || e.message.includes ('ECONNRESET')) {
log.bright.yellow ('[DDoS Protection Error] ' + e.message)
} else if (e instanceof ccxt.RequestTimeout) {
log.bright.yellow ('[Timeout Error] ' + e.message)
} else if (e instanceof ccxt.AuthenticationError) {
log.bright.yellow ('[Authentication Error] ' + e.message)
} else if (e instanceof ccxt.ExchangeNotAvailable) {
log.bright.yellow ('[Exchange Not Available Error] ' + e.message)
} else if (e instanceof ccxt.ExchangeError) {
log.bright.yellow ('[Exchange Error] ' + e.message)
} else {
throw e; // rethrow all other exceptions
}
// retry next proxy in round-robin fashion in case of error
currentProxy = ++currentProxy % proxies.length
}
}
log (id.green, 'loaded', exchange.symbols.length.green, 'markets')
}
log ('Loaded all markets'.green)
// get all unique symbols
let uniqueSymbols = ccxt.unique (ccxt.flatten (ids.map (id => exchanges[id].symbols)))
// filter out symbols that are not present on at least two exchanges
let arbitrableSymbols = uniqueSymbols
.filter (symbol =>
ids.filter (id =>
(exchanges[id].symbols.indexOf (symbol) >= 0)).length > 1)
.sort ((id1, id2) => (id1 > id2) ? 1 : ((id2 > id1) ? -1 : 0))
// print a table of arbitrable symbols
let table = arbitrableSymbols.map (symbol => {
let row = { symbol }
for (let id of ids)
if (exchanges[id].symbols.indexOf (symbol) >= 0)
row[id] = id
return row
})
log (asTable.configure ({ delimiter: ' | ' }) (table))
} else {
printUsage ()
}
process.exit ()
}) ()