# 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

```ts
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()`](https://fto-2.gitbook.io/fto-indicators-docs/indicators/indicator-structure/init) and [`Calculate()`](https://fto-2.gitbook.io/fto-indicators-docs/indicators/indicator-structure/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()`](https://fto-2.gitbook.io/fto-indicators-docs/configure_indicator/set-index-draw-begin)

#### 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()`](https://fto-2.gitbook.io/fto-indicators-docs/indicators/indicator-structure/calculate))
* **Modifying the actual parameter values** (handled internally)
* **Creating new parameters** (must be done in [`Init()`](https://fto-2.gitbook.io/fto-indicators-docs/indicators/indicator-structure/init))
* **Changing buffer count** with [`IndicatorBuffers()`](https://fto-2.gitbook.io/fto-indicators-docs/configure_indicator/indicator-buffers) (must be in [`Init()`](https://fto-2.gitbook.io/fto-indicators-docs/indicators/indicator-structure/init))
* **Loops through large datasets** or historical data processing

#### ❌ Wrong Approach

```ts
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

```ts
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

```ts
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

```ts
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

```ts
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.
