pythonlessons / RL-Bitcoin-trading-bot

Trying to create Reinforcement Learning powered Bitcoin trading bot
MIT License
383 stars 204 forks source link

Suggestion: Realistic order prices/fees #1

Open no-trick-pony opened 3 years ago

no-trick-pony commented 3 years ago

Hi!

I read your articles on pylessons, thanks a lot! I have a suggestion to make since I feel like you are missing two very important parts of the "trading environment": Bid-Ask-Spread and exchange fees. Especially the first one will MASSIVELY impact how your algorithm performs in real life. As far as I get from your code, you are currently determining the "current price" by just selecting the Open price of the current time window.

I don't know how familiar you are with crypto-trading or trading in general - I am myself a beginner at this, so don't take everything here to be correct - but when you want to buy or sell something, you have to find someone who is willing to buy or willing to sell at the price you suggest. In trading, this usually done by your broker (i.e. exchange in crypto) via the orderbook. Orders (bids and asks) with a target price for buying ore selling are placed there and if there is a matching price a trade is made. However, the difference between the current stock/coin price and the bids and asks can be very big and differs from exchange to exchange and throughout time dramatically. The difference between the best bid and ask price in the orderbook is called bid-ask spread. For bitcoin you can for example look at the previous bid ask spread here: https://data.bitcoinity.org/markets/spread/2y/USD?c=e&st=log&t=l - however, for smaller coins the spread is usually much higher since the market isn't that big. For MOB/USD on the FTX exchange for example bid/ask spread is currently 0.8%. That is HUGE. It means, every time you buy or sell you will lose 0.8% of your money.

So, what happens in reality when you want to buy/sell something?

You usually have a couple of choices to place an order, but the two most basic choices are:

  1. "Market order" which guarantees a sale by matching the bid price in the orderbook. For selling this means, it will be sold for the highest bid price in the order book, for buying it means it will be bought for the lowest ask price. It is usually guaranteed to be fulfilled but you don't have precise control over the price: If the price changes while you place the order and the order being fulfilled, you may loose or even gain a bit. I think the easiest way to model this is to take a random value between +-1% of the bid/ask price. Also if the highest bid or ask in the orderbook does not cover your whole order, the lower/higher ones will be taken, which is bad for you.
  2. "Limit order" where you can set a price yourself at which you want to sell. This means you do have control over the price but it's MUCH harder to get an immediate sale like that. The exact trading procedure is a science for itself. If you place your order at the current highest bid/lowest ask price in the orderbook, it usually will be fulfilled quickly, but there is no guarantee on that: If the price rises or falls, nobody will probably want your order.

Now on top of that, you have trading fees. They are exchange dependend, and there are two different ones:

  1. "Maker fees": A percentage you have to pay when you put an order in the orderbook and someone elses order gets matched against it. They are usually relatively low and on some exchange can even be negative! That means you even get money for trading. However, that means, that your order must not be immediately be matched against some others order in the orderbook. Maker fees for FTX for example are 0.025%, on other exchange like kraken they are higher - 0.16% and 0.1% on Binance. This means: No instant trade! So for our two order types, this means, they don't apply for the market order and for the limit order only if your order does not get matched immediately against an order in the orderbook. For that we have the
  2. "Taker fees": A percentage you have to pay when you put an order in the orderbook and it gets immediately matched against someone elses order (you put a bid there and it gets immediately matched against an ask in the orderbook). This is true for market orders --> market orders always have the taker fee. They are usually higher than the maker fees - on FTX 0.075%, on kraken 0.26% on Binance they are currently 0.1% too.

There are tricks to get maker fees with limit orders too (the POST option) but they usually don't guarantee an immediate sale either.

So what does all that mean?

The performance of your algorithm will be heavily impacted by the bid-ask spread of the market it tries to trade. The bid/ask fees are more or less static, but bid-ask spread is a problem. For comparison I implemented some simple hand written bots and traded on a sample of the DOGE/USD coin with it - one time I assumed 0.1% cost for a trade and one time 1% cost. It literally meant the difference between a 457.68% increase with 0.1% assumed trading costs to 0.00003% left of the original 100% with 1% cost. Because the bots were trading far too often to make the 1% costs of the trade feasible.

So bid-ask spread and proper ordering should be part of your model to make it realistic and something your agents should be able to observe and learn from.