Init

What is it?

The Init method is called once, right when your custom indicator is created or loaded onto the chart. This is where you set everything up — like naming your indicator, creating buffers, creating parameters and registering them, and more.


Syntax

public Init(): void {
    // initialization logic here
}

What MUST Be Done in Init

This method is like a constructor for your indicator. Here's what must happen inside:

1. Create and Register Parameters

All user-configurable parameters must be:

  • Declared as class-level fields using the ! syntax

  • Created in Init() using appropriate factory methods

  • Registered using this.api.RegOption() to appear in the UI

// Declare as class-level field
public period!: TOptValue_number;
public showLine!: TOptValue_bool;
public mode!: TOptValue_str;

public Init(): void {
    // Create parameters with factory methods
    this.period = this.api.createTOptValue_number(14);
    this.showLine = this.api.createTOptValue_bool(true);
    this.mode = this.api.createTOptValue_str("Simple");

    // Register parameters (required for UI visibility)
    this.api.RegOption("Period", TOptionType.INTEGER, this.period);
    this.api.RegOption("Show Line", TOptionType.BOOLEAN, this.showLine);
    this.api.RegOption("Mode", TOptionType.STRING, this.mode);

    // Optional: Set parameter constraints
    this.api.SetOptionRange("Period", 1, 200);
    this.api.SetOptionDigits("Period", 0);
}

2. Create and Configure Buffers

Buffers determine visualization and must be properly set up:

// Declare as class-level field
public mainBuffer!: TIndexBuffer;

public Init(): void {
    // 1. Register total number of buffers (MUST be called first)
    this.api.IndicatorBuffers(1);

    // 2. Create the buffer
    this.mainBuffer = this.api.CreateIndexBuffer();

    // 3. Bind buffer to index
    this.api.SetIndexBuffer(0, this.mainBuffer);

    // 4. Configure buffer appearance
    this.api.SetIndexLabel(0, "Main Line");
    this.api.SetIndexStyle(0, TDrawStyle.LINE, TPenStyle.SOLID, 1, '#FF0000');

    // 5. Optional: Set drawing start point
    this.api.SetIndexDrawBegin(0, 10);
}

3. Set Indicator Properties

  • Name: this.api.IndicatorShortName("Your Indicator Name")

  • Output Window: this.api.SetOutputWindow(TOutputWindow.CHART_WINDOW) or TOutputWindow.SEPARATE_WINDOW


What CAN Be Done in Init

Core Setup Methods

  • this.api.IndicatorShortName(name) - Set indicator display name

  • this.api.IndicatorBuffers(count) - Register number of buffers

  • this.api.CreateIndexBuffer() - Create buffer instances

  • this.api.SetIndexBuffer(index, buffer) - Bind buffers to indexes

  • this.api.RegOption(name, type, parameter) - Register parameters

Buffer Configuration Methods

  • this.api.SetIndexLabel(index, label) - Set buffer legend label

  • this.api.SetIndexStyle(index, drawStyle, penStyle, width, color) - Set visual style

  • this.api.SetIndexDrawBegin(index, startBar) - Set drawing start point

  • this.api.SetIndexVisibility(index, visible) - Control buffer visibility

Parameter Configuration Methods

  • this.api.SetOptionRange(name, min, max) - Set parameter limits

  • this.api.SetOptionDigits(name, digits) - Set decimal places

  • this.api.AddOptionValue(name, value) - Add dropdown options

  • this.api.RecalculateMeAlways() - Improves calculation accuracy but could slow down the performance of the indicator

  • this.api.SetOutputWindow(window) - Configure chart vs oscillator window

Advanced Configuration Methods

  • this.api.AddLevel(value) - Add horizontal reference lines

  • this.api.SetLevelValue(index, value) - Set level values

  • this.api.SetFixedMinMaxValues(min, max) - Set fixed scale range


What CANNOT Be Done in Init

❌ Forbidden Operations

  • Heavy calculations or complex mathematical operations

  • Per-bar data processing (use Calculate() instead)

  • Accessing bar data like this.api.Close(index), this.api.High(index), etc.

  • Setting buffer values using buffer.setValue(index, value)

  • Time-based calculations or market data analysis

  • Loops through historical data

❌ Wrong Approach

public Init(): void {
    // DON'T DO THIS - heavy calculations
    for (let i = 0; i < 1000; i++) {
        let value = this.api.Close(i) * 2; // ❌ Wrong!
        this.mainBuffer.setValue(i, value); // ❌ Wrong!
    }
}

✅ Correct Approach

public Init(): void {
    // ✅ Correct - only setup and configuration
    this.api.IndicatorShortName("My Indicator");
    this.api.IndicatorBuffers(1);
    this.mainBuffer = this.api.CreateIndexBuffer();
    // ... other setup code
}

public Calculate(index: number): void {
    // ✅ Correct - calculations go here
    let value = this.api.Close(index) * 2;
    this.mainBuffer.setValue(index, value);
}

Complete Example

export default class MovingAverage extends IndicatorImplementation {
  // Parameters - declared as class-level fields
  public Period!: TOptValue_number;
  public ShowLine!: TOptValue_bool;

  // Buffers - declared as class-level fields
  public MA!: TIndexBuffer;

  public Init(): void {
    // 1. Create and register parameters
    this.Period = this.api.createTOptValue_number(14);
    this.ShowLine = this.api.createTOptValue_bool(true);

    this.api.RegOption("Period", TOptionType.INTEGER, this.Period);
    this.api.RegOption("Show Line", TOptionType.BOOLEAN, this.ShowLine);
    this.api.SetOptionRange("Period", 1, 9999);

    // 2. Set indicator properties
    this.api.IndicatorShortName("Moving Average");
    this.api.SetOutputWindow(TOutputWindow.CHART_WINDOW);
    this.api.RecalculateMeAlways(); // Recommended

    // 3. Create and configure buffers
    this.api.IndicatorBuffers(1);
    this.MA = this.api.CreateIndexBuffer();
    this.api.SetIndexBuffer(0, this.MA);
    this.api.SetIndexLabel(0, "Moving Average");
    this.api.SetIndexStyle(0, TDrawStyle.LINE, TPenStyle.SOLID, 1, "#FF0000");
  }

  public Calculate(index: number): void {
    // Actual calculations happen here, not in Init()
    const periodValue = this.Period.value; // Access parameter value
    // ... calculation logic
  }
}

Key Rules Summary

  1. Init() is for setup only - no calculations or data processing

  2. All parameters must be created AND registered in Init()

  3. All buffers must be declared, created, and configured in Init()

  4. Use factory methods for parameter creation (createTOptValue_number, etc.)

  5. Register buffer count first with IndicatorBuffers() before configuring buffers

  6. Try including RecalculateMeAlways() for better accuracy

  7. Use Calculate() for all data processing and calculations


Pro Tip

Remember: Init() runs once when the indicator loads. It defines the structure, settings, and appearance. All dynamic calculations and data processing must happen in Calculate() which runs once per bar.

Last updated