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);
115 #pragma warning disable CS1574
123 #pragma warning restore CS1574
126 for (var i = _monitoredSymbolCapacity.Count - 1; i >= 0; --i)
128 var capacity = _monitoredSymbolCapacity[i];
129 if (capacity.UpdateMarketCapacity())
131 _monitoredSymbolCapacity.RemoveAt(i);
132 _monitoredSymbolCapacitySet.Remove(capacity);
136 var utcDate = _algorithm.UtcTime.Date;
137 if (forceProcess || utcDate >= _nextSnapshotDate && _capacityBySymbol.Count != 0)
139 var totalPortfolioValue = _algorithm.Portfolio.TotalPortfolioValue;
140 var totalSaleVolume = _capacityBySymbol.Values
141 .Sum(s => s.SaleVolume);
143 if (totalPortfolioValue == 0 || _capacityBySymbol.Count == 0)
148 var smallestAsset = _capacityBySymbol.Values
149 .OrderBy(c => c.MarketCapacityDollarVolume)
152 _smallestAssetSymbol = smallestAsset.Security.
Symbol;
155 var percentageOfSaleVolume = totalSaleVolume != 0
156 ? smallestAsset.SaleVolume / totalSaleVolume
160 .AbsoluteUsedBuyingPower * smallestAsset.Security.Leverage;
162 var percentageOfHoldings = buyingPowerUsed / totalPortfolioValue;
164 var scalingFactor = Math.Max(percentageOfSaleVolume, percentageOfHoldings);
165 var dailyMarketCapacityDollarVolume = smallestAsset.MarketCapacityDollarVolume / smallestAsset.Trades;
167 var newCapacity = scalingFactor == 0
169 : dailyMarketCapacityDollarVolume / scalingFactor;
172 if (_capacity.
Value != 0)
174 newCapacity = (0.33m * newCapacity) + (_capacity.
Value * 0.66m);
180 foreach (var capacity
in _capacityBySymbol.Select(pair => pair.Value).ToList())
182 if (!capacity.ShouldRemove())
190 _capacityBySymbol.Remove(capacity.Security.Symbol);
191 _monitoredSymbolCapacity.Remove(capacity);
192 _monitoredSymbolCapacitySet.Remove(capacity);
195 _nextSnapshotDate = utcDate + _snapshotPeriod;