Skip to content

State Management

levi edited this page Nov 6, 2025 · 2 revisions

State Management

Table of Contents

  1. FalseBreakoutState Dataclass
  2. State Attribute Details
  3. State Transition Logic
  4. Aggressive Mode Impact
  5. State Reset Mechanism
  6. Sequence Diagrams
  7. Debugging Guidance
  8. Thread Safety and Isolation
  9. Memory Usage and Optimization

FalseBreakoutState Dataclass

The FalseBreakoutState dataclass serves as the core state management component for the False Breakout Indicator. It encapsulates all necessary tracking information required to detect false breakout patterns in financial market data. This state object is instantiated within the calculate method of the FalseBreakoutIndicator class and persists throughout the processing of each data point in the time series. The state is designed to maintain continuity between consecutive bars, enabling the detection of multi-bar patterns that characterize false breakouts. The dataclass structure provides a clean, type-safe interface for state manipulation while ensuring all state variables are properly initialized through the __post_init__ method.

State Attribute Details

Count Attribute

The count attribute functions as a dual-purpose directional counter that tracks the sequence of new highs and lows. Positive values indicate an upward breakout sequence, while negative values represent a downward breakout sequence. This counter increments when a new low is detected and decrements when a new high is detected, effectively serving as the primary state tracker for breakout direction and momentum. The magnitude of the count value indicates the strength of the breakout sequence, with values of 2 or greater (in either direction) typically required to generate a valid signal.

Val Attribute

The val attribute stores the current trigger price, which is set to the low price when a new high is detected (for potential downward false breakouts) and to the high price when a new low is detected (for potential upward false breakouts). This trigger price serves as the reference point for subsequent price action, and a reversal beyond this price level constitutes the confirmation of a false breakout. The trigger price is updated with each new extreme price detection, ensuring the state remains current with market conditions.

Index Attribute

The index attribute maintains an array of the two most recent breakout indices, storing the bar positions where the last two significant highs or lows occurred. This array enables validity checks by allowing the system to verify the temporal relationship between consecutive breakouts. The most recent index is stored at position 0, while the previous index is stored at position 1, facilitating calculations related to the minimum period between breakouts and the maximum validity period of signals.

State Transition Logic

The state transitions occur through a systematic process during each iteration of the calculation loop. When a new high is detected, the system first checks if the current count is positive (indicating a potential conflicting downward sequence) and resets it to zero if necessary. It then decrements the count (making it negative to indicate upward breakout sequence), updates the trigger price to the current low, and records the current bar index in the index array. Conversely, when a new low is detected, the system checks for a negative count (conflicting upward sequence), resets it if needed, increments the count (making it positive), updates the trigger price to the current high, and updates the index array. These transitions ensure that only coherent breakout sequences are tracked and that conflicting signals do not interfere with each other.

flowchart TD
Start([Start]) --> CheckHighLow["Check for New High/Low"]
CheckHighLow --> |New High Detected| HandleHigh["Handle High Detection"]
CheckHighLow --> |New Low Detected| HandleLow["Handle Low Detection"]
CheckHighLow --> |No New Extremes| Continue["Continue to Next Bar"]
HandleHigh --> CheckCountPos{"Count > 0?"}
CheckCountPos --> |Yes| ResetCountPos["Set count = 0"]
CheckCountPos --> |No| SkipResetPos
ResetCountPos --> SkipResetPos
SkipResetPos --> DecrementCount["count -= 1"]
DecrementCount --> UpdateValHigh["val = current low price"]
UpdateValHigh --> UpdateIndexHigh["index = [current_bar, index[0]]"]
HandleLow --> CheckCountNeg{"Count < 0?"}
CheckCountNeg --> |Yes| ResetCountNeg["Set count = 0"]
CheckCountNeg --> |No| SkipResetNeg
ResetCountNeg --> SkipResetNeg
SkipResetNeg --> IncrementCount["count += 1"]
IncrementCount --> UpdateValLow["val = current high price"]
UpdateValLow --> UpdateIndexLow["index = [current_bar, index[0]]"]
UpdateIndexHigh --> SignalCheck["Check for Signal Generation"]
UpdateIndexLow --> SignalCheck
Continue --> SignalCheck
SignalCheck --> End([End])
Loading

Aggressive Mode Impact

The aggressive mode significantly alters the state initialization logic by inverting the high/low detection mechanism. When the aggressive parameter is enabled, the system uses the opposite price series for breakout detection: the low prices are used to detect "highs" and the high prices are used to detect "lows". This inversion is implemented in the _calculate_highest and _calculate_lowest method calls within the calculate function, where the ternary operation high if not aggressive else low and low if not aggressive else high reverses the input data series. This mode effectively makes the indicator more sensitive to price movements, potentially generating more signals by treating price contractions as expansions and vice versa. The state variables (count, val, and index) are updated using the same logic, but with the inverted detection criteria, which can lead to earlier signal generation and different state transition patterns compared to the standard mode.

State Reset Mechanism

The state reset mechanism is triggered immediately upon signal generation, ensuring that each false breakout signal is independent and preventing signal chaining. When a valid false breakout condition is detected (either upward or downward), the count variable is explicitly set to zero, effectively resetting the entire state tracking system. This reset occurs after the signal and associated graphical elements have been created but before processing the next bar. The reset prevents the current breakout sequence from influencing subsequent signal detection, ensuring that each signal represents a distinct market event. This mechanism is critical for maintaining signal integrity and preventing multiple signals from being generated from a single breakout event. The trigger price (val) and index array are not explicitly reset during this process, as they will be naturally updated by subsequent price action when new extremes are detected.

sequenceDiagram
participant Data as Data Stream
participant State as FalseBreakoutState
participant Detector as Breakout Detector
participant Signal as Signal Generator
Data->>Detector : New price data
Detector->>State : Update count, val, index
State->>Detector : Current state
Detector->>Detector : Check breakout conditions
alt Valid Breakout Detected
Detector->>Signal : Generate signal
Signal->>Detector : Signal created
Detector->>State : Set count = 0
else No Valid Breakout
Detector->>State : Continue tracking
end
Detector->>Data : Ready for next data point
Loading

Sequence Diagrams

Multi-Bar Upward Breakout Sequence

The following sequence diagram illustrates the state transitions during a multi-bar upward breakout scenario, where the price creates consecutive new highs before reversing below the trigger price:

sequenceDiagram
participant Bar1 as Bar 1
participant Bar2 as Bar 2
participant Bar3 as Bar 3
participant State as FalseBreakoutState
Bar1->>State : New high detected
State->>State : count = -1, val = low1, index = [1, 0]
Bar2->>State : New high detected
State->>State : count = -2, val = low2, index = [2, 1]
Bar3->>State : Price < val and Price[2] >= val
State->>State : Generate "False Breakout Down" signal
State->>State : count = 0
Loading

Multi-Bar Downward Breakout Sequence

The following sequence diagram illustrates the state transitions during a multi-bar downward breakout scenario, where the price creates consecutive new lows before reversing above the trigger price:

sequenceDiagram
participant Bar1 as Bar 1
participant Bar2 as Bar 2
participant Bar3 as Bar 3
participant State as FalseBreakoutState
Bar1->>State : New low detected
State->>State : count = 1, val = high1, index = [1, 0]
Bar2->>State : New low detected
State->>State : count = 2, val = high2, index = [2, 1]
Bar3->>State : Price > val and Price[2] <= val
State->>State : Generate "False Breakout Up" signal
State->>State : count = 0
Loading

Debugging Guidance

Persistent Count Issues

When encountering persistent count values that fail to reset properly, verify that the signal generation conditions are being met correctly. Check that the breakdown and breakup conditions are properly evaluating the price relative to the trigger price (val). Ensure that the maxvalid and minbars conditions are not preventing signal generation due to period constraints. If the count remains stuck at a non-zero value, confirm that the state reset line (state.count = 0) is being executed after signal creation.

Incorrect Trigger Prices

For issues with incorrect trigger prices, verify that the val attribute is being updated with the appropriate price (low for new highs, high for new lows). Check that the aggressive mode setting is not inadvertently inverting the price detection logic when not desired. Ensure that the rolling highest and lowest calculations are using the correct input data series based on the aggressive mode setting.

Missing Signals

When signals are not being generated as expected, validate that the state transitions are occurring correctly by checking the count values during consecutive new high/low detections. Verify that the index array is being updated properly to enable valid period calculations. Confirm that the minimum and maximum period constraints are not too restrictive for the current market conditions.

Thread Safety and Isolation

The state management system ensures thread safety and proper isolation in multi-chart environments through several design principles. Each instance of the FalseBreakoutIndicator maintains its own state object, preventing cross-contamination between different chart instances. The state is created anew within the calculate method for each invocation, ensuring that concurrent calculations on different data sets do not interfere with each other. The indicator base class supports chart isolation through the optional chart_id parameter in its constructor, allowing each chart to maintain independent state tracking. This design enables safe concurrent execution across multiple charts or timeframes without requiring external synchronization mechanisms, as each indicator instance operates on its own isolated state.

Memory Usage and Optimization

The state management system exhibits efficient memory usage characteristics, with a constant memory footprint regardless of data length. The FalseBreakoutState object requires only three variables (count, val, and index) plus a small fixed overhead for the dataclass structure. The index array maintains a fixed size of two elements, preventing unbounded memory growth even during extended calculations. For long-running instances, no specific optimizations are required as the state does not accumulate historical data beyond the two most recent breakout indices. The use of primitive data types (int and float) for state variables ensures minimal memory overhead, while the fixed-size list for indices prevents memory leaks. This design is inherently optimized for long-term operation, as the memory consumption remains constant regardless of the number of bars processed.

Clone this wiki locally