A Complete Beginner’s Guide to Visual Outputs (Plots).
Once you understand how NinjaTrader stores values with Series<T>, the next step is learning how NinjaTrader actually displays your indicator’s output visually — through Plots.
✅ Plots are the visual bridge between your raw calculations and the chart the trader sees.
Every time you add a plot to your indicator, NinjaTrader creates an internal Series<double> to store one value for every bar. These values are automatically linked through the Values[]
array — one “notebook” per plot — which NinjaTrader then draws as a line, histogram, dot, or other shapes depending on how you configure it.
In this guide, we’ll cover everything you need to know about Plots:
- How NinjaTrader organizes Plot data
- How to control settings like scale, overlays, price markers, and more
- How to dynamically color plots
- How Displacement can shift plots visually without changing calculations
- Common beginner mistakes — and how to avoid them
- And real-world examples that put all these ideas together
By the end of this post, you’ll understand exactly how to use Plots to make your NinjaScript indicators professional, functional, and easy to trade from.
👉 Save this official NinjaTrader Help Guide link:
- Plots – NinjaTrader Help Guide
- AddPlot() – NinjaTrader Help Guide
- ArePlotsConfigurable – NinjaTrader Help Guide
- Displacement – NinjaTrader Help Guide
- PlotBrushes – NinjaTrader Help Guide
- Values – NinjaTrader Help Guide
- ArePlotsConfigurable – NinjaTrader Help Guide
- IsOverlay – NinjaTrader Help Guide
- ScaleJustification – NinjaTrader Help Guide
- IsAutoScale – NinjaTrader Help Guide
- PaintPriceMarkers – NinjaTrader Help Guide
- ShowTransparentPlotsInDataBox – NinjaTrader Help Guide
- DisplayInDataBox – NinjaTrader Help Guide
- ZOrder – NinjaTrader Help Guide
📚 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>
📈 What Is a Plot? (Plain English)
In NinjaTrader, a Plot is how you draw a value on a chart.
✅ Think of a Plot like a pen that marks where an indicator’s value lands for each bar.
When you see a moving average line, or a buy/sell triangle — you’re really just seeing Plots drawing Series<double> data onto the screen.
Plots aren’t just pretty visuals either. Behind every plot, NinjaTrader keeps a recorded history of values bar-by-bar — so your script (and even your strategies) can access past and current values programmatically.
In one sentence:
A Plot is a visual output tied to a Series<double> that records one value per bar, letting you see and work with your indicator’s data.
🎯 Why Plots Matter
Plots aren’t just about making your indicator look cool — they serve two major purposes:
1. Visual Feedback
Plots show your calculations visually on the chart, which helps:
- Spot patterns faster
- Confirm signals at a glance
- Troubleshoot and debug your logic by seeing it in action
✅ Example: A trader can instantly tell if a moving average crossover is happening — because the plots visually cross each other on the chart.
2. Logical Tracking
Even if you don’t draw anything fancy, NinjaTrader internally tracks your plot values through Series<double>.
This means you can:
- Reference your plot values in other indicators or strategies
- Check historical plot values (e.g., was a signal triggered 3 bars ago?)
- Build logic off the data without needing a second calculation
✅ Example: You might plot a triangle marker when a setup happens, and later in a strategy, check Values[0][0]
to see if that marker (signal) is present.
✅ Bottom line:
Plots turn your data into something you can both see and use — making them essential for both charting and coding smart trading logic.
🎛️ Important Plot Settings Explained
NinjaTrader lets you control how plots look and behave through a handful of settings.
Let’s walk through them — what they do, why they matter, and how to use them.
🧩 ArePlotsConfigurable
What it does:
Controls whether users can customize plot settings (like color and width) through the chart UI.
Plain English:
Can a trader edit the plot’s appearance without touching the code?
✅ If true
: The plot will appear in the Indicators window, and users can tweak it.
✅ If false
: The plot stays hidden from the user — locked down.
Example:
ArePlotsConfigurable = true; // Allow customization
🧩 IsOverlay
What it does:
Decides whether the plot appears on top of price bars or in a separate panel.
Plain English:
Should the plot draw directly on the candlesticks, or have its own separate area?
✅ true
→ Plot overlaid on price bars (good for moving averages, signals)
✅ false
→ Plot in its own separate indicator panel (good for oscillators like RSI)
Example:
IsOverlay = true; // Draw over candlesticks
🧩 IsAutoScale
What it does:
Controls whether NinjaTrader adjusts the y-axis scale automatically to fit your plot.
Plain English:
Should the chart zoom in/out to make sure your plot stays visible?
✅ true
→ NinjaTrader adjusts the y-axis automatically
✅ false
→ Y-axis is not influenced by this plot
Example:
IsAutoScale = true; // Automatically fit into the y-axis scale
🧩 ScaleJustification
What it does:
Controls where the plot appears vertically if using multiple scales.
Plain English:
|If you have multiple indicators, should your plot’s axis appear on the left, right, or overlayed?
Options:
ScaleJustification.Right
ScaleJustification.Left
ScaleJustification.Overlay
Example:
ScaleJustification = ScaleJustification.Right;
🧩 PaintPriceMarkers
What it does:
Controls whether a small price label appears at the right edge of the chart for your plot.
Plain English:
Do you want a price tag showing your plot’s current value?
✅ true
→ Show a marker like “4305.25”
✅ false
→ No label shown
Example:
PaintPriceMarkers = true;
🧩 DisplayInDataBox
What it does:
Controls whether your plot’s value shows up in the Data Box when you hover the mouse over the chart.
Plain English:
Should this plot’s number appear when you inspect the chart with your mouse?
✅ true
→ Yes, show it in the Data Box
✅ false
→ No, hide it
Example:
DisplayInDataBox = true;
🧩 ShowTransparentPlotsInDataBox
What it does:
Controls if transparent (invisible) plots are still listed in the Data Box.
Plain English:
If you make a plot transparent (not drawn visually), do you still want its number to appear?
✅ true
→ Even invisible plots will show data
✅ false
→ Hide fully transparent plots from the Data Box
Example:
ShowTransparentPlotsInDataBox = false;
🧩 ZOrder
What it does:
Controls the drawing order of elements on the chart — lower numbers draw first (behind), higher numbers draw last (on top).
Plain English:
If plots overlap, which one goes in front?
✅ Lower ZOrder → Further back
✅ Higher ZOrder → Drawn over the top
Example:
protected override void OnStateChange()
{
if (State == State.Historical)
{
// Only select ONE of the following SetZOrder options:
SetZOrder(-1); // Draws behind the price bars (furthest back)
// SetZOrder(1); // Draws just slightly above the price bars
// SetZOrder(int.MaxValue); // Draws on top of everything (furthest front)
}
}
📋 Full Example Setting Common Options Inside State.SetDefaults
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
Name = "My Custom Plot Example";
// Allow users to edit the plot
ArePlotsConfigurable = true;
// Draw on top of the candlesticks
IsOverlay = true;
// Auto-scale chart to fit the plot
IsAutoScale = true;
// Show price marker on the right edge
PaintPriceMarkers = true;
// Display plot in the Data Box
DisplayInDataBox = true;
// Don't show fully transparent plots
ShowTransparentPlotsInDataBox = false;
// Align scale on the right
ScaleJustification = ScaleJustification.Right;
// Draw slightly above candles
SetZOrder(1);
// Add an example plot
AddPlot(Brushes.Blue, "MyFirstPlot");
}
}
✅ This is the typical setup for beginner-friendly, professional-looking plots!
🧠 Anatomy of a Plot: How It Works Behind the Scenes
Now that you know what a plot is and how you can control its settings, let’s dive deeper into what happens under the hood.
✅ Every plot in NinjaTrader isn’t just a visual line or marker — it’s powered by a Series<double>.
✅ That data is organized in the Values[] collection and updated bar-by-bar as new market data comes in.
Let’s break it all down.
🔋 Every Plot is Powered by a Series<double>
When you call AddPlot() in NinjaTrader, two important things happen:
- NinjaTrader creates a visual plot that shows up on your chart.
- NinjaTrader automatically creates a Series<double> behind the scenes.
✅ This Series<double> is how NinjaTrader tracks your plot values bar-by-bar, just like a notebook recording each day’s information.
✅ You don’t have to manually create this Series — it’s automatically handled for you when you add a Plot!
📚 Example
When you write:
AddPlot(Brushes.Blue, "My Trend Line");
NinjaTrader automatically does two things:
Step | What Happens |
---|---|
1 | A visual line called “My Trend Line” is prepared |
2 |
A Series |
From there, you can store values and access values for this plot just like any other Series.
✅ Plot = Visual Layer
✅ Series = Data Layer
You’re really working with both every time you use a Plot.
📚 Quick Tip:
You don’t have to “guess” which Series is tied to which Plot — they follow the order you add them!
- First AddPlot() →
Values[0]
- Second AddPlot() →
Values[1]
- Third AddPlot() →
Values[2]
and so on…
✅ Summary:
Every Plot isn’t just something you see — it’s backed by something you can use in your code: a full Series<double> tracking bar-by-bar data.
🧠 Values[]: The Backbone of Plots
When you add a plot, you’re not just making something appear visually — you are creating a full historical record.
✅ The Values[] collection is where NinjaTrader stores your plot’s data.
Each plot you create automatically adds one entry to Values[]
.
Each entry inside Values[]
is a Series<double>, meaning it records one value for every bar on the chart.
🛠️ Quick Breakdown:
Values[0]
→ Series for the first plot.Values[1]
→ Series for the second plot.Values[2]
→ Series for the third plot.- …and so on, if you add more plots.
✅ Each Series keeps track of values bar-by-bar — like writing down a number for every candle that forms.
✏️ Example in Action:
Suppose you added two plots:
AddPlot(Brushes.Blue, "TrendLine");
AddPlot(Brushes.Red, "SignalMarker");
Internally, NinjaTrader automatically does this:
Plot Name | Values Index | What It Stores |
---|---|---|
TrendLine | Values[0] | Trend line values per bar |
SignalMarker | Values[1] | Signal marker values per bar |
You now have:
Values[0]
to store and retrieve your trendline numbersValues[1]
to store and retrieve your signal data
✅ Values[] is your bridge between visual plots and logical historical data.
📚 Visual Metaphor: “Each Plot Has Its Own Notebook”
Imagine each Plot you create is like giving your indicator a new notebook.
- Each notebook (Plot) keeps track of one thing: your trend, your signals, your bands — whatever you are plotting.
- Each page inside the notebook represents one bar (one candle) on your chart.
- Every time NinjaTrader processes a new bar, it writes one new value onto the notebook’s next page.
✅ So when you say:
Values[0][0] = Close[0];
You’re doing two things:
- Opening the TrendLine notebook (Values[0])
- Writing the current Close price onto the page for the current bar (
[0]
).
If you wanted to check yesterday’s note?
Values[0][1];
Meaning:
- Look one page back.
If you wanted the note from two days ago?
Values[0][2];
✅ Every plot keeps its own diary of values — automatically.
You just have to write into it during OnBarUpdate().
🧩 Understanding the Second Bracket: Values[idx][BarsAgo]
Now that you understand each Plot is its own notebook, let’s zoom in on what the two brackets mean:
When you reference something like:
Values[0][0]
There are two pieces:
Part | Meaning |
---|---|
Values[0] | Which Plot (or notebook) you are using |
[0] | Which bar (or page) you are referencing, measured by BarsAgo |
✅ Plain English:
- The first number inside
Values[]
picks which Plot you’re working with. - The second number picks how far back you want to look in time.
🧠 What is BarsAgo?
The BarsAgo number tells NinjaTrader how many bars back you want to look:
BarsAgo Value | What It Means |
---|---|
[0] | Current bar |
[1] | One bar ago |
[2] | Two bars ago |
[10] | Ten bars ago |
etc. | and so on |
✅ BarsAgo counts backward from the current bar!
📋 Practical Example: Storing and Retrieving Plot Data
Suppose you’re building a trend indicator, and you want to store the Close price on each bar:
protected override void OnBarUpdate()
{
// Save the current bar's Close into Plot 0
Values[0][0] = Close[0];
// Compare recent trend using historical plot values
if (Values[0][1] > Values[0][2])
{
// Trend was rising between two bars ago and one bar ago
// You could plot something special, or signal something here
}
}
✅ In this example:
Values[0][0]
= Close price of the current bar.Values[0][1]
= Close price one bar ago.Values[0][2]
= Close price two bars ago.
🛠️ How to Add Plots with AddPlot()
Creating a plot in NinjaTrader is simple — you use the AddPlot()
method inside OnStateChange() when the state is SetDefaults (or, sometimes, Configure).
✅ When you call AddPlot():
- NinjaTrader automatically creates a new Plot (the visual line, bar, triangle, etc.)
- It also creates a Series<double> behind the scenes, linked inside Values[]
✏️ Basic Syntax for AddPlot()
There are two main ways to use AddPlot:
Syntax | Description |
---|---|
AddPlot(Brush brush, string name) | Adds a simple plot with a basic color and label |
AddPlot(Stroke stroke, PlotStyle plotStyle, string name) | Adds a plot with full control over the line style (dashed, dotted, thickness, etc.) and the shape |
✅ Plain English:
- Brush → A basic color (e.g., Brushes.Blue, Brushes.Red).
- Stroke → A “rich” way to define how the plot looks, including color, dash style, and thickness.
- PlotStyle → Controls the overall shape of the plot (line, bar, triangle up/down, etc.).
- Name → The friendly label that appears in the Indicator’s settings.
🎯 What is Stroke?
Stroke
is a special object that defines:
- Color (like blue, red, green)
- Dash style (solid, dashed, dotted, etc.)
- Thickness (line width in pixels)
- Opacity (how transparent the line is)
✅ You use Stroke when you want more control than just setting a basic Brush.
Example Stroke Syntax:
new Stroke(Brush color, DashStyleHelper dashStyle, double width, double opacity)
Parameter | Meaning | Example |
---|---|---|
Brush | Color of the line | Brushes.Red |
DashStyleHelper | Line pattern (Solid, Dash, Dot, etc.) | DashStyleHelper.Dash |
Width | Thickness in pixels | 3 |
Opacity | 0-100% transparent (1.0 = 100%) | 1.0 |
🎯 Example 1: Simple Moving Average Line
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
AddPlot(Brushes.Blue, "SMA Plot");
}
}
protected override void OnBarUpdate()
{
Values[0][0] = SMA(14)[0]; // Store SMA value into the plot
}
✅ This adds a simple blue line plotting the 14-period SMA.
🎯 Example 2: Dashed Line with Custom Thickness Using Stroke
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
AddPlot(new Stroke(Brushes.Red, DashStyleHelper.Dash, 3), PlotStyle.Line, "Dashed SMA");
}
}
protected override void OnBarUpdate()
{
Values[0][0] = SMA(14)[0];
}
✅ This draws a red dashed line, 3 units thick, using Stroke.
🎯 Example 3: Histogram Plot
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
AddPlot(new Stroke(Brushes.Green), PlotStyle.Bar, "Volume Histogram");
}
}
protected override void OnBarUpdate()
{
Values[0][0] = Volume[0];
}
✅ This plots vertical bars for each volume reading.
⚡ Important Tip: When to Call AddPlot
- Use State.SetDefaults → Normal plots (visible + configurable by user)
- Use State.Configure → Dynamic or conditional plots (⚠️ advanced only)
If you add a plot during Configure, the user cannot change its color/style in the UI panel!
✅ Best Practice for Beginners:
Stick with SetDefaults for now.
🛡️ Public Access to Plots (Exposing Them Cleanly)
When you create a plot, it automatically stores values in Values[0]
, Values[1]
, etc.
✅ But accessing by number like Values[0][0]
isn’t always intuitive — especially if you have multiple plots.
✅ Plus, if you want your indicator to be referenced easily in a strategy, Market Analyzer, or Strategy Builder, you should expose your plots publicly.
📢 Why Expose a Plot Publicly?
Reason | Why It Matters |
---|---|
Human-Readable Access | Easier to reference by a meaningful name |
Strategy Builder Compatible | Allows your plots to show up in dropdown menus |
External Use | Other scripts can “see” your plot data |
📋 How to Expose a Plot
✅ You create a public property that maps to your specific plot inside the Values[]
collection.
✅ You also add [Browsable(false)]
and [XmlIgnore]
attributes — so it doesn’t clutter the NinjaTrader settings UI but remains available for programmatic access.
Example: Public Property for a Plot
[Browsable(false)]
[XmlIgnore]
public Series<double> MySignalPlot
{
get { return Values[0]; }
}
✅ Explanation:
[Browsable(false)]
→ Hides it from the indicator settings panel.[XmlIgnore]
→ Prevents it from being serialized when saving layouts.MySignalPlot
→ The friendly name you can now use instead ofValues[0]
!
🎯 Practical Example: Full Flow
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
AddPlot(Brushes.LimeGreen, "Buy Signal");
}
}
protected override void OnBarUpdate()
{
if (CrossAbove(Close, SMA(20), 1))
MySignalPlot[0] = 1;
else
MySignalPlot.Reset();
}
[Browsable(false)]
[XmlIgnore]
public Series<double> MySignalPlot
{
get { return Values[0]; }
}
✅ Now, any other indicator or strategy can reference:
if (MyIndicator().MySignalPlot[0] == 1)
{
// Execute buy logic
}
Instead of:
if (MyIndicator().Values[0][0] == 1)
✅ Much cleaner, much easier to maintain!
🎨 Dynamic Coloring with PlotBrushes
By default, when you create a plot in NinjaTrader, it uses one static color for all bars (whatever you set in AddPlot()
).
But what if you want to dynamically change the plot’s color bar-by-bar based on your logic?
✅ That’s exactly what PlotBrushes allows you to do!
🖌️ What is PlotBrushes?
PlotBrushes
lets you override the color of a specific bar on a specific plot.- It’s an array of Brushes — one Brush (color) per bar.
- Each plot has its own
PlotBrushes[idx]
array.
✅ In simple terms:
PlotBrushes lets you paint individual bars however you want, without affecting the rest.
🛠️ How PlotBrushes Are Organized
Item | Meaning |
---|---|
PlotBrushes[0][0] | The Brush (color) for Plot 0 at the current bar |
PlotBrushes[0][1] | The Brush for Plot 0 one bar ago |
PlotBrushes[1][0] | The Brush for Plot 1 at the current bar |
✅ The first bracket: Which plot
✅ The second bracket: Which bar (BarsAgo, same as before)
🎯 Practical Example: Dynamic Plot Coloring
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
AddPlot(Brushes.Gray, "TrendPlot");
}
}
protected override void OnBarUpdate()
{
Values[0][0] = Close[0];
if (Close[0] > Open[0])
PlotBrushes[0][0] = Brushes.LimeGreen; // Bullish bar
else if (Close[0] < Open[0])
PlotBrushes[0][0] = Brushes.Red; // Bearish bar
else
PlotBrushes[0][0] = Brushes.Gray; // Neutral bar
}
✅ Now each bar on your plot will color green, red, or gray dynamically depending on bar behavior!
📢 Important Reminder!
When dynamically coloring plots:
- If you set a brush for a bar (
PlotBrushes[idx][0]
), that brush applies only to that bar. - If you do not set a brush, NinjaTrader will use the plot’s default color (the color you set with
AddPlot
).
✅ Good habit:
- Explicitly set
PlotBrushes[idx][0]
only when you want to override the default plot color. - If no dynamic color is assigned, NinjaTrader will automatically use the default color from
AddPlot
.
🔍 In Plain English:
If you skip setting it, NinjaTrader falls back to the default color you originally defined for the plot.
You don’t have to set PlotBrushes
on every bar unless you need the plot to change colors bar-by-bar.
🔄 Displacement: Shifting Plot Displays Forward or Backward
Sometimes, you want to move your plotted data forward or backward on the chart without actually changing the data itself.
✅ That’s where Displacement comes in!
🧠 What is Displacement?
- Displacement shifts the visual plot left or right.
- It does NOT change your calculations or your underlying Series values.
- It’s purely a visual adjustment to the position of plotted values.
✅ Plain English:
Displacement moves how things look — it doesn’t move how things calculate.
🧩 How to Set Displacement
You can set Displacement on a plot inside OnStateChange()
during State.SetDefaults
.
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
Displacement = 5; // Plots the indicator value from 5 bars ago on the current bar
AddPlot(Brushes.Blue, "ShiftedPlot");\
}
}
✅ Displacement Value:
- Positive number: shifts the plot to the right (into the future).
- Negative number: shifts the plot to the left (into the past).
🎯 Practical Example: Shifting a Moving Average
Let’s say you want your moving average to appear 5 bars forward on the chart.
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
Displacement = 5; // Plots the indicator value from 5 bars ago on the current bar
AddPlot(Brushes.Blue, "FutureMA");
}
}
protected override void OnBarUpdate()
{
Values[0][0] = SMA(Close, 20)[0];
}
✅ Now, even though the SMA value is based on past data, it will visually project 5 bars ahead.
⚡ Important Notes:
Tip | Why It Matters |
---|---|
Displacement only affects visuals | Your Values[] and logic still operate on the real, current bar |
Large displacement needs careful chart scaling | Otherwise, plots could extend off the chart |
Great for trend projection visuals | Like forecasting moving averages or SuperTrend |
🚫 Common Beginner Mistakes When Using Plots
Even though plots are simple once you understand them, many beginners fall into easy-to-avoid traps. Let’s go over the most common ones — and how to avoid them.
❌ Forgetting to Wait for Enough Bars Before Calculating
One of the most common beginner errors: trying to calculate or assign plot values before enough data has loaded.
Indicators like SMA, EMA, or ATR need several bars to produce correct results.
Always add a CurrentBar check at the start of your OnBarUpdate()
:
if (CurrentBar < 20)
return;
Without this, your plot might behave incorrectly, crash, or even show NaN (Not a Number) values.
❌ Not Exposing Your Plot Properly (Public Series<double>)
By default, you access plot data using Values[0]
, Values[1]
, etc. But if you want to reference your plot easily by name (especially inside a strategy or another indicator), you must expose it:
[Browsable(false)]
[XmlIgnore]
public Series<double> MyPlot
{
get { return Values[0]; }
}
Without exposing it, you’ll be stuck using clunky Values[idx]
access — much harder to maintain and debug later.
❌ Assuming the Plot Name Can Be Used Automatically
Just adding a name to AddPlot()
doesn’t magically make that name available to your code. Unless you expose the Series as shown above, you can’t reference the plot by its “pretty” name like MyPlot[0]
. Beginners often assume “if I named it, I can use it” — but NinjaTrader needs you to explicitly create the public property.
❌ Referencing the Wrong Plot Index
Each plot you add maps sequentially to Values[]
.
Example:
AddPlot(Brushes.Blue, "TrendLine"); // Values[0]
AddPlot(Brushes.Red, "SignalLine"); // Values[1]
If you mix up the indexes (like treating Values[1]
as your TrendLine), you’ll get wrong data and plots won’t match their intended behavior.
✅ Always keep track of the order you added your plots.
❌ Adding Plots in the Wrong State
Plots must be added in State.SetDefaults
.
If you add them during runtime or outside of SetDefaults, they may not appear in the indicator settings UI — or worse, they can cause unpredictable behavior.
✅ Only use dynamic plot addition in State.Configure if you have a very special reason.
❌ Not Resetting Conditional Plot Values in OnPriceChange or OnEachTick
When your indicator uses Calculate.OnPriceChange
or Calculate.OnEachTick
, the current bar is unfinished and values can keep changing. If you don’t reset your plot values each update, old signals can stick and falsely appear active.
Example of proper reset:
MyPlot.Reset();
if (Close[0] > SMA(20)[0])
MyPlot[0] = 1;
else if (Close[0] < SMA(20)[0])
MyPlot[0] = -1;
✅ Always clear or reset your conditional plots before reapplying your trading logic, so they reflect the current bar accurately.
📈 Real-World Examples: Plots in Action
Now that you understand the theory, let’s see how plots are actually used inside real indicators.
Here are practical examples of different ways to leverage plots:
✅ Example 1: Simple Moving Average Plot
A classic use: plotting a moving average across your chart.
private SMA mySMA;
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
AddPlot(Brushes.Blue, "Simple Moving Average");
}
else if (State == State.DataLoaded)
{
mySMA = SMA(14);
}
}
protected override void OnBarUpdate()
{
if (CurrentBar < 14)
return;
Values[0][0] = mySMA[0];
}
✅ Here, the moving average is continuously calculated and assigned to the plot’s Series.
✅ Example 2: Plotting Buy/Sell Signals
Plots can also be used to mark entry points, not just continuous lines.
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
AddPlot(Brushes.Lime, PlotStyle.TriangleUp, "Buy Signal");
AddPlot(Brushes.Red, PlotStyle.TriangleDown, "Sell Signal");
}
}
protected override void OnBarUpdate()
{
if (CurrentBar < 20)
return;
if (Close[0] > SMA(20)[0])
Values[0][0] = Low[0] - TickSize * 2; // Plot triangle up under bar
else if (Close[0] < SMA(20)[0])
Values[1][0] = High[0] + TickSize * 2; // Plot triangle down above bar
}
✅ Triangle markers are plotted dynamically based on the bar’s relationship to a moving average.
✅ Example 3: Color-Coded Trend Plots with PlotBrushes
Add dynamic coloring to plots based on market conditions!
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
AddPlot(Brushes.Gray, "TrendPlot");
}
}
protected override void OnBarUpdate()
{
if (CurrentBar < 1)
return;
Values[0][0] = Close[0];
if (Close[0] > Close[1])
PlotBrushes[0][0] = Brushes.Green;
else if (Close[0] < Close[1])
PlotBrushes[0][0] = Brushes.Red;
else
PlotBrushes[0][0] = Brushes.Gray;
}
✅ Now the plot turns green on up closes, red on down closes, and gray if flat.
🛠️ Key Takeaways from the Examples
- Plots aren’t just static lines — they can be dynamic signals, markers, trend shifts.
- You should manage your Values[0][0] assignments every bar!
- Dynamic visuals (color, shapes) make reading your indicator faster and more powerful.
🧠 Final Thoughts
By now, you should have a strong foundational understanding of what plots are and how they work inside NinjaTrader.
✅ In simple terms:
- A plot makes your data visible and tradeable.
- Every plot automatically links to a Series<double> under the hood.
- The Values[] array holds the bar-by-bar values your plots use.
- You control how plots look, behave, and are referenced — both visually and in logic.
✅ Plots are powerful because they serve two major roles:
- They make indicators human-readable by displaying data visually.
- They make indicators machine-readable by letting strategies easily reference values like signals, trends, or conditions.
✅ As a beginner, always remember:
- Add plots inside State.SetDefaults.
- Assign values to plots inside OnBarUpdate.
- Manage enough bars and reset logic carefully if needed.
- If you want to reference a plot by name (or use it in a strategy), expose it properly through a public property.
🎉 Prop Trading Discounts
💥91% off at Bulenox.com with the code MDT91