/*
* 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.");
}
}
}