Proof of the Pudding

The proof of the pudding is in the eating – ancient proverb. My xgb model has been predicting a 2% rise for a couple of days. The prediction is actually for a 2% rise within the following three days, so time is running out for this to be proven true. I have a sell order in place to sell my trial ETH when/if it rises 2%. Will it be executed soon? Is this xgb pudding good?

Update:

Well, well, well. My model has decided over the past few hours that the price is not going to go up 2% after all. In fact it’s going to fall at least 2% in the next three days. What to do? I think I’ll just leave my sell order in place and hope it changes it’s mind again.

On reflection…

With ETH/BTC trending down, it’s actually to be expected that the ‘trading range’ will drop over time. So I simply adjust my selling price down a bit, and buy back price down a bit (to the ‘new low’) and make my 2% as before.

The model should cope with a downward trend, because I’m using returns rather than actual prices as inputs. Maybe my RL model, once I get it up and running, will deal with these issues. I am putting some time into rounding out my knowledge of PyTorch so that I can port any TF code to that framework. Issues of backwards compatibility seem to be a bit more serious with TF than with PT, and I’m thinking that a comprehensive understanding of one platform, rather than a ‘good enough’ understanding, will be the best way to go from here on.

Inconsistency!!

I hate inconsistency. It drives me crazy. I’m reviewing basic operations in PyTorch and I think I’ve discovered a major cause of the confusion I often feel when reading pytorch related code.

Given a matrix (or 2D tensor) m x n, one can select columns. If you select 2 or more columns you get an m x no. of cols tensor as a result. Two dimensions. But if you select only one column, you don’t. You get a one dimensional m vector as a result. The second dimension has been dropped!! No wonder there are so many squeeze and unsqueeze and reshape calls in pytorch code. To my simple mind if you select a column you should get a column, but no. Well, maybe now I can reduce my confusion when reading this sort of code somewhat. I just wish they hadn’t done that. I’m probably just proving what an idiot I am.

The Trend is Your Friend

This is one of those classic aphorisms in trading. I’m heeding it at the moment, only doing short trades given that ETH/BTC has been trending down for nearly two years. So, if the price goes up a bit (technically a retracement in a downward trend) I sell some borrowed ETH for BTC, and when it drops a couple of percent I buy the ETH back again. Backtesting with my XGBoost model over the past year gives approximately 100% profit doing this, on recently updated prices.

Since most of my schemes make some money for a while and then lose a lot I’m not putting too much capital into this. I make $100 here and there. If it remains profitable for six to twelve months I might consider increasing my positions. Probably by then the strategy will stop working. My pessimism comes from experience. Any sensible person would have given up by now.

Christmas Comes Early

For a few months I’ve been anticipating the publication of Reinforcement Learning for Finance by Yves Hilpisch, supposedly in December, according to Amazon. However I found today that it is already available, and have purchased the Kindle edition. All the books I have on RL deal with non-financial problems, except for one by Ivan Gridin that has a chapter on RL in stock pricing, although it is a bit simplistic. So this text promises to fill a gap, which is exactly what Dr. Hilpisch said in his introduction.

I’m just about to get into it, and fortunately I have become a lot more comfortable with Tensorflow lately, and I expect that’s what he’ll be using. I don’t know how much time I’ll be able to devote to this at the moment – I have a few pressing matters to sort out over the next couple of months. However there’s no way I can not get started, at least. I’m hoping that all the study that I’ve already done on RL will make this book fairly easy to work through. Anyway, we’ll see.

Update:

Well, that was disappointing. I’ve reached Chapter 2, which starts to discuss DQNs, and the associated code gives me errors. The (first) error message suggested a fix, but in trying to implement it I ran into dependency issues and now I don’t know where I stand. I should be able to run it on the remote platform provided by the company associated with the author, but having bought one book there I have difficulty registering a second or third. I should eventually be able to work on their REPL platform, but it might take a while. The book was only published a week ago. I guess I can get something out of it without running their code. I don’t know Tensorflow well enough to be able to hack problems like this (yet).

On further thought:

One reason for using Tensorflow is the large amount of learning material available which uses that library. However it seems the change from Keras 2 to Keras 3 was sufficiently large to break older code. I’m rethinking my decision. Besides, it’s the principles that I need to learn, not any specific implementation. Of course getting code up and running helps learning principles, so a bit of a chicken and egg situation. I just need to master one library sufficiently that I can implement anything in it. I’m leaning towards PyTorch.

Discretionary Trading

Discretionary trading (aka trading on intuition) is what I’m doing at the moment, trading the ETH/BTC pair, short only. I can’t borrow and trade on Binance, but I can borrow elsewhere (AAVE), transfer to Binance, then trade it for BTC, so effectively a short even though Binance does not allow me to margin trade completely on Binance. I’m only trading a small amount, basically paper trading except that I am using a small amount rather than ‘fake’ coins. I’ll see what results I get in six to twelve months. Ernie Chan says anything less than that is not a meaningful test of a strategy.

I do check the XGBoost predictions from time to time, but there’s a bit of a disconnect between the predictions and my intuition. I’ll work on refining the signals when I get a bit more time. At the moment I’m taking a break from machine learning. A while ago I mentioned implementing a neural network that uses LSTM, and that’s certainly on my todo list. Preparing to move house is taking time and energy at the moment. PLus I’m getting out and getting some exercise, rather than sitting at the computer all day.

Meanwhile…

I’ve been concentrating on machine learning for quite a while now, but before that I had a significant interest in visual art. I’m getting back into photography after a long hiatus. For many years I’ve been doing computer graphics, both 2D and 3D but I started with photography. If interested check out my other blog.

LSTM

I finally got an LSTM up and running, courtesy of the course Neural Networks in Trading from Quantinsti. So, just running their code, but it really isn’t much more complicated than an ordinary MLP. Also I’m warming to Tensorflow. It has some nice features such as saving the current best model as training progresses, and it appears to integrate well with scikit-learn, which has some pipeline related features that could be useful once things get more complex.

The above graph represents an interesting idea. The spread between predictions and actual value is plotted and trades using a mean reversion strategy. Bollinger Bands at 2 STD are shown. So many possibilities. I could include some version of an LSTM in an ensemble along with my XGBoost model and the (furure) RL model. Maybe I’ll find something that is consistently profitable some day after all.

Disconnect

Train Accuracy: 99.42%
Test Accuracy: 85.93%
              precision    recall  f1-score   support

         0.0       0.88      0.93      0.90       545
         1.0       0.80      0.72      0.76       375
         2.0       0.88      0.89      0.88       416

    accuracy                           0.86      1336
   macro avg       0.85      0.85      0.85      1336
weighted avg       0.86      0.86      0.86      1336

These are pretty decent results for my current version of the model, using 4 hr. data. However despite getting buy signals for the past couple of days (that’s 6 buy signals per day) my current trade is in drawdown and would have hit the stop loss if I had actually set one. Of course the predictions cover a five day horizon, so still time to recover. But not very encouraging. The prediction is that price will go up and that it will not go down too far during the period, which is already invalidated.

I can’t see myself making any improvement on the above results, which are already hard to believe for this context. I must surely have some logic error somewhere. Anyway, time to go back to developing the RL model, with the intent of using them both in an ensemble. Meanwhile I must find a new place to live, work on this project will suffer.

Timeframe

I finally got around to changing from the 6 hour timeframe to the 4 hour timeframe. This gives me 50% more data to work with! Made a couple of minor adjustments but processing essentially unchanged. Target is still whether or not price reaches 2% take profit without hitting -2% stop loss, in the following 5 days. Testing the XGBoost model gave improved accuracy and precision, and backtesting over the past year (not counting moving averages or anything else) gave a slightly better return than previously. All in all a good move, and I don’t have to wait so long during the day for an update.

Shortin’

Just completed the first profitable trade using my new strategy, with a 2% profit. I’ve made a couple of other trades but basically opened and closed at same price due to changing signals from the strategy. This recent trade was a short, borrowed ETH on AAVE and sold it on Binance. Price dropped overnight and my OCO order was filled to cover. The way ETH is going against BTC lately I think all my profitable trades will be shorts. I’m going for 2% take profit, 2% stop loss. Not since my earliest days in trading have I used stop losses consistently. Maybe that’s why I always lost money.

UPDATE

Just lost it again. My model said the price would recover, but it didn’t. In fact it dropped a further 2% and my stop on the new long got hit. Win some, lose some.

Coming Together

It’s been a bit of a struggle, but I feel that my understanding of machine learning, and especially neural networks, is coming together. The books I’m currently reading, Artificial Intelligence in Finance, by Yves Hilpisch, and Deep Learning with Python by Francois Chollet, are fairly easy reading. I’ve accepted that I’ll have to work with Keras/Tensorflow and it’s really not that different from PyTorch. It’s all just getting a bit easier.

Meanwhile I’ve got my trading strategy up and running, but not going anywhere at the moment. Still early days. It’s not actually using a neural network yet, but that will come too eventually. Ensemble methods seem the way to go for good results and I’m hoping that combining several different algorithms will eventually get me good results.

Reference Point

Train Accuracy: 99.94%
Test Accuracy: 77.88%
              precision    recall  f1-score   support

         0.0       0.79      0.87      0.83       362
         1.0       0.70      0.63      0.67       243
         2.0       0.83      0.79      0.81       281

    accuracy                           0.78       886
   macro avg       0.77      0.76      0.77       886
weighted avg       0.78      0.78      0.78       886

The above results are what I am currently getting with my XGBoost model, using a test size of 10%. As previously mentioned, the classes are

  • 0 – Sell
  • 1 – Do nothing
  • 2 – Buy

Those scores aren’t too bad, but I’ll work on improving them. I’m posting here for the record. One think I might try is to use log returns instead of returns. Finance people seem to prefer those. Apparently they are more normally distributed than regular returns, which is considered a good thing.