mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-16 01:28:05 +00:00
style patterns
This commit is contained in:
@@ -59,7 +59,9 @@ public class AdxTests
|
||||
var bars = gbm.Fetch(100, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1));
|
||||
|
||||
for (int i = 0; i < 50; i++)
|
||||
{
|
||||
adx.Update(bars[i]);
|
||||
}
|
||||
|
||||
var originalValue = adx.Last;
|
||||
|
||||
@@ -110,7 +112,10 @@ public class AdxTests
|
||||
for (int i = 0; i < bars.Count; i++)
|
||||
{
|
||||
adx.Update(bars[i]);
|
||||
if (adx.IsHot) break;
|
||||
if (adx.IsHot)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Assert.True(adx.IsHot);
|
||||
@@ -124,7 +129,9 @@ public class AdxTests
|
||||
var bars = gbm.Fetch(50, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1));
|
||||
|
||||
for (int i = 0; i < 40; i++)
|
||||
{
|
||||
adx.Update(bars[i]);
|
||||
}
|
||||
|
||||
var nanBar = new TBar(DateTime.UtcNow, double.NaN, double.NaN, double.NaN, double.NaN, 100);
|
||||
var result = adx.Update(nanBar);
|
||||
@@ -140,7 +147,9 @@ public class AdxTests
|
||||
var bars = gbm.Fetch(50, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1));
|
||||
|
||||
for (int i = 0; i < 40; i++)
|
||||
{
|
||||
adx.Update(bars[i]);
|
||||
}
|
||||
|
||||
var infBar = new TBar(DateTime.UtcNow, double.PositiveInfinity, double.PositiveInfinity, 0, 100, 100);
|
||||
var result = adx.Update(infBar);
|
||||
@@ -161,7 +170,10 @@ public class AdxTests
|
||||
// 2. Streaming Mode
|
||||
var streamAdx = new Adx(14);
|
||||
for (int i = 0; i < bars.Count; i++)
|
||||
{
|
||||
streamAdx.Update(bars[i]);
|
||||
}
|
||||
|
||||
double streamResult = streamAdx.Last.Value;
|
||||
|
||||
Assert.Equal(expected, streamResult, 9);
|
||||
@@ -235,4 +247,4 @@ public class AdxTests
|
||||
Assert.Throws<ArgumentException>(() => new Adx(0));
|
||||
Assert.Throws<ArgumentException>(() => new Adx(-1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+66
-16
@@ -92,7 +92,9 @@ public sealed class Adx : ITValuePublisher
|
||||
public Adx(int period)
|
||||
{
|
||||
if (period <= 0)
|
||||
{
|
||||
throw new ArgumentException("Period must be greater than 0", nameof(period));
|
||||
}
|
||||
|
||||
_period = period;
|
||||
_decay = (period - 1.0) / period;
|
||||
@@ -177,14 +179,17 @@ public sealed class Adx : ITValuePublisher
|
||||
double prevClose = double.IsFinite(_prevBar.Close) ? _prevBar.Close : high;
|
||||
double prevHigh = double.IsFinite(_prevBar.High) ? _prevBar.High : high;
|
||||
double prevLow = double.IsFinite(_prevBar.Low) ? _prevBar.Low : low;
|
||||
|
||||
|
||||
double hl = high - low;
|
||||
double hpc = Math.Abs(high - prevClose);
|
||||
double lpc = Math.Abs(low - prevClose);
|
||||
double tr = Math.Max(hl, Math.Max(hpc, lpc));
|
||||
|
||||
// Guard TR against non-finite values
|
||||
if (!double.IsFinite(tr)) tr = 0;
|
||||
if (!double.IsFinite(tr))
|
||||
{
|
||||
tr = 0;
|
||||
}
|
||||
|
||||
// Calculate DM using guarded values
|
||||
double dmPlus = 0;
|
||||
@@ -193,14 +198,25 @@ public sealed class Adx : ITValuePublisher
|
||||
double downMove = prevLow - low;
|
||||
|
||||
// Guard moves against non-finite values
|
||||
if (!double.IsFinite(upMove)) upMove = 0;
|
||||
if (!double.IsFinite(downMove)) downMove = 0;
|
||||
if (!double.IsFinite(upMove))
|
||||
{
|
||||
upMove = 0;
|
||||
}
|
||||
|
||||
if (!double.IsFinite(downMove))
|
||||
{
|
||||
downMove = 0;
|
||||
}
|
||||
|
||||
if (upMove > downMove && upMove > 0)
|
||||
{
|
||||
dmPlus = upMove;
|
||||
}
|
||||
|
||||
if (downMove > upMove && downMove > 0)
|
||||
{
|
||||
dmMinus = downMove;
|
||||
}
|
||||
|
||||
if (isNew)
|
||||
{
|
||||
@@ -251,8 +267,15 @@ public sealed class Adx : ITValuePublisher
|
||||
}
|
||||
|
||||
// Guard against NaN/Infinity in DI calculations
|
||||
if (!double.IsFinite(diPlus)) diPlus = 0;
|
||||
if (!double.IsFinite(diMinus)) diMinus = 0;
|
||||
if (!double.IsFinite(diPlus))
|
||||
{
|
||||
diPlus = 0;
|
||||
}
|
||||
|
||||
if (!double.IsFinite(diMinus))
|
||||
{
|
||||
diMinus = 0;
|
||||
}
|
||||
|
||||
double diSum = diPlus + diMinus;
|
||||
if (diSum > 1e-10)
|
||||
@@ -261,7 +284,10 @@ public sealed class Adx : ITValuePublisher
|
||||
}
|
||||
|
||||
// Guard against NaN/Infinity in DX calculation
|
||||
if (!double.IsFinite(dx)) dx = 0;
|
||||
if (!double.IsFinite(dx))
|
||||
{
|
||||
dx = 0;
|
||||
}
|
||||
|
||||
// Smooth DX to get ADX
|
||||
if (_dxSamples < _period)
|
||||
@@ -281,17 +307,34 @@ public sealed class Adx : ITValuePublisher
|
||||
}
|
||||
|
||||
// Final guard on ADX
|
||||
if (!double.IsFinite(_adx)) _adx = _p_adx;
|
||||
if (!double.IsFinite(_adx))
|
||||
{
|
||||
_adx = _p_adx;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure all outputs are finite; if not, use previous values or 0
|
||||
if (!double.IsFinite(diPlus)) diPlus = double.IsFinite(DiPlus.Value) ? DiPlus.Value : 0;
|
||||
if (!double.IsFinite(diMinus)) diMinus = double.IsFinite(DiMinus.Value) ? DiMinus.Value : 0;
|
||||
|
||||
if (!double.IsFinite(diPlus))
|
||||
{
|
||||
diPlus = double.IsFinite(DiPlus.Value) ? DiPlus.Value : 0;
|
||||
}
|
||||
|
||||
if (!double.IsFinite(diMinus))
|
||||
{
|
||||
diMinus = double.IsFinite(DiMinus.Value) ? DiMinus.Value : 0;
|
||||
}
|
||||
|
||||
// Final guard on ADX output - ensure we always return a finite value
|
||||
double finalAdx = _adx;
|
||||
if (!double.IsFinite(finalAdx)) finalAdx = _p_adx;
|
||||
if (!double.IsFinite(finalAdx)) finalAdx = 0;
|
||||
if (!double.IsFinite(finalAdx))
|
||||
{
|
||||
finalAdx = _p_adx;
|
||||
}
|
||||
|
||||
if (!double.IsFinite(finalAdx))
|
||||
{
|
||||
finalAdx = 0;
|
||||
}
|
||||
|
||||
DiPlus = new TValue(input.Time, diPlus);
|
||||
DiMinus = new TValue(input.Time, diMinus);
|
||||
@@ -309,7 +352,10 @@ public sealed class Adx : ITValuePublisher
|
||||
|
||||
public TSeries Update(TBarSeries source)
|
||||
{
|
||||
if (source.Count == 0) return new TSeries([], []);
|
||||
if (source.Count == 0)
|
||||
{
|
||||
return new TSeries([], []);
|
||||
}
|
||||
|
||||
var len = source.Count;
|
||||
var v = new double[len];
|
||||
@@ -450,7 +496,11 @@ public sealed class Adx : ITValuePublisher
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static TSeries Batch(TBarSeries source, int period)
|
||||
{
|
||||
if (source.Count == 0) return new TSeries([], []);
|
||||
if (source.Count == 0)
|
||||
{
|
||||
return new TSeries([], []);
|
||||
}
|
||||
|
||||
var len = source.Count;
|
||||
var v = new double[len];
|
||||
Calculate(source.High.Values, source.Low.Values, source.Close.Values, period, v);
|
||||
@@ -464,4 +514,4 @@ public sealed class Adx : ITValuePublisher
|
||||
|
||||
return new TSeries(tList, [.. v]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,9 @@ public sealed class Adxr : ITValuePublisher
|
||||
public Adxr(int period)
|
||||
{
|
||||
if (period <= 0)
|
||||
{
|
||||
throw new ArgumentException("Period must be greater than 0", nameof(period));
|
||||
}
|
||||
|
||||
_period = period;
|
||||
Name = $"Adxr({period})";
|
||||
@@ -126,7 +128,10 @@ public sealed class Adxr : ITValuePublisher
|
||||
|
||||
public TSeries Update(TBarSeries source)
|
||||
{
|
||||
if (source.Count == 0) return new TSeries([], []);
|
||||
if (source.Count == 0)
|
||||
{
|
||||
return new TSeries([], []);
|
||||
}
|
||||
|
||||
int len = source.Count;
|
||||
var v = new double[len];
|
||||
@@ -205,14 +210,19 @@ public sealed class Adxr : ITValuePublisher
|
||||
finally
|
||||
{
|
||||
if (rentedAdx != null)
|
||||
{
|
||||
ArrayPool<double>.Shared.Return(rentedAdx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static TSeries Batch(TBarSeries source, int period)
|
||||
{
|
||||
if (source.Count == 0) return new TSeries([], []);
|
||||
if (source.Count == 0)
|
||||
{
|
||||
return new TSeries([], []);
|
||||
}
|
||||
|
||||
int len = source.Count;
|
||||
var v = new double[len];
|
||||
@@ -228,4 +238,4 @@ public sealed class Adxr : ITValuePublisher
|
||||
|
||||
return new TSeries(tList, [.. v]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -388,7 +388,9 @@ public class AmatTests
|
||||
for (int i = warmup; i < source.Length; i++)
|
||||
{
|
||||
if (Math.Abs(tseriesResult[i].Value - trend[i]) < 0.01)
|
||||
{
|
||||
matched++;
|
||||
}
|
||||
}
|
||||
// At least 95% of values after warmup should match
|
||||
double matchRate = (double)matched / (source.Length - warmup);
|
||||
|
||||
@@ -373,7 +373,7 @@ public sealed class AmatValidationTests : IDisposable
|
||||
|
||||
double trendMatchRate = (double)trendMatchCount / totalCount;
|
||||
double strengthMatchRate = (double)strengthMatchCount / totalCount;
|
||||
|
||||
|
||||
Assert.True(trendMatchRate > 0.95, $"Expected >95% trend match rate after warmup, got {trendMatchRate:P2}");
|
||||
Assert.True(strengthMatchRate > 0.95, $"Expected >95% strength match rate after warmup, got {strengthMatchRate:P2}");
|
||||
|
||||
@@ -437,4 +437,4 @@ public sealed class AmatValidationTests : IDisposable
|
||||
|
||||
_output.WriteLine($"Period combination ({fastPeriod}, {slowPeriod}) validated: Trend={amat.Last.Value}, Strength={amat.Strength.Value:F2}%");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,11 +123,19 @@ public sealed class Amat : ITValuePublisher, IDisposable
|
||||
public Amat(int fastPeriod = 10, int slowPeriod = 50)
|
||||
{
|
||||
if (fastPeriod <= 0)
|
||||
{
|
||||
throw new ArgumentException("Fast period must be greater than 0", nameof(fastPeriod));
|
||||
}
|
||||
|
||||
if (slowPeriod <= 0)
|
||||
{
|
||||
throw new ArgumentException("Slow period must be greater than 0", nameof(slowPeriod));
|
||||
}
|
||||
|
||||
if (fastPeriod >= slowPeriod)
|
||||
{
|
||||
throw new ArgumentException("Fast period must be less than slow period", nameof(fastPeriod));
|
||||
}
|
||||
|
||||
_fastAlpha = 2.0 / (fastPeriod + 1);
|
||||
_slowAlpha = 2.0 / (slowPeriod + 1);
|
||||
@@ -314,7 +322,10 @@ public sealed class Amat : ITValuePublisher, IDisposable
|
||||
/// <returns>Series of trend values</returns>
|
||||
public TSeries Update(TSeries source)
|
||||
{
|
||||
if (source.Count == 0) return [];
|
||||
if (source.Count == 0)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
int len = source.Count;
|
||||
var t = new List<long>(len);
|
||||
@@ -342,7 +353,10 @@ public sealed class Amat : ITValuePublisher, IDisposable
|
||||
private static double GetCompensatedValue(double ema, double e, bool isCompensated)
|
||||
{
|
||||
if (isCompensated || e <= COMPENSATOR_THRESHOLD)
|
||||
{
|
||||
return ema;
|
||||
}
|
||||
|
||||
return ema / (1.0 - e);
|
||||
}
|
||||
|
||||
@@ -358,7 +372,9 @@ public sealed class Amat : ITValuePublisher, IDisposable
|
||||
e *= decay;
|
||||
|
||||
if (!isHot && e <= COVERAGE_THRESHOLD)
|
||||
{
|
||||
isHot = true;
|
||||
}
|
||||
|
||||
if (e <= COMPENSATOR_THRESHOLD)
|
||||
{
|
||||
@@ -391,18 +407,35 @@ public sealed class Amat : ITValuePublisher, IDisposable
|
||||
int fastPeriod = 10, int slowPeriod = 50)
|
||||
{
|
||||
if (source.Length != trend.Length)
|
||||
{
|
||||
throw new ArgumentException("Source and trend must have the same length", nameof(trend));
|
||||
}
|
||||
|
||||
if (source.Length != strength.Length)
|
||||
{
|
||||
throw new ArgumentException("Source and strength must have the same length", nameof(strength));
|
||||
}
|
||||
|
||||
if (fastPeriod <= 0)
|
||||
{
|
||||
throw new ArgumentException("Fast period must be greater than 0", nameof(fastPeriod));
|
||||
}
|
||||
|
||||
if (slowPeriod <= 0)
|
||||
{
|
||||
throw new ArgumentException("Slow period must be greater than 0", nameof(slowPeriod));
|
||||
}
|
||||
|
||||
if (fastPeriod >= slowPeriod)
|
||||
{
|
||||
throw new ArgumentException("Fast period must be less than slow period", nameof(fastPeriod));
|
||||
}
|
||||
|
||||
int len = source.Length;
|
||||
if (len == 0) return;
|
||||
if (len == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
double fastAlpha = 2.0 / (fastPeriod + 1);
|
||||
double slowAlpha = 2.0 / (slowPeriod + 1);
|
||||
@@ -483,16 +516,30 @@ public sealed class Amat : ITValuePublisher, IDisposable
|
||||
int fastPeriod = 10, int slowPeriod = 50)
|
||||
{
|
||||
if (source.Length != trend.Length)
|
||||
{
|
||||
throw new ArgumentException("Source and trend must have the same length", nameof(trend));
|
||||
}
|
||||
|
||||
if (fastPeriod <= 0)
|
||||
{
|
||||
throw new ArgumentException("Fast period must be greater than 0", nameof(fastPeriod));
|
||||
}
|
||||
|
||||
if (slowPeriod <= 0)
|
||||
{
|
||||
throw new ArgumentException("Slow period must be greater than 0", nameof(slowPeriod));
|
||||
}
|
||||
|
||||
if (fastPeriod >= slowPeriod)
|
||||
{
|
||||
throw new ArgumentException("Fast period must be less than slow period", nameof(fastPeriod));
|
||||
}
|
||||
|
||||
int len = source.Length;
|
||||
if (len == 0) return;
|
||||
if (len == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
double fastAlpha = 2.0 / (fastPeriod + 1);
|
||||
double slowAlpha = 2.0 / (slowPeriod + 1);
|
||||
@@ -575,4 +622,4 @@ public sealed class Amat : ITValuePublisher, IDisposable
|
||||
var amat = new Amat(fastPeriod, slowPeriod);
|
||||
return amat.Update(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,7 +67,9 @@ public sealed class Aroon : ITValuePublisher
|
||||
public Aroon(int period)
|
||||
{
|
||||
if (period <= 0)
|
||||
{
|
||||
throw new ArgumentException("Period must be greater than 0", nameof(period));
|
||||
}
|
||||
|
||||
_period = period;
|
||||
Name = $"Aroon({period})";
|
||||
@@ -163,7 +165,10 @@ public sealed class Aroon : ITValuePublisher
|
||||
|
||||
public TSeries Update(TBarSeries source)
|
||||
{
|
||||
if (source.Count == 0) return new TSeries([], []);
|
||||
if (source.Count == 0)
|
||||
{
|
||||
return new TSeries([], []);
|
||||
}
|
||||
|
||||
int len = source.Count;
|
||||
var v = new double[len];
|
||||
@@ -288,7 +293,10 @@ public sealed class Aroon : ITValuePublisher
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static TSeries Batch(TBarSeries source, int period)
|
||||
{
|
||||
if (source.Count == 0) return new TSeries([], []);
|
||||
if (source.Count == 0)
|
||||
{
|
||||
return new TSeries([], []);
|
||||
}
|
||||
|
||||
int len = source.Count;
|
||||
var v = new double[len];
|
||||
@@ -304,4 +312,4 @@ public sealed class Aroon : ITValuePublisher
|
||||
|
||||
return new TSeries(tList, [.. v]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,9 @@ public sealed class AroonOsc : ITValuePublisher
|
||||
public AroonOsc(int period)
|
||||
{
|
||||
if (period <= 0)
|
||||
{
|
||||
throw new ArgumentException("Period must be greater than 0", nameof(period));
|
||||
}
|
||||
|
||||
_period = period;
|
||||
Name = $"AroonOsc({period})";
|
||||
@@ -148,7 +150,10 @@ public sealed class AroonOsc : ITValuePublisher
|
||||
|
||||
public TSeries Update(TBarSeries source)
|
||||
{
|
||||
if (source.Count == 0) return new TSeries([], []);
|
||||
if (source.Count == 0)
|
||||
{
|
||||
return new TSeries([], []);
|
||||
}
|
||||
|
||||
int len = source.Count;
|
||||
var v = new double[len];
|
||||
@@ -189,7 +194,10 @@ public sealed class AroonOsc : ITValuePublisher
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static TSeries Batch(TBarSeries source, int period)
|
||||
{
|
||||
if (source.Count == 0) return new TSeries([], []);
|
||||
if (source.Count == 0)
|
||||
{
|
||||
return new TSeries([], []);
|
||||
}
|
||||
|
||||
int len = source.Count;
|
||||
var v = new double[len];
|
||||
@@ -205,4 +213,4 @@ public sealed class AroonOsc : ITValuePublisher
|
||||
|
||||
return new TSeries(tList, [.. v]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,9 @@ public class DmxTests
|
||||
var bars = gbm.Fetch(100, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1));
|
||||
|
||||
for (int i = 0; i < 50; i++)
|
||||
{
|
||||
dmx.Update(bars[i]);
|
||||
}
|
||||
|
||||
var originalValue = dmx.Last;
|
||||
|
||||
@@ -114,7 +116,9 @@ public class DmxTests
|
||||
var bars = gbm.Fetch(50, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1));
|
||||
|
||||
for (int i = 0; i < 30; i++)
|
||||
{
|
||||
dmx.Update(bars[i]);
|
||||
}
|
||||
|
||||
var nanBar = new TBar(DateTime.UtcNow, double.NaN, double.NaN, double.NaN, double.NaN, 100);
|
||||
var result = dmx.Update(nanBar);
|
||||
@@ -130,7 +134,9 @@ public class DmxTests
|
||||
var bars = gbm.Fetch(50, DateTime.UtcNow.Ticks, TimeSpan.FromMinutes(1));
|
||||
|
||||
for (int i = 0; i < 30; i++)
|
||||
{
|
||||
dmx.Update(bars[i]);
|
||||
}
|
||||
|
||||
var infBar = new TBar(DateTime.UtcNow, double.PositiveInfinity, double.PositiveInfinity, 0, 100, 100);
|
||||
var result = dmx.Update(infBar);
|
||||
@@ -151,7 +157,10 @@ public class DmxTests
|
||||
// 2. Streaming Mode
|
||||
var streamDmx = new Dmx(14);
|
||||
for (int i = 0; i < bars.Count; i++)
|
||||
{
|
||||
streamDmx.Update(bars[i]);
|
||||
}
|
||||
|
||||
double streamResult = streamDmx.Last.Value;
|
||||
|
||||
Assert.Equal(expected, streamResult, 9);
|
||||
|
||||
+19
-1
@@ -109,10 +109,14 @@ public sealed class Dmx : ITValuePublisher
|
||||
double downMove = _prevBar.Low - input.Low;
|
||||
|
||||
if (upMove > downMove && upMove > 0)
|
||||
{
|
||||
dmPlusRaw = upMove;
|
||||
}
|
||||
|
||||
if (downMove > upMove && downMove > 0)
|
||||
{
|
||||
dmMinusRaw = downMove;
|
||||
}
|
||||
|
||||
double tr1 = input.High - input.Low;
|
||||
double tr2 = Math.Abs(input.High - _prevBar.Close);
|
||||
@@ -147,7 +151,9 @@ public sealed class Dmx : ITValuePublisher
|
||||
{
|
||||
int count = source.Count;
|
||||
if (count == 0)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
var t = new List<long>(count);
|
||||
var v = new List<double>(count);
|
||||
@@ -182,13 +188,19 @@ public sealed class Dmx : ITValuePublisher
|
||||
{
|
||||
int len = high.Length;
|
||||
if (len == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (low.Length != len || close.Length != len || destination.Length != len)
|
||||
{
|
||||
throw new ArgumentException("All input spans must have the same length", nameof(destination));
|
||||
}
|
||||
|
||||
if (period <= 0)
|
||||
{
|
||||
throw new ArgumentException("Period must be greater than zero.", nameof(period));
|
||||
}
|
||||
|
||||
// Use single ArrayPool rent with slicing for better cache locality and fewer allocations
|
||||
// Need 6 buffers of len each: dmPlus, dmMinus, tr, dmPlusSmooth, dmMinusSmooth, trSmooth
|
||||
@@ -238,10 +250,14 @@ public sealed class Dmx : ITValuePublisher
|
||||
double dmMinusRaw = 0.0;
|
||||
|
||||
if (upMove > downMove && upMove > 0.0)
|
||||
{
|
||||
dmPlusRaw = upMove;
|
||||
}
|
||||
|
||||
if (downMove > upMove && downMove > 0.0)
|
||||
{
|
||||
dmMinusRaw = downMove;
|
||||
}
|
||||
|
||||
double tr1 = h - l;
|
||||
double tr2 = Math.Abs(h - pc);
|
||||
@@ -275,7 +291,9 @@ public sealed class Dmx : ITValuePublisher
|
||||
finally
|
||||
{
|
||||
if (rented != null)
|
||||
{
|
||||
ArrayPool<double>.Shared.Return(rented);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,4 +302,4 @@ public sealed class Dmx : ITValuePublisher
|
||||
var dmx = new Dmx(period);
|
||||
return dmx.Update(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,4 +265,4 @@ public sealed class Super : ITValuePublisher
|
||||
var indicator = new Super(period, multiplier);
|
||||
return indicator.Update(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user