When you first start coding indicators in NinjaScript, it’s common to think bar-by-bar:

  • What’s the Close price now?
  • What’s the High price now?
  • What’s happening on this single bar?

But sometimes, you need to track bigger stories across an entire session
like the highest high and lowest low — and doing that with basic variables can quickly get messy.

That’s where creating your own class comes in. 📦

✅ A class lets you group related data together into one object.
✅ You can then store those objects in a List, update them easily, and use them however you want.
✅ It’s cleaner, more powerful, and unlocks custom tracking NinjaTrader doesn’t do for you automatically.

In this guide, you’ll learn:

  • 📦 How to create a custom class to store session highs and lows
  • 📋 How to add each session to a List as it completes
  • 🖼️ How to use that List to draw, analyze, or build signals from past session data

We’ll go step-by-step — and by the end, you’ll not only understand how to create and use classes, but also why they are one of the best tools for building smarter, cleaner indicators in NinjaScript.

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

📦 What Is a Class?

When you’re building indicators in NinjaScript, you’re probably used to thinking in terms of individual variables: things like High[0], Low[0], or Close[0]. Each variable holds one piece of information about one bar — nice and simple.

But what if you want to track something larger — like an entire session?
What if you need to remember both the highest high and lowest low for every session across the entire day, or even multiple days?

Trying to manage all of that with individual variables quickly becomes messy and frustrating. You’d be juggling dozens of values, trying to keep track of which high belongs to which low, and hoping they all stay synced.

That’s why we use classes. 📦

🧠 A Class Is a Blueprint

A class is your way of telling NinjaTrader: “Hey, I want to group these specific pieces of data together into a new type of object.”

You design the class once, and then you can create as many objects from it as you want. Each object will carry its own copy of the information you defined.

Think of a class like a folder template 📁:

  • You design a folder that has two pages inside — one labeled “Session High” and one labeled “Session Low.”
  • Every time you need to track a new session, you make a fresh copy of the folder and fill it with that session’s data.

✅ That folder template is the class.
✅ Every filled folder you create from it is an object.

🛠️ A Tiny Example: Defining a Class

Here’s a very simple class that we’ll use later:

private class SessionData
{
    public double SessionHigh { get; set; }
    public double SessionLow { get; set; }
}

This tiny piece of code defines what a SessionData object will look like:

  • It will have a place to store the highest high.
  • It will have a place to store the lowest low.

At this point, the class is just a plan. No actual data has been created yet. We’ve simply told NinjaTrader, “If I ever need a SessionData object, here’s what it should contain.”

🧰 Access Modifiers: Controlling Visibility

When you create a class, you also get to decide who can see it and who can use it.
In C# (and NinjaScript), this is done using something called access modifiers.

Access modifiers are like rules you attach to your class that say:

  • “Only I can use this.”
  • “Anyone can use this.”
  • “Only people inside my project can use this.”

There are three main ones you’ll see:

🛡️ private

When you mark a class as private, it means that only the code inside the same containing script (your indicator) can see it or create objects from it.

Example:

private class SessionData
{
    public double SessionHigh { get; set; }
    public double SessionLow { get; set; }
}

This is what we’ll use for our session tracker, because we’re only going to need this class inside the same indicator. Nobody else (no other indicators, no strategies) needs access to it.

If you leave out the private keyword, nested classes inside another class (like inside an Indicator) are private by default — but it’s still a good habit to write it explicitly so it’s clear.

🌍 public

If you mark a class as public, you’re saying that any other script anywhere in NinjaTrader can use it.

Example:

public class SessionData
{
    public double SessionHigh { get; set; }
    public double SessionLow { get; set; }
}

When would you do this?
Only if you were building a more complicated addon — like a reusable toolkit —
where you expect other scripts to create and use your custom objects.

When NOT to do this:
For simple helper classes like we’re building inside a single indicator, you don’t want to expose them unnecessarily. It just adds risk and clutter.

🏢 internal

internal means that only scripts inside the same compiled assembly (basically the same .cs file or NinjaScript script) can use it.

Example:

internal class SessionData
{
    public double SessionHigh { get; set; }
    public double SessionLow { get; set; }
}

You almost never need this when you’re just building indicators and strategies.
It’s used more when people are developing bigger addon packages or plugins.

🧹 Why Are We Using private Here?

Because our SessionData class is only going to be used inside the same indicator. It doesn’t need to be visible to anything else.

✅ It keeps our code tighter, safer, and easier to maintain.
✅ If we ever need to expand later, we can still change it to public if necessary — but start private unless you have a good reason not to.

📚 Quick Summary: Access Modifiers

Modifier Who Can See It When to Use
private Only the same indicator Almost always for small helper classes
public Any other script Only when you are intentionally sharing
internal Same assembly/script Rarely needed for basic indicator work

✅ Big Takeaway

  • A class is a blueprint 📐.
  • It lets you group related data together (like Session High and Session Low).
  • Access modifiers control who can use your class.
  • In this case, we’ll use a private class to keep everything organized inside our indicator.

👉 Now that you understand what a class really is and how it behaves,
let’s move forward and look at what happens when we actually create real objects based on this class! 🏡

🏡 What Is an Object?

In the last section, you learned that a class is just a blueprint — a way to describe what kind of information you want to group together.

But a class by itself doesn’t actually do anything. It’s like a house blueprint — you can stare at the drawing all day, but you can’t live in it.

✅ You have to build something real based on that blueprint.
✅ You have to create an object.

In programming, when you “build” a real instance from a class, that real thing is called an object.

🏗️ Building an Object from a Class

When you create an object, you’re telling NinjaTrader: “Okay, take that SessionData blueprint we designed — now make a real one for me to use!”

Here’s how you actually build an object:

SessionData todaySession = new SessionData();
todaySession.SessionHigh = 4565.25;
todaySession.SessionLow = 4530.75;

✅ This code does two important things:

  1. new SessionData() creates a fresh new empty object in memory.
  2. Assigning values (SessionHigh = 4565.25, SessionLow = 4530.75) fills the object with real data.

Now you have a real folder 📁 in your “desk” (your computer’s memory), with two pages inside it: one page showing the High and one page showing the Low for today’s session.

🧠 Important Concept: Each Object Is Separate

Every time you create a new object, you get a completely new, independent container.

Example:

SessionData mondaySession = new SessionData();
mondaySession.SessionHigh = 4550;
mondaySession.SessionLow = 4500;

SessionData tuesdaySession = new SessionData();
tuesdaySession.SessionHigh = 4575;
tuesdaySession.SessionLow = 4525;

mondaySession and tuesdaySession are two separate objects:

  • They each have their own High.
  • They each have their own Low.
  • Changing one does not affect the other.

They are completely independent “folders” 📁 in memory.

📚 Real-World Analogy

Think of a class as designing a blank medical form 📝:

  • Name
  • Date of Birth
  • Blood Pressure

When a patient comes into the doctor’s office, you fill out a real copy of the form for them — that filled-in form is an object.

✅ Every patient gets their own copy.
✅ Every copy can be filled out differently.
✅ No two patients share the same form — just like no two SessionData objects share the same High and Low.

🛠️ What Happens Behind the Scenes (In Memory)

When you create a new object:

  • NinjaTrader asks the computer to reserve a block of memory for that object.
  • That memory space has areas to store the SessionHigh and SessionLow.
  • You can then read from or write to those values whenever you want.

✅ The object stays alive in memory as long as you keep a reference to it (like assigning it to a variable or adding it to a List).
✅ When you’re done with it (or if you remove it from the List), the system will eventually clean up the memory (automatically).

🧹 Why It Matters

If you didn’t have objects, you’d be stuck manually juggling dozens of loose variables:

double mondayHigh, mondayLow;
double tuesdayHigh, tuesdayLow;
double wednesdayHigh, wednesdayLow;
// etc.

😵 Imagine trying to keep all that straight after 20, 30, or 100 sessions! It would be extremely easy to mix up values or lose track of what belongs to what.

With objects:
Each session’s data is self-contained, organized, and easy to manage. You can create new sessions dynamically as they happen, store them in a clean structure (a List), and work with them confidently.

📚 Quick Summary: What Is an Object?

Concept Easy Explanation
Object A real, live copy of a class blueprint
How to create one new SessionData()
Where it lives In computer memory
Why it matters Clean organization, easy tracking, scalable coding

✅ Now you understand that classes are blueprints 📐 and objects are real instances 🏡 built from those blueprints.

Each object you create is an independent memory container you can fill, update, and use however you want.

👉 Next, we’ll talk about why using classes and objects is way better than trying to juggle loose variables manually — and how this clean organization changes everything when you build real indicators!

🛠️ Why Use Classes and Objects Instead of Just Variables?

At this point, you understand that:

  • A class is a blueprint 📐, and
  • An object is a real thing 🏡 built from that blueprint.

Now you might be wondering: “Okay, but couldn’t I just use some regular variables instead? Why bother with classes and objects at all?”

✅ Good question — and one that every programmer asks early on.

Let’s walk through it carefully.

🧠 What Happens If You Just Use Variables?

Imagine you’re trying to track the highest high and lowest low for multiple sessions.
Without using a class, you would have to create separate variables for each session.

Example:

double mondayHigh, mondayLow;
double tuesdayHigh, tuesdayLow;
double wednesdayHigh, wednesdayLow;
double thursdayHigh, thursdayLow;
// and so on...

At first, this might seem manageable. But after just a few days (or even a few hours of real-time data), your code will explode into dozens or hundreds of individual variables.

Every time you add a new session, you’d have to:

  • Declare new variables
  • Remember which variables belong together
  • Write extra logic to update and manage all of them separately

😵‍💫 It gets messy very fast.

❌ Problems with Just Variables:

  • No scalability: You have to manually create new variables forever.
  • Easy to make mistakes: You might accidentally update the wrong High or Low.
  • Hard to loop through: You can’t easily loop through variables like you can through objects in a List.
  • No organization: It becomes unclear what data belongs to what session.

Simply put: The more sessions you track, the worse it gets.

🏡 What Happens When You Use Classes and Objects?

Now imagine you’ve defined a simple class, SessionData, like this:

private class SessionData
{
    public double SessionHigh { get; set; }
    public double SessionLow { get; set; }
}

Now, instead of creating dozens of variables, you create one object for each session:

SessionData monday = new SessionData();
SessionData tuesday = new SessionData();
SessionData wednesday = new SessionData();

✅ Each object carries both the High and the Low values, bundled neatly together.
✅ You don’t have to manually manage which High goes with which Low — they’re tied together inside the object itself.
✅ You can easily store all the objects in a List and loop through them:

List<SessionData> sessionList = new List<SessionData>();
sessionList.Add(monday);
sessionList.Add(tuesday);
sessionList.Add(wednesday);

✅ Now you can use a simple foreach loop to walk through all your sessions and work with their data.

No chaos. No manual headaches. Just clean, scalable code.

🖼️ Tiny Practical Example

Without classes:

double mondayHigh = 4550;
double mondayLow = 4500;
double tuesdayHigh = 4575;
double tuesdayLow = 4525;

// To print all highs
Print(mondayHigh);
Print(tuesdayHigh);

With classes:

SessionData monday = new SessionData { SessionHigh = 4550, SessionLow = 4500 };
SessionData tuesday = new SessionData { SessionHigh = 4575, SessionLow = 4525 };

List<SessionData> sessionList = new List<SessionData> { monday, tuesday };

foreach (var session in sessionList)
    Print(session.SessionHigh);

Same result — but way cleaner
✅ And the class-based version can handle 2 sessions or 200 sessions with no extra work.

📚 Quick Side-by-Side Comparison

Approach Pros Cons
Just Variables Simple for 1–2 items Unmanageable beyond a few sessions
Classes and Objects Clean, scalable, organized Slightly more setup at first (but worth it)

🧠 Big Picture: Why It Matters for Real Indicators

In real-world NinjaScript development:

  • Markets have sessions, patterns, trades, zones, signals, and more.
  • All of these are groups of related data, not just one number.
  • If you use loose variables, you will hit a wall quickly as your indicators become more complex.
  • If you use classes and objects, you can build almost anything — and your code will stay organized and understandable.

✅ This is one of the major transitions from “beginner coder” to “real developer” in NinjaScript.

✅ Big Takeaway

  • Loose variables are fine for extremely small, short-term tracking.
  • Classes and objects are how you build systems that can grow and stay clean.
  • If you want to track multiple things over time — like sessions — classes and objects are absolutely the way to go.

👉 Now that you understand why using classes and objects makes your life so much easier, let’s actually build the real class we’re going to use for tracking session highs and lows! 🛠️

✍️ Define a Custom Class for Session Tracking

Now that you understand what a class is and why using objects is so powerful, it’s time to build a real, working class for our session tracking indicator.

This class will be small — on purpose. We’re keeping it focused only on what we need: the highest high and the lowest low for each session.

But even though it’s simple, it’s a huge step forward compared to juggling loose variables.

Let’s break it down.

🧠 What We Want the Class to Do

Think about the goal:

  • For every new session that starts on the chart, we want to start tracking the highs and lows.
  • As the session progresses, we want to update those values if new highs or new lows occur.
  • When the session ends, we want to save that session’s data so we can look at it later, draw it, or analyze it.

✅ Each session’s data — High and Low — should stay together.
✅ Each session’s data should be kept separate from other sessions.

That’s exactly what our custom class will let us do.

📦 Writing the Class

Here’s the simple structure we need:

private class SessionData
{
    public double SessionHigh { get; set; }
    public double SessionLow { get; set; }
}

✅ This class is named SessionData.
✅ It has two properties:

  • SessionHigh — the highest price reached during a session
  • SessionLow — the lowest price reached during a session

✅ Each property uses { get; set; }, which automatically creates storage for a value that can be read and written later.

🧰 Why Use private?

The private keyword is important here.

✅ We only need this SessionData class inside our indicator.
✅ We don’t want other indicators, strategies, or external scripts to be able to access it.
✅ Keeping it private helps protect our code and keep things organized.

Rule of thumb: If a class is only used inside one indicator or strategy, make it private.

✅ If you were designing a big tool or library meant to be shared with other scripts, then you’d think about making it public — but that’s not what we’re doing here.

🧠 How NinjaTrader Handles This

When you define a private class inside your indicator, NinjaTrader (and C#) will:

  • Know that it’s only available inside that script
  • Compile it along with your indicator
  • Let you create as many SessionData objects as you need while the indicator runs

✅ You don’t need to create a new file.
✅ You don’t need to add extra imports or settings.
✅ It’s clean, self-contained, and lightweight.

📄 Full Code: How It Fits Inside an Indicator

It’s very important to see the full structure — so here’s exactly what it looks like when you add this class inside an indicator file:

namespace NinjaTrader.NinjaScript.Indicators
{
    public class MySessionTracker : Indicator
    {
        // 👇 Here’s our custom SessionData class
        private class SessionData
        {
            public double SessionHigh { get; set; }
            public double SessionLow { get; set; }
        }

        // --- Other variables and logic will go below this ---

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

        protected override void OnBarUpdate()
        {
            // We'll add logic to create and update SessionData objects here soon!
        }
    }
}

✅ Notice how the SessionData class sits inside the indicator, but outside of any methods like OnStateChange() or OnBarUpdate().
✅ It’s ready to be used anywhere inside this indicator — and only this indicator.
✅ It will travel along with your indicator when it runs live, saves templates, or reloads — without needing anything extra.

🧠 Important Notes for Beginners

Concept Explanation
Placement Class goes inside your indicator’s { }, but outside of any method bodies
Naming Pick clear names (SessionData) that describe what your class holds
Access Modifier private means only this script can use it (good for helpers like this)
Why not in another file? You only move classes into separate .cs files when they are big or shared across many indicators — not needed here

✅ Big Takeaway

You’ve now defined a real custom class inside your indicator — one that can store, organize, and protect the session data you’ll track.

This is a major step forward in your NinjaScript skills:

  • You’re not just tracking one number at a time anymore.
  • You’re building a small system that can track sessions dynamically.

👉 Next, we’ll set up a List where we can store multiple SessionData objects — because one session isn’t enough when you want to build real trading logic! 📚

🗂️ Building a List to Hold Session Data

Now that we’ve defined the SessionData class to track the High and Low for each session, we need a way to store every completed session so we can work with them later.

✅ We’re going to create a List that will hold all of our SessionData objects.

🛠️ Declaring the List

At the top of your indicator (along with your other variables), add this line to create a fresh, empty List:

private List<SessionData> sessionList = new List<SessionData>();

Quick breakdown:

  • private — only this indicator can use it.
  • List<SessionData> — a collection specifically for storing SessionData objects.
  • sessionList — the name of our List.
  • new List<SessionData>() — starts the List empty, ready to add sessions as they happen.

✅ This List will grow automatically as each new session completes — no extra work needed to resize it or manage it manually.

📄 Full Updated Code So Far

Here’s how your indicator should look now, including both the SessionData class and the sessionList variable:

namespace NinjaTrader.NinjaScript.Indicators
{
    public class MySessionTracker : Indicator
    {
        // 👇 Our custom SessionData class
        private class SessionData
        {
            public double SessionHigh { get; set; }
            public double SessionLow { get; set; }
        }

        // 👇 List to hold all completed sessions
        private List<SessionData> sessionList = new List<SessionData>();

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

        protected override void OnBarUpdate()
        {
            // We'll add live session tracking here soon!
        }
    }
}

✅ Now we have two important pieces ready:

  • A SessionData class to hold each session’s High and Low.
  • A List to store all completed sessions over time.

🧠 Why This Matters

Without this List, you could only track one session at a time — and the moment a new session started, you’d lose the old one.

✅ With this List, you can keep a full historical memory of sessions, ready to loop through, draw from, or build smarter trading logic with.

✅ Big Takeaway

You’ve now prepared a real storage system for your session data — one that will grow as the market runs, keeping every session safe, organized, and ready for analysis.

👉 Next, we’ll actually start creating SessionData objects live, updating them during the session, and saving them when each session finishes! 📈

That’s where all the pieces start coming together!

🔄 Creating and Updating Session Objects During Live Bars

Now that we have:

✅ A SessionData class to store Highs and Lows
✅ A List called sessionList to hold completed sessions

…it’s time to start putting everything into action while the chart is running.

✅ This is where we actually create a SessionData object at the start of a session, update it as bars come in, and save it when the session completes.

Let’s break it down.

🛠️ How Live Bar Updates Work

When you build a NinjaScript indicator, your OnBarUpdate() method runs every time a new bar is closed (or every tick, depending on your settings).

  • Every time a bar closes, NinjaTrader calls OnBarUpdate() automatically.
  • You can use this method to check conditions, analyze price action, and update your own data.

✅ We’ll use OnBarUpdate() to:

  • Detect when a new session starts
  • Initialize a new SessionData object
  • Update the High and Low for the current session
  • Save the finished session into our List

📅 Step 1: Detecting a New Session

NinjaTrader gives you a built-in tool for this:

if (Bars.IsFirstBarOfSession)

✅ This condition checks if the current bar is the first bar of a new trading session (after midnight, after RTH close, etc.).
✅ We’ll use this moment to finalize the previous session and start tracking a new one.

🧱 Step 2: Setting Up a “Current Session” Tracker

Before you can track a session live, you need a variable to hold the session that’s happening right now.

At the top of your indicator (with your other variables), declare this:

private SessionData currentSession;

✅ This currentSession variable will:

  • Hold the High and Low as the session progresses
  • Get filled in bar-by-bar
  • Get added to the sessionList when a new session starts

✍️ Full Code for Live Session Tracking

Here’s what your OnBarUpdate() method will look like now:

protected override void OnBarUpdate()
{
    if (BarsInProgress != 0)
        return; // Only run on the primary data series

    if (CurrentBar < 1)
        return; // Safety check: make sure there's enough data

    if (Bars.IsFirstBarOfSession)
    {
        // If we were already tracking a session, save it
        if (currentSession != null)
            sessionList.Add(currentSession);

        // Start a new session
        currentSession = new SessionData
        {
            SessionHigh = High[0],
            SessionLow = Low[0]
        };
    }
    else if (currentSession != null)
    {
        // Update the current session's High and Low if necessary
        currentSession.SessionHigh = Math.Max(currentSession.SessionHigh, High[0]);
        currentSession.SessionLow = Math.Min(currentSession.SessionLow, Low[0]);
    }
}

🧠 What This Code Does (Step-by-Step)

  1. BarsInProgress Check
    Make sure we’re only running this code for the main chart — not for other timeframes or data series.
  2. CurrentBar Check
    Protects against weird behavior when there are no bars loaded yet (first couple bars on load).
  3. New Session Detected
    • If a new session starts (Bars.IsFirstBarOfSession):
      • Save the old session (if one exists) into sessionList.
      • Create a new currentSession object with the High and Low of the first bar.
  4. Updating During the Session
    • As new bars close:
      • Update the SessionHigh if the new High is higher.
      • Update the SessionLow if the new Low is lower.

✅ Every session is tracked live, bar-by-bar, without missing a beat.
✅ As soon as a session ends, its finished data is stored safely in the sessionList.

📄 Full Indicator Code So Far

Here’s what your entire working structure looks like now:

namespace NinjaTrader.NinjaScript.Indicators
{
    public class MySessionTracker : Indicator
    {
        private class SessionData
        {
            public double SessionHigh { get; set; }
            public double SessionLow { get; set; }
        }

        private List<SessionData> sessionList = new List<SessionData>();
        private SessionData currentSession;

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

        protected override void OnBarUpdate()
        {
            if (BarsInProgress != 0)
                return;

            if (CurrentBar < 1)
                return;

            if (Bars.IsFirstBarOfSession)
            {
                if (currentSession != null)
                    sessionList.Add(currentSession);

                currentSession = new SessionData
                {
                    SessionHigh = High[0],
                    SessionLow = Low[0]
                };
            }
            else if (currentSession != null)
            {
                currentSession.SessionHigh = Math.Max(currentSession.SessionHigh, High[0]);
                currentSession.SessionLow = Math.Min(currentSession.SessionLow, Low[0]);
            }
        }
    }
}

✅ Your indicator is now live, tracking sessions as the market moves, storing each completed session in a clean List for future use.

🧹 Tiny Improvements We’ll Make Later

  • Trim the List so it doesn’t grow forever (we’ll limit the number of stored sessions)
  • Draw session highs and lows from the saved data
  • Analyze old sessions to build smarter trading strategies

✅ But for now, your session memory system is fully working!

✅ Big Takeaway

  • You now have live session tracking running inside OnBarUpdate().
  • Each session’s High and Low are recorded, updated, and stored safely.
  • Your indicator can now build real logic based on what happens across entire sessions — not just one bar at a time!

👉 Next, we’ll clean things up by making sure we manage the List properly — so it doesn’t grow too large over long trading days! 📚

🧹 Managing the Session List (Trimming and Clearing)

Now that you have your indicator creating, updating, and storing session objects as the market runs, you might be wondering:

"If this keeps running all day (or for weeks), won't the List just keep growing forever?"

✅ That’s a smart question — and yes, if we don’t manage the List, it could eventually become very large.

Even though storing basic Highs and Lows isn’t heavy on memory, it’s still a good habit to control the size of your Lists — especially when you’re building indicators meant to run live for long periods.

📚 Why You Should Trim the List

Imagine your indicator runs every day without restarting NinjaTrader:

  • After 1 week, you have 5 sessions stored.
  • After 1 month, maybe 22 sessions.
  • After a year… 250+ sessions.

Each session is small — just two numbers — but good programming discipline says:

✅ Keep your memory usage tight and efficient.
✅ Only keep what you actually need for your trading logic.

🛠️ How to Trim the List Automatically

You can add a simple check inside your OnBarUpdate() method (or right after adding a new session) to limit the number of stored sessions.

Here’s the code:

if (sessionList.Count > 20)
    sessionList.RemoveAt(0); // Remove the oldest session (at the start of the List)

✅ This says:

  • If there are more than 20 sessions stored,
  • Delete the oldest one (the one at position 0).

Why RemoveAt(0)? Because Lists work like a line at the grocery store:

  • The first item added is at index 0,
  • New items get added at the end,
  • So the oldest session is always at position 0.

✍️ Where Should You Put This?

You should place this trimming logic right after you add a completed session into the List.

✅ So inside your OnBarUpdate(), after adding the currentSession, it looks like this:

if (Bars.IsFirstBarOfSession)
{
    if (currentSession != null)
    {
        sessionList.Add(currentSession);

        // 👇 Manage list size here
        if (sessionList.Count > 20)
            sessionList.RemoveAt(0);
    }

    currentSession = new SessionData
    {
        SessionHigh = High[0],
        SessionLow = Low[0]
    };
}

✅ This keeps your session memory under control automatically as the market continues to run.
✅ You don’t have to manually monitor or reset anything — it’s built right into the indicator.

🧹 Optional: Clearing the List on Major Events

Sometimes you might want to clear the entire session list based on major events like:

  • Switching to a new instrument (different symbol)
  • Resetting for a new trading week

You can easily do that by calling:

sessionList.Clear();

✅ This wipes out the List completely, freeing up memory instantly.
✅ You could put sessionList.Clear() inside OnStateChange() when the State is State.DataLoaded, or in a custom logic block if you detect a special condition.

📄 Full OnBarUpdate With Trimming

Here’s what your updated OnBarUpdate() now looks like:

protected override void OnBarUpdate()
{
    if (BarsInProgress != 0)
        return;

    if (CurrentBar < 1)
        return;

    if (Bars.IsFirstBarOfSession)
    {
        if (currentSession != null)
        {
            sessionList.Add(currentSession);

            // Trim the list to 20 sessions
            if (sessionList.Count > 20)
                sessionList.RemoveAt(0);
        }

        currentSession = new SessionData
        {
            SessionHigh = High[0],
            SessionLow = Low[0]
        };
    }
    else if (currentSession != null)
    {
        currentSession.SessionHigh = Math.Max(currentSession.SessionHigh, High[0]);
        currentSession.SessionLow = Math.Min(currentSession.SessionLow, Low[0]);
    }
}

✅ Your indicator is now self-managing:

  • Tracks sessions live
  • Stores sessions neatly
  • Trims old sessions automatically

✅ Big Takeaway

  • Lists grow automatically — but smart indicators manage their size.
  • Trimming keeps your indicator fast, efficient, and ready for real-world trading.
  • You can scale your session tracking logic without worrying about memory leaks or slowdowns.

👉 Now that your session data is tracked and cleaned properly, we can finally use it to draw session High and Low levels onto your chart! You’ll actually see the sessions you’ve been tracking!

🎯 Drawing Session Highs and Lows on the Chart

Now that you’ve built a system that:

Creates a SessionData object for each session
Updates the High and Low during the session
Stores completed sessions neatly in a List
Trims old sessions automatically to control memory…

…it’s finally time to start using that session data visually!

✅ We’re going to draw horizontal lines on your chart showing:

  • The highest point of each past session
  • The lowest point of each past session

This will let you see your session tracking working in real time — and it’s the first step toward building visual indicators that traders can use directly on the chart.

🛠️ How Drawing Works in NinjaScript

NinjaTrader gives you built-in drawing tools inside indicators:

  • Draw.Line() to draw a line between two points
  • Draw.Text() to write words on the chart
  • And many more (shapes, regions, highlights)

✅ For our session tracker, we’ll use Draw.Line() to create clean, simple horizontal lines at the session High and Low.

🧠 When Should We Draw?

Since we are saving completed sessions into the sessionList, we can loop through that List on every bar, and re-draw the highs and lows for each saved session.

✅ Even if you reload your chart, your indicator will rebuild all the past session drawings immediately, because all the session data is safely stored in the List.

✍️ Drawing Code Example

Here’s how you draw session lines from the List:

foreach (var session in sessionList)
{
    int idx = sessionList.IndexOf(session);

    Draw.Line(this, 
        "HighLine" + idx, 
        true, 
        0, session.SessionHigh, 
        20, session.SessionHigh, 
        Brushes.Green);

    Draw.Line(this, 
        "LowLine" + idx, 
        true, 
        0, session.SessionLow, 
        20, session.SessionLow, 
        Brushes.Red);
}

✅ Let’s break that down carefully:

  • foreach (var session in sessionList) — loop through every saved session.
  • sessionList.IndexOf(session) — get a unique number (index) for each session, so our line names are different.
  • "HighLine" + idx — name for the high line.
  • "LowLine" + idx — name for the low line.
  • 0, session.SessionHigh — the start point (current bar, at the session’s high).
  • 20, session.SessionHigh — the end point (20 bars into the past, at the same price level).
  • Brushes.Green and Brushes.Red — colors for the high and low lines.

✅ You can customize the length later — for now we’re making each line 20 bars long just so you can see them clearly.

📄 Where to Put the Drawing Code

You should place the drawing loop at the bottom of your OnBarUpdate(), after you update the session list and current session data.

✅ That way:

  • All session data is up-to-date before drawing
  • New sessions appear immediately once completed

Updated OnBarUpdate() structure:

protected override void OnBarUpdate()
{
    if (BarsInProgress != 0)
        return;

    if (CurrentBar < 1)
        return;

    if (Bars.IsFirstBarOfSession)
    {
        if (currentSession != null)
        {
            sessionList.Add(currentSession);

            if (sessionList.Count > 20)
                sessionList.RemoveAt(0);
        }

        currentSession = new SessionData
        {
            SessionHigh = High[0],
            SessionLow = Low[0]
        };
    }
    else if (currentSession != null)
    {
        currentSession.SessionHigh = Math.Max(currentSession.SessionHigh, High[0]);
        currentSession.SessionLow = Math.Min(currentSession.SessionLow, Low[0]);
    }

    // 👇 Draw session highs and lows
    foreach (var session in sessionList)
    {
        int idx = sessionList.IndexOf(session);

        Draw.Line(this, 
            "HighLine" + idx, 
            true, 
            0, session.SessionHigh, 
            -20, session.SessionHigh, 
            Brushes.Green);

        Draw.Line(this, 
            "LowLine" + idx, 
            true, 
            0, session.SessionLow, 
            -20, session.SessionLow, 
            Brushes.Red);
    }
}

🎨 What You Should See on the Chart

✅ After the first session ends, you should see two horizontal lines appear:

  • A green line at that session’s highest price
  • A red line at that session’s lowest price

✅ As more sessions happen, you’ll see more pairs of lines appear — one for each session you saved.
✅ The newest sessions will overwrite old ones if you trimmed the List to a fixed size (like 20).

🧹 Tiny Optimization for the Future

Later on (if you want to get even fancier), you can:

  • Use Draw.HorizontalLine() if you want infinitely extending lines
  • Draw lines as they update during the session
  • Draw lines after session close and track when they are “broken” by price
  • Optimize the draw line so it does not re-draw on every new bar

But for now, this simple Draw.Line() setup is perfect — easy to understand, easy to customize later.

✅ Big Takeaway

  • You’re now drawing real market structures based on your own session memory system.
  • You’ve moved from just “tracking numbers” to building real visual indicators that traders can use.
  • This is the first step toward building full session-based trading systems, breakout strategies, and more!

🧠 Final Thoughts

You just built more than a simple indicator — you built the foundation for thinking like a real NinjaScript developer.

When you first start coding, it’s easy to get trapped in a “one bar at a time” mindset. Track a High here. Check a Close there. But real indicators — real trading tools — are built by tracking, remembering, and organizing information over time.

✅ By learning how to design a class, create objects, store them in a List, and work with them across sessions, you’ve taken a huge step forward.

You’re no longer just reacting to the last price.
✅ You’re building memory.
✅ You’re tracking behavior.
✅ You’re laying the groundwork for more advanced tools — tools that actually give you an edge.

Most beginner coders struggle because they never build these mental habits:

  • Structuring related data clearly
  • Managing growth and scaling cleanly
  • Thinking about code like building blocks instead of one-off commands

✅ Now, you have those habits starting to form. And every bigger project you build — whether it’s breakout indicators, trade trackers, or zone analyzers — will come from this same basic skill you just practiced here.

🎉 Prop Trading Discounts

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

Categorized in:

Learn NinjaScript,

Tagged in: