I created an algorithm that improves any
investment strategy. Here’s how it works.
A guide on how to use AI to create and
optimize any trading strategy
When I was a graduate student at Carnegie
Mellon, I learned about a rare and powerful
algorithm – genetic optimization.
The genetic algorithm is unlike any AI
algorithm. When I saw how we used it to
transform a chaotic jumble of random strings
into the exact target phrase ‘To be or not to
be.’ — all by simulating natural selection — I
was blown away. I thought about how I can apply
this to real-world problems.
As an avid investor, my mind immediately went to
how we can apply this same algorithm to optimize
investing strategies.
I coded the algorithm with resounding success,
creating a tool capable of theoretically
improving any investment strategy. Here’s how it
works.
What is a Genetic Algorithm?
A genetic algorithm is a biologically-inspired
AI algorithm that operates differently than
ordinary Machine Learning (ML) algorithms.
Traditional optimization algorithms require
gradients. These
gradients basically tell us how we ought to move
the parameters of the thing we’re trying to
improve in order to get closer to our final
goal.
For example, with large language models, these
gradients tell us how to adjust the weights and
biases in order to better predict the next token
in a sequence.
Genetic algorithms, however, do not use
gradients.
They work by using a combination of operators
that mimic real-world biological phenomenon. For
optimizing a trading strategy, they are used to
continuously find the best set of trading
strategies without calculating
gradients, which
are impossible for most set of complex problems.
In the context of trading strategy optimization,
these operators are:
-
Initialization:
Creates the initial population of random
investment strategies, starting from a
specific strategy, and making random changes
to it.
-
Selection:
Picks the best performing strategies from the
population, similar to “survival of the
fittest” in nature. Better performing
strategies have a higher chance of being
selected.
-
Crossover or recombination: Takes two successful strategies and
combines their features to create new
“offspring” strategies. Like genetic
recombination in biology, this creates new
variations that might perform even better than
their “parents.”
-
Mutation:
Randomly modifies small parts of our
strategies to maintain diversity and explore
new possibilities. This prevents the algorithm
from getting stuck in local optima.
-
Evaluation:
Tests each strategy against historical data or
simulated scenarios to measure its
performance. Better performing strategies get
higher “fitness scores.”
-
Replacement:
Removes poorly performing strategies and
replaces them with new offspring, maintaining
a constant population size while improving
overall quality over generations.
Knowing that these rare algorithms can optimize
any function, I sought to implement it into my
trading platform.
And now everybody in the world has access to a
trading strategy optimization algorithm. Here’s
how it works.
Optimizing a trading strategy
I created a platform that is capable of
optimizing any investment strategy using genetic
algorithms. I’m going to show how I’m using the
OpenAI o1 model and genetic algorithms to create
the best simple moving average crossover
strategy.
1. Creating an initial trading strategy with AI
First, we’ll go to
nexustrade.io/chat, and switch the
model to OpenAI’s o1 model. We’ll then type the
following into the AI chat.
Create the best Simple Moving Average
Crossover strategy for META stock
We need at least 1 buy strategy and at least 2
sell strategies, including stop losses and/or
take profits
Unlike other large language model, the O1 model
“thinks” about the question. In theory, this
thinking helps the model create the best trading
strategy that it possibly can.
After around 3 minutes, the model comes up with
the following strategy.
The results of the O1 model
If you want to see the full conversation for
yourself,
check out this link.
We can see that the model created a profitable
investing strategy. Let’s zoom in on it and see
the exact trading rules.
The SMA trading strategy for META
While this strategy is already good, we’re gonna
make it better with genetic optimization. Let’s
create a new portfolio and move on to step 2.
2. Define our optimization parameters
Our new META Portfolio
After creating a portfolio, we’ll be
automatically navigated to the portfolio's
dashboard. On the dashboard, we can see a big
OPTIMIZE button.
We’ll click that button, and once we do, a modal
will pop-up.
The optimization configuration for this
portfolio
The platform has many different fields we can
use to optimize our portfolio. We can click the
“?” next to the field, and it’ll briefly explain
its purpose.
For an in-depth guide on what these parameters
do,
check out the following article.
For now, we’ll leave most of the parameters to
their default value, but change the following:
-
Increase the population size from 25 to 30
-
Increase the number of generations from 5 to
50
-
Increase the number of windows from 3 to 6
-
Increase the mutation from 0.1 to 0.3
-
Modify the first “fitness function” to
percentChange.
-
Change the start date to 01/04/2017
The updated optimization configuration
We’ll then click submit. This starts the
optimization process.
3. Optimize the portfolio and understand what’s
happening
The optimization process in action
The optimization process is an iterative
algorithm that slowly improves the performance
of the portfolio across time. In this example,
the two things that will be improved, called the
“fitness functions", are the final percent
change and the average drawdown.
The percent change is simply the ratio between
the final portfolio value and the initial
portfolio value. Higher values are preferred.
In contrast, the average drawdown is the average
distance from the highest point in the graph to
the subsequent lowest point. Lower values are
better because it means the portfolio didn’t
experience many large drops while being
deploying
By optimizing these two objectives, we’ll create
an entire population of portfolios. Some will
have a high percent change but a relatively
higher drawdown. Others will have a low percent
change, but near-0 drawdown.
By generating an entire population, we can look
through all of the different options, and pick
the best portfolio with a trade-off between the
two “fitness functions”.
Larger windows take longer to optimize than
shorter windows. Because we're optimizing across
7 years, the process will take longer than if we
were to optimize over 1 to 2. So, we must wait.
Twenty minutes later, we receive an email
notification that the optimization process is
complete. Let’s see our results.
4. Explore our final population of optimized
portfolios
The final optimization results
After a short amount of time, we’ve successfully
generated a population of trading strategies,
each better than the initial portfolio.
On average, here’s how our portfolio changed
from generation 1 to generation 50 in the
training set.
-
Percent Change: 11.65% => 29.49%
-
Sharpe Ratio : -0.17 => 0.33
-
Sortino Ratio: -0.18 => 0.24
-
Max Drawdown: 9.41% => 13.49%
-
Average Drawdown: 2.32% => 2.15%
As we can see, the average performance increased
for nearly every metric. the percent change,
risk-adjusted returns, and average drawdown were
also significantly better towards the end.
This boost in performance isn’t just limited to
the training set. The validation set, or the set
of data that is used to evaluate the model's
performance on unseen data during training, also
improved significantly.
The validation set performance
From generation 1 to generation 50, the
validation set performance had the following
improvements:
-
Percent Change: 44.44% => 72.41%
-
Sharpe Ratio : -0.35 => 0.39
-
Sortino Ratio: -0.06 => 0.29
-
Max Drawdown: 21.84% => 24.88%
-
Average Drawdown: 5.19% => 2.75%
Just like in the training set, the validation
set performance improved
significantly for
every metric except the maximum drawdown.
Objectively, we’ve created a population of
portfolios that outperform the original
portfolio,
even when tested on unseen data.
We can now browse the different portfolios that
we created. Some of them have a drawdown of 0,
because they didn’t make a single trade. This is
the “best” portfolio if we consider max drawdown
as the metric that we want to improve (because
we can’t have a better drawdown than 0).
An example of a portfolio with a drawdown of 0
Other portfolios have an insanely high percent
return, with a higher drawdown. Here is one such
example:
A portfolio with a high percent return
With these amazing returns, you would think that
we successfully cracked the stock market, right?
Unfortunately, it’s not THAT easy.
A deeper look on our generated portfolios
With these above results, we would naturally
think that we cracked the code for algorithmic
trading.
Unfortunately, it’s not that easy. If we zoom in
on our above strategy, here’s what we see.
The backtest performance of our strategy
Within the past year, our portfolio didn’t make
a single trade at all! The S&P500 increased
more than 20% in the year, and our portfolio was
completely flat!
This is true for all of our optimized
portfolios. This happens because stock market
returns are
nonstationary, meaning the distribution of returns change over
time.
In other words, returns for stock returns for
one year might change for the next.
And, even though the performance of our strategy
is satisfactory when we zoom out an additional
year, the reality is that this simply isn’t good
enough for real-world trading.
The backtest performance of our strategy for
the past two years
Fortunately, not all hope is lost. There are a
number of things we can do to solve our problem.
Solving this problems
We just learned that optimizing our trading
strategy is more complex than clicking a single
button. However, there are still a number of
things we can do.
For one, we can tune our hyperparameters. It
might be the case that optimizing for the past
year is better than optimizing for the past few
years.
Changing our optimization range
Additionally, we can make modifications to our
indicators themselves.
For example, we can update the range of possible
values for the optimization. By updating the
left SMA to be between 20 and 40 and the right
SMA to be between 200 to 400, we’ll force the
left indicator to always be less than the right
indicator.
Updating the min/max value for the left SMA
indicator
This may allow the optimization process to trade
more frequently.
So, while the optimization process isn’t
perfect, there are ways to improve it, all
within the NexusTrade app. The curious investor
can dive deeper into it, and see if they can
discover the secrets to automated trading
strategy optimization.
Conclusion
Genetic algorithms are a unique and powerful
optimization algorithm, capable of optimizing
nearly anything. Unlike traditional optimization
algorithms, they don’t require
gradients, and
can be used to optimize complex things such as
trading strategies.
And thus, inspired by my CMU class project, I
applied genetic optimization to the stock
market. While the results initially looked
promising, both on the training set and
validation set, we can see that the portfolios
didn’t make a single trade for the year of 2024.
While genetic algorithms show immense promise
for optimizing trading strategies, their
application requires careful fine-tuning and
real-world adjustments. With NexusTrade, retail
investors have unprecedented access to these
advanced tools, empowering them to bridge the
gap between theory and practice and unlock new
possibilities in algorithmic trading.
Don’t believe me? Try it for yourself. Getting
started is free.