Create a Custom Fitness Function for NinjaTrader 8 (NinjaScript)
In this post we will discuss the role of fitness functions in the NinjaTrader 8 platform and create a custom function to be used in optimizing and backtesting trading strategies.
Fitness functions, called Optimization Fitnesses (OF) in NT8, are used during the strategy optimization process. They tell the optimizer what to optimize for, such as net profit, profit factor, drawdown, etc. NT8 comes with many of the standard fitness functions that you need. Still, it also allows you to make your own with NinjaScript.
The profit factor OF has been my go-to fitness function when testing trading strategies. I like it because it factors in net loss and net profit. However, I always compare the drawdown of those results to see what variations are better suited for my risk tolerance. I think it would be cool if we had an OF similar to profit factor that minimized draw down, too, so I created one. With some help from TradeStation, that is.
If you haven't setup your environment for being able to code and debug NinjaScript files you can view the Trade Testing Environment article. Be sure to continuously check out the House Keeping post for updates as well. It is designed to help make navigation around the Substack easier and to keep you informed about what is going on with HGT and the logic behind it. Paid subscribers will have access to this code (and more) on the HGT private GitHub repository. Code will always be updated first on the GitHub before articles get updated and not all the code in the GitHub has an associated tutorial.
Disclaimer: the following post is an organized representation of my research and project notes. It doesn't represent any type of advice, financial or otherwise. Its purpose is to be informative and educational.
The TradeStation Index
In this post, we will recreate the TradeStation Index fitness function for NT8 using NinjaScript. This fitness maximizes net profit and winners while minimizing intraday drawdown.1 It's important to think about keeping these functions as simple as possible. While we could create a multi-objective OF and calculate whatever ratios we think are important into one function, this could lead to overfitting. Ideally, you want to see the same (or similar) parameter optimizations perform well (enough) across different optimizations. In other words, we don't want to design a fitness function that will only show us outliers.