Creating a crypto trading bot for fun and profit

Photo by Austin Distel on UnsplashI started crypto trading a few months ago regarding an unpleasant incident that put me out of work for two months. Looking at the bright side, I thought maybe it’s my chance to finally learn about crypto and trading fo…


This content originally appeared on Level Up Coding - Medium and was authored by Hossein Babaei

Photo by Austin Distel on Unsplash

I started crypto trading a few months ago regarding an unpleasant incident that put me out of work for two months. Looking at the bright side, I thought maybe it’s my chance to finally learn about crypto and trading for “fun and profit”. I started watching youtube videos and reading blog posts to learn the basics of cryptos and trading. Here are my top resources:

  1. CoinBureau is a youtube channel that provides high quality crypto related content.
  2. AltCoin Daily is another youtube channel that provides daily updates on everything that’s happening around the crypto market.
  3. Binance academy is like a blog where you can find contents regarding crypto and trading.

After a while I started trading manually with BTC, ETH, ADA, and MATIC based on Guy’s videos. It didn’t take much time to realize that trading is a full time job and I would need to stare at lots of screens to monitor the prices if I don’t want to miss an opportunity. Although it was an enjoyable hobby, I didn’t want to change my career and become a trader.

Among these youtube videos, this one caught my attention and put the idea of developing a trading bot in my head. How hard could it be, right? My first attempt was a disaster in every possible way. It had very poor performance, low profit, super complex, and very hard to backtest. It used the technical analysis of the 9MA and 24MA crosses (Death and Golden crosses). It was so bad that I almost let go of the idea until I learned about grid bots which this article is about.

Disclaimer

Before we jump into the actual content I have a disclaimer to make. I am not a financial advisor and nothing in this article should be considered as financial advice. Always Do Your Own Investigation (DYOI) and only invest with what you can risk to lose.

Don’t forget that a small bug in your code might cost you a considerable amount of money. I learned it the hard way!

It would be nice to have the basic knowledge of trading concepts and terms like candlesticks, orders, positions, bull, bear, and sideways market, going short and going long, and technical analysis. If not, Binance academy is a great place to get started. However, not knowing these won’t be a blocker for this article.

One last thing to keep in mind while reading this article: For the sake of simplicity (and keeping this as short as possible), lots of codes have been removed and the remaining codes are pseudo codes to explain the concept.

Grid bots

When it comes to platforms, there are many that offer limited free trading bots e.g. 3commas, Pionex, and KuCoin. After watching this video from Guy I decided to give it a shot and started with 3Commas. The concepts seemed very simple and easy to implement. So why not giving it a try?

Backtesting

When you develop a bot, you would want to test it before putting your money on it. In the trading universe this is called backtesting. Backtesting is providing historical data to the bot and checking how it performs.

This is one of the most important concepts to have in mind when making design decisions for your bot. You have to make sure that the implementation provides an easy way to execute a backtest. things like Dependency Injection, pure functions, and being deterministic. Your bot should always return the same result for the same input, and it should not be time dependent!

Exchange

Your bot needs to connect to an API in order to fetch last prices, and place a buy or sell order. You have to figure out which exchange you want to work with. It should provide you with good documentation and flexible APIs that match your requirements.

I am using Binance! However none of my code is tight to it. So at any time I can switch to another exchange by refactoring the Exchange class. Binance provides a well documented API and test network to get started with. No need to mention this video from Guy.

The Exchange class implements three methods:

  1. getBalance will return the account balance.
  2. createOrder will create a [market] order. it should check the balance before creating the order to prevent an order failure.
  3. getAllPrices fetches the last price for all pairs.

You might need to add some more methods regarding the exchange you decided to work with.

How grid bot works

A grid bot splits a range of prices into buy and sell orders. Grid bots normally create buy and sell orders per grid line when they start. However I prefer to execute and order after a buy or sell line has been met.

Pair or Symbol: Pair is what you buy or sell for example BTC/USDT. Symbols or pairs consist of two assets or tokens. the first asset is called baseAsset (BTC) and the second part is called quoteAsset(USDT). When you buy a pair you gain baseAsset by giving quoteAsset. And when you sell, you gain quoteAsset by selling the baseAsset. In order to keep things simple I only select pairs with USDT as their quoteAsset.

Configuring a grid bot starts with choosing the lower band (minPrice) and upper band. These values are selected by looking at previous market prices. For example 3Commas uses the highest and lowest price in the last 7 days with 3% offset. Pionex uses the backtest for the last 7 days to set the configurations when you select the AI strategy.

The next parameter is called gridCount. The gridCount is the number of splits to have between the min and max price. With bigger gridCounts comes more trades but less profit (smaller gridWidth) and vice versa . gridWidth is the difference between two consecutive gridLines. There’s a trade off between the number of positions and the amount of profit per position. For example if we consider BTC, for the past 7 days, a lower band of 58281 and upper band of 69344 seems reasonable. If we split this range into 24 grids we would have a gridWidth of 481. Meaning if you buy, and price moves up 481 USDT, then you make a profit of tradeAmount x 481. If we split this range by 12, then price has to move up 962 USDT for the position to be closed, however the profit would be higher tradeAmount x 962.

The last part in configuration is creating the gridLines. They can be created using minPrice, gridWidth, and gridCount. After generating grid lines, the line nearest to the current price will be deactivated. All lines above this will be SELL and the lines below will be BUY.

If price moves down and crosses a BUY line, a buy order will be executed, that line will be deactivated, and all lines above this line will change to active and SELL. On the other hand if price moves up and crosses a SELL line, a sell order will be executed, this line will be deactivated, and all the lines below this line will change to BUY and active.

Check this amazing GIF made by 3Commas that elaborates every step of a grid bot.

How grid bots work by 3Commas

Below is a pseudo code for the grid bot.

The decide method will check the lastPrice with each active line for a buy or sell situation. To find the best buy spot you want to start from the lowest price and move up, while for a sell spot you want to start from the highest price and move down.

This method should also take into account if the price moves above the upper band or falls below the lower band. Most grid bots will deactivate in these cases, until price gets back to the range or user interfere and alter the configs e.g. 3commas. Pionex Infinity grid bot on the other hand, adds new grid lines to the top (increasing the upper band) if price moves above the grid, but still deactivates if prices falls below the grid.

You can decide for your own on how you want your bot to behave in these cases, but make sure you have thoroughly backtested these decisions.

Managing bots

Now that we have a grid bot, we need an engine to manage our instances. We don’t want to run this for only one symbol. This is the good part of developing your own bot. Using free versions of grid trading platforms you are limited on the number of grid bots you can run.

When you start a bot, the engine will fetch the bot’s data from the database, create an instance and call the bot.start method. It will also call the bot.execute method on every interval (1 minute in this code), with the last price fetched from exchange. For stopping a bot the engine will call the bot.stop, giving the bot a chance to save its state and stop gracefully.

Backtesting grid bot

The backtesting engine will fetch historical data needed for testing the bot and initiate a bot by configuring it. Then it will run bot.execute for all bots and return the final profit of this combination.

By combination I mean the group of assets that you have selected to run the backtest e.g. BTC,ETH,ADA,LTC,MATIC,.... You should also know that even the order in which these bots are being called will affect the benefit -unless you have unlimited amount of quoteAsset. We will talk more about this later.

We also need to mock the Exchange class for backtesting. The way we implement the grid bot will allow us to inject this class as dependency (IoC).

A setBalance method is added to set the initial balance of your account. The createOrder method should check if a buy or sell order is valid by checking the balance, and if so, it should update the balance. The getAllPrices method should return the historical data for all the pairs in the backtest.

When you have done enough backtesting it’s time to test your bot on a test network to see if the orders are being executed correctly. Usually a couple of weeks should be enough to verify that it’s working as expected.

Finding the best pairs

When you run your bots on a real network you might notice that after a while they are not making any trades because your account is out of baseAsset. This happens when all your pairs are following the same bullish or bearish market. For example let’s imagine you have 1000 USDT as your quoteAsset, and you spent 200 USDT for each trade. In this case the first 5 bots that are executed by engine, will spend all the assets and the remaining bots will fail to create a buy order. It would be great if some of these pairs would move in opposite directions. So when some bots are selling, the others would be buying and vice versa.

If you have a huge amount of baseAsset, then save yourself some time and stop right here. The remaining part of the article deals with this issue.

So here is the million dollar question: How to pick the best combination of pairs to assure the maximum profit?

Greedy algorithm

With a greedy algorithm we have to calculate all possible combinations of all pairs with different lengths. The length is the number of pairs to participate in trades. If there are 200 pairs, there might be a combination of 40 pairs that has higher profit than just using all these pairs together. Therefore we have to consider all possible lengths as well as all possible orders within each length.

You might think, with the computers that we have nowadays, this shouldn’t take much time. Well, you are wrong!

In mathematics there are n!/(n-r)! combinations to pick r items from n items when order matters. As I explained earlier BTC,ADA,… has a different profit than ADA,BTC,… when we have limited quoteAsset. Let’s assume we have 20 pairs and we want to figure out the best combination with the min length of 10:

Total number of combinations with the length of 10 to 20 from 20 items

I’m not going to calculate this number but just to give you an estimation, let’s only consider the last number in this sequence, 20!. If we had a machine capable of running 1000000 backtests in one second (which is highly doubtable), this would take 77,146 years to calculate all these combinations!

2,432,902,008,176,640,000 / (1000000*60*60*24*365) = 77,146

Backtesting a single combination means calling the bot.execute method for each bot on each interval with the last price. Let’s imagine we have a combination of 16 bots, and we are backtesting on 1 minutes interval for the past two month which means 60*24*60*16=1,382,400 decide operation on a single combination. No need to mention the network latency for fetching historical data, configuring bots, database and I/O operations. With my Macbook Pro (16GB RAM, M1 chip, and SSD disk) I get a maximum of 20 backtests per second!

At the time of writing this article, Binance has 1778 pairs. Since I only use USDT pairs, this leaves me with 356 pairs. With some filters on gridWidth, minPrice, and calculating average grid profit, I manage to reduce this number to 189. You do the math!

Genetic algorithm

Although Greedy algorithms guarantee the best combination, it’s not applicable for this use case. In these cases we usually use genetic algorithms which provide a good-enough (if not the best) solution within a reasonable amount of time.

Attention: You might notice in different places of my code that token (asset) is being used instead of pair or symbol. Since I am using USDT as the quote asset for all pairs, it’s easy to convert a token to pair and vice versa. Keep that in mind if you plan to use other quote assets.

Modeling

To model a chromosome I have used an array of strings (genes) to represent the pairs. genes[i] may contain a token or an empty string. In order to simplify the crossover and mutation operations, the length of all chromosomes are the same. That’s why some genes contain empty cells.

Fitness

The fitness is simply calculated by running a backtest on all tokens in a chromosome respecting their order. It is the same as the profit.

Initial population

A single chromosome is generated by randomly pushing a token or an empty string into a genes array. When a chromosome is generated it should be refined. Refining a chromosome guarantees that all tokens are unique, and the number of tokens is greater than a configurable value called minGeneSize.

Here is a pseudo code for the Chromosome class.

Crossover and Mutation

The crossover will split the two parents into half, and then creates two offspring (single-point crossover) by cross merging them. The first offspring has the first half of the first parent and second half of the second parent. The second offspring has the first half of the second parent and second half of the first parent. These offsprings have to be validated because they might be empty, having duplicate pairs, or they might already exist.

After crossover (creating next generation), we have to mutate some of these chromosomes. The mutation will prevent the algorithm from converging on a local optimum solution. The mutation will swap two random indices with each other. The discovery.mutate method will select mutationRate*populationSize chromosomes from the population and calls the mutate method on each of those chromosomes.

Selection

After calculating the fitness, a new population will be generated by combining the previous generation and new generation. Then this population will be refined (to remove duplicates) and sorted based on their fitness (profit). The top populationSize of this list will be selected for the next iteration.

Below is the pseudo code for Discovery class which implements this algorithm.

Running this algorithm on historical data of two months (September and October of 2021), 3 minutes interval, 189 pairs, 20 iterations, population size of 200, mutation rate of 0.1, and initial balance of 2000 USDT, took 82 minutes to complete and found the following combination with 3503 USDT profit. Not bad, right?

POLY,NU,WAVES,ATA,WTC,XTZ,XRP,VIDT,SOL,AXS,POLS,CTSI,MASK,FTM,CLV,GTC,STRAX,ALPACA,SUSHI,NKN,ILV,QNT,ALGO,GALA

Although there might be a better combination, considering the amount of time spent on this, I would say 175% profit for two month, is pretty darn good. Keep in mind that this is a backtesting result and the future market might not be the same. Crypto market is highly volatile.

Do not hesitate to share your ideas, opinions, and bring up a discussion in the comment section. I would also appreciate it if you could let me know of any mistakes in the content so I can improve it for the next one who reads it.

If you are going to start with any of these services, here are my referrals that would benefit both of us on transactions and commission fees: Binance, 3Commas, Pionex, and KuCoin.

May profit be with you ;)


Creating a crypto trading bot for fun and profit was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.


This content originally appeared on Level Up Coding - Medium and was authored by Hossein Babaei


Print Share Comment Cite Upload Translate Updates
APA

Hossein Babaei | Sciencx (2021-11-24T20:07:38+00:00) Creating a crypto trading bot for fun and profit. Retrieved from https://www.scien.cx/2021/11/24/creating-a-crypto-trading-bot-for-fun-and-profit/

MLA
" » Creating a crypto trading bot for fun and profit." Hossein Babaei | Sciencx - Wednesday November 24, 2021, https://www.scien.cx/2021/11/24/creating-a-crypto-trading-bot-for-fun-and-profit/
HARVARD
Hossein Babaei | Sciencx Wednesday November 24, 2021 » Creating a crypto trading bot for fun and profit., viewed ,<https://www.scien.cx/2021/11/24/creating-a-crypto-trading-bot-for-fun-and-profit/>
VANCOUVER
Hossein Babaei | Sciencx - » Creating a crypto trading bot for fun and profit. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2021/11/24/creating-a-crypto-trading-bot-for-fun-and-profit/
CHICAGO
" » Creating a crypto trading bot for fun and profit." Hossein Babaei | Sciencx - Accessed . https://www.scien.cx/2021/11/24/creating-a-crypto-trading-bot-for-fun-and-profit/
IEEE
" » Creating a crypto trading bot for fun and profit." Hossein Babaei | Sciencx [Online]. Available: https://www.scien.cx/2021/11/24/creating-a-crypto-trading-bot-for-fun-and-profit/. [Accessed: ]
rf:citation
» Creating a crypto trading bot for fun and profit | Hossein Babaei | Sciencx | https://www.scien.cx/2021/11/24/creating-a-crypto-trading-bot-for-fun-and-profit/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.