Files
quanxiel/course/14-crypto-trading-bots.md
T

14 KiB
Raw Blame History

14 · Crypto Trading Bots(加密货币 · RSI 动量)

🎯 本集要点(中文导读)

本集讲 加密货币(Crypto)算法。

  • 支持的交易所:Bitfinex(346 对)、Coinbase Pro(原 GDAX,9 对)、Binance;数据回溯到 2014(取决于币种);统一 UTC 时区。
  • ⚠️ 必须按 Cashbook(现金簿)决策:做多 BTC-EUR 需先持有 EUR,做多 ETH-BTC 需先持有 BTC。可用 self.Portfolio.CashBook[...].Amount 查某币持仓量。只想规避此问题就专做各币的 USD 计价对。
  • 添加数据:self.AddCrypto("BTCUSD", resolution, market)(支持 tick~日线;market 选 Bitfinex/GDAX/Binance)。
  • 实盘:需在受支持的交易所注册、生成 API token,并在 QuantConnect 实盘向导里配置。
  • 示例 bot:动量策略——用 RSI 识别上行动量后买入,动量消退则平仓(做多若干加密对)。
  • ⚠️ 作者提醒:加密回测极易"虚高"(过去是大牛市);且只用了"当前仍被支持的币",仍存在幸存者偏差,换环境可能失效。

📝 完整文稿(英文 · 自动转写)

由本地 ASR(faster-whisper)从视频音轨转录,未人工校对,供检索/精读使用。原始讲解以上方视频为准。

Hello and welcome back to another video of my Python algorithmic trading course. So far we have explored how you can create trading algorithms for equities, forex, CFDs and options inside of QuantConnect. In this video I will show you how you can create crypto trading bots. But note that if you are new to this series I recommend starting at the beginning since the previous video lessons are just as relevant to crypto trading as for the other asset types. That said, let's start with a brief theory part before moving on to coding an example crypto trading bot. QuantConnect currently supports crypto trading on Bitfinex, Coinbase Pro which was previously known as Gdex and Binance. Furthermore, Crocken will be supported soon. Bitfinex offers 346 cryptocurrency pairs whereas Coinbase Pro currently only offers 9 pairs. The data goes back all the way to 2014 but since some cryptocurrencies are newer the availability of data depends on the currency. For a full list of the supported pairs check out the link documentation page below. All crypto data uses the UTC time zone. One important thing to note when trading cryptocurrencies is that you must make trading decisions based on the cash book. The cash book keeps track of what kind of currency your portfolio currently holds. For example, if you want to buy the crypto pair Bitcoin Euro you would need to hold Euro in your portfolio. The same goes for a pair like Ethereum Bitcoin. To buy this pair you would need to own some Bitcoin since you are buying their Ethereum with Bitcoin. But note that you can also just buy crypto currencies against USD if you just focus on the crypto USD pairs. To get the amount of a certain coin in your portfolio you can access the amount property of the cash book of your portfolio. For example, this line would get the amount of Bitcoin that you own in your portfolio. Similar to the ad equity and ad for X methods that also exists in ad crypto method to add the data for crypto pair to your algorithm. As always, the first argument here simply is the ticker of the pair and the second argument is the resolution. Bitcoin Connect supports everything from tick, second, minute hourly to daily resolution for cryptos. As for Forex, the third argument is where you can specify the exchange that you want the data from. Here you can currently decide between BitFenix, GDAX and Binance. To live trade crypto currencies through QuantConnect you would have to sign up to one of the supported exchanges. You would then have to create an API token and specify this in the live trading setup wizard within QuantConnect. For more details on this however check out the documentation page. With that being said, let me now outline the strategy that we will implement in the coding part of this video. The strategy that we will implement is a simple momentum strategy where we try to identify crypto currencies with upward momentum and buy them until the momentum fades. To measure momentum we will use the relative strength index indicator also known as RSI in short. If the RSI for a given crypto crosses above a certain threshold we want to buy it and we first close the position if RSI drops below an exit threshold. The goal of developing and back testing algorithm trading strategies is to best possibly model reality so that the results obtained from analysis are actually meaningful. Therefore, you have to pay special attention to removing as many hidden biases as you can. Actually, one of the biggest challenges of back testing that just describes strategy is realistically modeling the universe selection process. One possible way to go about the universe selection would be to simply look at the currently most actively traded cryptos and then use them as the base universe. However, then the results would be heavily biased from survivorship bias since we are not considering currencies that no longer exist or used to be much more popular than they are today. In other words, we are applying a filter to only consider the surviving cryptos from today's perspective. So be very careful when developing your own bots and always ask yourself whether you are unknowingly applying such a filter. For this algorithm I will add the data for all crypto USD pairs that are supported by Bitfinex. The algorithm will then look at the 30 day average daily dollar volume and it only adds those cryptos to the current active universe if they have sufficiently high enough dollar volume. Only for these cryptos it then looks at the RSI for potential momentum trades. I hope this brief explanation makes it clear what the algorithm that we will code next is supposed to do. If you haven't already, I highly recommend creating a free QuantConnect account so that you can code along. Inside of QuantConnect we will create a new algorithm inside of the lab tab. As always we will start by implementing the Initialized method. Firstly, I will set the start and end date for the back test to the beginning of 2019 until 2021. Note that depending on which cryptocurrencies you want to trade the available data might be limited. After that I will keep the starting cash balance to be $100,000. Before we move on to creating some helper variables let me set the free portfolio value percentage to 5%. Doing this will ensure that always at least 5% of our portfolio will stay in cash which can be useful if you want to have a cash buffer for your portfolio. Now we will create four variables that will store some parameter values. The first is called Position Size USD and this is where we specify the amount we want to allocate to a single position. Here we will go with $5,000. The next two parameters will hold the Entry and Exit threshold for the relative strength indicators. We will use $70 as the entry threshold and $65 for the exit. This means if RSI rises above $70 we enter and we first exit if it falls below $65. Last but not least we specify the average daily dollar volume that we will use to filter out illiquid securities from our active universe. Here I will go with a value of $1 million. Note that all these values are chosen quite arbitrarily and you could definitely try out different ones if you want to. However, note that over optimizing them by backtesting and adjusting them over and over again is the quickest way to end up with a useless overfit algorithm. Next up we want to add the data for all available crypto USD pairs. For this I created a list with all these crypto pairs available on the bidfinex exchange. If you are coding along you can copy this list from the description box below. Note that there also is a link in the description box to copy my entire finished code but in my opinion coding along leads to a better learning experience. We now want to iterate through this list and add all the data for these tickers. However, since we want to access certain properties of all these tickers later it makes sense to create a custom class for this. So let's do that first. We will call this class pair and we will start by implementing its python init constructor. As arguments the constructor will take our algorithm, a ticker and a minimum volume which we will use to determine whether or not we want to invest in this pair. Firstly, we now want to add the data for the ticker. We can use the add crypto method to accomplish this. The first argument is the ticker, the second the resolution and the third is where we specify the bidfinex exchange. Next up we want to create a RSI indicator for this symbol. To create an RSI indicator we can use the RSI helper method and specify the symbol, period, type of moving average and resolution. I will go with the most common 40 day RSI but feel free to try out different values. In the next step we want to create an indicator that keeps track of the average daily dollar volume over the past 30 days. For this we will use the indicator extension that multiplies two indicators together. The two indicators that we want to multiply are a 30 day simple moving average of the cryptos volume and a 30 day SMA of its price. With that this volume variable should now keep track of the 30 day average daily dollar volume. Last but not least we save the past minimum volume argument into a class variable. Generally it is good practice to group things together that belong to one ticker by defining a class such as this one. Before we head back to the initialised method of the actual algorithm let me create a method with the name investable. As the name implies this method should return true if the crypto pair is investable. We define this to be the case if the average dollar volume exceeds the minimum volume threshold that we passed when initialising the pair object. With that being done let's now head back to the initialised method of the original algorithm class. Here we can now create a list saving all these custom pair objects by iterating through the lists of the tickers that we specified earlier. After that we set the bitcoin use D pair to be the benchmark of this algorithm. Furthermore we set the warm up time for this algorithm to be 30 days since the indicators that we use require this. After that we are now done with the niche loss method. This means all that's left to do now is implement the on data method where the actual trade decision making will take place. In the on data method we will iterate through our pairs lists. The first thing that we want to do is check if the RSI indicator for the current pair is ready. We do this by checking the isready attribute of the RSI. Next up we save the symbol as well as the current value of the RSI of the given pair into a local variable since we will need these multiple times in the next few lines. In the remainder of this for loop we want to differentiate between two cases. The first being that we already are invested in the current pair. We can test this by checking the invested property of our portfolio. If we are invested there are two conditions that would lead to us wanting to close the position. Firstly, the average volume of the pair might have fallen too low. We can check this with the investable helper method that we defined in the custom pair class. In that case we liquidate the position. Otherwise the RSI might have fallen below our exit threshold which we can check with a simple comparison. In this case we also use self.liquidate to close the position. After that we jump to the next iteration of the for loop since the rest is irrelevant for this case. So in the remainder of this loop we can assume that we do not have any active position in the given pair. Therefore we want to test if the RSI is above its entry threshold. However, we only want to do this if the volume of the pair is high enough which we once again test with the investable helper method. If it's not we continue to the next iteration. Otherwise we test if the RSI is above its entry threshold and that the remaining margin in our portfolio is above the desired position size. If both these conditions are fulfilled we open a position using the self.buy helper method. As the position size we need to divide the position size in USD by the price of the crypto pair. With that we are now done coding this crypto trading algorithm. So let's now click on build and backtest to look at its performance over the backtest time frame. As you can see this seems to be a quite volatile strategy which shouldn't be too surprising considering that it trades very volatile cryptocurrencies. After the end of 2020 this strategy pretty much only breaks even and most of the profits come after that. Here it is important to note that it is very easy to develop a crypto bot that performs incredibly well in backtesting since the crypto space has gone through one of the biggest bull markets ever. Just for reference you can look at the Bitcoin benchmark chart and see its incredible bull run. In general it's not hard to develop a profitable bullish strategy in a strong bull market. However, as soon as the market environment changes most of these strategies would not work anymore. So try to keep this in mind when developing a crypto trading bot. Besides that this strategy likely still falls prey to survivorship bias since we only consider cryptos that are currently supported by QuantConnect and Bitfinex. This list likely would have been different a few years ago. Another interesting chart to look at is the exposure chart which allows you to see the percentage of your portfolio allocated to various long or short positions. Here we can see that most of the time the exposure only was about 5 to 10% of our portfolio which equates to 1 to 2 positions since each position is worth about $5,000. Just once in a while the exposure jumps up to between 30 and 50% for a short period of time. If you want to check out this report and my code in more detail make sure to use the link in the description box below to clone the code. That said I hope you enjoyed this video and learned a lot. If you did make sure to smash the like button, subscribe and turn on the notification bell. Thanks for watching.