Skip to content

Conversation

@nemcek
Copy link

@nemcek nemcek commented Dec 4, 2025

Description

Implemented the base NHNL indicator as well as Difference, Ratio & Volume Ration NHNL indicators.
The architecture closely follows architecture of ADR indicators.

Related Issue

This PR implements new indicators as in #8356

Motivation and Context

This change adds new indicators.

Requires Documentation Change

Probably adding the new indicators into the list of available indicators.

How Has This Been Tested?

Added unit tests for each new indicator.
Tests closely resemble the tests of ADR indicators.
Also created a test dava (.csv) based on the test data of ADR indicators.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • Refactor (non-breaking change which improves implementation)
  • Performance (non-breaking change which improves performance. Please add associated performance test and results)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Non-functional change (xml comments/documentation/etc)

Checklist:

  • My code follows the code style of this project.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • My branch follows the naming convention bug-<issue#>-<description> or feature-<issue#>-<description>

Copy link
Member

@Martin-Molinero Martin-Molinero left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @nemcek! Thank you for the PR 💪, leaving some concerns and requests

Comment on lines +30 to +32
private readonly IDictionary<SecurityIdentifier, TradeBar> _currentPeriod = new Dictionary<SecurityIdentifier, TradeBar>();
private readonly IDictionary<SecurityIdentifier, Maximum> _rollingPreviousHighs = new Dictionary<SecurityIdentifier, Maximum>();
private readonly IDictionary<SecurityIdentifier, Minimum> _rollingPreviousLows = new Dictionary<SecurityIdentifier, Minimum>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think instead of having 3 collections per SID, could just have 1 collection with a small private class holdings these 3 attributes, will make the implementation cleaner I think and runtime performance much better

/// the number of stocks reaching new highs and the number of stocks reaching new lows
/// in defined time period.
/// </summary>
public abstract class NewHighsNewLowsIndicator : TradeBarIndicator, IIndicatorWarmUpPeriodProvider
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally I think 'Difference' and 'Ratio' indicators should not really exist but just be a property of this base indicator, see other indicators like BollingerBands/AverageDirectionalIndex/etc exposing some state through indicatorbase.
Another thought is that ideally this base indicator does not require a TradeBar (which has volume) but requires a Bar, so it would work with QuoteBars, see examples IBaseDataBar/BarIndicator/etc. I would keep a second indicator inheriting from this one which adds volume ratio and enforces tradebar, might need to use some T type handling I think

Minor should remove Indicator from names like NewHighsNewLowsIndicator

Comment on lines +129 to +130
List<TradeBar> newHighStocks = new List<TradeBar>();
List<TradeBar> newLowStocks = new List<TradeBar>();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally shouldn't create collections unless required, same comment in the foreach above, there's not need to ToList, thinking of performance should be as lazy as possible

{
Enqueue(input);

if (HasMissingCurrentPeriodValue() || !HasSufficientPreviousDataForComputation())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another thought I think ideally even if not all symbols are ready we could calculate the indicator values with those that are? might even simplify the logic, the indicator state wouldn't be ready yet but have valid value at least

return new IndicatorResult(vNext);
}

private void Enqueue(TradeBar input)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see the indicator is very similar to AdvanceDeclineIndicator generally, seems there is some room to inherit and merge maybe?

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.

2 participants