smithery/lgbarn

ninja-patterns

NinjaTrader 8 NinjaScript indicator scaffold and patterns. Provides C# structure guidance and triggers doc-researcher for API verification. Use when developing NinjaTrader indicators.

Installation

$ npx skills add smithery/lgbarn --skill ninja-patterns

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery/lgbarn.

npx skills add smithery/lgbarn

Browse all from smithery/lgbarn

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 6,181 B
  • docs SUMMARY.md 205 B

History

  1. First recorded snapshot · 0 installs

SKILL.md

NinjaScript Patterns

Lightweight scaffold for NinjaTrader 8 NinjaScript/C# indicator development.

Before Generating Code

ALWAYS use doc-researcher agent or Ref MCP tools to verify:

  • NinjaTrader 8 API methods
  • Property attribute usage
  • Drawing object APIs

File Conventions

  • File naming: *LB.cs
  • Author: // Author: Luther Barnum

Namespace & Class

namespace NinjaTrader.NinjaScript.Indicators.LB
{
    public class [Name]LB : Indicator
    {
        // Implementation
    }
}

Lifecycle Methods

OnStateChange()

protected override void OnStateChange()
{
    if (State == State.SetDefaults)
    {
        Description = "Indicator description";
        Name = "IndicatorName";
        // Set property defaults
    }
    else if (State == State.Configure)
    {
        AddPlot(Brushes.Blue, "PlotName");
    }
    else if (State == State.DataLoaded)
    {
        // Initialize Series objects
    }
}

OnBarUpdate()

protected override void OnBarUpdate()
{
    if (CurrentBar < BarsRequiredToPlot) return;
    // Calculations
}

Property Attributes

[NinjaScriptProperty]
[Display(Name = "Period", Order = 1, GroupName = "Parameters")]
[Range(1, int.MaxValue)]
public int Period { get; set; }

Session Detection

if (Bars.IsFirstBarOfSession)
{
    // Reset session values
}

Series Objects

private Series<double> myValues;

// In State.DataLoaded:
myValues = new Series<double>(this);

Drawing Objects

Draw.Rectangle(this, "tag", startBar, startPrice, endBar, endPrice, Brushes.Blue);
Draw.Line(this, "tag", startBar, startPrice, endBar, endPrice, Brushes.Red);
Draw.Text(this, "tag", "Label", 0, High[0] + TickSize, Brushes.White);

Complete Example

Reference: /Users/lgbarn/Personal/Indicators/Ninjatrader/PEMA.cs

#region Using declarations
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Windows.Media;
using NinjaTrader.Gui.Chart;
using NinjaTrader.NinjaScript.DrawingTools;
#endregion

// Author: Luther Barnum

namespace NinjaTrader.NinjaScript.Indicators.LB
{
    public class SimpleMALB : Indicator
    {
        private EMA fastEma;
        private SMA slowSma;

        protected override void OnStateChange()
        {
            if (State == State.SetDefaults)
            {
                Description = "Simple MA Crossover Indicator";
                Name = "SimpleMALB";
                Calculate = Calculate.OnBarClose;
                IsOverlay = true;

                // Default parameters
                FastPeriod = 9;
                SlowPeriod = 21;

                // Add plots
                AddPlot(Brushes.Cyan, "FastMA");
                AddPlot(Brushes.Orange, "SlowMA");

                Plots[0].Width = 2;
                Plots[1].Width = 2;
            }
            else if (State == State.DataLoaded)
            {
                fastEma = EMA(Close, FastPeriod);
                slowSma = SMA(Close, SlowPeriod);
            }
        }

        protected override void OnBarUpdate()
        {
            if (CurrentBar < SlowPeriod)
                return;

            FastMA[0] = fastEma[0];
            SlowMA[0] = slowSma[0];
        }

        #region Properties
        [NinjaScriptProperty]
        [Range(1, int.MaxValue)]
        [Display(Name = "Fast Period", Order = 1, GroupName = "Parameters")]
        public int FastPeriod { get; set; }

        [NinjaScriptProperty]
        [Range(1, int.MaxValue)]
        [Display(Name = "Slow Period", Order = 2, GroupName = "Parameters")]
        public int SlowPeriod { get; set; }

        [Browsable(false)]
        [XmlIgnore]
        public Series<double> FastMA { get { return Values[0]; } }

        [Browsable(false)]
        [XmlIgnore]
        public Series<double> SlowMA { get { return Values[1]; } }
        #endregion
    }
}

VWAP Calculation Pattern

private double cumVolume;
private double cumVwap;
private double cumVwap2;

protected override void OnBarUpdate()
{
    if (Bars.IsFirstBarOfSession)
    {
        cumVolume = 0;
        cumVwap = 0;
        cumVwap2 = 0;
    }

    double typicalPrice = (High[0] + Low[0] + Close[0]) / 3.0;
    cumVolume += Volume[0];
    cumVwap += Volume[0] * typicalPrice;
    cumVwap2 += Volume[0] * typicalPrice * typicalPrice;

    if (cumVolume > 0)
    {
        double vwap = cumVwap / cumVolume;
        double variance = (cumVwap2 / cumVolume) - (vwap * vwap);
        double stdev = variance > 0 ? Math.Sqrt(variance) : 0;

        VWAP[0] = vwap;
        UpperBand[0] = vwap + stdev;
        LowerBand[0] = vwap - stdev;
    }
}

Error Handling Patterns

Check bar history

protected override void OnBarUpdate()
{
    // Ensure enough bars for calculation
    if (CurrentBar < BarsRequiredToPlot)
        return;

    // Or use specific period
    if (CurrentBar < Period - 1)
        return;
}

Null/zero checks

// Safe division
double divisor = High[0] - Low[0];
double result = divisor != 0 ? (Close[0] - Low[0]) / divisor : 0.5;

// Check indicator values
if (myIndicator[0] != 0 && !double.IsNaN(myIndicator[0]))
{
    // Safe to use
}

Validate parameters

if (State == State.SetDefaults)
{
    // Use [Range] attribute for validation
}
else if (State == State.Configure)
{
    // Additional validation
    if (SlowPeriod <= FastPeriod)
        SlowPeriod = FastPeriod + 1;
}

Historical data access

// Safe access to previous bars
if (CurrentBar >= barsAgo)
{
    double previousValue = Close[barsAgo];
}

Trading Context

  • Focus: /ES, /NQ futures
  • Timeframe: 5-minute
  • Key concepts: VWAP+bands, IB, Pivots
  • Location: /Users/lgbarn/Personal/Indicators/Ninjatrader/

Documentation Sources

Use Ref MCP to search:

  • NinjaTrader 8 Help Guide
  • NinjaScript Reference