// Updates this model using the new price information in the specified security instance // Update is a mandatory method public void Update(Security security, BaseData data) { var timeSinceLastUpdate = data.EndTime - _lastUpdate; if (timeSinceLastUpdate >= _periodSpan && data.Price > 0m) { if (_lastPrice > 0) { _window.Add(data.Price / _lastPrice - 1.0m); _needsUpdate = _window.IsReady; } _lastUpdate = data.EndTime; _lastPrice = data.Price; } if (_window.Count() < 2) { Volatility = 0; return; } if (_needsUpdate) { _needsUpdate = false; var mean = _window.Average(); var std = Math.Sqrt((double)_window.Sum(x => (x - mean) * (x - mean)) / _window.Count()); Volatility = Convert.ToDecimal(std * Math.Sqrt(252d)); } }
// Recycles unused blocks by removing them from the beginning // of the block list and adding them back to the end of it. private void Recycle() { const int Sentinel = -1; // Don't recycle blocks too often so we don't // spend too much time spinning our wheels Ticks recycleTime = DateTime.UtcNow; if ((recycleTime - m_lastRecycle).ToSeconds() < 1.0D) { return; } // The retention time tells whether a block is old // enough that the cosumer doesn't need it anymore Ticks retentionTime = m_retentionTime; int unusedBlockCount = -1; // Make sure to access m_blocks by index to avoid exceptions during // iteration if another thread adds a block to the end of the list for (int i = 0; i < m_endBlock && m_blocks[i].Timestamp < retentionTime; i++) { unusedBlockCount++; } if (unusedBlockCount <= 0) { return; } // The number of blocks retained is computed statistically // to minimize both unused space and block allocations int retainedBlockCount = unusedBlockCount; m_removedBlockCounts.Add(unusedBlockCount); if (m_removedBlockCounts[StatWindow - 1] != Sentinel) { retainedBlockCount = Math.Min((int)Math.Ceiling(m_removedBlockCounts.Average()) + 1, unusedBlockCount); } List <MeasurementBlock> retainedBlocks = m_blocks.GetRange(0, retainedBlockCount); // Now lock the block list since changes to the // list may contend with the queuing thread lock (m_blockLock) { m_blocks.RemoveRange(0, unusedBlockCount); retainedBlocks.ForEach(block => block.Reset()); m_blocks.AddRange(retainedBlocks); m_endBlock -= unusedBlockCount; } m_lastRecycle = recycleTime; }
public void WhenComputing_The_ResultIsTheArithmeticMeanOfAllDataInTheWindow() { const int period = 5; var sut = new MeanComputation(); var window = new RollingWindow <double>(period); for (int i = 0; i < 2 * period; i++) { window.Add(i); var result = sut.Compute(window); Assert.AreEqual(window.Average(), result); } }
public void Scan(TradeBar data) { var isDecreasingVolume = _volume.Skip(27).Average() < _volume.Average(); var tb = new TradeBar { EndTime = data.EndTime, Close = data.Close }; if (_rsi > 70 && !_securityHolding.Invested) { Signal = SignalType.Short; } else if (_rsi < 30 && !_securityHolding.Invested) { Signal = SignalType.Long; } else { Signal = SignalType.NoSignal; } }