OnStateChange()

View as Markdown

Definition

An event driven method which is called whenever the script enters a new State. The OnStateChange() method can be used to configure script properties, create one-time behavior when going from historical to real-time, as well as manage clean up resources on termination.

Notes:

  • Viewing any UI element which lists NinjaScript classes (such as the Indicators or Strategies window, a chart’s Chart Style dropdown menu, etc.) will initialize all classes of that Type when it is opened, which causes each script to enter State.SetDefaults, even if it is not actively configured or running in any window. It is important to keep this in mind when adding logic within State.SetDefaults in OnStateChange(), as this logic will be processed each time the script is initialized. For example, opening the Indicators window will trigger State.SetDefaults for all indicators in the system, and closing the Indicators window will trigger State.Terminated for all Indicators. In addition, disconnecting or connecting to a data provider can cause State transitions for any currently active scripts. Further discussion of this aspect of the state change model can be found via Understanding the lifecycle of your NinjaScript objects.
  • When an indicator is configured on a chart while a Compile is taking place in the NinjaScript Editor, it can appear that the script passes through State.Terminated. However, this is the result of a copy of the script being initialized at compile-time, NOT the result of the indicator on the chart being disabled and re-initialized.
PropertyDescription
SetState()Method is used for changing the State of any running NinjaScript object.
StateRepresents the current progression of the object as it advances from setup, processing data, to termination.

Method Return Value

This method does not return a value.

Syntax

See example below. The NinjaScript wizards automatically generate the method syntax for you.

Possible states are:

State NameThis state is called whenThis state is where you should
State.SetDefaultsSetDefaults is always called when displaying objects in a UI list such as the Indicators dialogue window since temporary objects are created for the purpose of UI display* Keep as lean as possible * Set default values (pushed to UI)
State.ConfigureConfigure is called after a user adds an object to the applied list of objects and presses the OK or Apply button. This state is called only once for the life of the object.* Add additional data series via AddDataSeries() Declare custom resources Override and configure values set by the UI
State.ActiveActive is called once after the object is configured and is ready to process data (DrawingTools could see multiple calls as internally an object for hit testing is cloned)* Used for objects such as Share Service which do not process price series data * Indicate the object is ready to being processing information
State.DataLoadedDataLoaded is called only once after all data series have been loaded.* Use for logic that needs to access data related objects like Bars, Instruments, BarsPeriod, TradingHours or instantiating indicators Notify that all data series have been loaded Initialize any class level variables (including custom Series<t> objects)
State.HistoricalHistorical is called once the object begins to process historical data. This state is called once when running an object in real-time. This object is called multiple times when running a backtest optimization and the property IsInstantiatedOnEachOptimizationIteration is true (default behavior)* Notify that the object is processing historical data
State.TransitionTransition is called once as the object has finished processing historical data but before it starts to process realtime data.* Notify that the indicator or strategy is transitioning to realtime data * Prepare realtime related resources
State.RealtimeRealtime is called once when the object begins to process realtime data.* Notify that the indicator or strategy is processing realtime data * Execute realtime related logic
State.TerminatedTerminated is called once when the object terminates.* Notify the object is shutting down * Use to clean up/dispose of resources

Active States vs Data Processing States

After State.Configure, each type of NinjaScript type has its own state management system which can be classified under two categories:

  • Active state: State.Active

  • Data Processing states: State.DataLoaded, State.Historical, State.Transition, State.Realtime

The table below lists each NinjaScript type and its designed state management system:

NinjaScript TypeState Management System
AddOns*Active state
BarTypesActive state
ChartStylesActive state
DrawingToolsActive state
IndicatorsData Processing states
ImportTypesActive state
Market Analyzer ColumnsData Processing states
OptimizationFitnessesActive state
OptimizersActive state
PerformanceMetricsActive state
ShareServicesActive state
StrategiesData Processing states
SuperDOM ColumnsActive state

Tips:

  • Resources created in State.Configure and not disposed of immediately will be kept and utilized if the NinjaScript object resides in grids (e.g. Strategy tab on Control Center), even if it is not enabled. Try to create resources in State.Historical or State.DataLoaded instead, if possible.
  • State.Historical is called multiple times when running a backtest optimization on a strategy and the property “IsInstantiatedOnEachOptimizationIteration” is true (default behavior).
  • Embedded scripts within a calling parent script should not use a different Calculate property since it is already utilizing the Calculate property of the parent script (i.e. the strategy your indicator is called from).
  • Since the parent NinjaScript therefore governs this setting, it should be set to the highest needed setting satisfying all its children.
  • When instantiating indicators in a Multi-Series script in OnStateChange, the input any hosted indicator is running on should be explicitly stated (since a specific BarsInProgress is not guaranteed)

Examples

1protected override void OnStateChange()
2{
3 if (State == State.SetDefaults)
4 {
5 // Calculate once at the end of every single bar
6 Calculate = Calculate.OnBarClose;
7
8 // Add two plots
9 AddPlot(Brushes.Blue, "Upper");
10 AddPlot(Brushes.Orange, "Lower");
11 }
12 else if (State == State.Configure)
13 {
14 // Adds a 5-minute Bars object to the strategy and is automatically assigned
15 // a Bars object index of 1 since the primary data the strategy is run against
16 // set by the UI takes the index of 0.
17 AddDataSeries("AAPL", BarsPeriodType.Minute, 5);
18 }
19}