mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-11-02 07:26:12 +00:00
Series arithmetic (lib/numerics): - Add, Sub, Mul, Div, Lag, reusing BiInputIndicatorBase at period=1 - Div publishes 0.0 (not NaN) on a zero denominator, since a non-finite ComputeError result permanently poisons the base's running sum - BiInputIndicatorBase gains Subscribe(a, b) implementing the strategy-primitives spec's time-join rule for event-chained two-input nodes Phase 0 contracts (lib/core): - TTradeContext, BracketFlags, ExitReason, TrendState, VolState - SignalConstants (DefaultEpsilon, TruthThreshold), OutOfRangePolicy - ConfirmOnClose: bar-confirmation wrapper (Section 8.6) Signal predicates (lib/signals/predicates), Phase 1: - Above, Below, Equal (ComparePredicateBase<TOp> generic comparison core) - InsideChannel, OutsideChannel, ChannelPosition (new MultiInputBase, 3-input time-join) - IsRising, IsFalling (exclude current bar, confirm-then-push window) - AtHighest, AtLowest (include current bar, rebuild-on-correction, mirrors channels/Dc) - Hysteresis, PercentDistance All new nodes ship with .cs, tests, and .md docs; indices and the StrategyPrimitives.Spec.md are updated with placement decisions and design notes. Full suite: 16730 tests, 0 failures, 0 warnings.
55 lines
2.2 KiB
C#
55 lines
2.2 KiB
C#
// EQUAL: Approximate Equality Predicate
|
|
// Crisp predicate: publishes 1.0 when |a - b| <= epsilon, 0.0 otherwise, NaN while cold.
|
|
|
|
using System.Runtime.CompilerServices;
|
|
|
|
namespace QuanTAlib;
|
|
|
|
/// <summary>
|
|
/// EQUAL: Approximate Equality Predicate
|
|
/// Tests whether two values (or a value and a fixed scalar) are equal within an epsilon.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Key properties:
|
|
/// - Crisp output: exactly 1.0 (true) or 0.0 (false) while hot, NaN while cold
|
|
/// - Epsilon defaults to <see cref="SignalConstants.DefaultEpsilon"/> (1e-10), never
|
|
/// <see cref="double.Epsilon"/>, which is a machine-level spacing value unsuitable as a
|
|
/// financial comparison tolerance
|
|
/// - Built on <see cref="ComparePredicateBase{TOp}"/> (a thin sealed class over
|
|
/// <see cref="BiInputIndicatorBase"/> at period = 1): rollback and NaN-substitution for the
|
|
/// two inputs come from the shared base with no extra state
|
|
/// - This is a value predicate, not C# object identity or structural equality
|
|
/// </remarks>
|
|
/// <seealso href="Equal.md">Detailed documentation</seealso>
|
|
[SkipLocalsInit]
|
|
public sealed class Equal : ComparePredicateBase<EqualOp>
|
|
{
|
|
/// <summary>
|
|
/// Creates an Equal predicate for direct pull-style updates.
|
|
/// </summary>
|
|
/// <param name="epsilon">Comparison tolerance; defaults to the library-wide default</param>
|
|
public Equal(double epsilon = SignalConstants.DefaultEpsilon) : base("Equal", epsilon)
|
|
{
|
|
if (epsilon < 0.0 || !double.IsFinite(epsilon))
|
|
{
|
|
throw new ArgumentException("Epsilon must be a finite, non-negative number", nameof(epsilon));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates an Equal predicate chained to two upstream publishers using the time-join rule.
|
|
/// </summary>
|
|
public Equal(ITValuePublisher a, ITValuePublisher b, double epsilon = SignalConstants.DefaultEpsilon) : this(epsilon)
|
|
{
|
|
SubscribeTwo(a, b);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates an Equal predicate testing a stream against a fixed scalar.
|
|
/// </summary>
|
|
public Equal(ITValuePublisher a, double scalar, double epsilon = SignalConstants.DefaultEpsilon) : this(epsilon)
|
|
{
|
|
SubscribeScalar(a, scalar);
|
|
}
|
|
}
|