Sometimes, the market can be inefficient and there can be a situation that if we convert BTC into LTC, and then to USDT, and finally back to BTC, we can get more BTC than what we have originally, i.e. triangular arbitrage.  

Triangular arbitrage is a simple way to make profit by taking no or very little risk. To detect triangular arbitrage opportunities, we need to simply compute the final rate of the three conversions.

In the above example, we simply multiply the conversion rates of BTC/LTC, LTC/USDT, and USDT/BTC (which is the inverse of BTC/USDT). If the final result is greater than 1, it means we will have more BTC after the conversion.

For our exchange, you can use the following sample code to detect such opportunities. The code also considers the trading commission fees. Because different account levels have different fees (, you can change CRYPTO_FEE and FIAT_FEE according to your account level. You can also directly run it here:

import requests
import sets
from collections import defaultdict

FIATS = ['USD', 'SGD', 'MYR', 'CAD']

# change the following fees based on your own account level. 
CRYPTO_FEE = 0.00095
FIAT_FEE = 0.0018

def get_fee(c1, c2):
    if c1 in FIATS or c2 in FIATS:
        return FIAT_FEE
        return CRYPTO_FEE

s = requests.Session() # use HTTP/1.1 to share the same connection across requests to minimise latency
insts ='', '{"request": "inst_list", "sec_type": "SPOT", "nonce": 1234}').json()['SPOT']

while True:
    r = s.get('').json()
    curs = sets.Set()
    rates = defaultdict(dict)
    for a in r:
        inst = insts[a['asset']][0]
        base = inst['base']
        quote = inst['quote']

        rates[base][quote] = float(a['highest_buy'])
        rates[quote][base] = 1.0/float(a['lowest_sell'])

    print "--------------------------- Triangular arbitrage opportunities -----------------------------------"
    for c1 in curs:
        for c2 in curs:
            if c1 == c2:

            for mid in curs:
                if c1 in rates and mid in rates and c2 in rates and mid in rates[c1] and c2 in rates[mid] and c1 in rates[c2]:
                    pair1_rate = rates[c1][mid] * (1-get_fee(c1, mid))
                    pair2_rate = rates[mid][c2] * (1-get_fee(mid, c2))
                    pair3_rate = rates[c2][c1] * (1-get_fee(c2, c1))
                    total_rate = pair1_rate * pair2_rate * pair3_rate

                    if total_rate > 1:
                        print "%4s %4s %4s %15.8f %15.8f %15.8f %15.8f" % (c1, mid, c2, rates[c1][mid], rates[mid][c2], rates[c2][c1], total_rate)

Run the above code, and we indeed find some opportunities!

If you need more information on our API, please check