Big Mistake

I recently upgraded my OS to Ubuntu 24 (from Ubuntu 22), and was immediately reminded why I always decide afterwards that it was a big mistake. It only happens once every few years, so I forget the pain that happened last time.

Minor issues are fairly easily fixed. Getting 640×480 res on your 4k monitor? No worries, just change the settings back to use the nVidia driver. All your python packages gone AWOL because the system default version of python has been upgraded? Try reinstalling them.

But now there are lots of warnings that there didn’t used to be. ‘This is an externally managed environment, don’t mess with it’. So I could go through the new approach to installing packages system wide, but I’m not sure if I should. Back to using Docker for all my environments. But now jupyter notebooks no longer work. Servers don’t respond. I can’t open a notebook either inside PyCharm or without.

Of course I could go back to using Google Colab for notebooks, or just do everything in .py files. At least they still work. If the packages are installed. Lots of ‘invalid interpreter’ messages on my various PyCharm projects. I have been trying to avoid conflicts by using the system installation wherever possible, but now that that’s been overridden almost nothing works.

When I was doing computer graphics I read somewhere that when a studio starts on a new project they freeze all the software that they’re using, even if the project takes years. One doesn’t want an upgrade on some crucial tool to wreck years of work. I should adopt a policy of getting a new OS only when I get a new computer, which doesn’t happen very often.

Listen to the Machine

Yesterday I had a position open which was down 2%. My intuition was that it would go back up again shortly, but my XGBoost model was giving me a no-go signal. I thought there wasn’t much point in developing the model if I didn’t use it, so I took the loss. For the past day (every six hours) I get another no-go, and indeed the price, while fluctuating a bit, has generally been down. I’m gaining some confidence in the model, especially as so far it gives no-go signals fairly rarely.

Functional Programming

I’ve recently been concerned with the problem of understanding the Python language better. I frequently encounter code that I struggle to parse/interpret. Take the following snippet for example:

final_state_locations =
   next_states.flatten(start_dim=1).max(dim=1)[0].eq(0).type(torch.bool)

I’m sure an experienced python programmer won’t see a problem, but I’m basically an amateur. I picked up basic python, then it’s use in a data science context, so mainly pandas, plus a few statistical functions from scikit-learn or similar package. Now I’m learning how to use Python for machine learning and, well, multi-dimensional tensors in PyTorch are a bit harder to work with than a flat dataframe in Pandas.

So, my quest for greater understanding has lead me down an alternative path. Functional Programming. FP is not about understanding code better. It’s about writing code so that it’s more understandable. Less focus on implementation details and more on general intention. There are a few main principles of this programming paradigm, and one of them is immutable state, and functions without side effects. So I’m wondering how this could possibly apply to training an ML model, which is all about changing node weights to minimize some error function.

I guess there is a FP solution to this problem. Instead of changing weighs one creates a new set of weights from the old weights, and then loads the new weights into the model! Replace the old version with a new version instead of changing the old version. I guess that’s how immutability works, which I first came across when learning about the immutability of strings in Java. I’m not really seeing how this is going to make my code easier to understand. I guess I’ve got a way to go in my understanding of functional programming, or perhaps it’s just not a good fit for machine learning. Anyway, it’s interesting I guess.

On reflection, that example I gave at the top of the post is probably an example of functional programming. A new object is created by running some existing data through a string of functions. Not sure where that leaves me.

Down the Rabbit Hole

Perennial question – how much do I need to know to achieve my goals? Especially when I’m not 100% clear on what my goals are.

In all my studies of ML lately I’m frequently confronted by an inadequate understanding of the basic language. I’d like to become much more fluent in Python, but that’s actually a big job. My current reading, on Reinforcement Learning, adopts a ‘create code from scratch’ approach which I appreciate, but that rabbit hole is looking pretty deep.

I’ve reached the part where they are making extensive, and sophisticated, use of iterators and generators to implement certain functions. RL by nature involves very iterative functionality. So, I’m feeling the need to have a better understanding of iterators and generators, and I already have just the course, or courses, on that. Fred Baptiste has some excellent courses on basic Python functionality (basic as in out of the box, not involving third party libraries such as pandas or scikit-learn). However, each of the fours courses is about 40 hours of content. He’s very thorough. But course 2, which includes iterators and generators, definitely builds on material from course 1, especially scope and closures. That’s a lot of material. And all just so that the book I actually want to study is more accessible. And it’s all just a pastime anyway. So what else might I be doing with my life?

I had a strong interest in computer graphics for about 15 years, mostly 3D but also some digital painting, and spent a lot of time doing courses and workshops, and just creating work. Far more than the time I’m now looking at getting to the next level in Python programming. I have another blog documenting that, sadly now rather neglected.

Fortunately I do have a trading system up and running. There’s some satisfaction in that even if it does need a lot more work to improve it. This makes actually putting time into relevant work not so frustrating. Slogging along with no light at the end of the tunnel can be demotivating, but that’s not where I am at the moment.

One Thing Leads to Another

Whither now? Having got my basic trading system in place I now need to work on the details. I need to actually put together a dataframe (table) with a bunch of returns from several different sources (crypto index, spy, nasdaq, other) all lined up by date. Not difficult, but rather boring. And since my current level of trading is low, and my profits likely to be in the range of a few dollars, motivation is not high. I will get it done but I need to be in the mood for getting boring stuff done, and that doesn’t happen very often. I’m not a details person, which is probably why I suck at languages, art, music, etc.

So I was browsing in my local cheese shop online bookstore and found an interesting looking book on the subject of Reinforcement Learning. I’m trying to stick with PyTorch and am avoiding books that use TensorFlow for code examples, so I went to the GitHub site the authors gave for code access. Lo and behold they eschew all those libraries and basically roll their own. Interesting. One thing I really want to do is improve my mastery of Python as a language, and this seems a good opportunity to do that. It’s great that I can check out what they’re doing in code through GitHub, almost makes up for the inability to actually browse through a shelf of books in a real bookstore like I used to be able to do. Those were the days.

Anyway, Amazon provides a sample to look at before purchase (how I found the GitHub site) and in the introduction they did say one needs a good undergraduate level in probability to follow this book. Probability, not my forte. However, one of the books I have acquired over the years (but not actually read) is Probability for Machine Learning by Jason Brownlee of machinelearningmastery.com. So, as the title says, one thing leads to another.

My main aim is to keep my mind occupied in my doting years. At this stage the trading is just an excuse. I’ve lost too much money in the past through trading that I’ll only risk that again if BTC goes up enough that I have money to burn. At this stage that’s looking pretty unlikely. Even buying a small apartment to mitigate the rental crisis problem here is looking problematic. No matter. I’ll keep those grey cells humming with a good book on probability.

Meta Labelling

I’ve mentioned meta labelling a couple of times, and I think this actually is an example of it (according to Ernie Chan)

[0.09863082 0.90136915]

These two numbers are the result of running my RL model on the latest price data for the cryptocurrency marketcap (w/o BTC or ETH) index. According to the model, these are the probabilities that not buying is the best action, and that buying is the best action, respectively. This model doesn’t give a definite answer, just the probabilities that each available action is the best one. So this could be used to manage risk. If the probability that buy is the best action is a bit low, say 0.7, one could enter a position with reduced size. Or set a tighter stop loss. Or some other risk management strategy.

It’s Done

Finally got a very basic implementation of the RL model up and running, basic in that the input data is just a few lags of the cryptocap chart. Much work to be done, but I do have an XGBoost model predicting the prospects specifically for ADAUSDT over the next few days, and an RL model using broader market data to tell whether it’s ‘a good time to trade’. As I said, much work to be done, but the basic system is in place. From here on – refinement. I’ve been working on this for quite a while now (mostly learning how to implement Deep Reinforcement Learning in the context of trading) and I’m very happy to reach this point at last.

At the moment both models are telling me to trade, but my intuition says otherwise. I think I’ll give it another 12 hours or so to see which way the wind is blowing. Is there still room for intuition? Maybe.

Back to Square One

During the week I had a few small wins, and a larger loss (8%) that wiped out those wins and brought me back to square one. Almost. So, business as usual. Actually I’m 10 cents down on my initial 100USDT, but close enough.

I still haven’t got the RL model up and running, but I have been tweaking the XGBoost model a bit. I’m also changing my basic trading method, now using trailing stops that should prevent larger losses but will probably mean more smaller losses. I’ve come to hate stops over the years because they always have meant that the price drops to hit my stop, sell me out at a loss, than bounce back up again so I can’t buy back in at the lower price. Has this changed? Probably not but I’ll see I guess.

A few insights are emerging from my explorations. XGBoost has a handy feature to print a chart of which features are most important in its decision making, and it seems recent price movements are the least important. The most important features seem to be the total change and the volatility over the past 90 days. I guess those are showing the overall trend. I’m not sure I need an ML model for that.

Basic State for RL

For the input to the RL model that I’ll use to ‘supervise’ the xgboost model I’ve gathered a crypto market cap index, SPY, Nasdaq, and a crypto Fear and Greed index which goes back to Feb 2018. The others go back further than that but I might have to use the Feb 18 as the start date. This should be enough to make a start on constructing state for the RL model and generating rewards.

My plan at the moment is simply to use the 1 day future return on the cryptomarketcap as the reward. I think I need episodes for the A2C model, so I guess I can just use a set number of days for an episode. I’m using daily data for this, not 6 hourly, which I think will work OK, just have to see. There won’t be any direct interaction between the RL model and the XGBoost model. The process will be that the RL model will predict whether it’s ‘a good time to trade’, i.e. positive return on the current day’s state, or not. If not, then whatever the XGBoost model says about trading ADA specifically will be ignored. If both are in agreement on green to trade, then do so. As the RL model is looking at broader market conditions (SPY, Nasdaq, broad crypto index) then the two models should complement each other, or at least that’s the plan. I think this qualifies as an implementation of meta-labelling, although a very minimal and rough one. Well, the proof is in the pudding, as they say.

Actually, having done a quick review of meta-labelling I’m not sure that what I’m doing does qualify as such. However I did read somewhere some pundit opine that using a deep ML model to ‘critique’ a shallower ML model was a good procedure, and I can certainly make the RL model ‘deeper’ than the XGBoost model, if that actually helps.

Note to Self re Spy

For my RL model I’ve decided to use a crypto total market cap index, excluding BTC and ETH, as my main source of data, and will probably generate rewards based on that. All well and good.

So I’m also adding the SPY index, but have problems relating to dates and times. I downloaded data from TradingView, and all the dates have the time portion at 13:30 or maybe 14:30. I’m guessing this is the opening time of the US exchanges (probably NYSE), in UTC time. Also, no Saturday or Sunday prices. I’m sure there’s a proper way to convert the datetime to 00:00:00 hours so that I can concatenate the columns with the cryptocap data but I used a hack. Converting the datetime to just the date (with date() function), saving the dataframe to a CSV file, then loading that back in to a new dataframe, parsing the date column, gave me 2024-08-12 00:00:00 instead of the original 2024-08-12 13:30:00. Also, using the asfreq(‘d’) function on the dataframe filled in the missing weekend days, forward filling with Friday prices. All a bit of a hack but I can’t think of any better way to deal with this issue. Not all data I might want to use for this model will be conveniently in daily format, at UTC time.

Progress – Closed

Trading ADA

Start 11th August 2024. Balance will be updated after each trade is closed. Trades take place at irregular intervals, and for variable lengths of time, so simply numbered here.

UPDATE – STRATEGY CLOSED

I’m moving on to a modified strategy, combining traditional and ML algorithms, one that includes stop losses. Testing shows fewer trades (1 or 2 per month) but fewer, smaller drawdowns. It will be a while before I know how successful that will be.

Tradin’

I don’t have my risk management (trained RL model) in place yet but decided to get started on my ‘trading hobby’ anyway. So, with a prediction from xgboost of an increase of at least 1% in the price of ADAUSDT over the next 5 days, I bought 100USDT worth. I plan to make 100USDT trades, not compounding here. I’ve put a bit more than 100USDT in my Binance spot account to handle any drawdowns. Currently the precision (number of true positives out of all positives) is about 80% so I might lose. I’ll have to consider whether to close when I reach 1% profit, or when 5 days is up, or something else. My strategy is still a bit vague at this point. However this is the first time I’ve traded using a signal generated by an ML model. I’ve seen plenty of warnings not to do that. I guess I’ll find out.

I thought a progress bar might be a nice touch, so I installed the Ultimeter plugin but it doesn’t show for some reason, neither on a page I pasted the code into, nor a post. Maybe my theme doesn’t support it. Too bad. I’ll just report progress from time to time.

UPDATE: Just made my first 1% profit. Was going to hold out for a higher price but my algo predicts the price will not go up by another 1% in next 5 days, so I decided to take profit while it lasted. Be interesting to see what does happen over the next few days.