Skip to content

Instantly share code, notes, and snippets.

@Valian
Created January 18, 2018 23:33
Show Gist options
  • Star 50 You must be signed in to star a gist
  • Fork 15 You must be signed in to fork a gist
  • Save Valian/d16ef72a0e17ee82c0acf606d6a744d7 to your computer and use it in GitHub Desktop.
Save Valian/d16ef72a0e17ee82c0acf606d6a744d7 to your computer and use it in GitHub Desktop.
Short script for finding Binance Triangle arbitrage opportunities - requires python-binance installed
from collections import defaultdict
from operator import itemgetter
from time import time
from binance.client import Client
FEE = 0.0005
PRIMARY = ['ETH', 'USDT', 'BTC', 'BNB']
def main():
start_time = time()
prices = get_prices()
prices_time = time()
print(f"Downloaded in: {prices_time - start_time:.4f}s")
triangles = list(find_triangles(prices))
print(f"Computed in: {time() - prices_time:.4f}s")
if triangles:
for triangle in sorted(triangles, key=itemgetter('profit'), reverse=True):
describe_triangle(prices, triangle)
else:
print("No triangles found, try again!")
def get_prices():
client = Client(None, None)
prices = client.get_orderbook_tickers()
prepared = defaultdict(dict)
for ticker in prices:
pair = ticker['symbol']
ask = float(ticker['askPrice'])
bid = float(ticker['bidPrice'])
for primary in PRIMARY:
if pair.endswith(primary):
secondary = pair[:-len(primary)]
prepared[primary][secondary] = 1 / ask
prepared[secondary][primary] = bid
return prepared
def find_triangles(prices):
triangles = []
starting_coin = 'BTC'
for triangle in recurse_triangle(prices, starting_coin, starting_coin):
coins = set(triangle['coins'])
if not any(prev_triangle == coins for prev_triangle in triangles):
yield triangle
triangles.append(coins)
def recurse_triangle(prices, current_coin, starting_coin, depth_left=3, amount=1.0):
if depth_left > 0:
pairs = prices[current_coin]
for coin, price in pairs.items():
new_price = (amount * price) * (1.0 - FEE)
for triangle in recurse_triangle(prices, coin, starting_coin, depth_left - 1, new_price):
triangle['coins'] = triangle['coins'] + [current_coin]
yield triangle
elif current_coin == starting_coin and amount > 1.0:
yield {
'coins': [current_coin],
'profit': amount
}
def describe_triangle(prices, triangle):
coins = triangle['coins']
price_percentage = (triangle['profit'] - 1.0) * 100
print(f"{'->'.join(coins):26} {round(price_percentage, 4):-7}% <- profit!")
for i in range(len(coins) - 1):
first = coins[i]
second = coins[i + 1]
print(f" {second:4} / {first:4}: {prices[first][second]:-17.8f}")
print('')
if __name__ == '__main__':
main()
@Valian
Copy link
Author

Valian commented Jan 18, 2018

I made this script to check if there is an easy way to get rich ^^ Basically, because all pairs are independent of each other, there should be "triangles" allowing to always benefit. Profits are usually lower than 1%, and it's almost impossible to buy it because of a slow API, but still, it's interesting to find out that such opportunities exist. Example output:

Downloaded in: 1.5233s
Computed in: 0.0078s
BTC->ETH->NAV->BTC          0.1038% <- profit!
     ETH  / BTC :       11.03874600
     NAV  / ETH :      338.52403521
     BTC  / NAV :        0.00026320

BTC->BCPT->BNB->BTC         0.0145% <- profit!
     BCPT / BTC :    15001.50015002
     BNB  / BCPT:        0.05253000
     BTC  / BNB :        0.00126200

@seven7e
Copy link

seven7e commented Apr 12, 2018

Hi Valian, I also interested in cryptocurrency arbitrage. Have you ever consider the fees in triangle arbitrage? It seems to be significant, e.g. 0.1% for Binance.com, considering the profit is < 1% usually.

@storerjeremy
Copy link

storerjeremy commented Apr 14, 2018

@nanoix9 Looks like he is handling the fees in this line here - new_price = (amount * price) * (1.0 - FEE)

@seven7e
Copy link

seven7e commented Apr 15, 2018

Thanks @storerjeremy, I didn't read the code carefully.

@K4mB
Copy link

K4mB commented May 12, 2018

This is working?

@delislecl
Copy link

delislecl commented May 16, 2018

Pulling data in: 0.2061s Transforming data in: 0.2649s Find opportunities in: 0.0702s

Time to receive data from API is decent (200ms) and to process data for too (70ms), however transforming pulled data into dictionnary is quite long (260ms). Maybe a way to make this step more efficient could make those opportunities tradable ?
Latency for trading via API is usually around 200ms.
Trying to optimize data transformation part might worth a shot ?

@wa1one
Copy link

wa1one commented Jul 6, 2018

actually if you put your bot to amazon tokyo instance you will get 10 ms for api response. Should be enough for triarb
Also you should check orderbook for big txamounts, good luck

@Tilanthi
Copy link

Tilanthi commented Oct 19, 2018

Hi Valian

I have an error trying to run your script, I wonder if you would kindly be able to advise what the likely reason for this is please - many thanks - obviously I did modify the script to add my api keys.

root@Ubuntu-1804-bionic-64-minimal /opt/TrangularArbitrage # python triangular_arbitrage.py
Traceback (most recent call last):
File "triangular_arbitrage.py", line 80, in
main()
File "triangular_arbitrage.py", line 13, in main
prices = get_prices()
File "triangular_arbitrage.py", line 38, in get_prices
prepared[primary][secondary] = 1 / ask
ZeroDivisionError: float division by zero

@ebinum83
Copy link

i have the same error too!!

@ClemDelp
Copy link

ClemDelp commented Sep 23, 2019

@Tilanthi @GRTTX just means that there aren't ask prices on the current ticker, just add:

        if ask == 0.0:
            continue

before the for loop

@jurgenBE
Copy link

jurgenBE commented Mar 20, 2021

I am looking into arbitrage also on Binance but the problem is the precision of your amount to put in the orderbook, it's not always precision 8, for example BNB trade at 3 places after the comma, so if your first leg of the arbitrage buys bnb's for usdt then you have perhaps 2.8647899 bnb but if you place an order you must stay with precision three so this amount becomes a rounddown to 2.864 instead of rouding up to 2.865, so you already have some leftover bnb coins in your account like 0.0007899 bnb OR you must with every coin you look at for arbitrage do a roudup but that means for every 'crap' coin you must buy some and sell after so that you have some 'leftovers'. Sometimes you have an arbitrage of > 0.00225 percent (the fees for Binance) BUT if you then actually take a wager amount to start from and you have to do the Rounddown in step 2 and also sometimes on step 3 (depends on the situation bidaskbid-askaskbid-bidbidask etc..). My opinion is that these roudndown make it even harder to do the placeing of orders in reality... If someone has another opinion on that matter or a solution please let me know!!!

@ugik
Copy link

ugik commented Jun 8, 2021

Binance 'Taker' (limit order) fees (currently) are 0.00075 rather than 0.0005, this is a significant difference, even at VIP1 level the fee is 0.000675. Besides this it's impossible to know how long a specific arbitrage opportunity will remain open. With API latency of 500ms this means the window would be approx. 2secs and it's clear that most of the arbitrage openings identified do not last this long.

@Tilanthi
Copy link

Tilanthi commented Jun 8, 2021 via email

@alissonf216
Copy link

FEE = 0.0075

@Tilanthi
Copy link

Tilanthi commented Dec 20, 2021

Hey alissonf216 - thanks for the comment correcting @uk ... 's fee figure (which I think was meant to be percentage). But essentially for the retail trader, tri-arb has not really been a profitable strategy for the last few years - most retail traders do not have access to sufficiently optimised low latency configurations, and the available liquidity on most of the exchanges that have low enough fees to allow any possibility of profit is usually too low to guarantee closure of a triangular loop, with the consequence that the trader builds up a substantial 'bank' of intermediate coins where the tri-arbitrage loop has not closed. This strategy was 'fun' many years ago, but with the aggressive front-running bots now active on most exchanges (perhaps even 'zero-latency' ones co-located within the exchange racks) it is not worth wasting time with, apart from if you want a flutter for a bit of crypto fun. There are possibilities if you understand how to build things, in quad arbitrage - but it is a much slower kind of arbitrage strategy, and the available profitable windows tend to only last for short periods of time (sometimes as much as a few 10's of minutes a day) before they close - so again, not really suitable for the average retail trader, and requires simultaneously running a simulator to determine the short periods when a given market quadruplet is in a profitable situation. There are much easier ways these days to make money with automated trading bots, and in my view you would have to be a true tri-arb aficionado to expect this kind of strategy to produce any significant profit. Perhaps someone will jump in here and tell us all that they are making mega squillions of dollars a year with tri-arb - but I would be surprised should this prove to be the case !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment