Fitness functions
A fitness function turns each combination's in-sample result into one score. The Optimizer ranks the combinations by that score and keeps the best ones as candidates. You choose it in Optimize on.
What a fitness function does
For every combination it tries, the Optimizer runs a backtest on the period's in-sample history and works out the result: profit, drawdown, trades and so on. The fitness function picks or combines those numbers into a single score. A higher score is better.
The combinations that pass the filters are ranked by score, highest first. The top ones, as many as Keep best strategy allows, become the period's candidates, and rank 1 becomes its selection. The Performance value column of the Best strategies list shows each candidate's score.
The score only ranks in-sample results. The out-of-sample results are shown next to them, but they play no part in the ranking.
Choose a fitness function
In the Strategy panel, choose one in Optimize on. Setup presets and saved runs keep the choice.
The shipped fitness functions
| Fitness function | Ranks highest | Watch out for |
|---|---|---|
| Max Net Profit | The largest net profit after commission. | It ignores risk: a combination with a deep drawdown can still rank first. |
| Max Profit Factor | The highest gross profit divided by gross loss. | With no losing trades the profit factor is infinite, so a combination with a handful of winning trades can rank first. Set Min trades IS. |
| Max Sharpe | The steadiest monthly profit: mean monthly net profit divided by its standard deviation, times the square root of 12. Months without trades count as 0. | It needs enough months in the in-sample part to mean much. |
| Max Sortino | Like Max Sharpe, but only losing months count as risk. | Same as Max Sharpe. |
| Min Draw Down | The shallowest worst drawdown, measured on open equity, or on closed equity where there is no open figure. | It ignores profit: a combination that barely trades and loses a little can rank first. A combination with no trades ranks last. |
| Min Draw Down Days | The shortest worst drawdown in time: the longest stretch, in calendar days, from an equity peak to the trade that recovered it. | It ignores profit. A combination with no trades ranks last. |
A combination whose score cannot be worked out, for example a profit factor with no winning and no losing trades, ranks last.
The same measures appear in the results' Summary, where you can hold the mouse over a name to read its definition. See Backtest results.
How to choose
Pick the score that matches what you would want from the strategy in live trading. Some points to weigh:
- A score that looks only at profit, or only at drawdown, rewards combinations that do one thing well and the other badly. Use the filters to rule out the extremes: Min trades IS for too few trades, DrawDown level for too deep a drawdown. See Setting up the Optimizer.
- Max Sharpe and Max Sortino work on monthly profit, so give them in-sample parts several months long.
- To compare two fitness functions, run the same setup and periods once with each, save both runs and compare their walk-forward totals. See Saved runs and PDF reports.
Write your own
Fitness functions are scripts, compiled together with your strategies and indicators. The shipped ones are in Documents\AlgoDesk\bin\Custom\OptimizationFitnesses. To add your own:
- Create a new .cs file in that folder, with a new name.
- Write a class like the one below. The
OptimizationFitnessNametext is the name shown in Optimize on. - Set
Valueto the score. The Optimizer keeps the highest values; to prefer a low number, such as drawdown days, multiply it by -1. - Compile the scripts from the toolbar. Your fitness function appears in Optimize on.
using AlgoDesk.Core.DataCalc;
using AlgoDesk.Core.DataCalc.Optimization;
using AlgoDesk.Core.Enums;
namespace AlgoDesk.Custom.OptimizationFitnesses
{
public class MaxCalmar : OptimizationFitness
{
private const string OptimizationFitnessName = "Max Calmar";
public override void OnCalculatePerformanceValue(StrategyBase strategy)
{
Value = strategy.SystemPerformance.Summary.GetValue(AnalyticalFeature.Calmar);
}
}
}
The example scores each combination by its Calmar ratio, one of the measures in the results' Summary. Any measure listed there can be read the same way.
Every update replaces the shipped fitness functions. Do not change them; make your own file under a new name, which updates leave alone.
See How scripts work and Compiling.