Genetic Optimization
-
Is there any plan to incorporate genetic (or similar) algorithms to optimize a strategy?
I have 2 parameters I need to test with ranges from 1-200 (i'm not overoptimizing/curvefitting) and the brute force method takes forever on a laptop.
For reference: http://outlace.com/Simple-Genetic-Algorithm-in-15-lines-of-Python/
btw, loving the platform so far! nice work
-
It would be great if genetic optimization can be implemented.
In order to avoid long waiting now , I usually do draft optimization with larger parameter steps (say not 1, but 5), identify interesting local areas, and then run detailed optimization with the small step on the local, smaller than original area. This might help.
-
Adding a use case to support uses cases which don't simply go over the entire range of parameters could be considered.
The question is:
- how does one decide if a given parameter combination is the path to follow?
Some options:
- Greater total value
- Larger Sharpe Ratio
- Many others
Some of the analyzers return
dict
which contain for exampledatetime
timestamps andreturns
(for a giventimeframe
) and the core code cannot consider analyzers that people may plug in with unknown values.Some kind of callback would have to be implemented in each strategy to return a score.
-
@backtrader It would be useful to have an ability to use output from any analyzer of the strategy as a goal for optimization and then set an action - maximize it or minimize it.
-
@backtrader said in Genetic Optimization:
Adding a use case to support uses cases which don't simply go over the entire range of parameters could be considered.
The question is:
- how does one decide if a given parameter combination is the path to follow?
Some options:
- Greater total value
- Larger Sharpe Ratio
- Many others
Some of the analyzers return
dict
which contain for exampledatetime
timestamps andreturns
(for a giventimeframe
) and the core code cannot consider analyzers that people may plug in with unknown values.Some kind of callback would have to be implemented in each strategy to return a score.
yes - Genetic Optimizers (or any other optimization algorithm) need a 'reward' function... the output from an Analyzer would be a natural fit for this. Time frame should be the entire run of the strategy, unless it's a walk-forward optimization (which is possibly a different discussion altogether).
In another platform I use - ninjatrader - reward functions are customizable (via C# code) using strategy performance outputs. The reward type is passed to the optimizer as a parameter at execution. Time frames are not allowed in reward functions since the time period to optimize and the days to test out-of-sample are also passed as parameters to the optimizer.
Not sure how all that would translate to the backtrader framework, but this would be key in backtesting a strategy imo.
-
The difference being that in backtrader the analyzers are plugged by the user and there cannot be an incredibly wise function to understand how to evaluate each possible combination of analyzers.
One possible way would be to implement the reward/scoring mechanism by means of an analyzer. This is possible because analyzers can host sub-analyzers.
This mechanism offers an advantage: switching to a different reward mechanism implies only switching from
analyzer_reward_A
toanalyzer_reward_B
.In any case such
analyzer_reward_X
would need to offer a well-defined interface. -
I managed to implement a Particle Swarm Optimization algorithm to optimize two SMA parameters in the example strategy.
The PSO algorithm is part of the opptunity python package at https://github.com/claesenm/optunity
Essentially the steps are:
- define strategy as per usual
- define a function to accept parameters, run the strategy, and return a performance measure (in this case, net value of the portfolio)
- pass function in #2 to the optimizer and let it do its work
- take optimal parameters calculated in #3 and pass into the function in #2 to get result
This method works well, although the opptunity library has some known limitations (e.g. can only work with float-based parameters.. thus having to convert to int in the strategy). Hopefully this is helpful for anyone trying to do the same thing.
# example of optimizing SMA crossover strategy parameters using # Particle Swarm Optimization in the opptunity python library # https://github.com/claesenm/optunity from datetime import datetime import backtrader as bt import optunity import optunity.metrics class SmaCross(bt.SignalStrategy): params = ( ('sma1', 10), ('sma2', 30), ) def __init__(self): SMA1 = bt.ind.SMA(period=int(self.params.sma1)) SMA2 = bt.ind.SMA(period=int(self.params.sma2)) crossover = bt.ind.CrossOver(SMA1, SMA2) self.signal_add(bt.SIGNAL_LONG, crossover) data0 = bt.feeds.YahooFinanceData(dataname='YHOO', fromdate=datetime(2011, 1, 1), todate=datetime(2012, 12, 31)) def runstrat(sma1,sma2): cerebro = bt.Cerebro() cerebro.addstrategy(SmaCross, sma1=sma1, sma2=sma2) cerebro.adddata(data0) cerebro.run() return cerebro.broker.getvalue() opt = optunity.maximize(runstrat, num_evals=100, sma1=[2, 55], sma2=[2, 55]) optimal_pars, details, _ = opt print('Optimal Parameters:') print('sma1 = %.2f' % optimal_pars['sma1']) print('sma2 = %.2f' % optimal_pars['sma2']) cerebro = bt.Cerebro() cerebro.addstrategy(SmaCross, sma1=optimal_pars['sma1'], sma2=optimal_pars['sma2']) cerebro.adddata(data0) cerebro.run() cerebro.plot()
-
Many thanks for the code!
It is quite short and easy to understand -
I've tried
pyevolve
library for evolutionary optimization. This is first shot for the system shown above (2 params only, but lets be consistent), takes longer time than particle swarm optimization.# example of optimizing SMA crossover strategy parameters using # evolutionary Optimization in the pyevolve python library # http://pyevolve.sourceforge.net/ from datetime import datetime import backtrader as bt from pyevolve import G1DList from pyevolve import GSimpleGA class SmaCross(bt.SignalStrategy): params = ( ('sma1', 10), ('sma2', 30), ) def __init__(self): SMA1 = bt.ind.SMA(period=int(self.params.sma1)) SMA2 = bt.ind.SMA(period=int(self.params.sma2)) crossover = bt.ind.CrossOver(SMA1, SMA2) self.signal_add(bt.SIGNAL_LONG, crossover) data0 = bt.feeds.YahooFinanceData(dataname='YHOO', fromdate=datetime(2011, 1, 1), todate=datetime(2012, 12, 31)) def runstrat(chromosome): cerebro = bt.Cerebro() cerebro.addstrategy(SmaCross, sma1=chromosome[0], sma2=chromosome[1]) cerebro.adddata(data0) cerebro.run() return cerebro.broker.getvalue() genome = G1DList.G1DList(2) genome.setParams(rangemin=2, rangemax=55) genome.evaluator.set(runstrat) ga = GSimpleGA.GSimpleGA(genome) ga.setGenerations(5) ga.setMutationRate(0.2) ga.setCrossoverRate(1.0) ga.setPopulationSize(10) ga.evolve(freq_stats=1) print ga.bestIndividual()
-
I've put more efforts trying to apply
optunity
module. It maybe not a discussion related tobt
, but it would be nice to hear from people used/usingoptunity
. If you can point me discussion board foroptunity
, I would appreciate it. I've run number of their solvers with different number of evaluations and received interesting results.Strategy: 5 parameter strategy, 3 indicators. Total amount of parameter configurations 48 x 48 x 48 x 248 x 98 = 2,687,827,968 :). Recovery Factor (RF) was maximized.
For optimization I've used the following
optunity
solvers:particle swarm
,sobol
,random search
,cma-es
,grid search
with standard settings. I know that other trading software widely usesparticle swarm
andcma-es
, so these solvers were my main hope.I've made 4 runs for each of the following number of evaluations: 100, 250, 500 and 750 (twice only).
Results:
particle swarm
,sobol
,random search
: for the same number of evaluations each separte run gave different sets of parameters and different optimal RF. These RFs were quite far from maximum value.cma-es
: same optimal parameters for 100, 250 and 500 evaluations resulted in zero RFs (meaning roughly negative returns of the strategy). And only 750 evaluations resulted in some positive values, again far from maximum value.grid search
: same optimal parameters for all runs for the same number of evaluations, number of evaluations affects slightly, resulted in maximum RF from all study. Also took 2-2.5 less time compare to other solvers for the same number of evaluations.Best solver -
grid search
, which surprised me a lot.Inviting @d416 @Harel-Rozental
-
Hi,
Well grid search should be the same as what backtrader does when you do optstrategy,
so given the data-caching and other things it does behind the scenes it should be even faster for that.I don't see why grid-search should be faster than "smarter" algorithms, though obviously it is always optimal (in the constrained region).
Weird.My intention is to try to make backtrader let me use optstrategy's speed with smart algorithms such as particle swarm or a variation of hill-climbing
-
@ab_trader said in Genetic Optimization:
Best solver -
grid search
, which surprised me a lot.Excellent work. Grid Search is basically a run of all permutations of parameters so I'm also surprised it took less time. My only guesses for the reasons behind these results are:
- fetching the stats from cerebro in a wrapper function may not as efficient as the native optimizer would do it
- your Recovery Factor must be calculated at some point during the iterations... maybe this is slowing it down?
- In terms of grid search bearing the best RF, I find that algorithmic optimizers are best used if the goal is to find patters within data. Any type of reward that incorporates profit (net, gross, profit factor, etc.) are the best to use imo, since these optimizers tend to 'zero in' on the one optimal answer. With RF, there could be multiple optimal answers yielding slightly different results, so an optimizer may just end up picking a solution right down the middle. For these types of problems - i.e. the ones where a grid search would yield the best out of multiple possible results, Machine Learning algorithms would be the way to go. Example: http://machinelearningmastery.com/grid-search-hyperparameters-deep-learning-models-python-keras/
My personal preference in optimizers is to get the top 10 iterations by measure of profit, then pick the best one that yielded a strategy-specific statistic. This ensures that I'm finding the patterns in the market as opposed to my strategy.
Full disclosure: I'm not an expert by any means and I only know what I've read out there.. Also, Python is new to me, but hope it all helps people somehow nonetheless.
If you can point me discussion board for optunity, I would appreciate it.
According to the docs, this is the place to post optunity questions and comments:
https://gitter.im/claesenm/optunity
The creator also provides an email address:
marc.claesen@esat.kuleuven.be -
Something I just thought about - are you sure it's the same number of evaluations?
If you look at a parameter such as period, going from 1 to 5,
GrisSearch only has to run 5 times on it, whereas the other algorithms go over real numbers so they also try things such as 1.25 (which is just another way of saying 1 for this parameter). -
@Harel-Rozental I've used same number of evaluations as an argument for
optunity.maximize
. Maybe internally it is transformed to the different amount of runs for evaluation function, I didn't check internal processing. -
@d416 Thanks for the link!
I've done optimization study on the Net profit, will post results later.
I was also thinking that my number of evaluations (750 max) covers only tiny part of the all possible configurations, and it can be a reason that
grid search
is better, since it covers all the field even sparsely and has more chances to get to the maximum. Others simply stick in the localized area. -
So in terms of stable outputs search methods (
sobol
,grid search
,random search
) won the race for Net profit optimization.grid search
is least time consuming.particle swarm
method might give more optimal results with larger number of evaluations and larger number of runs. Probably it will be more effective on smaller parameter spaces.Maybe the good approach is to make 2 step optimization:
- identify some intermediate optimal parameters using search approaches
- select smaller space near these parameters and run smarter approaches
-
Hi,
am I right, that it is not necessary anymore to use external libraries like optunity, because now there is a built-in optimizer (cerebro.optstrategy()) - see docs/quickstart/quickstart11.py?
Thanks in advance!
-
The built-in optimization (
cerebro.optstrategy
) was always there from day one. This thread is about Genetic Optimization which implies not simply blindly traversing the cartesian product of all possibilities, but choosing and discarding paths based on outcomes ofrun
. I.e.: If you have 3 parameters and one of the runs gives you a-50%
profit, it is highly unlikely that slightly modifying one of the parameters for the nextrun
is going to suddenly make you reach. It will likely deliver a result around-50%
. You can therefore discard this part of the tree and focus on some other branches. -
@Paska-Houso said in Genetic Optimization:
The built-in optimization (
cerebro.optstrategy
) was always there from day one. This thread is about Genetic Optimization which implies not simply blindly traversing the cartesian product of all possibilities, but choosing and discarding paths based on outcomes ofrun
. I.e.: If you have 3 parameters and one of the runs gives you a-50%
profit, it is highly unlikely that slightly modifying one of the parameters for the nextrun
is going to suddenly make you reach. It will likely deliver a result around-50%
. You can therefore discard this part of the tree and focus on some other branches.Thanks!
-
@ab_trader
I copied and tried optunity's 'grid search' option. What I found is that the searching term between parameter values are decided by num_evals. (High num_evals => 1..2..3..n/ Low num_evals => 1..5..10..n) That's why grid search is faster than the theory.