23 using System.Collections.Generic;
38 private readonly Dictionary<Symbol, SymbolCapacity> _capacityBySymbol;
39 private List<SymbolCapacity> _monitoredSymbolCapacity;
45 private HashSet<SymbolCapacity> _monitoredSymbolCapacitySet;
46 private DateTime _nextSnapshotDate;
47 private TimeSpan _snapshotPeriod;
48 private Symbol _smallestAssetSymbol;
62 get => _capacity.
Value.DiscretelyRoundBy(1000.00m);
77 _algorithm = algorithm;
78 _capacityBySymbol =
new Dictionary<Symbol, SymbolCapacity>();
79 _monitoredSymbolCapacity =
new List<SymbolCapacity>();
80 _monitoredSymbolCapacitySet =
new HashSet<SymbolCapacity>();
82 _snapshotPeriod = TimeSpan.FromDays(Math.Max(Math.Min((_algorithm.EndDate - _algorithm.StartDate).TotalDays - 1, 7), 1));
83 _nextSnapshotDate = _algorithm.StartDate + _snapshotPeriod;
98 SymbolCapacity symbolCapacity;
99 if (!_capacityBySymbol.TryGetValue(orderEvent.
Symbol, out symbolCapacity))
101 symbolCapacity =
new SymbolCapacity(_algorithm, orderEvent.
Symbol);
102 _capacityBySymbol[orderEvent.
Symbol] = symbolCapacity;
105 symbolCapacity.OnOrderEvent(orderEvent);
106 if (_monitoredSymbolCapacitySet.Contains(symbolCapacity))
111 _monitoredSymbolCapacity.Add(symbolCapacity);
112 _monitoredSymbolCapacitySet.Add(symbolCapacity);
124 for (var i = _monitoredSymbolCapacity.Count - 1; i >= 0; --i)
126 var capacity = _monitoredSymbolCapacity[i];
127 if (capacity.UpdateMarketCapacity())
129 _monitoredSymbolCapacity.RemoveAt(i);
130 _monitoredSymbolCapacitySet.Remove(capacity);
134 var utcDate = _algorithm.UtcTime.Date;
135 if (forceProcess || utcDate >= _nextSnapshotDate && _capacityBySymbol.Count != 0)
137 var totalPortfolioValue = _algorithm.Portfolio.TotalPortfolioValue;
138 var totalSaleVolume = _capacityBySymbol.Values
139 .Sum(s => s.SaleVolume);
141 if (totalPortfolioValue == 0 || _capacityBySymbol.Count == 0)
146 var smallestAsset = _capacityBySymbol.Values
147 .OrderBy(c => c.MarketCapacityDollarVolume)
150 _smallestAssetSymbol = smallestAsset.Security.
Symbol;
153 var percentageOfSaleVolume = totalSaleVolume != 0
154 ? smallestAsset.SaleVolume / totalSaleVolume
158 .AbsoluteUsedBuyingPower * smallestAsset.Security.Leverage;
160 var percentageOfHoldings = buyingPowerUsed / totalPortfolioValue;
162 var scalingFactor = Math.Max(percentageOfSaleVolume, percentageOfHoldings);
163 var dailyMarketCapacityDollarVolume = smallestAsset.MarketCapacityDollarVolume / smallestAsset.Trades;
165 var newCapacity = scalingFactor == 0
167 : dailyMarketCapacityDollarVolume / scalingFactor;
170 if (_capacity.
Value != 0)
172 newCapacity = (0.33m * newCapacity) + (_capacity.
Value * 0.66m);
178 foreach (var capacity
in _capacityBySymbol.Select(pair => pair.Value).ToList())
180 if (!capacity.ShouldRemove())
188 _capacityBySymbol.Remove(capacity.Security.Symbol);
189 _monitoredSymbolCapacity.Remove(capacity);
190 _monitoredSymbolCapacitySet.Remove(capacity);
193 _nextSnapshotDate = utcDate + _snapshotPeriod;