Hunt Gather Trade

Hunt Gather Trade

Share this post

Hunt Gather Trade
Hunt Gather Trade
Create a Custom Fitness Function for NinjaTrader 8 (NinjaScript)
Copy link
Facebook
Email
Notes
More
User's avatar
Discover more from Hunt Gather Trade
This Substack is a refined version of my notes taken while exploring how to be self-sustainable in the markets. I am attempting to understand, and hopefully deploy, automatic/hybrid trading systems. Tutorials, concepts, strategy research, code and more.
Over 1,000 subscribers
Already have an account? Sign in

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.

Larry Kann's avatar
Larry Kann
Dec 08, 2023
1

Share this post

Hunt Gather Trade
Hunt Gather Trade
Create a Custom Fitness Function for NinjaTrader 8 (NinjaScript)
Copy link
Facebook
Email
Notes
More
2
Share

Update:

This artcle was originally published for paid subscribers but has since then been set free. It has been some time since I have visited this article or used NinjaScript/NinjaTrader. Reach out if you have any questions.


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.

a black and white photo of a number of calculations
Photo by Dan Cristian Pădureț on Unsplash

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.

Code

The calculation for the TradeStation Index is:

Net Profit * NumWinTrades / AbsValue (Max. Intraday Drawdown) 

We will create a few helper functions to help get the values needed for this OF. We will use these functions to define our calculation and create some simple logic to help remove any funky results. Lastly, we assign the "Value" of the OF the result of our calculation. All of the logic for our calculation will be performed inside the OnCalculatePerformanceValue() method.2

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace NinjaTrader.NinjaScript.OptimizationFitnesses
{
    internal class TradeStationIndex : OptimizationFitness
    {
        private double _drawDown;
        private double _fitnessFunction;

        protected override void OnStateChange()
        {
            if (State == State.SetDefaults)
                Name = "Trade Station Index";
        }

        protected override void OnCalculatePerformanceValue(StrategyBase strategy)
        {
            _drawDown = Math.Abs(GetDrawDown(strategy));

            if (_drawDown == 0)
            {
                _drawDown = 1;
            }

            _fitnessFunction = GetNetProfit(strategy) * GetWins(strategy) / _drawDown;

            if (double.IsInfinity(_fitnessFunction) || double.IsNaN(_fitnessFunction))
                _fitnessFunction = 0;

            Value = _fitnessFunction;
        }

        #region Helper Funtions

        private double GetNetProfit(StrategyBase strategy)
        {
            return strategy.SystemPerformance.AllTrades.TradesPerformance.NetProfit;
        }

        private double GetDrawDown(StrategyBase strategy)
        {
            return strategy.SystemPerformance.AllTrades.TradesPerformance.Currency.Drawdown;
        }

        private int GetWins(StrategyBase strategy)
        {
            return strategy.SystemPerformance.AllTrades.WinningTrades.TradesCount;
        }

        #endregion
    }
}

Conclusion

There is nothing incredibly complex about creating this particular Optimization Fitness. In the future, I will experiment with creating some multi-objective optimization functions using some of the more popular metrics that people like to look at when testing their strategies. It would appear that we could also create a custom optimizer to use (instead of the one built-in), if one were inclined to do so.

Feel free to comment below or e-mail me if you need help with anything, wish to criticize, or have thoughts on improvements. Paid subscribers can access this code and more at the private HGT GitHub repo. As always, this newsletter represents refined versions of my research notes. That means these notes are plastic. There could be mistakes or better ways to accomplish what I am trying to do. Nothing is perfect, and I always look for ways to improve my techniques.

1

Trade Station Fitness Function Fields

2

Optimization Fitness


Subscribe to Hunt Gather Trade

By Larry Kann · Launched 2 years ago
This Substack is a refined version of my notes taken while exploring how to be self-sustainable in the markets. I am attempting to understand, and hopefully deploy, automatic/hybrid trading systems. Tutorials, concepts, strategy research, code and more.
Celan Bryant (CB)'s avatar
1 Like
1

Share this post

Hunt Gather Trade
Hunt Gather Trade
Create a Custom Fitness Function for NinjaTrader 8 (NinjaScript)
Copy link
Facebook
Email
Notes
More
2
Share

Discussion about this post

User's avatar
Celan Bryant (CB)'s avatar
Celan Bryant (CB)
Dec 8, 2023

Interesting. How does this match up against the "strength" fitness function?

Expand full comment
Like
Reply
Share
1 reply by Larry Kann
1 more comment...
Strategy 9 -- An NDX rotational momentum strategy
This strategy captures trending stocks and uses volatility adjusted sizing techniques with dynamic weekly rebalancing to produce a CAR of 22%, MaxDD of…
Aug 9, 2024 â€¢ 
Larry Kann
13

Share this post

Hunt Gather Trade
Hunt Gather Trade
Strategy 9 -- An NDX rotational momentum strategy
Copy link
Facebook
Email
Notes
More
10
Strategy 12 -- An MES futures strategy
The first strategy that resulted from learning about the VIX and the VIX/SPX relationship. S11 has a profit factor of 2, a Sharpe of 2.6, a MAR, of…
Oct 5, 2024 â€¢ 
Larry Kann
7

Share this post

Hunt Gather Trade
Hunt Gather Trade
Strategy 12 -- An MES futures strategy
Copy link
Facebook
Email
Notes
More
2
Strategy 10 -- A simple and effective NDX mean reversion strategy
It started off as a remix but ended up being a brand-new strategy that made $538k with a PF of 2.85, Sharpe of 0.96, 63% accuracy, a CAR of 19%, and…
Sep 4, 2024 â€¢ 
Larry Kann
6

Share this post

Hunt Gather Trade
Hunt Gather Trade
Strategy 10 -- A simple and effective NDX mean reversion strategy
Copy link
Facebook
Email
Notes
More

Ready for more?

© 2025 Larry Kann
Privacy ∙ Terms ∙ Collection notice
Start writingGet the app
Substack is the home for great culture

Share

Copy link
Facebook
Email
Notes
More

Create your profile

User's avatar

Only paid subscribers can comment on this post

Already a paid subscriber? Sign in

Check your email

For your security, we need to re-authenticate you.

Click the link we sent to , or click here to sign in.