Skip to content

Fix (InitialBalance): lifecycle, validation and code-health cleanups#167

Open
AlbertoAmadorBelchistim wants to merge 7 commits into
AtasPlatform:Developfrom
AlbertoAmadorBelchistim:fix/InitialBalance-defaults-and-lifecycle
Open

Fix (InitialBalance): lifecycle, validation and code-health cleanups#167
AlbertoAmadorBelchistim wants to merge 7 commits into
AtasPlatform:Developfrom
AlbertoAmadorBelchistim:fix/InitialBalance-defaults-and-lifecycle

Conversation

@AlbertoAmadorBelchistim
Copy link
Copy Markdown
Contributor

InitialBalance: lifecycle, validation and code-health cleanups

This PR bundles a set of small, self-contained fixes and clean-ups for InitialBalance.cs. Each commit is independent and easy to cherry-pick or revert; happy to split into separate PRs if preferred.

Changes

  1. Release PropertyChanged subscriptions in OnDispose — the constructor wires nine ValueDataSeries.PropertyChanged handlers and never detaches them, so they accumulate as zombie subscriptions across reloads. Adds the missing OnDispose that mirrors every += with a matching -=.

  2. Subscribe _mid to PropertyChanged so its labels react to color changes_mid is the only series with a dedicated branch in GetLabelTagSuffixes that was not subscribed in the constructor. As a result, changing the Mid color in the property grid did not refresh the "Mid" AddText labels. Adds the missing subscription for parity with the other nine series.

  3. Disambiguate StartTime / EndTime display order — both properties were declared with Order = 20 inside the SessionTime group, leaving their relative order in the property grid undefined. Bumps EndTime to Order = 25.

  4. Constrain X1 / X2 / X3 multipliers to a positive range — adds [Range(0.1, 100)] to the three multipliers. Negative values used to invert the extension levels (IBHX* below the IB high, IBLX* above the IB low).

  5. Remove the unused using Pen = CrossPen; alias — the alias is never referenced; every site uses CrossPen directly.

  6. Mark RangeDataSeries fields as readonly — the eight fields are initialized at declaration and never reassigned. Matches the convention already used by the ten ValueDataSeries in the same file.

  7. Skip the _endTime assignment when PeriodMode is Bars — in Bars mode the session-end check is bar - _lastStartBar >= Period and _endTime is never read. Wraps the assignment in if (PeriodMode is PeriodType.Minutes) so the dependency between _endTime and PeriodMode is explicit.

End-user impact

  • Memory: lower across reloads (fix 1).
  • UI correctness: Mid label color now updates with its series (fix 2); SessionTime properties have a deterministic order (fix 3); multipliers cannot produce crossed bands (fix 4).
  • Visual output: unchanged on existing charts.

Open questions for the maintainers

A few decisions I would rather defer to you than take unilaterally:

1. What is the intended state of the _mid series?

_mid is initialized with CrossColor.FromArgb(0, 0, 255, 0)A = 0, fully transparent — so the line and its "Mid" AddText labels are invisible by default. At the same time, the series is still calculated every bar, exposed in the property grid (color editable), described via SessionAveragePriceDescription and labelled in the OnCalculate text block. Two equally plausible interpretations:

  • Bug. The intended default was visible (e.g. FromArgb(255, 0, 255, 0)). Follow-up: pick a sensible default such as DefaultColors.Green.Convert().
  • Soft-deprecation. The series is being phased out but kept around so chart templates that reference "MidId" still load. Follow-up: replace the alpha=0 trick with the canonical hidden-series pattern (VisualType = VisualMode.Hide, IsHidden = true) and drop the now-dead "Mid" AddText call together with the _mid branch in GetLabelTagSuffixes.

Could you confirm which one is intended? I held this fix out of the present PR on purpose and am happy to send the matching patch as a small follow-up.

2. Renaming the unprefixed value fields

The internal value variables ibhx1..3, iblx1..3, mid (lines 199–206) are the only fields in the file without the _ prefix that the rest of the private state uses. Renaming them to e.g. _ibhx1Value..3, _iblx1Value..3, _midValue would make the distinction between the value (ibhx1) and the corresponding ValueDataSeries (_ibhx1) explicit and remove an easy-to-confuse shadow.

The change would touch every call site inside OnCalculate and the labels block — a noisy diff for a cosmetic gain — so I left it out of this PR. Would you take it as a separate chore: rename internal value fields in InitialBalance PR, or would you rather leave the current naming?

3. Splitting drawing concerns out of OnCalculate in a follow-up PR

Today OnCalculate mixes pure calculation (DataSeries writes) with drawing-side state management (ten AddText calls per bar, DrawingRectangle creation and per-bar mutation in Rectangles). The usual SDK pattern keeps OnCalculate for state writes and OnRender for read-only drawing.

Would you be open, in a future PR, to exploring whether the label management and the IB rectangle update could move to OnRender? I would rather check the direction is acceptable before investing in the refactor.


Thanks for reviewing.

The constructor wires 9 ValueDataSeries.PropertyChanged handlers to
DataSeriesPropertyChanged but never detaches them. Each time the
indicator is removed and re-added on the same chart, the previous
handlers stay alive on the orphan instances and accumulate across
reloads.

Add OnDispose that mirrors every += with a matching -= (including
_mid, see follow-up commit) so the subscriptions are released when
the indicator is disposed.
GetLabelTagSuffixes already returns "Mid" as the tag suffix for the
Mid series, and UpdateLabelColors knows how to repaint the matching
labels. But _mid was the only ValueDataSeries not subscribed to
DataSeriesPropertyChanged in the constructor, so changing its color
in the property grid did not refresh the "Mid" AddText labels until
an unrelated repaint happened.

Add the missing subscription so the Mid color now propagates to its
labels consistently with the other 9 series.
Both StartDate and EndDate were declared with Order = 20 inside the
SessionTime property group, which leaves their relative position in
the property grid undefined.

Bump EndDate to Order = 25 so StartTime is rendered first and
EndTime second, matching the natural reading order.
The X1, X2 and X3 multiplier properties accepted any decimal value.
Negative values invert the extension levels (IBHX* fall below the
Initial Balance high and IBLX* rise above the Initial Balance low),
producing crossed and visually nonsensical bands. Very large values
push levels off the chart with no warning.

Add [Range(0.1, 100)] to all three multipliers to keep the resulting
extension levels above the Initial Balance high (for IBHX*) and
below the Initial Balance low (for IBLX*).
The Pen alias declared at the top of the file is never referenced —
every call site uses CrossPen directly. Drop the dead using directive.
The eight RangeDataSeries fields (_ibhx32, _ibhx21, _ibhx1h, _ibHm,
_ibMl, _ibl1, _iblx12, _iblx23) are initialized at declaration and
never reassigned. Marking them readonly matches the convention
already used for the ten ValueDataSeries in the same file.
In Bars mode the session-end check is `bar - _lastStartBar >= Period`
and _endTime is never read. The assignment
`_endTime = candleFullDateTime.AddMinutes(_period)` runs anyway on
every session start, with no observable effect.

Wrap the assignment in `if (PeriodMode == PeriodType.Minutes)` to
make the dependency between _endTime and PeriodMode explicit.
@AlbertoAmadorBelchistim AlbertoAmadorBelchistim changed the title Fix (InitialBlance): lifecycle, validation and code-health cleanups Fix (InitialBalance): lifecycle, validation and code-health cleanups May 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant