Skip to content

Commit

Permalink
new T3 initialization (#989)
Browse files Browse the repository at this point in the history
  • Loading branch information
DaveSkender committed Dec 29, 2022
1 parent d558832 commit 1a22bc3
Show file tree
Hide file tree
Showing 6 changed files with 46 additions and 160 deletions.
2 changes: 0 additions & 2 deletions docs/_indicators/T3.md
Expand Up @@ -42,7 +42,6 @@ IEnumerable<T3Result>
- This method returns a time series of all available indicator values for the `quotes` provided.
- It always returns the same number of elements as there are in the historical quotes.
- It does not return a single incremental indicator value.
- The first `6×(N-1)` periods will have `null` values since there's not enough data to calculate.

> :hourglass: **Convergence warning**: The first `6×(N-1)+250` periods will have decreasing magnitude, convergence-related precision errors that can be as high as ~5% deviation in indicator values for earlier periods.
Expand All @@ -57,7 +56,6 @@ IEnumerable<T3Result>

- [.Condense()]({{site.baseurl}}/utilities#condense)
- [.Find(lookupDate)]({{site.baseurl}}/utilities#find-indicator-result-by-date)
- [.RemoveWarmupPeriods()]({{site.baseurl}}/utilities#remove-warmup-periods)
- [.RemoveWarmupPeriods(qty)]({{site.baseurl}}/utilities#remove-warmup-periods)

See [Utilities and helpers]({{site.baseurl}}/utilities#utilities-for-indicator-results) for more information.
Expand Down
135 changes: 26 additions & 109 deletions src/s-z/T3/T3.Series.cs
Expand Up @@ -15,130 +15,47 @@ public static partial class Indicator
int length = tpList.Count;
List<T3Result> results = new(length);

if (length == 0)
{
return results;
}

double k = 2d / (lookbackPeriods + 1);
double a = volumeFactor;
double c1 = -a * a * a;
double c2 = (3 * a * a) + (3 * a * a * a);
double c3 = (-6 * a * a) - (3 * a) - (3 * a * a * a);
double c4 = 1 + (3 * a) + (a * a * a) + (3 * a * a);

double? e1 = 0, e2 = 0, e3 = 0, e4 = 0, e5 = 0, e6 = 0;
double? sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0, sum5 = 0, sum6 = 0;
double? e1;
double? e2;
double? e3;
double? e4;
double? e5;
double? e6;

// add initial value
(DateTime date, double value) r0 = tpList[0];
e1 = e2 = e3 = e4 = e5 = e6 = r0.value;
results.Add(new T3Result(r0.date) { T3 = r0.value });

// roll through quotes
for (int i = 0; i < length; i++)
for (int i = 1; i < length; i++)
{
(DateTime date, double value) = tpList[i];
T3Result r = new(date);
results.Add(r);

// first smoothing
if (i > lookbackPeriods - 1)
{
e1 += k * (value - e1);

// second smoothing
if (i > 2 * (lookbackPeriods - 1))
{
e2 += k * (e1 - e2);

// third smoothing
if (i > 3 * (lookbackPeriods - 1))
{
e3 += k * (e2 - e3);

// fourth smoothing
if (i > 4 * (lookbackPeriods - 1))
{
e4 += k * (e3 - e4);

// fifth smoothing
if (i > 5 * (lookbackPeriods - 1))
{
e5 += k * (e4 - e5);

// sixth smoothing
if (i > 6 * (lookbackPeriods - 1))
{
e6 += k * (e5 - e6);

// T3 moving average
r.T3 = ((c1 * e6) + (c2 * e5) + (c3 * e4) + (c4 * e3)).NaN2Null();
}

// sixth warmup
else
{
sum6 += e5;

if (i == 6 * (lookbackPeriods - 1))
{
e6 = sum6 / lookbackPeriods;

// initial T3 moving average
r.T3 = ((c1 * e6) + (c2 * e5) + (c3 * e4) + (c4 * e3)).NaN2Null();
}
}
}

// fifth warmup
else
{
sum5 += e4;

if (i == 5 * (lookbackPeriods - 1))
{
sum6 = e5 = sum5 / lookbackPeriods;
}
}
}

// fourth warmup
else
{
sum4 += e3;

if (i == 4 * (lookbackPeriods - 1))
{
sum5 = e4 = sum4 / lookbackPeriods;
}
}
}

// third warmup
else
{
sum3 += e2;

if (i == 3 * (lookbackPeriods - 1))
{
sum4 = e3 = sum3 / lookbackPeriods;
}
}
}

// second warmup
else
{
sum2 += e1;

if (i == 2 * (lookbackPeriods - 1))
{
sum3 = e2 = sum2 / lookbackPeriods;
}
}
}

// first warmup
else
{
sum1 += value;

if (i == lookbackPeriods - 1)
{
sum2 = e1 = sum1 / lookbackPeriods;
}
}
e1 += k * (value - e1);
e2 += k * (e1 - e2);
e3 += k * (e2 - e3);
e4 += k * (e3 - e4);
e5 += k * (e4 - e5);
e6 += k * (e5 - e6);

// T3 moving average
r.T3 = ((c1 * e6) + (c2 * e5) + (c3 * e4) + (c4 * e3)).NaN2Null();
}

return results;
Expand Down
17 changes: 0 additions & 17 deletions src/s-z/T3/T3.Utilities.cs

This file was deleted.

6 changes: 5 additions & 1 deletion tests/external/Test.Convergence.cs
Expand Up @@ -8,7 +8,11 @@ namespace External.Other;
public class Convergence : TestBase
{
private static readonly int[] QuotesQuantities =
new int[] { 5, 14, 28, 40, 50, 75, 100, 110, 120, 130, 140, 150, 160, 175, 200, 250, 350, 500, 600, 700, 800, 900, 1000 };
new int[]
{
5, 14, 28, 40, 50, 75, 100, 110, 120, 130, 140, 150,
160, 175, 200, 250, 350, 500, 600, 700, 800, 900, 1000
};

[TestMethod]
public void Adx()
Expand Down
Binary file modified tests/indicators/s-z/T3/T3.Calc.xlsx
Binary file not shown.
46 changes: 15 additions & 31 deletions tests/indicators/s-z/T3/T3.Tests.cs
Expand Up @@ -15,26 +15,26 @@ public void Standard()

// proper quantities
Assert.AreEqual(502, results.Count);
Assert.AreEqual(478, results.Count(x => x.T3 != null));
Assert.AreEqual(502, results.Count(x => x.T3 != null));

// sample values
T3Result r1 = results[23];
Assert.IsNull(r1.T3);
T3Result r5 = results[5];
Assert.AreEqual(213.9654, r5.T3.Round(4));

T3Result r2 = results[24];
Assert.AreEqual(215.9343, NullMath.Round(r2.T3, 4));
T3Result r24 = results[24];
Assert.AreEqual(215.9481, r24.T3.Round(4));

T3Result r3 = results[44];
Assert.AreEqual(224.9412, NullMath.Round(r3.T3, 4));
T3Result r44 = results[44];
Assert.AreEqual(224.9412, r44.T3.Round(4));

T3Result r4 = results[149];
Assert.AreEqual(235.8851, NullMath.Round(r4.T3, 4));
T3Result r149 = results[149];
Assert.AreEqual(235.8851, r149.T3.Round(4));

T3Result r5 = results[249];
Assert.AreEqual(257.8735, NullMath.Round(r5.T3, 4));
T3Result r249 = results[249];
Assert.AreEqual(257.8735, r249.T3.Round(4));

T3Result r6 = results[501];
Assert.AreEqual(238.9308, NullMath.Round(r6.T3, 4));
T3Result r501 = results[501];
Assert.AreEqual(238.9308, r501.T3.Round(4));
}

[TestMethod]
Expand All @@ -46,7 +46,7 @@ public void UseTuple()
.ToList();

Assert.AreEqual(502, results.Count);
Assert.AreEqual(478, results.Count(x => x.T3 != null));
Assert.AreEqual(502, results.Count(x => x.T3 != null));
}

[TestMethod]
Expand All @@ -69,7 +69,7 @@ public void Chainee()
.ToList();

Assert.AreEqual(502, results.Count);
Assert.AreEqual(477, results.Count(x => x.T3 != null));
Assert.AreEqual(501, results.Count(x => x.T3 != null));
}

[TestMethod]
Expand All @@ -81,7 +81,6 @@ public void Chainor()
.ToList();

Assert.AreEqual(502, results.Count);
Assert.AreEqual(469, results.Count(x => x.Sma != null));
}

[TestMethod]
Expand Down Expand Up @@ -111,21 +110,6 @@ public void NoQuotes()
Assert.AreEqual(1, r1.Count);
}

[TestMethod]
public void Removed()
{
List<T3Result> results = quotes
.GetT3(5, 0.7)
.RemoveWarmupPeriods()
.ToList();

// assertions
Assert.AreEqual(502 - ((6 * (5 - 1)) + 250), results.Count);

T3Result last = results.LastOrDefault();
Assert.AreEqual(238.9308, NullMath.Round(last.T3, 4));
}

[TestMethod]
public void Exceptions()
{
Expand Down

0 comments on commit 1a22bc3

Please sign in to comment.