17 using System.Collections.Concurrent;
18 using System.Collections.Generic;
32 private const decimal _tolerance = 0.01m;
33 private readonly
int _fastPeriod;
34 private readonly
int _slowPeriod;
35 private readonly
int _universeCount;
38 private readonly ConcurrentDictionary<Symbol, SelectionData> _averages;
50 int universeCount = 500,
52 : base(false, universeSettings)
54 _fastPeriod = fastPeriod;
55 _slowPeriod = slowPeriod;
56 _universeCount = universeCount;
57 _averages =
new ConcurrentDictionary<Symbol, SelectionData>();
68 return (from cf in coarse
70 let avg = _averages.GetOrAdd(cf.Symbol, sym =>
new SelectionData(_fastPeriod, _slowPeriod))
72 where avg.Update(cf.EndTime, cf.AdjustedPrice)
74 where avg.Fast > avg.Slow * (1 + _tolerance)
76 orderby avg.ScaledDelta descending
78 select cf.Symbol).Take(_universeCount);
82 private class SelectionData
87 public SelectionData(
int fastPeriod,
int slowPeriod)
94 public decimal ScaledDelta => (Fast - Slow) / ((Fast + Slow) / 2m);
97 public bool Update(DateTime time, decimal value) => Fast.Update(time, value) & Slow.Update(time, value);