Created
September 27, 2020 11:12
-
-
Save ahancock1/ada9f03cfbf6f6d183c24949b9b3b503 to your computer and use it in GitHub Desktop.
Observable extensible generic trading indicator series
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.Linq; | |
public interface ISeries | |
{ | |
void Attach(ISeries series); | |
void AttachTo(ISeries series); | |
void Detach(ISeries series); | |
void DetachFrom(ISeries series); | |
void Notify(); | |
void OnNext(); | |
void Clear(); | |
} | |
public interface ISeries<T> : ISeries, IEnumerable<T> | |
{ | |
int Size { get; } | |
int Available { get; } | |
T this[int n] { get; } | |
void SetValue(T value); | |
} | |
public class Series<T> : ISeries<T> | |
{ | |
private readonly T[] _data; | |
private readonly Func<T> _evaluator; | |
private readonly IList<ISeries> _observers = | |
new List<ISeries>(); | |
private int _index; | |
private Series(Func<T> evaluator, int count) | |
: this(count) | |
{ | |
_evaluator = evaluator; | |
} | |
private Series(int count) | |
{ | |
_index = -1; | |
_data = new T[count]; | |
Size = count; | |
} | |
public int Size { get; } | |
public int Available { get; private set; } | |
public T this[int n] | |
{ | |
get | |
{ | |
n = Math.Max(Math.Min(n, Available - 1), 0); | |
var i = (_index + Size - n) % Size; | |
return _data[i]; | |
} | |
} | |
public void Attach(ISeries series) | |
{ | |
_observers.Add(series); | |
} | |
public void AttachTo(ISeries series) | |
{ | |
series.Attach(this); | |
} | |
public void Detach(ISeries series) | |
{ | |
_observers.Remove(series); | |
} | |
public void DetachFrom(ISeries series) | |
{ | |
series.Detach(this); | |
} | |
public void Notify() | |
{ | |
foreach (var observer in _observers) | |
{ | |
observer.OnNext(); | |
} | |
} | |
public virtual void SetValue(T value) | |
{ | |
_index = (_index + 1) % Size; | |
Available = Math.Min(Available + 1, Size); | |
_data[_index] = value; | |
Notify(); | |
} | |
public virtual void OnNext() | |
{ | |
var value = default(T); | |
if (_evaluator != null) | |
{ | |
value = _evaluator.Invoke(); | |
} | |
SetValue(value); | |
} | |
public virtual void Clear() | |
{ | |
_index = -1; | |
Available = 0; | |
foreach (var observer in _observers) | |
{ | |
observer.Clear(); | |
} | |
} | |
public IEnumerator<T> GetEnumerator() | |
{ | |
return Enumerable | |
.Range(0, Available) | |
.Select(x => this[x]) | |
.ToList() | |
.GetEnumerator(); | |
} | |
IEnumerator IEnumerable.GetEnumerator() | |
{ | |
return GetEnumerator(); | |
} | |
public static ISeries<T> Create(int count = 256) | |
{ | |
return new Series<T>(count); | |
} | |
public static ISeries<T> Create(Func<T> evaluator, int count = 256) | |
{ | |
return new Series<T>(evaluator, count); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment