Lean icon indicating copy to clipboard operation
Lean copied to clipboard

PythonIndicator Updated is not Called on Manual Updates

Open AlexCatarino opened this issue 2 months ago • 0 comments

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

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

AlexCatarino avatar Nov 13 '25 21:11 AlexCatarino