A Complete Beginner’s Guide to Coloring in NinjaTrader.
When you build custom indicators or strategies in NinjaTrader, you’ll often want to control the color of what you draw — whether it’s a trend line, a signal marker, or even the background of the chart.
Brushes are how you manage all of that.
✅ In plain English:
A Brush is your digital paintbrush. It defines what color (and sometimes texture) NinjaTrader uses when drawing something.
You’ll use Brushes to:
- Color plots (green for bullish, red for bearish)
- Color horizontal Lines
- Color shapes like rectangles, arrows, or text
- Color chart backgrounds or highlights
Good color usage isn’t just about looking nice — it’s practical:
- Makes signals easier to read visually
- Speeds up your chart interpretation
- Helps automate recognizing trends and alerts
Under the hood, a Brush isn’t just a color name like “Red” — it’s a C# object.
That means it can hold solid colors, gradients, or even more complex effects if you need them.
✅ Most of the time in NinjaScript, you’ll use simple solid color Brushes like:
Brushes.Red
Brushes.Green
Brushes.Blue
But you can also create your own custom colors if you want full control.
👉 Save this official NinjaTrader Help Guide links:
📚 Related NinjaScript Lessons So Far
If you’re new here, make sure you check out the earlier posts too:
- Understanding the NinjaTrader Indicator Structure
- Variables and Properties in NinjaScript
- OnStateChange() Lifecycle Explained
- OnBarUpdate() Fully Explained
- Learn how to use Series<T>
- Learn NinjaScript Plots
- Learn NinjaScript Lines
🎨 Common Ways to Use Brushes in NinjaScript
In NinjaTrader, a Brush defines how something looks — especially its color, but also optionally its opacity, gradient, or even pattern.
Brushes are used in all kinds of visual output:
✅ Plot Colors (with PlotBrushes)
If you want your indicator plots to change color dynamically (like red for downtrend, green for uptrend), you’ll use PlotBrushes
:
PlotBrushes[0][0] = Close[0] > Open[0] ? Brushes.Green : Brushes.Red;
PlotBrushes[0]
: Applies to the first plot (Values[0]).[0]
: The current bar.Brushes.Green
: A built-in Brush color.
📌 This is common for indicators like:
- Moving averages that change color based on trend
- Signal plots showing buy/sell zones
✅ Drawing Tools (Lines, Text, Regions)
Brushes are also used with Draw objects like Draw.Line()
, Draw.Region()
, or Draw.Text()
:
Draw.Line(this, "trendLine", 10, Low[10], 0, Low[0], Brushes.Blue);
Here, Brushes.Blue
determines the line’s color. You can use any solid or custom Brush.
✅ Background or Bar Highlighting
Want to highlight the background or individual bars? Use BackBrushes
or BarBrushes
:
BackBrushes[0] = Brushes.LightYellow; // Highlights current bar background
BarBrushes[0] = Brushes.OrangeRed; // Changes bar color itself
This is especially helpful for:
- Highlighting signals or market phases
- Indicating volume spikes or volatility zones
✅ Signals and Visual Feedback
Brushes are ideal for calling attention to special moments — like entries, exits, or caution zones. For example:
if (CrossAbove(Close, SMA(20), 1))
{
Draw.TriangleUp(this, "buySignal" + CurrentBar, false, 0, Low[0] - TickSize * 5, Brushes.LimeGreen);
}
Here, the triangle is colored LimeGreen using a Brush.
✅ Custom Styling (Your Own Brushes)
You can also define your own custom Brushes with opacity:
Brush semiTransparentRed = new SolidColorBrush(Color.FromArgb(128, 255, 0, 0));
semiTransparentRed.Freeze(); // Required in NinjaTrader
We’ll cover this in more detail in a later section, but just know you can go beyond the default Brushes.Red
, Brushes.Green
, etc.
🧩 How to Make a Brush a Property (So Users Can Customize It)
When building indicators or strategies in NinjaTrader, you often want to give users the ability to customize the colors in the settings window — like changing the bullish signal to lime green, or choosing a custom fill color for a region.
That’s where making a Brush a public property comes in.
✅ Step-by-Step: Making a Brush a Configurable Property
Let’s walk through how to expose a Brush so users can change it in the Indicator UI panel.
👇 Code Example
// Declare the property
[NinjaScriptProperty]
[XmlIgnore]
[Display(Name = "Bullish Brush", GroupName = "Visuals", Order = 1)]
public Brush BullishBrush { get; set; }
// Required for serialization (to save/load workspaces and templates)
[Browsable(false)]
public string BullishBrushSerialize
{
get { return Serialize.BrushToString(BullishBrush); }
set { BullishBrush = Serialize.StringToBrush(value); }
}
🔍 What Each Attribute Does
Attribute | Purpose |
---|---|
[NinjaScriptProperty] | Makes it accessible in strategy builder / external scripts. |
[XmlIgnore] | Prevents direct serialization (we handle it manually below). |
[Display(...)] | Controls how it appears in the UI (label, group, order). |
BullishBrushSerialize | Converts the Brush to/from string for saving in templates. |
✅ Example Usage in Your Code
PlotBrushes[0][0] = Close[0] > Open[0] ? BullishBrush : BearishBrush;
Here you’re using the user-defined brushes on rising and falling bars.
🌈 Controlling Opacity with Brushes
A Brush in NinjaTrader isn’t just about color — you can also adjust how bold or transparent that color appears on the chart using opacity.
This is useful for:
- Making signals stand out (fully visible),
- Drawing subtle zones (semi-transparent),
- Fading inactive areas or less-confident conditions.
💡 What Is Opacity?
Opacity controls how see-through a visual element is:
Opacity Value | Meaning |
---|---|
255 | Fully opaque (solid) |
128 | 50% transparent |
0 | Fully transparent |
You can set this using Color.FromArgb(alpha, red, green, blue)
:
Brush fadedBlue = new SolidColorBrush(Color.FromArgb(80, 0, 0, 255)); // 30% visible blue
fadedBlue.Freeze();
✅ Always call .Freeze()
on your brush to improve rendering performance!
🧪 Example: Subtle Region Highlight
Here’s how you might use opacity in a chart zone:
Brush regionFill = new SolidColorBrush(Color.FromArgb(60, 0, 200, 255)); // Light blue
regionFill.Freeze();
Draw.Region(this, "MyZone", 0, 10, SMA(20), SMA(50), regionFill, Brushes.Transparent, 0);
This fills the area between two moving averages with a faint blue highlight.
⚙️ Custom Opacity Helpers (Reusable Methods)
To make dynamic opacity easier in your indicators, you can use helper functions like these:
// Change the opacity of an existing brush (xOpacity = 0–100)
public static Brush mdtBrushChangeOpacity(Brush xBrush, int xOpacity)
{
Brush newBrush = xBrush.Clone();
newBrush.Opacity = xOpacity * 0.01;
newBrush.Freeze();
return newBrush;
}
Or create a brush directly from an ARGB integer:
public static SolidColorBrush mdtBrushFromArgb(int argb)
{
return new SolidColorBrush(Color.FromArgb(
(byte)(argb >> 24),
(byte)(argb >> 16),
(byte)(argb >> 8),
(byte)(argb)));
}
Or reuse a brush’s color but apply a new alpha:
public static SolidColorBrush mdtBrushFromArgb(int alpha, Brush baseBrush)
{
var solid = (SolidColorBrush)baseBrush;
return new SolidColorBrush(Color.FromArgb(
(byte)alpha,
solid.Color.R,
solid.Color.G,
solid.Color.B));
}
🔁 Practical Use: Fade a Brush Based on Logic
Brush baseColor = Brushes.Orange;
bool isActive = Close[0] > Open[0];
Brush faded = mdtBrushChangeOpacity(baseColor, isActive ? 100 : 30);
PlotBrushes[0][0] = faded;
✅ Now your signal will be bright when active and dim when not — without needing multiple color definitions!
🧱 Initializing Brushes in OnStateChange()
When working with Brushes in NinjaTrader, it’s important to initialize them at the right time and freeze them when needed, especially if they’ll be reused frequently or assigned to visual elements like plots, lines, or draw tools.
🔀 Where Should I Initialize a Brush?
🧪 Internal Brushes Example (with opacity)
private Brush bullishBrush;
private Brush bearishBrush;
protected override void OnStateChange()
{
if (State == State.DataLoaded)
{
// Green with 80% opacity
bullishBrush = new SolidColorBrush(Color.FromArgb(204, 0, 200, 0));
bullishBrush.Freeze();
// Red with 80% opacity
bearishBrush = new SolidColorBrush(Color.FromArgb(204, 200, 0, 0));
bearishBrush.Freeze();
}
}
✅ Why DataLoaded?
This ensures all instruments and data series are ready, and your brush is only created once — no memory leaks or duplicate clones.
🧪 Public Property Example: Brush + Opacity
Let’s say you want the user to set both the color and opacity of a signal highlight. You expose a color property and an opacity level, and then create a frozen brush internally.
[Browsable(false)]
[XmlIgnore]
[NinjaScriptProperty]
[Display(Name = "Signal Color", GroupName = "Visuals", Order = 1)]
public Brush SignalColor { get; set; }
// Required for serialization (to save/load workspaces and templates)
[Browsable(false)]
public string SignalColorSerialize
{
get { return Serialize.BrushToString(SignalColor); }
set { SignalColor = Serialize.StringToBrush(value); }
}
[NinjaScriptProperty]
[Range(1, 100)]
[Display(Name = "Signal Opacity", GroupName = "Visuals", Order = 2)]
public int SignalOpacity { get; set; }
private Brush frozenSignal;
Then in OnStateChange()
:
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
SignalColor = Brushes.DeepSkyBlue;
SignalOpacity = 80;
}
else if (State == State.DataLoaded)
{
// Clone + apply opacity + freeze
frozenSignal = SignalColor.Clone();
frozenSignal.Opacity = SignalOpacity * 0.01;
frozenSignal.Freeze();
}
}
✅ Use frozenSignal
anywhere in your code where you assign brushes — like PlotBrushes
, Draw
, or Line.Brush
.
🔁 Do You Always Need to Freeze?
Brush Type | Freeze Required? |
---|---|
Brushes.Red / Brushes.Blue (built-in) | ❌ Already frozen |
Custom SolidColorBrush | ✅ Yes |
Cloned property brush | ✅ Yes |
✅ Rule of thumb: If you make or modify the brush manually (especially changing opacity), you need to call .Freeze()
.
🎨 Creating Custom Brushes Manually
While built-in brushes like Brushes.Red
or Brushes.Green
cover most basic needs, sometimes you want more control — such as a specific color tone or level of transparency.
That’s where creating custom brushes comes in.
🧪 Example: Create a Custom Solid Brush
Brush customPurple = new SolidColorBrush(Color.FromRgb(128, 0, 128));
customPurple.Freeze();
This creates a fully opaque purple brush using the RGB color model:
- 128 = red
- 0 = green
- 128 = blue
✅ Don’t forget to call .Freeze()
to improve rendering performance in NinjaTrader!
🌫️ Add Transparency with ARGB
To make the brush semi-transparent, use FromArgb
instead of FromRgb
:
Brush transparentPurple = new SolidColorBrush(Color.FromArgb(128, 128, 0, 128));
transparentPurple.Freeze();
The values mean:
- 128 (Alpha): 50% transparent
- 128, 0, 128: same purple color
🎨 What Is ARGB?
Component | Meaning |
---|---|
A | Alpha (opacity) — 0 is invisible, 255 is solid |
R | Red |
G | Green |
B | Blue |
🔁 Dynamic Opacity Helper Example
If you need to dynamically adjust brush opacity during runtime, here’s a reusable method:
public static Brush mdtBrushChangeOpacity(Brush baseBrush, int opacityPercent)
{
Brush result = baseBrush.Clone();
result.Opacity = opacityPercent * 0.01;
result.Freeze();
return result;
}
This lets you do:
Brush fadedBlue = mdtBrushChangeOpacity(Brushes.Blue, 40); // 40% visible
✅ When Should You Create a Custom Brush?
Use a custom SolidColorBrush
when:
- You want a specific shade or tint not available in
Brushes.X
- You want fine-tuned transparency
- You want your visuals to match a brand or color scheme
- You’re dynamically updating visuals and need flexibility
🧠 Brush Tips for Dynamic Drawing (PlotBrushes, Draw, etc.)
Once you’ve defined your brushes — either from built-in colors, user properties, or custom ARGB creation — you’ll start using them to dynamically color chart elements like plots, shapes, signals, and backgrounds.
Here’s how to do it right:
🟢 Using PlotBrushes[] for Dynamic Plot Colors
When you want to change the color of a plot line based on logic, use the PlotBrushes[]
array:
PlotBrushes[0][0] = Close[0] > Open[0] ? BullishBrush : BearishBrush;
✅ Explanation:
PlotBrushes[0]
: Refers to the brush for your first plot (Values[0]
)[0]
: Refers to the current bar- Result: The plot will be green (BullishBrush) if the bar closed higher, red (BearishBrush) otherwise
✏️ Coloring Shapes, Signals, or Markers with Draw Methods
Use your brushes when drawing visual signals or shapes. For example:
if (CrossAbove(Close, SMA(20), 1))
{
Draw.TriangleUp(this, "bullSignal" + CurrentBar, false, 0, Low[0] - TickSize * 4, SignalBrush);
}
✅ This will draw a green triangle 4 ticks below the current low when a bullish signal appears.
🎨 Highlighting Backgrounds and Bars
Brushes also work for visual emphasis through background and bar color overlays:
BackBrushes[0] = Brushes.LightYellow; // Highlights background
BarBrushes[0] = Brushes.OrangeRed; // Colors the candle itself
✅ You can use this to:
- Highlight trade entry/exit zones
- Call attention to volatility
- Show trend phases
🔄 Dynamic Opacity During Live Calculations
Use mdtBrushChangeOpacity()
to dynamically fade or strengthen visuals:
bool isActive = Close[0] > Open[0];
Brush fadedSignal = mdtBrushChangeOpacity(SignalBrush, isActive ? 100 : 30);
PlotBrushes[0][0] = fadedSignal;
✅ This makes your signal fully visible when active, and semi-transparent when inactive.
❗ Don’t Use Non-Frozen Custom Brushes Repeatedly
If you’re building brushes dynamically, never skip .Freeze()
:
Brush temp = new SolidColorBrush(Color.FromArgb(128, 255, 0, 0));
temp.Freeze(); // Always freeze before assigning
Failing to freeze may cause performance issues or NinjaTrader warnings.
⚠️ Common Brush Mistakes (And How to Avoid Them)
Brushes are powerful, but a few common missteps can lead to confusing chart behavior or even NinjaTrader warnings. Let’s walk through what to watch out for and how to fix it.
❌ Not Freezing Custom Brushes
If you create a custom brush in code (e.g., using Color.FromArgb
), you must call .Freeze()
before using it in rendering.
🚫 Wrong:
Brush myBrush = new SolidColorBrush(Color.FromArgb(120, 0, 255, 0));
PlotBrushes[0][0] = myBrush; // This may trigger a rendering error!
✅ Right:
Brush myBrush = new SolidColorBrush(Color.FromArgb(120, 0, 255, 0));
myBrush.Freeze(); // Now it’s safe
PlotBrushes[0][0] = myBrush;
❌ Using Brush as a Property Without Serialization
If you make a Brush
public, you need to pair it with a serialized string property — or your script won’t save/load correctly in templates.
🚫 Wrong:
[NinjaScriptProperty]
[XmlIgnore]
[Display(Name = "Signal Color", GroupName = "Visuals", Order = 1)]
public Brush MySignalColor { get; set; }
✅ Right:
[NinjaScriptProperty]
[XmlIgnore]
[Display(Name = "Signal Color", GroupName = "Visuals", Order = 1)]
public Brush MySignalColor { get; set; }
[Browsable(false)]
public string MySignalColorSerialize
{
get { return Serialize.BrushToString(MySignalColor); }
set { MySignalColor = Serialize.StringToBrush(value); }
}
❌ Overcomplicating with Custom Opacity
If you just want a lighter red, use a built-in brush or a solid brush with opacity once — don’t recreate it on every bar unless necessary.
✅ Best practice:
Freeze once and reuse, or use a helper like mdtBrushChangeOpacity()
for clarity and reuse.
🧠 Final Thoughts
Brushes might seem like a small detail in NinjaScript, but they’re an important part of creating clear, readable, and responsive indicators and strategies.
🎨 Use them to:
- Highlight signals (PlotBrushes)
- Color important zones (Draw.Region, BackBrushes)
- Mark transitions or alerts (Draw.Text, Draw.TriangleUp)
- Give users flexibility with configurable brush properties
💡 And remember:
- Always freeze custom brushes created in code
- Expose brushes correctly if users need to customize them
- Use opacity and custom methods to make visuals more useful (not just pretty)
Brushes don’t just make your chart look nice — they enhance your decision-making by making patterns and signals easier to spot at a glance.
As you get more comfortable with NinjaScript, you’ll find yourself reaching for brushes naturally — they’re one of the most versatile tools in your scripting toolbox.
🎉 Prop Trading Discounts
💥91% off at Bulenox.com with the code MDT91