Back to Ccxt

Arbitrage Pairs

wiki/examples/js/arbitrage-pairs.md

4.5.604.5 KB
Original Source
javascript
// @NO_AUTO_TRANSPILE
import ccxt from '../../js/ccxt.js';
import asTable from 'as-table';
import fs from 'fs';
import ololog from 'ololog';
const log = ololog.configure({ locate: false }), verbose = process.argv.includes('--verbose'), keysGlobal = 'keys.json', keysLocal = 'keys.local.json', keysFile = fs.existsSync(keysLocal) ? keysLocal : (fs.existsSync(keysGlobal) ? keysGlobal : false), config = keysFile ? require('../../' + keysFile) : {};
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(getExchangeMarketsTable(exchange));
};
let getExchangeMarketsTable = (exchange) => {
    return asTable.configure({ delimiter: ' | ' })(Object.values(exchange.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) {
            let settings = config[id] || {};
            // instantiate the exchange by id
            let exchange = new ccxt[id](ccxt.extend({
            // verbose,
            // 'proxy': 'https://cors-anywhere.herokuapp.com/',
            }, settings));
            // 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.toString().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();
})();