OnParamsChange

What is it?

The OnParamsChange method is called automatically when the user changes any parameter of your indicator — for example, the period, color, MA type, etc.

It allows you to respond to these changes and implement custom logic that should happen when parameters are modified.

Important: This method is NOT used for the actual parameter values to change — that happens internally. This method is only for custom logic that needs to be executed when parameters are changed.


Syntax

public OnParamsChange(): void {
    // custom logic after parameter change
}

When and Why to Use It

This method is called after the user updates the settings in the indicator panel, but before the indicator is recalculated.

Use OnParamsChange() When You Need To:

  • Recalculate internal values based on new parameter values

  • Adjust or re-create custom chart objects (lines, labels, etc.)

  • Update dependencies between parameters

  • Perform validation or parameter-based setup

  • Reset internal state that depends on parameters

  • Apply dynamic styling or configuration changes

Don't Use OnParamsChange() If:

  • You only need basic parameter changes (values update automatically)

  • You don't have any custom logic dependent on parameter changes

  • Your indicator works fine with just Init() and Calculate()


What CAN Be Done in OnParamsChange

Buffer and Display Updates

  • Modify buffer properties (styles, labels, visibility)

  • Update buffer configuration based on parameter changes

  • Reconfigure drawing styles and colors

  • Adjust buffer drawing ranges with SetIndexDrawBegin()

Chart Object Management

  • Create, modify, or remove custom chart objects

  • Update object positions based on parameter changes

  • Reconfigure object properties (colors, styles, positions)

  • Manage dynamic visual elements

Internal State Management

  • Reset calculation counters or accumulators

  • Update lookup tables or cached calculations

  • Reconfigure internal algorithms based on parameters

  • Initialize parameter-dependent variables


What CANNOT Be Done in OnParamsChange

❌ Forbidden Operations

  • Heavy calculations or complex mathematical operations

  • Per-bar data processing (this should be in Calculate())

  • Modifying the actual parameter values (handled internally)

  • Creating new parameters (must be done in Init())

  • Changing buffer count with IndicatorBuffers() (must be in Init())

  • Loops through large datasets or historical data processing

❌ Wrong Approach

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

    // DON'T DO THIS - creating new parameters
    this.newParam = this.api.createTOptValue_number(10); // ❌ Wrong!
    this.api.RegOption("New Param", TOptionType.INTEGER, this.newParam); // ❌ Wrong!
}

✅ Correct Approach

public OnParamsChange(): void {
    // ✅ Correct - lightweight parameter-dependent logic
    this.internalMultiplier = this.period.value * 2;

    // ✅ Correct - update buffer styling based on parameters
    if (this.showLine.value) {
        this.api.SetIndexStyle(0, TDrawStyle.LINE, TPenStyle.SOLID, 1, this.lineColor.value);
    } else {
        this.api.SetIndexVisibility(0, false);
    }

    // ✅ Correct - reset internal state
    this.calculationCounter = 0;
}

Practical Examples

Example 1: Dynamic Buffer Styling

export default class CustomIndicator extends IndicatorImplementation {
  public period!: TOptValue_number;
  public lineColor!: TOptValue_str;
  public showLine!: TOptValue_bool;
  public mainBuffer!: TIndexBuffer;

  public OnParamsChange(): void {
    // Update line color when user changes it
    this.api.SetIndexStyle(
      0,
      TDrawStyle.LINE,
      TPenStyle.SOLID,
      1,
      this.lineColor.value
    );

    // Show/hide line based on boolean parameter
    this.api.SetIndexVisibility(0, this.showLine.value);

    // Adjust drawing start based on period
    this.api.SetIndexDrawBegin(0, this.period.value);
  }
}

Example 2: Parameter Validation and Dependencies

export default class AdvancedIndicator extends IndicatorImplementation {
  public fastPeriod!: TOptValue_number;
  public slowPeriod!: TOptValue_number;
  public validConfiguration: boolean = true;

  public OnParamsChange(): void {
    // Validate parameter relationship
    if (this.fastPeriod.value >= this.slowPeriod.value) {
      this.validConfiguration = false;
      // Could log warning or set visual indicator
    } else {
      this.validConfiguration = true;
    }

    // Update internal calculation variables
    this.periodDifference = this.slowPeriod.value - this.fastPeriod.value;
  }

  private periodDifference: number = 0;
}

Example 3: Chart Object Management

export default class LevelIndicator extends IndicatorImplementation {
  public levelValue!: TOptValue_number;
  public showLevel!: TOptValue_bool;

  public OnParamsChange(): void {
    // Remove existing level line
    this.api.RemoveAllObjects();

    // Create new level line if enabled
    if (this.showLevel.value) {
      // Create horizontal line at new level value
      this.CreateLevelLine(this.levelValue.value);
    }
  }

  private CreateLevelLine(value: number): void {
    // Custom method to create chart objects
    // Implementation depends on your specific needs
  }
}

Best Practices

✅ Do This

  • Keep it lightweight - only essential parameter-dependent logic

  • Use it for setup/configuration that depends on parameters

  • Reset internal state when parameters change

  • Update visual properties based on parameter values

  • Validate parameter combinations if needed

❌ Avoid This

  • Heavy computational work (belongs in Calculate())

  • Complex loops or data processing

  • Modifying parameter values

  • Creating new parameters or buffers (belongs in Init())


When NOT to Implement OnParamsChange()

You can skip implementing this method if:

  • Your indicator only uses basic parameters for calculations

  • No custom logic is needed when parameters change

  • All parameter-dependent behavior happens in Calculate()

  • You don't have dynamic visual elements or chart objects


Key Rules Summary

  1. OnParamsChange() is optional - only implement if you need custom logic

  2. Keep it lightweight - no heavy calculations or data processing

  3. Parameter values update automatically - this method is for additional logic only

  4. Use it for configuration and setup that depends on parameter values

  5. Cannot create new parameters or buffers - only modify existing ones

  6. Runs before recalculation - perfect for resetting internal state

  7. Great for dynamic visuals - updating styles, objects, and display properties


Pro Tip

Think of OnParamsChange() as your "parameter change reaction" method. It's the perfect place to update anything that depends on parameter values but doesn't belong in the per-bar Calculate() method. Keep it fast and focused on configuration rather than calculation.

Last updated