public void CouldCalculateSMAWithWidthEQ() { Assert.Throws <NotImplementedException>(() => { var count = 20; var sm = new SortedMap <int, double>(); sm.Add(0, 0); for (int i = 2; i <= count; i++) { sm.Add(i, i); } sm.Remove(11); sm.Remove(12); var onlineOp = new SumAvgOnlineOp <int, double, SortedMapCursor <int, double> >(); var smaOp = new SpanOpWidth <int, double, double, SortedMapCursor <int, double>, SumAvgOnlineOp <int, double, SortedMapCursor <int, double> > > (2, Lookup.EQ, onlineOp); var smaSeries = new SpanOpImpl <int, double, double, SpanOpWidth <int, double, double, SortedMapCursor <int, double>, SumAvgOnlineOp <int, double, SortedMapCursor <int, double> > >, SortedMapCursor <int, double> >(sm.GetEnumerator(), smaOp).Source; foreach (var keyValuePair in smaSeries) { Trace.WriteLine($"{keyValuePair.Key} - {keyValuePair.Value}"); } }); }
internal SMA(TCursor cursor, TKey width, Lookup lookup) : this() { var op = new SumAvgOnlineOp <TKey, TValue, TCursor>(); var spanOp = new SpanOp <TKey, TValue, TValue, TCursor, SumAvgOnlineOp <TKey, TValue, TCursor> >(width, lookup, op, cursor.Comparer); _cursor = new SpanOpImpl <TKey, TValue, TValue, SpanOp <TKey, TValue, TValue, TCursor, SumAvgOnlineOp <TKey, TValue, TCursor> >, TCursor >(cursor, spanOp); }
internal SMA(TCursor cursor, int width = 1, bool allowIncomplete = false) : this() { if (width <= 0) { throw new ArgumentOutOfRangeException(nameof(width)); } var op = new SumAvgOnlineOp <TKey, TValue, TCursor>(); var spanOp = new SpanOp <TKey, TValue, TValue, TCursor, SumAvgOnlineOp <TKey, TValue, TCursor> >(width, allowIncomplete, op, cursor.Comparer); _cursor = new SpanOpImpl <TKey, TValue, TValue, SpanOp <TKey, TValue, TValue, TCursor, SumAvgOnlineOp <TKey, TValue, TCursor> >, TCursor >(cursor, spanOp); }
public void CouldCalculateSMAWithWidth() { var count = 20; var sm = new SortedMap <int, double>(); for (int i = 1; i <= count; i++) { sm.Add(i, i); } DoTest(Lookup.EQ); DoTest(Lookup.GE); DoTest(Lookup.GT); DoTest(Lookup.LE); DoTest(Lookup.LT); DoTestViaSpanOpWidth(Lookup.EQ); DoTestViaSpanOpWidth(Lookup.GE); DoTestViaSpanOpWidth(Lookup.GT); DoTestViaSpanOpWidth(Lookup.LE); DoTestViaSpanOpWidth(Lookup.LT); void DoTest(Lookup lookup) { // width 9 is the same as count = 10 for the regular int series var smaOp = new MAvgWidth <int, double, SortedMapCursor <int, double> >(9, lookup); var smaCursor = new SpanOpImpl <int, double, double, MAvgWidth <int, double, SortedMapCursor <int, double> >, SortedMapCursor <int, double> >(sm.GetEnumerator(), smaOp); // this monster type must be hidden in the same way Lag hides its implementation Series <int, double, SpanOpImpl <int, double, double, MAvgWidth <int, double, SortedMapCursor <int, double> >, SortedMapCursor <int, double> > > smaSeries; smaSeries = smaCursor.Source; var sm2 = smaSeries.ToSortedMap(); Assert.AreEqual(sm2.First, smaSeries.First); Assert.AreEqual(sm2.Last, smaSeries.Last); Assert.True(SeriesContract.MoveAtShouldWorkOnLazySeries(smaSeries)); Assert.True(SeriesContract.ClonedCursorsAreIndependent(smaSeries)); if (lookup == Lookup.EQ || lookup == Lookup.GE) { var trueSma = sm.Window(10).Map(x => x.Values.Average()); Assert.True(trueSma.Keys.SequenceEqual(smaSeries.Keys)); Assert.True(trueSma.Values.SequenceEqual(smaSeries.Values)); } if (lookup == Lookup.GT) { var trueSma = sm.Window(11).Map(x => x.Values.Average()); Assert.True(trueSma.Keys.SequenceEqual(smaSeries.Keys)); Assert.True(trueSma.Values.SequenceEqual(smaSeries.Values)); } if (lookup == Lookup.LE) { var smaOp1 = new MAvgCount <int, double, SortedMapCursor <int, double> >(10, true); var trueSma = new SpanOpImpl <int, double, double, MAvgCount <int, double, SortedMapCursor <int, double> >, SortedMapCursor <int, double> >(sm.GetEnumerator(), smaOp1).Source; Assert.True(trueSma.Keys.SequenceEqual(smaSeries.Keys)); Assert.True(trueSma.Values.SequenceEqual(smaSeries.Values)); } if (lookup == Lookup.LT) { var smaOp1 = new MAvgCount <int, double, SortedMapCursor <int, double> >(9, true); var trueSma = new SpanOpImpl <int, double, double, MAvgCount <int, double, SortedMapCursor <int, double> >, SortedMapCursor <int, double> >(sm.GetEnumerator(), smaOp1).Source; Assert.True(trueSma.Keys.SequenceEqual(smaSeries.Keys)); Assert.True(trueSma.Values.SequenceEqual(smaSeries.Values)); } Debug.WriteLine("SMA"); foreach (var keyValuePair in smaSeries) { Debug.WriteLine($"{keyValuePair.Key} - {keyValuePair.Value}"); } } void DoTestViaSpanOpWidth(Lookup lookup) { // width 9 is the same as count = 10 for the regular int series var onlineOp = new SumAvgOnlineOp <int, double, SortedMapCursor <int, double> >(); var smaOp = new SpanOpWidth <int, double, double, SortedMapCursor <int, double>, SumAvgOnlineOp <int, double, SortedMapCursor <int, double> > >(9, lookup, onlineOp); var smaCursor = new SpanOpImpl <int, double, double, SpanOpWidth <int, double, double, SortedMapCursor <int, double>, SumAvgOnlineOp <int, double, SortedMapCursor <int, double> > >, SortedMapCursor <int, double> >(sm.GetEnumerator(), smaOp); // this monster type must be hidden in the same way Lag hides its implementation Series <int, double, SpanOpImpl <int, double, double, SpanOpWidth <int, double, double, SortedMapCursor <int, double>, SumAvgOnlineOp <int, double, SortedMapCursor <int, double> > >, SortedMapCursor <int, double> > > smaSeries; smaSeries = smaCursor.Source; var sm2 = smaSeries.ToSortedMap(); Assert.AreEqual(sm2.First, smaSeries.First); Assert.AreEqual(sm2.Last, smaSeries.Last); Assert.True(SeriesContract.MoveAtShouldWorkOnLazySeries(smaSeries)); Assert.True(SeriesContract.ClonedCursorsAreIndependent(smaSeries)); if (lookup == Lookup.EQ || lookup == Lookup.GE) { var trueSma = sm.Window(10).Map(x => x.Values.Average()); Assert.True(trueSma.Keys.SequenceEqual(smaSeries.Keys)); Assert.True(trueSma.Values.SequenceEqual(smaSeries.Values)); } if (lookup == Lookup.GT) { var trueSma = sm.Window(11).Map(x => x.Values.Average()); Assert.True(trueSma.Keys.SequenceEqual(smaSeries.Keys)); Assert.True(trueSma.Values.SequenceEqual(smaSeries.Values)); } if (lookup == Lookup.LE) { var smaOp1 = new MAvgCount <int, double, SortedMapCursor <int, double> >(10, true); var trueSma = new SpanOpImpl <int, double, double, MAvgCount <int, double, SortedMapCursor <int, double> >, SortedMapCursor <int, double> >(sm.GetEnumerator(), smaOp1).Source; Assert.True(trueSma.Keys.SequenceEqual(smaSeries.Keys)); Assert.True(trueSma.Values.SequenceEqual(smaSeries.Values)); } if (lookup == Lookup.LT) { var smaOp1 = new MAvgCount <int, double, SortedMapCursor <int, double> >(9, true); var trueSma = new SpanOpImpl <int, double, double, MAvgCount <int, double, SortedMapCursor <int, double> >, SortedMapCursor <int, double> >(sm.GetEnumerator(), smaOp1).Source; Assert.True(trueSma.Keys.SequenceEqual(smaSeries.Keys)); Assert.True(trueSma.Values.SequenceEqual(smaSeries.Values)); } Debug.WriteLine("SMA"); foreach (var keyValuePair in smaSeries) { Debug.WriteLine($"{keyValuePair.Key} - {keyValuePair.Value}"); } } }
public void CouldCalculateSMAWithCount() { var count = 20; var sm = new SortedMap <int, double>(); for (int i = 1; i <= count; i++) { sm.Add(i, i); } DoTest(true); DoTest(false); DoTestViaSpanOpCount(true); DoTestViaSpanOpCount(false); void DoTest(bool allowIncomplete) { // TODO separate tests/cases for true/false var smaOp = new MAvgCount <int, double, SortedMapCursor <int, double> >(10, allowIncomplete); var smaCursor = new SpanOpImpl <int, double, double, MAvgCount <int, double, SortedMapCursor <int, double> >, SortedMapCursor <int, double> >(sm.GetEnumerator(), smaOp); // this monster type must be hidden in the same way Lag hides its implementation Series <int, double, SpanOpImpl <int, double, double, MAvgCount <int, double, SortedMapCursor <int, double> >, SortedMapCursor <int, double> > > smaSeries; smaSeries = smaCursor.Source; var sm2 = smaSeries.ToSortedMap(); Assert.AreEqual(sm2.First, smaSeries.First); Assert.AreEqual(sm2.Last, smaSeries.Last); Assert.True(SeriesContract.MoveAtShouldWorkOnLazySeries(smaSeries)); Assert.True(SeriesContract.ClonedCursorsAreIndependent(smaSeries)); if (!allowIncomplete) { var trueSma = sm.Window(10).Map(x => x.Values.Average()); Assert.True(trueSma.Keys.SequenceEqual(smaSeries.Keys)); Assert.True(trueSma.Values.SequenceEqual(smaSeries.Values)); } Debug.WriteLine("SMA"); foreach (var keyValuePair in smaSeries) { Debug.WriteLine($"{keyValuePair.Key} - {keyValuePair.Value}"); } } void DoTestViaSpanOpCount(bool allowIncomplete) { // TODO separate tests/cases for true/false var onlineOp = new SumAvgOnlineOp <int, double, SortedMapCursor <int, double> >(); var smaOp = new SpanOpCount <int, double, double, SortedMapCursor <int, double>, SumAvgOnlineOp <int, double, SortedMapCursor <int, double> > >(10, allowIncomplete, onlineOp); var smaCursor = new SpanOpImpl <int, double, double, SpanOpCount <int, double, double, SortedMapCursor <int, double>, SumAvgOnlineOp <int, double, SortedMapCursor <int, double> > >, SortedMapCursor <int, double> >(sm.GetEnumerator(), smaOp); // this monster type must be hidden in the same way Lag hides its implementation Series <int, double, SpanOpImpl <int, double, double, SpanOpCount <int, double, double, SortedMapCursor <int, double>, SumAvgOnlineOp <int, double, SortedMapCursor <int, double> > >, SortedMapCursor <int, double> > > smaSeries; smaSeries = smaCursor.Source; var sm2 = smaSeries.ToSortedMap(); Assert.AreEqual(sm2.First, smaSeries.First); Assert.AreEqual(sm2.Last, smaSeries.Last); Assert.True(SeriesContract.MoveAtShouldWorkOnLazySeries(smaSeries)); Assert.True(SeriesContract.ClonedCursorsAreIndependent(smaSeries)); if (!allowIncomplete) { var trueSma = sm.Window(10).Map(x => x.Values.Average()); Assert.True(trueSma.Keys.SequenceEqual(smaSeries.Keys)); Assert.True(trueSma.Values.SequenceEqual(smaSeries.Values)); } Debug.WriteLine("SMA"); foreach (var keyValuePair in smaSeries) { Debug.WriteLine($"{keyValuePair.Key} - {keyValuePair.Value}"); } } }