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
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
!
syntaxCreated in
Init()
using appropriate factory methodsRegistered 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)
orTOutputWindow.SEPARATE_WINDOW
What CAN Be Done in Init
Init
Core Setup Methods
this.api.IndicatorShortName(name)
- Set indicator display namethis.api.IndicatorBuffers(count)
- Register number of buffersthis.api.CreateIndexBuffer()
- Create buffer instancesthis.api.SetIndexBuffer(index, buffer)
- Bind buffers to indexesthis.api.RegOption(name, type, parameter)
- Register parameters
Buffer Configuration Methods
this.api.SetIndexLabel(index, label)
- Set buffer legend labelthis.api.SetIndexStyle(index, drawStyle, penStyle, width, color)
- Set visual stylethis.api.SetIndexDrawBegin(index, startBar)
- Set drawing start pointthis.api.SetIndexVisibility(index, visible)
- Control buffer visibility
Parameter Configuration Methods
this.api.SetOptionRange(name, min, max)
- Set parameter limitsthis.api.SetOptionDigits(name, digits)
- Set decimal placesthis.api.AddOptionValue(name, value)
- Add dropdown options
Recommended Methods
this.api.RecalculateMeAlways()
- Improves calculation accuracy but could slow down the performance of the indicatorthis.api.SetOutputWindow(window)
- Configure chart vs oscillator window
Advanced Configuration Methods
this.api.AddLevel(value)
- Add horizontal reference linesthis.api.SetLevelValue(index, value)
- Set level valuesthis.api.SetFixedMinMaxValues(min, max)
- Set fixed scale range
What CANNOT Be Done in Init
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
Init() is for setup only - no calculations or data processing
All parameters must be created AND registered in Init()
All buffers must be declared, created, and configured in Init()
Use factory methods for parameter creation (
createTOptValue_number
, etc.)Register buffer count first with
IndicatorBuffers()
before configuring buffersTry including
RecalculateMeAlways()
for better accuracyUse
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