From trading-indicators
NinjaTrader 8 NinjaScript indicator scaffold and patterns. Provides C# structure guidance and triggers doc-researcher for API verification. Use when developing NinjaTrader indicators.
npx claudepluginhub joshuarweaver/cascade-code-devops-misc-2 --plugin lgbarn-trading-indicator-pluginsThis skill uses the workspace's default tool permissions.
Lightweight scaffold for NinjaTrader 8 NinjaScript/C# indicator development.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Checks Next.js compilation errors using a running Turbopack dev server after code edits. Fixes actionable issues before reporting complete. Replaces `next build`.
Lightweight scaffold for NinjaTrader 8 NinjaScript/C# indicator development.
ALWAYS use doc-researcher agent or Ref MCP tools to verify:
*LB.cs// Author: Luther Barnumnamespace NinjaTrader.NinjaScript.Indicators.LB
{
public class [Name]LB : Indicator
{
// Implementation
}
}
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
}
}
protected override void OnBarUpdate()
{
if (CurrentBar < BarsRequiredToPlot) return;
// Calculations
}
[NinjaScriptProperty]
[Display(Name = "Period", Order = 1, GroupName = "Parameters")]
[Range(1, int.MaxValue)]
public int Period { get; set; }
if (Bars.IsFirstBarOfSession)
{
// Reset session values
}
private Series<double> myValues;
// In State.DataLoaded:
myValues = new Series<double>(this);
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);
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
}
}
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;
}
}
protected override void OnBarUpdate()
{
// Ensure enough bars for calculation
if (CurrentBar < BarsRequiredToPlot)
return;
// Or use specific period
if (CurrentBar < Period - 1)
return;
}
// 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
}
if (State == State.SetDefaults)
{
// Use [Range] attribute for validation
}
else if (State == State.Configure)
{
// Additional validation
if (SlowPeriod <= FastPeriod)
SlowPeriod = FastPeriod + 1;
}
// Safe access to previous bars
if (CurrentBar >= barsAgo)
{
double previousValue = Close[barsAgo];
}
/Users/lgbarn/Personal/Indicators/Ninjatrader/Use Ref MCP to search: