Survival Of The Fittest
Intro
Friendly reminder that none of the content on my blog is to be considered financial advice.
Well the gloves have come off; it’s time to slam my problem; I am taking the nuclear option…alright, alright this is a trading post not a political one I’ll nock it off with the buzz words.
I have been on a slight hiatus from writing the last few weeks because I undertook a rather large project… Genetic optimization.
Artificial intelligence is considered the holy grail for automated traders, especially on the retail level. Though it is far from deep learning I am hoping that It can help give me seek out and find edges in the markets that I have yet to truly exploit, specifically the short side of crypto, BTC pairs and stocks. Even better as with most non-trading specific pieces of my software I will be making the library open source just as soon as I polish it off.
Starting with the basics genetic optimization is a metaheuristic inspired by the process of natural selection that belongs to the larger class of evolutionary algorithms (big thanks to Wikipedia on that one). Through a population of classes (bots) into a fitness test (trading a specific time frame and asset) and then rate them on a score (in our case net gains divided by net losses) and base on that score mix and match their parameters into the next generation while randomly tweaking a parameter here or there. The goal is to produce a group of parameters that converges on a global maximum score.
I hope I got all that squared away for you guys. Here we go into the nitty gritty.
The Bot
Without boring you with the details here is the logic as it exists with the bot I designed for this process.
switch (bot.stage) {
case 0: //intro
if (ma1 < ma2) {
bot.setStage(1);
} else {
bot.setStage(3);
}
break;
case 1: //wait for long
if (ma1 > ma2) {
bot.trade_manager.marketEnter(cpd, () => {
bot.next();
});
}
break;
case 2: //exit long and flip
if (ma1 < ma2) {
bot.trade_manager.marketExit(cpd, () => {
bot.reset(3);
bot.trade_manager.marketEnterShort(cpd, () => {
bot.setStage(4);
});
});
}
break;
case 3: //wait for short
if (ma1 < ma2) {
bot.trade_manager.marketEnterShort(cpd, () => {
bot.next();
});
}
break;
case 4: //exit short
if (ma1 > ma2) {
bot.trade_manager.marketExit(cpd, () => {
bot.reset(1);
bot.trade_manager.marketEnter(cpd, () => {
bot.setStage(2);
});
});
}
break;
}
It is a simple strategy that keeps the bot switching back and forth from long to short and vice versa. I handle my bots’ logic like rocket stages moving from one state to another during the trading process. Stage 0 here is the intro stage, when the bot starts up it looks to see what the current position is and then goes and waits for that position to change so it doesn’t try to play catch up in a trade that it didn’t see the signal on.
I am not expecting this to truly work especially given the research I did recently on the difference in up and down moves in BTC. I hardly expect both sides to work on the same parameters. This is just a simple experiment to test the genetic optimization platform I created.
The Expierment
First run through was a population size of 40 and 20 generations of optimization. This took 14 and a half hours to run on my desktop. On average a back test of 2016 to present takes 3-5 minutes and I run them in batches of 8. There are a lot of places where I can improve performance form the back testing itself to pipelining the runs to always have the full 8 going at once. This will come in later weeks. For now, let’s look at the results.
The best preforming individual for the above strategy was a moving average one length of 72 and a moving average 2 length of 240. It should be noted that the maximum bound for the variables was 250. This is a relatively slow signal time compared to the “recommended” length of the strategy. The profit factor for the strategy was 1.63, for perspective Hulk the strategy I made early one and have consistently traded on BTC has a profit factor of over three. So, I do not think we discovered anything remarkable but let us look.
Yeah, I think my presumption was correct. The strategy performed really, we in 2016-2017 and briefly touched new equity highs in 2018 but then bled out all of 2019 till now. That is not to say there isn’t anything there, I would want to see how much the short and long side both contribute to the gains of the strategy. Based on past research I really do not think the simple moving average lengths would be one size fits all for shorts and longs.
If you have the means to play around with the parameters do some back testing of your own and let me know what you think.
I will follow up next week with the breakdown of the long and short halves of this computer designed monstrosity. Until then enjoy your week and thank you for stoping by.