/* * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ using System; using System.Collections; using System.Collections.Generic; using QuantConnect.Data; using QuantConnect.Data.Auxiliary; using QuantConnect.Interfaces; namespace QuantConnect.Lean.Engine.DataFeeds.Enumerators { /// /// This enumerator will update the when required /// and adjust the raw prices based on the provided . /// Assumes the prices of the provided are in raw mode. /// public class PriceScaleFactorEnumerator : IEnumerator { private readonly IEnumerator _rawDataEnumerator; private readonly SubscriptionDataConfig _config; private readonly IFactorFileProvider _factorFileProvider; private DateTime _nextTradableDate; private IFactorProvider _factorFile; private bool _liveMode; private DateTime? _endDate; /// /// Explicit interface implementation for /// object IEnumerator.Current => Current; /// /// Last read object from this type and source /// public BaseData Current { get; private set; } /// /// Creates a new instance of the . /// /// The underlying raw data enumerator /// The to enumerate for. /// Will determine the to use. /// The instance to use /// True, is this is a live mode data stream /// The enumerator end date /// /// For normalization mode, /// the prices are scaled to the prices on the /// public PriceScaleFactorEnumerator( IEnumerator rawDataEnumerator, SubscriptionDataConfig config, IFactorFileProvider factorFileProvider, bool liveMode = false, DateTime? endDate = null) { _config = config; _liveMode = liveMode; _nextTradableDate = DateTime.MinValue; _rawDataEnumerator = rawDataEnumerator; _factorFileProvider = factorFileProvider; _endDate = endDate; } /// /// Dispose of the underlying enumerator. /// public void Dispose() { _rawDataEnumerator.Dispose(); } /// /// Advances the enumerator to the next element of the collection. /// /// /// True if the enumerator was successfully advanced to the next element; /// False if the enumerator has passed the end of the collection. /// public bool MoveNext() { var underlyingReturnValue = _rawDataEnumerator.MoveNext(); Current = _rawDataEnumerator.Current; if (underlyingReturnValue && Current != null && _factorFileProvider != null && _config.DataNormalizationMode != DataNormalizationMode.Raw) { var priceScaleFrontier = Current.GetUpdatePriceScaleFrontier(); if (priceScaleFrontier >= _nextTradableDate) { _factorFile = _factorFileProvider.Get(_config.Symbol); _config.PriceScaleFactor = _factorFile.GetPriceScale(priceScaleFrontier.Date, _config.DataNormalizationMode, _config.ContractDepthOffset, _config.DataMappingMode, _endDate); // update factor files every day _nextTradableDate = priceScaleFrontier.Date.AddDays(1); if (_liveMode) { // in live trading we add a offset to make sure new factor files are available _nextTradableDate = _nextTradableDate.Add(Time.LiveAuxiliaryDataOffset); } } Current = Current.Normalize(_config.PriceScaleFactor, _config.DataNormalizationMode, _config.SumOfDividends); } return underlyingReturnValue; } /// /// Reset the IEnumeration /// /// Not used public void Reset() { throw new NotImplementedException("Reset method not implemented. Assumes loop will only be used once."); } } }