Liquidity Providing and Pure Arbitrage with XRP (and other crypto) on Coinfield

jack

Administrator
Staff member
[Update: This post will remain online, but the crypto regulatory landscape has changed and CoinField got barked out of Canada by regulators a while ago... and has since changed a lot about their business... so i'd expect all info here is good for a reference, and a practical example for the concepts of off market prints, liquidity, orders clearing levels in an exchange's book, an algo approach to market inefficiencies.. etc.. etc... but I wouldn't go running to this now offshore exchange as if the info provided here is fresh and working... I've removed links and brand exposure for the exchange.. hope people got something out of this over the years while the good times lasted and they didn't have withdrawal issues.]

I’m about to talk about something most traders would keep a secret as long as possible. I’m about to explain, in detail, how even a small retail trader can take advantage of market making and arbitrage strategies in crypto markets.

And it starts with a Canadian crypto exchange named Coinfield…

Nearly 3 quarters of a year ago I stumbled upon something interesting.

XRP --that beloved crypto started by Ripple-- had been making rounds in the news as supporters took to social media and demanded XRP be listed on more crypto exchanges. It was kinda funny, the social media buzz was so strong many thought it was an organized marketing ploy to push XRP, and even gave a nick name to the droves of twitter accounts who’d swarm in whenever XRP was mentioned: the XRP army. But I digress… Some companies took advantage of the social media buzz and started catering to XRP fans by offering special deals for trading in XRP, or heck, even just announcing your company was going to support XRP in one way, shape, for form would get you plenty of attention.

Coinfiled jumped in the mix and announced free balance / wallet transfers inbound and outbound so long as they were in XRP. As well, Coinfield offered reduced XRP trading fees when XRP was being traded on their exchange. (This promo has since been adjusted.) It was a good play, and many people retweeted, shared, liked, and projected this across the net, giving Coinfield much exposure (and presumably many new signups.) It also got me to dig a bit deeper into Coinfield’s offering. Being a fellow Canadian and all it was the least I could do.

And then I noticed patterns like this:

zNQNIr9.png
bCoYiac.png
kpeLHmC.png


At first I thought this was just a bad data feed. After all, they were using TradingView’s charting library but with their own custom data source, so it’s entirely likely a bad “tick” might pop up here and there should their implementation of TradingView's library be a bit off... But I just knew I had to dig deeper.

X7E4vpW.png


or here..

vXJWgfG.png


And there it was… some trades seemed to be trading away from the prevailing market price around other exchanges. But was it real volume? Or maybe it was just a delayed print? Some other data feed gone bad? Nope, look closely, the lead up to a peek price on any given spike fills earlier prices in the book. These were micro swipes of multiple levels at once! This was an opportunity!

I want to be very clear here. Coinfield wasn’t doing anything bad.. they simply were processing market orders (or marketable limit orders) that were for a size the NBBO couldn’t fill all at once. Punch-happy retail traders were disregarding the liquidity available and just buying/selling blind into the market available. This was (and still is) any market maker’s dream; order flow willing to pay a premium in price to get the liquidity they demand.

I manually set out orders to see if I could interact with such order flow just in case it was all a data glitch, and pleasantly I started getting fills!

If you’re not following along so far, let me spell it out: Retail (or some other type) of order flow hitting Coinfield's exchange was cutting into the book, and since the underlying price of XRP or other instruments weren’t changing, once you got the fill at seemingly off-market rates, all you had to do was trade out of your new position at the fair market price. Rinse and repeat… and repeat… and repeat… and repeat...

I grew my account by 31% within a few weeks just doing this manually and then via an algo with small positions. Given this was a pure arb, and I was just providing liquidity, this return was a very attractive return!

Think I'm bullshitting you? ...


kmcSeZQ.png


This is the PDF account statement Coinfield emails you at the end of each month. All on the same day in February of 2019...
This was JUST XRP/CAD, I also was running this strat on 5 or 6 other pairs that month.

Guess what? ALL chart and time of sales examples given in this article are from THIS WEEK. The arb is still going strong as it has been for the last year I've been messing with it.

Obviously using a bot to provide liquidity and capture the arb was my best bet, so I wrote one. The bot's logic was very crude and simple:
  • Look at the book and if the book is thin (that is to say, even a few hundred dollars worth of crypto would cause price to slip beyond 50+ basis points, submit orders to provide liquidity on that pair.
  • As price moves, adjust the orders as required, always staying 50-300 basis points away from the mid point of the price quote.
  • Once I eventually get a fill, post orders at the midpoint price plus 5 or 10 bps of premium to get out of the positions exposure. I'd give up a little profit here just to get out of the position quickly so I can immediately re-post my off-market orders and provide more liquidity. This was because these spikes of price / orders would sometimes come in quick succession.
  • If another large order joins the book near my limit orders, I couldn't sit further away from the market price than them, as the larger order would absorb the order flow I was trying to capture. So once other large orders on the book were detected, the algo would get in front of them by a few ticks. Sometimes this meant fighting with another trader who was also trying to do the very thing I was doing (competition,) and sometimes this meant we'd just be repricing ourselves until there was not as much profit to be made. How to manage this was a fun meta-game of this strategy.
The code I wrote wasn't complicated. It was written in Python and runs on my own custom algo platform that I created from scratch. I won't be providing the full code here for obvious reasons -- seriously, this is a learning experience, take advantage of it and use what I'm telling you here as motivation to grind out a trading algo --but I've described the basic logic in a way that anyone, even a novice, can whip up something comparable in a very short period of time.

EDIT: I will give more info on the algo itself in python:

Challenges and how I solved them quick and dirty with python:​
* How do we know the true market price if Coinfield's own price quotes reflect the off market prints? Two ways: pull data from Binance as a reference, and average (smooth out) Coinfields own prices since any given price spike won't affect the average as drastically as natural price movements. Basically.. capture multiple types of quotes from multiple sources and smooth it all out. Here is the logic I used on all incoming quote changes:​
Code:
    def OnQuote(self):
        # if any data is missing from the quote feed (ie, not yet populated) just return
        if type(self.L1[self.data_feed][self.settings["alt_quote"]]['AskPrice']) != str:
            return
        if type(self.L1[self.data_feed][self.symbol]['AskPrice']) != str:
            return
       
        fprices = [self.Mid(), self.Last(), ] # adding midpoint and last to recent prices
       
        if 'None' not in self.settings['alt_quote']: # alt quote would be an external source like Binance
            fprices.append(self.rounder(self.Mid(sym=self.settings["alt_quote"])*float(self.settings["ex_rate"])))

        if self.inst_fair_price != self.rounder(s.mean(fprices)):
            self.inst_fair_price = self.rounder(s.mean(fprices))
            self.fair_store.append(self.inst_fair_price)
            self.fair_price = self.rounder(s.mean(self.fair_store))
           
        # don't start until smoothed fair price can be fully calc'd
        # I can use == here since the fair_store variable is a deque list
        if len(self.fair_store) == int(self.settings['fair_price_smoothing']):
            # engage agents that manage orders and positions on each tick once quotes have populated
            self.Passive_agent()
            self.Profit_agent()

        else:
            self.log.info("Start up, Collecting quotes: {} of {}".format(len(self.fair_store), int(self.settings['fair_price_smoothing'])))

* How can I make the order handling dead simple? How can I have two different agents running in the same thread not step on each other's toes? This one was simple, I just used local variables that other parts of the strategy referenced and used. Here's the first few lines of my profit agent method that worked with some of the strategy object's variables to help manage things. Basically there's order statuses that signal the profit agent's TP orders have been filled or changed and need adjusting:​
Code:
    def Profit_agent(self):
        end_game_orders = ['Filled', 'Cancelled', 'Rejected']
        if self.nbbo_working_buy_oid:
            if self.OrderStatus(self.nbbo_working_buy_oid) in end_game_orders:
                self.passive_working_buy_partial -= float(self.ORD[self.nbbo_working_buy_oid]['FilledSize'])
                self.nbbo_working_buy_oid = None
                self.nbbo_working_buy_price = None
            elif self.rounder(self.fair_price + (self.fair_price * self.bp_aggressive)) > self.nbbo_working_buy_price:
                self.cancel(self.nbbo_working_buy_oid)
            else: pass

Obviously the code snippets above are crude and incomplete, but it gives you an idea of how fast I cobbled together something that would do the job. It doesn't need to be elegant, not every job worth doing is worth doing well, it just needs to work.​

Coinfield offers a restful API and working with it is pretty simple. However, I do wish they'd create a demo environment for the API; I had to do all my initial development and testing in live markets which isn't always fun. Once you sign up, just request API access via chat and a customer service rep will link you the documentation and details.


So why am I telling you all this? Won't this just create more competition and the arb opportunity will be reduced? Sure, I expect a little of that. However, this was a great and CURRENT example of something I see many new algo traders talk about but few actually pull off in a practical way. This article was about the process of investigating, planning, and executing a simple but profitable algo... Put bluntly, many wannabe quants are data mining years worth of historical price data looking for arbs.. only to find false positive and dashed hopes. And yet here we found a pure arb with nothing more than a pair of eyes and some understanding of how exchanges and order matching works. Not to mention the barrier to entry on Coinfield is so minimal just about any retail trader can join in and give it a shot.


Here it comes... The big question... Will you step up? Will you sign up and start capturing some decent fills? Or are you just going to read yet another crypto article and daydream about trading?

This whole example is also a way to look through other exchanges who might be exhibiting the same behavior! This isn't just some crafted article meant to indirectly capture referrals to Coinfield. The process here is the same as I would apply to any exchange should I see the same order flow take place.


I hope you found this interesting! Trade well!

----

P.S. I gave up some edge in hopes people can learn from this example, so if you found this helpful or went out and made money with this method and would like to thank me, below are a few donation addresses:

BTC: 35S3bzNRZyWhPganBNRncqjPDq2jTmkHSa

ETH: 0x00099a47b2e0e09b044749D782F05557aF77d29F

XRP: rL8HjBMEcNwQBbdegJDmBVqhwp3iqj5vN9

Thank you,
Jack Larkin
 
Last edited:
.... the BTC/XRP exchange pair has been giving up off market prints like mad over the last 48 hours... smaller size but consistently filling.

Again, this arb is still going strong:

0NpTefa.png
 
.... the BTC/XRP exchange pair has been giving up off market prints like mad over the last 48 hours... smaller size but consistently filling.

Again, this arb is still going strong:

0NpTefa.png

Hi Jack

First post here. I looked up XRP/BTC on Binance and BTC/XRP on Trading View for 1st to 3rd October as shown bellow and the charts didn't look like this with the spikes coming down to the 33000 level. Were these spikes only on the Coinbase charts? Also is your chart a 1min chart?

Thanks

Adam
Screen Shot 2019-10-20 at 4.49.43 pm.png
 
Hi Jack

First post here. I looked up XRP/BTC on Binance and BTC/XRP on Trading View for 1st to 3rd October as shown bellow and the charts didn't look like this with the spikes coming down to the 33000 level. Were these spikes only on the Coinbase charts? Also is your chart a 1min chart?

Thanks

Adam
View attachment 8066

Coinfield uses the TradingView library (which TV provides to third parties who want to feed it with their own data.) CoinField then uses TV charts with CoinField data in their web platform. A lot of people do this.. even you can use the TV library for your own projects... you can read more about the TV library for use with your own data here:
 
Last edited:
Back
Top