Enums (short for enumerations) are a powerful yet simple tool available to NinjaScript developers. They help you organize your code, make your indicator settings user-friendly, and significantly improve readability. If you’ve ever wondered how some indicators provide neat dropdown menus or clearly labeled options, enums are usually behind the scenes making it happen.

In this post, I’ll show you exactly how to create and implement custom enums in your NinjaTrader indicators—from private enums used within a single indicator, to shared enums placed in external namespaces, and even how to add friendly display names to enums for an improved user experience. By the end of this tutorial, you’ll have a clear understanding of enums and how they can elevate your NinjaScript coding.

If you’re new here, make sure you check out the earlier posts too:

🔍 Understanding Enums: A Quick Refresher

If you’ve never heard of enums before, think of them as a list of fixed options you can name in your code. Instead of typing strings like "EMA" or numbers like 1, you define a list once, give each option a name, and then use that list anywhere in your script.

🧱 What does that look like?

Here’s an example:

public enum MaType
{
    SMA,
    EMA,
    WMA
}

This creates a new type called MaType, and it can only be one of three things: SMA, EMA, or WMA.

You can now use it like this:

MaType selectedType = MaType.EMA;

You no longer need to type strings or remember what number EMA was supposed to be. It’s all built in.

🤔 Why not just use strings?

Using strings is dangerous. Someone might type "SMA" one time and "sma" another. Or misspell "EMA" as "EAM". Your code won’t throw an error until it breaks.

With enums, you can’t make that mistake. The value has to come from the list you defined. That means fewer bugs and easier debugging.

🖥️ Enums in NinjaTrader

NinjaTrader treats enums really well. If you use an enum in a public property, it automatically becomes a dropdown in the indicator or strategy settings window. No extra code needed.

Example:

[NinjaScriptProperty]
[Display(Name = "MA Type", GroupName = "Parameters", Order = 1)]
public MaType MovingAverageType { get; set; }

Now users just pick from a dropdown. No typing, no guessing.

🔁 Where enums show up all the time

  • Long vs. Short
  • SMA vs. EMA vs. WMA
  • Line vs. Dot vs. Histogram
  • Trend mode vs. Reversal mode
  • Entry filter: On / Off / Confirmed

If you’ve ever used a dropdown in an indicator or strategy—there’s probably an enum behind it.

⚡ Why it matters

Enums help:

  • Keep your code clean
  • Prevent bad input
  • Make your scripts more professional
  • Give users a better experience

They’re simple. You define them once and use them everywhere.

🔒 Private Enums: Internal Indicator Logic

Private enums are used when you only need the values inside one script. You’re not exposing them to the user, and you don’t need to reuse them anywhere else.

🧱 Example: Trade Direction

Let’s say you want to keep track of trade bias—long, short, or neutral. You can define it like this:

private enum TradeDirection
{
    Long,
    Short,
    Flat
}

Then use it in your logic:

TradeDirection direction = TradeDirection.Flat;

if (Close[0] > Open[0])
    direction = TradeDirection.Long;
else if (Close[0] < Open[0])
    direction = TradeDirection.Short;

It reads clean. It’s hard to mess up. No weird strings or magic numbers.

✅ What makes it private?

You declared it with private, so it can’t be used outside the script.

  • But just to be clear:
  • Public enums also don’t show up in the UI unless you expose them through a property.
  • The difference is: public enums can be reused in other scripts. Private ones can’t.

Use private enums when:

  • The values are only used inside one script
  • You want cleaner logic
  • You don’t need UI access or reuse across files

🌐 Public Enums: Sharing Across Scripts

If you want to reuse an enum in more than one indicator, strategy, or add-on—you make it public.

A public enum can live in the same file, or in a shared utility file. Either way, once it’s public, any script in your project can reference it.

🧱 Example

public enum MovingAverageType
{
    SMA,
    EMA,
    WMA
}

Now any script can use it:

MovingAverageType selected = MovingAverageType.EMA;

Still just as readable as before—but now you can share it across everything.

🔁 When to use public enums

  • You’re using the same values in multiple scripts
  • You want to expose it as a property in the UI
  • You’re building something reusable (like an add-on or toolkit)

⚠️ One thing to know

Just because an enum is public doesn’t mean it shows up in the UI.
It only becomes visible to users when you expose it through a [NinjaScriptProperty].

Public enums = reusable, but you still control what shows up in the settings window.

🧰 Where Do I Put My Enums in a NinjaScript?

Once you’ve created an enum, you need to decide where to put it. The placement affects whether the enum is reusable, visible in other scripts, safe to export, or prone to conflicts.

Here are four valid placements with examples of how they actually appear inside your code.

Option 1: Inside the class (private use only)

This defines the enum inside your indicator or strategy class, typically near the bottom.

public class MyIndicator : Indicator
{
    private TradeDirection direction;

    protected override void OnBarUpdate()
    {
        if (Close[0] > Open[0])
            direction = TradeDirection.Long;
        else
            direction = TradeDirection.Short;
    }

    private enum TradeDirection
    {
        Long,
        Short,
        Flat
    }
}
  • Scope is limited to this class.
  • Not accessible from other scripts.
  • Won’t appear in the UI.
  • May cause export issues if the script is shared.

Option 2: Outside the class, same file

This places the enum directly after the class in the same .cs file.

public class MyIndicator : Indicator
{
    public TradeDirection DirectionSetting { get; set; }
}

public enum TradeDirection // This could also go above "public class MyIndicator : Indicator"
{
    Long,
    Short,
    Flat
}
  • The enum is public and reusable across scripts compiled together.
  • This is valid and works reliably as long as it’s defined once.
  • If you copy this enum into multiple scripts, you will get duplicate type definition errors.
  • Acceptable for single-file projects or local-only work, but not recommended for widely distributed tools.

Option 3: In a separate file with a namespace

This is the preferred method for reusable or distributed code. Create a new file like CustomEnums.cs:

namespace MyCustomEnums
{
    public enum TradeDirection
    {
        Long,
        Short,
        Flat
    }
}

Then use it in your indicator:

using MyCustomEnums;

public class MyIndicator : Indicator
{
    public TradeDirection DirectionSetting { get; set; }
}
  • Reusable across indicators, strategies, and add-ons.
  • Avoids conflicts during export or import.
  • Keeps enums organized and easy to update.
  • Recommended by NinjaTrader for anything public or shared.

Option 4: In a custom namespace, same file

This approach defines the enum in its own namespace, but still within the same .cs file.

public class MyIndicator : Indicator
{
    public MyIndicatorEnums.TradeDirection DirectionSetting { get; set; }
}

namespace MyIndicatorEnums
{
    public enum TradeDirection
    {
        Long,
        Short,
        Flat
    }
}
  • Useful for distributing a self-contained script with no external dependencies.
  • Prevents naming conflicts if the namespace is unique.
  • Still allows reuse across scripts that include the same namespace.
  • Safer than Option 2 for deployment, but less scalable than Option 3.

🎨 Decorated Enums (User-Friendly Display Names)

By default, enums show up in the UI using their raw names—SMA, EMA, WMA, etc. That works, but it’s not very clean if you want to display something like “Simple Moving Average” instead of just SMA.

To fix that, you can decorate your enums with attributes to control what gets shown in the dropdown.

🧱 Step 1: Add [Description] Attributes

This lets you assign a friendly label to each enum value:

public enum CalculationMode
{
    [Description("Simple Moving Average")]
    SMA,

    [Description("Exponential Moving Average")]
    EMA,

    [Description("Weighted Moving Average")]
    WMA
}

These attributes don’t work by themselves in the NinjaTrader UI. To make them show up, you need to use a custom converter.

🧱 Step 2: Add a Custom TypeConverter

This converts the enum values into the friendly labels you defined above.

public class EnumDescriptionConverter : EnumConverter
{
    private Type enumType;

    public EnumDescriptionConverter(Type type) : base(type)
    {
        enumType = type;
    }

    public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destType)
    {
        FieldInfo fi = enumType.GetField(value.ToString());
        var attr = (DescriptionAttribute)Attribute.GetCustomAttribute(fi, typeof(DescriptionAttribute));
        return attr != null ? attr.Description : value.ToString();
    }

    public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
    {
        foreach (FieldInfo fi in enumType.GetFields())
        {
            var attr = (DescriptionAttribute)Attribute.GetCustomAttribute(fi, typeof(DescriptionAttribute));
            if (attr != null && (string)value == attr.Description)
                return Enum.Parse(enumType, fi.Name);
        }
        return Enum.Parse(enumType, (string)value);
    }

    public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
    {
        var values = new List<string>();
        foreach (var v in Enum.GetValues(enumType))
        {
            FieldInfo fi = enumType.GetField(v.ToString());
            var attr = (DescriptionAttribute)Attribute.GetCustomAttribute(fi, typeof(DescriptionAttribute));
            values.Add(attr != null ? attr.Description : v.ToString());
        }
        return new StandardValuesCollection(values);
    }
}

🧱 Step 3: Apply it to Your Property

You tell NinjaTrader to use this converter and also enable the dropdown editor:

[NinjaScriptProperty]
[TypeConverter(typeof(EnumDescriptionConverter))]
[PropertyEditor("NinjaTrader.Gui.Tools.StringStandardValuesEditorKey")]
[Display(Name = "Calculation Mode", Description = "Choose the calculation method.", GroupName = "Parameters", Order = 1)]
public CalculationMode Mode { get; set; }

🧩 Putting It All Together – Full Example (Using a Utility Namespace at the Bottom of the File)

Let’s put it all together — from the decorated enum to the TypeConverter, and how to hook it up in your indicator. This is exactly how you’d structure it in a single .cs file in NinjaTrader. No guesswork. Just copy, paste, and it works.

#region Using declarations
using System;
using System.ComponentModel;
using System.Globalization;
using System.Collections.Generic;
using System.Reflection;
using NinjaTrader.Cbi;
using NinjaTrader.Gui.Tools;
using NinjaTrader.NinjaScript;
#endregion

// This is your indicator
namespace NinjaTrader.NinjaScript.Indicators
{
    public class DecoratedEnumExample : Indicator
    {
        private MyPlotMode plotMode = MyPlotMode.Solid;

        [NinjaScriptProperty]
        [TypeConverter(typeof(MyEnums.EnumDescriptionConverter))]
        [PropertyEditor("NinjaTrader.Gui.Tools.StringStandardValuesEditorKey")]
        [Display(Name = "Plot Mode", GroupName = "Parameters", Order = 1)]
        public MyPlotMode PlotMode
        {
            get { return plotMode; }
            set { plotMode = value; }
        }

        protected override void OnBarUpdate()
        {
            if (PlotMode == MyPlotMode.Solid)
            {
                // Do something for solid
            }
        }
    }
}

// This is your utility section — it lives at the bottom of the same file
namespace MyEnums
{
    public enum MyPlotMode
    {
        [Description("Solid Line")]
        Solid,

        [Description("Dashed Line")]
        Dashed,

        [Description("Dotted Line")]
        Dotted
    }

    public class EnumDescriptionConverter : EnumConverter
    {
        private Type enumType;

        public EnumDescriptionConverter(Type type) : base(type)
        {
            enumType = type;
        }

        public override bool CanConvertFrom(ITypeDescriptorContext context, Type srcType)
        {
            return srcType == typeof(string);
        }

        public override bool CanConvertTo(ITypeDescriptorContext context, Type destType)
        {
            return destType == typeof(string);
        }

        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            foreach (FieldInfo fi in enumType.GetFields())
            {
                var attr = (DescriptionAttribute)Attribute.GetCustomAttribute(fi, typeof(DescriptionAttribute));
                if (attr != null && (string)value == attr.Description)
                    return Enum.Parse(enumType, fi.Name);
            }
            return Enum.Parse(enumType, (string)value);
        }

        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destType)
        {
            FieldInfo fi = enumType.GetField(value.ToString());
            var attr = (DescriptionAttribute)Attribute.GetCustomAttribute(fi, typeof(DescriptionAttribute));
            return attr != null ? attr.Description : value.ToString();
        }

        public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
        {
            var values = new List<string>();
            foreach (var v in Enum.GetValues(enumType))
            {
                FieldInfo fi = enumType.GetField(v.ToString());
                var attr = (DescriptionAttribute)Attribute.GetCustomAttribute(fi, typeof(DescriptionAttribute));
                values.Add(attr != null ? attr.Description : v.ToString());
            }
            return new StandardValuesCollection(values);
        }
    }
}

⚠️ Important Notes

  • This works in NinjaTrader 8, but it’s not officially supported.
  • NinjaTrader support won’t help if this breaks—use it at your own risk.
  • Most community devs use this anyway—it’s stable if done properly.

↔️ Best Practices and Common Pitfalls

Best Practices:

  • Use a separate namespace or utility file for any enum used in more than one script.
  • Keep enum names short but descriptive.
  • Add [Description] tags only when you want them to display differently in the UI.
  • Group related enums together in the same namespace or file to stay organized.

Common Pitfalls:

  • Declaring enums inside your indicator class and expecting them to work elsewhere.
  • Using the same [Description("None")] for multiple enums without realizing it can cause weird UI behavior.
  • Forgetting that enums don’t show in the UI unless they’re exposed via [NinjaScriptProperty].

📖 Final Thoughts

Enums are one of those small tools that make a big difference in NinjaScript.

Once you understand how to define them, where to put them, and how to optionally decorate them, your code becomes easier to manage — and a lot harder to break.

Use private enums for internal logic, public ones for shared settings, and keep them in a clear place (either at the top, bottom, or in a utility namespace). And if you want them to look clean in the UI? Decorate them.

That’s it. Clean, readable, and built for scale.

🎉 Prop Trading Discounts

💥91% off at Bulenox.com with the code MDT91

Categorized in:

Learn NinjaScript,

Tagged in: