using System.Runtime.CompilerServices; namespace QuanTAlib; /// /// PRS: Price Relative Strength /// A momentum indicator that compares the performance of a security against a benchmark, /// helping identify which is showing stronger relative momentum. /// /// /// The PRS calculation process: /// 1. Take the current price of the security /// 2. Take the current price of the benchmark /// 3. Calculate the ratio between them /// 4. Multiply by a scaling factor for better visualization /// /// Key characteristics: /// - Measures relative performance against a benchmark /// - Helps identify market leaders and laggards /// - Rising PRS indicates outperformance /// - Falling PRS indicates underperformance /// /// Formula: /// PRS = (Price / Benchmark) * 100 /// /// Sources: /// Technical Analysis of Financial Markets by John J. Murphy /// StockCharts.com Technical Indicators /// [SkipLocalsInit] public sealed class Prs : AbstractBase { private const double ScalingFactor = 100.0; private double _benchmark; private double _p_benchmark; /// /// Initializes a new instance of the PRS indicator /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public Prs() { WarmupPeriod = 1; Name = "PRS"; } /// The data source object that publishes updates. [MethodImpl(MethodImplOptions.AggressiveInlining)] public Prs(object source) : this() { var pubEvent = source.GetType().GetEvent("Pub"); pubEvent?.AddEventHandler(source, new ValueSignal(Sub)); } /// /// Sets the current benchmark value /// /// The benchmark value to compare against [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SetBenchmark(double benchmark) { _benchmark = benchmark; } [MethodImpl(MethodImplOptions.AggressiveInlining)] protected override void ManageState(bool isNew) { if (isNew) _p_benchmark = _benchmark; else _benchmark = _p_benchmark; } [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] protected override double Calculation() { ManageState(Input.IsNew); if (_benchmark <= double.Epsilon) return 0.0; return (Input.Value / _benchmark) * ScalingFactor; } }