Skip to content

PythonIndicator Updated is not Called on Manual Updates #9085

@AlexCatarino

Description

@AlexCatarino

Expected Behavior

When we set updated to a callback method, and update the indicator with update, the callback method is called as it happens to LEAN/C# indicators.

Actual Behavior

When we set updated to a callback method, and update the indicator with update, the callback method is not called. If we use self.register_indicator, it is.

Potential Solution

PythonIndicator should require implementing compute_next_value, and when update is called, it will call compute_next_value as in C#, and triggering the updated event.

Reproducing the Problem

_on_update method isn't called:

from collections import deque 

class CustomIndicatorsAlgorithm(QCAlgorithm):
    def initialize(self) -> None:
        self.set_start_date(2024, 9, 1)
        self.set_end_date(2024, 12, 31)
        self.spy = self.add_equity("SPY").symbol
        self.custom_mfi = CustomMoneyFlowIndex(20)
        self.custom_mfi.updated += self._on_update

    def _on_update(self, sender, consolidated):
        self.log(str(consolidated))

    def on_data(self, slice: Slice) -> None:
        bar = slice.bars.get(self.spy)
        if bar:
            self.custom_mfi.update(bar)

class CustomMoneyFlowIndex(PythonIndicator):
    def __init__(self, period: int) -> None:
        super().__init__()
        self.value = 0
        self.previous_typical_price = 0
        self.negative_money_flow = deque(maxlen=period)
        self.positive_money_flow = deque(maxlen=period)
    
    def update(self, input: BaseData) -> bool:
        typical_price = (input.high + input.low + input.close) / 3
        money_flow = typical_price * input.volume
            
        if abs(self.previous_typical_price / typical_price - 1) < 1e-10:
            self.previous_typical_price = typical_price
        
        self.negative_money_flow.appendleft(money_flow if typical_price < self.previous_typical_price else 0)
        self.positive_money_flow.appendleft(money_flow if typical_price > self.previous_typical_price else 0)
        self.previous_typical_price = typical_price
    
        positive_money_flow_sum = sum(self.positive_money_flow)        
        total_money_flow = positive_money_flow_sum + sum(self.negative_money_flow)

        self.value = 100
        if total_money_flow != 0:
            self.value *= positive_money_flow_sum / total_money_flow    
        return len(self.positive_money_flow) == self.positive_money_flow.maxlen

Checklist

  • I have completely filled out this template
  • I have confirmed that this issue exists on the current master branch
  • I have confirmed that this is not a duplicate issue by searching issues
  • I have provided detailed steps to reproduce the issue

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions