Skip to content

Instantly share code, notes, and snippets.

@risentveber
Created July 16, 2018 14:12
Show Gist options
  • Save risentveber/ff34c237c34a97f470356e78f8060052 to your computer and use it in GitHub Desktop.
Save risentveber/ff34c237c34a97f470356e78f8060052 to your computer and use it in GitHub Desktop.
Arbitrage with Bellman-Ford algo abstraction
const request = require('superagent');
const R = require('ramda');
function get(url) {
return new Promise((resolve, reject) => {
request
.get(url)
.end((err, res) =>{
if (err) {
reject(err);
return;
}
resolve(res.body);
});
});
}
function path(first, last, vertexes, prices) {
const distances = vertexes.reduce((m, name) => {
m[name] = Infinity;
return m;
}, {});
distances[first] = -1;
const fullPathes = {
[first]: [first]
};
vertexes.forEach(u => {
vertexes.forEach(v => {
const d = prices[v + '_' + u];
if (d) {
if (distances[u] > distances[v] * d ) {
distances[u] = distances[v] * d;
fullPathes[u] = Array.from(fullPathes[v] || []).concat([u]);
}
}
});
});
return {
gross: distances[last] * prices[last + '_' + first] * -1,
net: distances[last] * prices[last + '_' + first] * -1 * Math.pow(1 - 0.002, fullPathes[last].length),
path: fullPathes[last].concat([first])
};
}
setInterval(() =>
get('https://api.exmo.com/v1/ticker/')
.then((rawPrices) => {
const pairs = Object.keys(rawPrices);
const prices = pairs.map(R.split('_')).reduce((memo, [l, r]) =>{
const d = rawPrices[l + '_' + r];
memo[l + '_' + r] = Number(d.buy_price);
memo[r + '_' + l] = 1 / Number(d.sell_price);
return memo;
}, {});
const vertexes = R.uniq(R.flatten(pairs.map(R.split('_'))));
const result = [];
const computed = {};
for(let i = 0; i < vertexes.length; i++) {
for(let k = 0; k < vertexes.length; k++) {
const first = vertexes[i];
const last = vertexes[k];
if (!prices[first + '_' + last] || computed[last + '_' + first]) {continue;}
result.push(path(first, last, vertexes, prices));
computed[first + '_' + last] = true;
}
}
// console.log(JSON.stringify(result, null, 2));
const filtered = result.filter(r => r.net > 1);
if (filtered.length) {
console.log('============================================================================');
filtered.forEach(({ net, path }) => {
console.log(`${net} ${path.join('=>')}`);
});
}
}, console.error), 5000);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment