1
$\begingroup$

I am using the Bittrex exchange API to ping markets to poll whether there are triangular arbitrage opportunities available for USD/BTC/LTC/USD. Note that I am not trading but rather synthesising them by using the API to collect bid and ask data for each of the 3 markets. My test polls also account for fees too. My current code base that uses the API is as follows

import requests as rq 
import json 
from CONSTANTS import API_PUBLIC, API_SECRET
import time
import hmac 
import hashlib 

def arbitrage():

    nonce = time.time()

    #Defines the API call that gets the price data
    usd_btc_market = 'https://api.bittrex.com/api/v1.1/public/getticker?market=USD-BTC&apikey={0}&nonce={1}'.format(API_PUBLIC, nonce)
    btc_ltc_market = 'https://api.bittrex.com/api/v1.1/public/getticker?market=BTC-LTC&apikey={0}&nonce={1}'.format(API_PUBLIC, nonce)
    usd_ltc_market = 'https://api.bittrex.com/api/v1.1/public/getticker?market=USD-LTC&apikey={0}&nonce={1}'.format(API_PUBLIC, nonce)

    #Ensures connections are secured through hashing
    usd_btc_signature = hmac.new(API_SECRET.encode(), usd_btc_market.encode(), hashlib.sha512).hexdigest()
    btc_ltc_signature = hmac.new(API_SECRET.encode(), btc_ltc_market.encode(), hashlib.sha512).hexdigest()
    usd_ltc_signature = hmac.new(API_SECRET.encode(), usd_ltc_market.encode(), hashlib.sha512).hexdigest()

    #Conducts the hypothetical trades using the API bid/ask prices from each market. 
    #Assumes a starting capital value of $1
    btc_balance = (1 / json.loads(rq.get(usd_btc_market, headers = {'apisign': usd_btc_signature}).content.decode('utf-8'))['result']['Ask']) * 0.998
    ltc_balance = (btc_balance / json.loads(rq.get(btc_ltc_market, headers = {'apisign': btc_ltc_signature}).content.decode('utf-8'))['result']['Ask']) * 0.998
    usd_balance = (ltc_balance * json.loads(rq.get(usd_ltc_market, headers = {'apisign': usd_ltc_signature}).content.decode('utf-8'))['result']['Bid'])* 0.998

    print(usd_balance) 

while True:
    arbitrage()
    time.sleep(3) #Limited to 60 API calls per minute, ensures not too many calls are made

The hypothetical trade results appear nearly profitable. Note that if we started with $1, then the final balance at the end of the arbitrage loop are as follows (code ran every 3 seconds):

#Time span of over a 5 minute period
#Each arbitrage loop takes on average 0.48 seconds to run
0.9915490241394859
0.9915511459969782
0.9915511459969782
...
0.9901270999326443
0.9901250816417339
0.9901269101525229

I am using Python to run this bot, however I am wondering if the 'so close yet so far' conundrum could be rectified by switching to a faster language such as c++? According to this post, c++ is atleast 10 times faster than python. My thinking is, could this language, with its faster runtime, overcome the minutely small time increments between each API market call? Could this be the reason why such opportunities aren't being found, that Python is simply to slow to take advantage of fleeting arbitrage opportunities? Or, is it just the case that the Cryptocurrency market is more efficient than I thought and arbitrage opportunities don't persist. Looking forward to hearing back what you think.

$\endgroup$
  • 1
    $\begingroup$ It is fairly possible that some of the wrapper functions you use are build for CONVENIENCE. For example, they likely include a lot of code for handling exceptions (errors, warnings, etc.) and such. These things take time, even if only very little time. If you re-code some of it on your own, you might be able to shave a few milliseconds, but it's going to be a big undertaking and I don't think you should even bother trying to get into a speed competition -- you won't win. $\endgroup$ – Stéphane May 9 at 19:35
  • 1
    $\begingroup$ On the other hand, there might be circumstances where that kind of trade will pay and in which big players would refuse to jump in, but that would likely come at the price of exposing yourself to some types of risk related to market disruptions -- liquidity drying out, volatiltiy exploding, etc. $\endgroup$ – Stéphane May 9 at 19:37
  • 3
    $\begingroup$ Depending on how those Python functions are themselves coded, you could make some gains in speed. But the problem isn't how fast you can go versus yourself. It's how fast you can go versus others... You might be able to speed up the code several times over, but if you cannot get your trade executed before other people, you end up behind the curve and you will loose money. $\endgroup$ – Stéphane May 9 at 19:42
  • 1
    $\begingroup$ It seems to me that you should at least try to use websockets to get a stream of quotes instead of getting them once every 3 seconds. If you get every quote you cast a much wider net. I doubt you’ll be fast enough to do this without quite a substantial amount of extra effort. $\endgroup$ – Bob Jansen May 9 at 20:45
  • 1
    $\begingroup$ To be honest, I think the issues mentioned here are far more pressing than the choice of language. But yes, C++ can be a lot faster. $\endgroup$ – Bob Jansen May 10 at 6:42
1
$\begingroup$

To expand on what others have said, C++ is only faster on your machine; it's not going to help your counterparty.

Polling over HTTP is the slowest imaginable way to get data, but if that's all Bittrex provides, then perhaps an alternative venue is needed. You are literally waiting three seconds to sample the data; by that point, the market has likely moved to a more efficient price.

Ideally you'd have an open socket with a callback mechanism. The venue should alert you in realtime whenever a new quote appears. Then, at least, the performance of your machine becomes a factor because you'll have to consume the data fast enough to keep up.

Beyond that, there is another issue: the speed of light. I assume you are not colocated with the venue. And in fact, if you're running over the Internet, then your latency is completely at the whim of your connection. If it takes you 40 ms to get the data and your competitors only 20 ms, then no amount of code will make-up for that. It is extremely difficult to comparatively measure this, and almost impossible to control.

| improve this answer | |
$\endgroup$
  • $\begingroup$ Thank you for answer, it was really insightful. Aside from connection speed, why would HTTP be the slowest way possible to get data? Additionally, if this implies that there are faste ways to get the data, how do the co-located Computers get it? $\endgroup$ – Hamish Gibson Jun 3 at 23:29
  • 1
    $\begingroup$ @HamishGibson Polling is slow because of the wait, independent of protocol. HTTP is its own troubles, because it (1) has to be parsed and (2) runs over TCP. Compare to exchanges with binary protocols over UDP. All of this is separate from colocation, which simply means to physically put your computers in the same data center as your counterparty, often with a dedicated telecom connection. $\endgroup$ – chrisaycock Jun 3 at 23:39
3
$\begingroup$

It’s likely the gets and decoding are where the time is spent. If you want to speed this up, run the three gets in parallel instead of in serial, then make that calculation.

C or C++ can be faster, but here it’s more about the code than the language.

| improve this answer | |
$\endgroup$
  • $\begingroup$ I see, because that’s my concern too. Arbitrage opportunities exist concurrently and therefore if the calls are made in a serial way then the price data could become stale quickly. $\endgroup$ – Hamish Gibson May 10 at 9:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.