Beispiel #1
0
        /// <summary>
        /// Merge two slice with same Time
        /// </summary>
        /// <param name="inputSlice">slice instance</param>
        /// <remarks> Will change the input collection for re-use</remarks>
        public void MergeSlice(Slice inputSlice)
        {
            if (UtcTime != inputSlice.UtcTime)
            {
                throw new InvalidOperationException($"Slice with time {UtcTime} can't be merged with given slice with different {inputSlice.UtcTime}");
            }

            _bars                = (TradeBars)UpdateCollection(_bars, inputSlice.Bars);
            _quoteBars           = (QuoteBars)UpdateCollection(_quoteBars, inputSlice.QuoteBars);
            _ticks               = (Ticks)UpdateCollection(_ticks, inputSlice.Ticks);
            _optionChains        = (OptionChains)UpdateCollection(_optionChains, inputSlice.OptionChains);
            _futuresChains       = (FuturesChains)UpdateCollection(_futuresChains, inputSlice.FuturesChains);
            _splits              = (Splits)UpdateCollection(_splits, inputSlice.Splits);
            _dividends           = (Dividends)UpdateCollection(_dividends, inputSlice.Dividends);
            _delistings          = (Delistings)UpdateCollection(_delistings, inputSlice.Delistings);
            _symbolChangedEvents = (SymbolChangedEvents)UpdateCollection(_symbolChangedEvents, inputSlice.SymbolChangedEvents);

            if (inputSlice._rawDataList.Count != 0)
            {
                if (_rawDataList.Count == 0)
                {
                    _rawDataList = inputSlice._rawDataList;
                    _data        = inputSlice._data;
                }
                else
                {
                    // Should keep this._rawDataList last so that selected data points are not overriden
                    // while creating _data
                    inputSlice._rawDataList.AddRange(_rawDataList);
                    _rawDataList = inputSlice._rawDataList;
                    _data        = new Lazy <DataDictionary <SymbolData> >(() => CreateDynamicDataDictionary(_rawDataList));
                }
            }
        }
Beispiel #2
0
            public IEnumerable <TimeSlice> GetTimeSlices()
            {
                var bars            = new TradeBars();
                var quotes          = new QuoteBars();
                var ticks           = new Ticks();
                var options         = new OptionChains();
                var futures         = new FuturesChains();
                var splits          = new Splits();
                var dividends       = new Dividends();
                var delistings      = new Delistings();
                var symbolChanges   = new SymbolChangedEvents();
                var dataFeedPackets = new List <DataFeedPacket>();
                var cashUpdateData  = new List <UpdateData <Cash> >();
                var customData      = new List <UpdateData <Security> >();
                var changes         = SecurityChanges.None;

                do
                {
                    var slice     = new Slice(default(DateTime), _data, bars, quotes, ticks, options, futures, splits, dividends, delistings, symbolChanges);
                    var timeSlice = new TimeSlice(_frontierUtc, _data.Count, slice, dataFeedPackets, cashUpdateData, securitiesUpdateData, _consolidatorUpdateData, customData, changes);
                    yield return(timeSlice);

                    _frontierUtc += FrontierStepSize;
                }while (_frontierUtc <= _endTimeUtc);
            }
Beispiel #3
0
        /// <summary>
        /// Process delistings
        /// </summary>
        /// <param name="delistings">Delistings to process</param>
        public void ProcessDelistings(Delistings delistings)
        {
            // Process our delistings, important to do options first because of possibility of having future options contracts
            // and underlying future delisting at the same time.
            foreach (var delisting in delistings?.Values.OrderBy(x => !x.Symbol.SecurityType.IsOption()))
            {
                Log.Trace($"BacktestingBrokerage.ProcessDelistings(): Delisting {delisting.Type}: {delisting.Symbol.Value}, UtcTime: {Algorithm.UtcTime}, DelistingTime: {delisting.Time}");
                if (delisting.Type == DelistingType.Warning)
                {
                    // We do nothing with warnings
                    continue;
                }

                var security = Algorithm.Securities[delisting.Symbol];

                if (security.Symbol.SecurityType.IsOption())
                {
                    // Process the option delisting
                    OnOptionNotification(new OptionNotificationEventArgs(delisting.Symbol, 0));
                }
                else
                {
                    // Any other type of delisting
                    OnDelistingNotification(new DelistingNotificationEventArgs(delisting.Symbol));
                }

                // don't allow users to open a new position once we sent the liquidation order
                security.IsTradable = false;
                security.IsDelisted = true;

                // the subscription are getting removed from the data feed because they end
                // remove security from all universes
                foreach (var ukvp in Algorithm.UniverseManager)
                {
                    var universe = ukvp.Value;
                    if (universe.ContainsMember(security.Symbol))
                    {
                        var userUniverse = universe as UserDefinedUniverse;
                        if (userUniverse != null)
                        {
                            userUniverse.Remove(security.Symbol);
                        }
                        else
                        {
                            universe.RemoveMember(Algorithm.UtcTime, security);
                        }
                    }
                }

                if (!Algorithm.IsWarmingUp)
                {
                    // Cancel any other orders
                    var cancelledOrders = Algorithm.Transactions.CancelOpenOrders(delisting.Symbol);
                    foreach (var cancelledOrder in cancelledOrders)
                    {
                        Log.Trace("AlgorithmManager.Run(): " + cancelledOrder);
                    }
                }
            }
        }
Beispiel #4
0
 /// <summary>
 /// Performs delisting logic for the securities specified in <paramref name="newDelistings"/> that are marked as <see cref="DelistingType.Delisted"/>.
 /// This includes liquidating the position and removing the security from the algorithm's collection.
 /// If we're unable to liquidate the position (maybe daily data or EOD already) then we'll add it to the <paramref name="delistingTickets"/>
 /// for the algo manager time loop to check later
 /// </summary>
 private static void HandleDelistedSymbols(IAlgorithm algorithm, Delistings newDelistings, ICollection <OrderTicket> delistingTickets)
 {
     foreach (var delisting in newDelistings.Values)
     {
         // submit an order to liquidate on market close
         if (delisting.Type == DelistingType.Warning)
         {
             Log.Trace("AlgorithmManager.Run(): Security delisting warning: " + delisting.Symbol.ToString());
             var security = algorithm.Securities[delisting.Symbol];
             if (security.Holdings.Quantity == 0)
             {
                 continue;
             }
             var submitOrderRequest = new SubmitOrderRequest(OrderType.MarketOnClose, security.Type, security.Symbol,
                                                             -security.Holdings.Quantity, 0, 0, algorithm.UtcTime, "Liquidate from delisting");
             var ticket = algorithm.Transactions.ProcessRequest(submitOrderRequest);
             delisting.SetOrderTicket(ticket);
             delistingTickets.Add(ticket);
         }
         else
         {
             Log.Trace("AlgorithmManager.Run(): Security delisted: " + delisting.Symbol.ToString());
             algorithm.Securities.Remove(delisting.Symbol);
             Log.Trace("AlgorithmManager.Run(): Security removed: " + delisting.Symbol.ToString());
         }
     }
 }
Beispiel #5
0
 private DataUpdates(DateTime occuredutc, DataPoint[] dataPoints, Delistings delistings, Dividends dividends,
                     Earnings earnings, Financials financials, KeyStats keystats, QuoteBars quotebars, Splits splits,
                     TradeBars tradebars, TradingStatusUpdates tradingStatusUpdates,
                     Ticks ticks)
 {
     //TODO: for cloning this object (so it becomes immutable)
     throw new NotImplementedException();
 }
Beispiel #6
0
        /// <summary>
        /// Performs delisting logic for the securities specified in <paramref name="newDelistings"/> that are marked as <see cref="DelistingType.Delisted"/>.
        /// This includes liquidating the position and removing the security from the algorithm's collection.
        /// If we're unable to liquidate the position (maybe daily data or EOD already) then we'll add it to the <paramref name="delistings"/>
        /// for the algo manager time loop to check later
        /// </summary>
        private static void HandleDelistedSymbols(IAlgorithm algorithm, Delistings newDelistings, ICollection <Delisting> delistings)
        {
            foreach (var delisting in newDelistings.Values)
            {
                // submit an order to liquidate on market close
                if (delisting.Type == DelistingType.Warning)
                {
                    SubmitOrderRequest request;

                    delistings.Add(delisting);
                    Log.Trace("AlgorithmManager.Run(): Security delisting warning: " + delisting.Symbol.ID);
                    var security = algorithm.Securities[delisting.Symbol];
                    if (security.Holdings.Quantity == 0)
                    {
                        continue;
                    }

                    if (security.Type == SecurityType.Option)
                    {
                        var underlying = algorithm.Securities[security.Symbol.Underlying];
                        var option     = (Option)security;

                        if (option.IsAutoExercised(underlying.Close))
                        {
                            request = new SubmitOrderRequest(OrderType.OptionExercise, security.Type, security.Symbol,
                                                             security.Holdings.Quantity, 0, 0, algorithm.UtcTime, "Automatic option exercise on expiration");
                        }
                        else
                        {
                            request = new SubmitOrderRequest(OrderType.MarketOnClose, security.Type, security.Symbol,
                                                             -security.Holdings.Quantity, 0, 0, algorithm.UtcTime, "Automatic option lapse on expiration");
                        }
                    }
                    else
                    {
                        request = new SubmitOrderRequest(OrderType.MarketOnClose, security.Type, security.Symbol,
                                                         -security.Holdings.Quantity, 0, 0, algorithm.UtcTime, "Liquidate from delisting");
                    }
                    var ticket = algorithm.Transactions.ProcessRequest(request);
                    delisting.SetOrderTicket(ticket);
                }
                else
                {
                    Log.Trace("AlgorithmManager.Run(): Security delisted: " + delisting.Symbol.ID);
                    var cancelledOrders = algorithm.Transactions.CancelOpenOrders(delisting.Symbol);
                    foreach (var cancelledOrder in cancelledOrders)
                    {
                        Log.Trace("AlgorithmManager.Run(): " + cancelledOrder);
                    }
                }
            }
        }
Beispiel #7
0
 /// <summary>
 /// Returns the input delistings if non-null, otherwise produces one from the dynamic data dictionary
 /// </summary>
 private Delistings CreateDelistingsCollection(Delistings delistings)
 {
     if (delistings != null)
     {
         return(delistings);
     }
     delistings = new Delistings(Time);
     foreach (var delisting in _data.Value.Values.Select(x => x.GetData()).OfType <Delisting>())
     {
         delistings[delisting.Symbol] = delisting;
     }
     return(delistings);
 }
Beispiel #8
0
 public Slice(DateTime time, IEnumerable <BaseData> data, TradeBars tradeBars, QuoteBars quoteBars, Ticks ticks, OptionChains optionChains, Splits splits, Dividends dividends, Delistings delistings, SymbolChangedEvents symbolChanges, bool?hasData = null)
 {
     Time                 = time;
     _dataByType          = new Dictionary <Type, Lazy <object> >();
     _data                = new Lazy <DataDictionary <SymbolData> >(() => CreateDynamicDataDictionary(data));
     HasData              = hasData ?? _data.Value.Count > 0;
     _ticks               = CreateTicksCollection(ticks);
     _bars                = CreateCollection <TradeBars, TradeBar>(tradeBars);
     _quoteBars           = CreateCollection <QuoteBars, QuoteBar>(quoteBars);
     _optionChains        = CreateCollection <OptionChains, OptionChain>(optionChains);
     _splits              = CreateCollection <Splits, Split>(splits);
     _dividends           = CreateCollection <Dividends, Dividend>(dividends);
     _delistings          = CreateCollection <Delistings, Delisting>(delistings);
     _symbolChangedEvents = CreateCollection <SymbolChangedEvents, SymbolChangedEvent>(symbolChanges);
 }
 public void OnData(Delistings data)
 {
     foreach (var kvp in data)
     {
         var symbol = kvp.Key;
         var delisting = kvp.Value;
         if (delisting.Type == DelistingType.Warning)
         {
             Console.WriteLine("OnData(Delistings): {0}: {1} will be delisted at end of day today.", Time, symbol);
         }
         if (delisting.Type == DelistingType.Delisted)
         {
             Console.WriteLine("OnData(Delistings): {0}: {1} has been delisted.", Time, symbol);
         }
     }
 }
Beispiel #10
0
 public void OnData(Delistings data)
 {
     foreach (var kvp in data)
     {
         var symbol    = kvp.Key;
         var delisting = kvp.Value;
         if (delisting.Type == DelistingType.Warning)
         {
             Console.WriteLine("OnData(Delistings): {0}: {1} will be delisted at end of day today.", Time, symbol);
         }
         if (delisting.Type == DelistingType.Delisted)
         {
             Console.WriteLine("OnData(Delistings): {0}: {1} has been delisted.", Time, symbol);
         }
     }
 }
Beispiel #11
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Slice"/> class
        /// </summary>
        /// <param name="time">The timestamp for this slice of data</param>
        /// <param name="data">The raw data in this slice</param>
        /// <param name="tradeBars">The trade bars for this slice</param>
        /// <param name="ticks">This ticks for this slice</param>
        /// <param name="splits">The splits for this slice</param>
        /// <param name="dividends">The dividends for this slice</param>
        /// <param name="delistings">The delistings for this slice</param>
        public Slice(DateTime time, IEnumerable <BaseData> data, TradeBars tradeBars, Ticks ticks, Splits splits, Dividends dividends, Delistings delistings)
        {
            Time = time;

            _dataByType = new Dictionary <Type, Lazy <object> >();

            // market data
            _data  = CreateDynamicDataDictionary(data);
            _ticks = CreateTicksCollection(ticks);
            _bars  = CreateTradeBarsCollection(tradeBars);

            // auxiliary data
            _splits     = CreateSplitsCollection(splits);
            _dividends  = CreateDividendsCollection(dividends);
            _delistings = CreateDelistingsCollection(delistings);
        }
Beispiel #12
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Slice"/> class
        /// </summary>
        /// <param name="time">The timestamp for this slice of data</param>
        /// <param name="data">The raw data in this slice</param>
        /// <param name="tradeBars">The trade bars for this slice</param>
        /// <param name="ticks">This ticks for this slice</param>
        /// <param name="splits">The splits for this slice</param>
        /// <param name="dividends">The dividends for this slice</param>
        /// <param name="delistings">The delistings for this slice</param>
        /// <param name="symbolChanges">The symbol changed events for this slice</param>
        public Slice(DateTime time, IEnumerable <BaseData> data, TradeBars tradeBars, Ticks ticks, Splits splits, Dividends dividends, Delistings delistings, SymbolChangedEvents symbolChanges)
        {
            Time = time;

            _dataByType = new Dictionary <Type, Lazy <object> >();

            // market data
            _data  = CreateDynamicDataDictionary(data);
            _ticks = CreateTicksCollection(ticks);
            _bars  = CreateCollection <TradeBars, TradeBar>(tradeBars);

            // auxiliary data
            _splits              = CreateCollection <Splits, Split>(splits);
            _dividends           = CreateCollection <Dividends, Dividend>(dividends);
            _delistings          = CreateCollection <Delistings, Delisting>(delistings);
            _symbolChangedEvents = CreateCollection <SymbolChangedEvents, SymbolChangedEvent>(symbolChanges);
        }
        /// <summary>
        /// Processes all synchronous events that must take place before the next time loop for the algorithm
        /// </summary>
        public override void ProcessSynchronousEvents()
        {
            // we process pending order requests our selves
            Run();

            base.ProcessSynchronousEvents();

            _brokerage.SimulateMarket();
            _brokerage.Scan();

            // Run our delistings processing, only do this once a slice
            if (_algorithm.CurrentSlice != null && _algorithm.CurrentSlice.Delistings != _lastestDelistings)
            {
                _lastestDelistings = _algorithm.CurrentSlice.Delistings;
                _brokerage.ProcessDelistings(_algorithm.CurrentSlice.Delistings);
            }
        }
 public void OnData(Delistings data)
 {
     foreach (var kvp in data)
     {
         var symbol    = kvp.Key;
         var delisting = kvp.Value;
         if (delisting.Type == DelistingType.Warning)
         {
             _toBeDelisted.Add(symbol);
             Debug($"OnData(Delistings): {Time}: {symbol} will be delisted at end of day today.");
         }
         if (delisting.Type == DelistingType.Delisted)
         {
             _delisted.Add(symbol);
             Debug($"OnData(Delistings): {Time}: {symbol} has been delisted.");
         }
     }
 }
Beispiel #15
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Slice"/> class
        /// </summary>
        /// <param name="time">The timestamp for this slice of data</param>
        /// <param name="data">The raw data in this slice</param>
        /// <param name="tradeBars">The trade bars for this slice</param>
        /// <param name="quoteBars">The quote bars for this slice</param>
        /// <param name="ticks">This ticks for this slice</param>
        /// <param name="optionChains">The option chains for this slice</param>
        /// <param name="futuresChains">The futures chains for this slice</param>
        /// <param name="splits">The splits for this slice</param>
        /// <param name="dividends">The dividends for this slice</param>
        /// <param name="delistings">The delistings for this slice</param>
        /// <param name="symbolChanges">The symbol changed events for this slice</param>
        /// <param name="hasData">true if this slice contains data</param>
        public Slice(DateTime time, IEnumerable <BaseData> data, TradeBars tradeBars, QuoteBars quoteBars, Ticks ticks, OptionChains optionChains, FuturesChains futuresChains, Splits splits, Dividends dividends, Delistings delistings, SymbolChangedEvents symbolChanges, bool?hasData = null)
        {
            Time = time;

            // market data
            _data = new Lazy <DataDictionary <SymbolData> >(() => CreateDynamicDataDictionary(data));

            HasData = hasData ?? _data.Value.Count > 0;

            _ticks         = ticks;
            _bars          = tradeBars;
            _quoteBars     = quoteBars;
            _optionChains  = optionChains;
            _futuresChains = futuresChains;

            // auxiliary data
            _splits              = splits;
            _dividends           = dividends;
            _delistings          = delistings;
            _symbolChangedEvents = symbolChanges;
        }
        public void OnData(Delistings data)
        {
            foreach (var kvp in data)
            {
                var symbol    = kvp.Key;
                var delisting = kvp.Value;
                if (delisting.Type == DelistingType.Warning)
                {
                    Debug($"OnData(Delistings): {Time}: {symbol} will be delisted at end of day today.");

                    // liquidate on delisting warning
                    SetHoldings(symbol, 0);
                }
                if (delisting.Type == DelistingType.Delisted)
                {
                    Debug($"OnData(Delistings): {Time}: {symbol} has been delisted.");

                    // fails because the security has already been delisted and is no longer tradable
                    SetHoldings(symbol, 1);
                }
            }
        }
Beispiel #17
0
        /// <summary>
        /// Initializes a new instance used by the <see cref="PythonSlice"/>
        /// </summary>
        /// <param name="slice">slice object to wrap</param>
        /// <remarks>This is required so that python slice enumeration works correctly since it relies on the private <see cref="_data"/> collection</remarks>
        protected Slice(Slice slice)
        {
            Time = slice.Time;

            _dataByType = slice._dataByType;

            _data = slice._data;

            HasData = slice.HasData;

            _ticks         = slice._ticks;
            _bars          = slice._bars;
            _quoteBars     = slice._quoteBars;
            _optionChains  = slice._optionChains;
            _futuresChains = slice._futuresChains;

            // auxiliary data
            _splits              = slice._splits;
            _dividends           = slice._dividends;
            _delistings          = slice._delistings;
            _symbolChangedEvents = slice._symbolChangedEvents;
        }
Beispiel #18
0
 /// <summary>
 /// Performs delisting logic for the securities specified in <paramref name="newDelistings"/> that are marked as <see cref="DelistingType.Delisted"/>.
 /// </summary>
 private static void HandleDelistedSymbols(IAlgorithm algorithm, Delistings newDelistings, List <Delisting> delistings)
 {
     foreach (var delisting in newDelistings.Values)
     {
         // submit an order to liquidate on market close
         if (delisting.Type == DelistingType.Warning)
         {
             if (!delistings.Any(x => x.Symbol == delisting.Symbol && x.Type == delisting.Type))
             {
                 delistings.Add(delisting);
                 Log.Trace("AlgorithmManager.Run(): Security delisting warning: " + delisting.Symbol.Value);
             }
         }
         else
         {
             Log.Trace("AlgorithmManager.Run(): Security delisted: " + delisting.Symbol.Value);
             var cancelledOrders = algorithm.Transactions.CancelOpenOrders(delisting.Symbol);
             foreach (var cancelledOrder in cancelledOrders)
             {
                 Log.Trace("AlgorithmManager.Run(): " + cancelledOrder);
             }
         }
     }
 }
Beispiel #19
0
        /// <summary>
        /// Creates a new <see cref="TimeSlice"/> for the specified time using the specified data
        /// </summary>
        /// <param name="utcDateTime">The UTC frontier date time</param>
        /// <param name="algorithmTimeZone">The algorithm's time zone, required for computing algorithm and slice time</param>
        /// <param name="cashBook">The algorithm's cash book, required for generating cash update pairs</param>
        /// <param name="data">The data in this <see cref="TimeSlice"/></param>
        /// <param name="changes">The new changes that are seen in this time slice as a result of universe selection</param>
        /// <returns>A new <see cref="TimeSlice"/> containing the specified data</returns>
        public static TimeSlice Create(DateTime utcDateTime, DateTimeZone algorithmTimeZone, CashBook cashBook, List <DataFeedPacket> data, SecurityChanges changes)
        {
            int count               = 0;
            var security            = new List <UpdateData <Security> >();
            var custom              = new List <UpdateData <Security> >();
            var consolidator        = new List <UpdateData <SubscriptionDataConfig> >();
            var allDataForAlgorithm = new List <BaseData>(data.Count);
            var cash = new List <UpdateData <Cash> >(cashBook.Count);

            var cashSecurities = new HashSet <Symbol>();

            foreach (var cashItem in cashBook.Values)
            {
                cashSecurities.Add(cashItem.SecuritySymbol);
            }

            Split              split;
            Dividend           dividend;
            Delisting          delisting;
            SymbolChangedEvent symbolChange;

            // we need to be able to reference the slice being created in order to define the
            // evaluation of option price models, so we define a 'future' that can be referenced
            // in the option price model evaluation delegates for each contract
            Slice slice       = null;
            var   sliceFuture = new Lazy <Slice>(() => slice);

            var algorithmTime = utcDateTime.ConvertFromUtc(algorithmTimeZone);
            var tradeBars     = new TradeBars(algorithmTime);
            var quoteBars     = new QuoteBars(algorithmTime);
            var ticks         = new Ticks(algorithmTime);
            var splits        = new Splits(algorithmTime);
            var dividends     = new Dividends(algorithmTime);
            var delistings    = new Delistings(algorithmTime);
            var optionChains  = new OptionChains(algorithmTime);
            var futuresChains = new FuturesChains(algorithmTime);
            var symbolChanges = new SymbolChangedEvents(algorithmTime);

            foreach (var packet in data)
            {
                var list   = packet.Data;
                var symbol = packet.Security.Symbol;

                if (list.Count == 0)
                {
                    continue;
                }

                // keep count of all data points
                if (list.Count == 1 && list[0] is BaseDataCollection)
                {
                    var baseDataCollectionCount = ((BaseDataCollection)list[0]).Data.Count;
                    if (baseDataCollectionCount == 0)
                    {
                        continue;
                    }
                    count += baseDataCollectionCount;
                }
                else
                {
                    count += list.Count;
                }

                if (!packet.Configuration.IsInternalFeed && packet.Configuration.IsCustomData)
                {
                    // This is all the custom data
                    custom.Add(new UpdateData <Security>(packet.Security, packet.Configuration.Type, list));
                }

                var securityUpdate     = new List <BaseData>(list.Count);
                var consolidatorUpdate = new List <BaseData>(list.Count);
                for (int i = 0; i < list.Count; i++)
                {
                    var baseData = list[i];
                    if (!packet.Configuration.IsInternalFeed)
                    {
                        // this is all the data that goes into the algorithm
                        allDataForAlgorithm.Add(baseData);
                    }
                    // don't add internal feed data to ticks/bars objects
                    if (baseData.DataType != MarketDataType.Auxiliary)
                    {
                        if (!packet.Configuration.IsInternalFeed)
                        {
                            PopulateDataDictionaries(baseData, ticks, tradeBars, quoteBars, optionChains, futuresChains);

                            // special handling of options data to build the option chain
                            if (packet.Security.Type == SecurityType.Option)
                            {
                                if (baseData.DataType == MarketDataType.OptionChain)
                                {
                                    optionChains[baseData.Symbol] = (OptionChain)baseData;
                                }
                                else if (!HandleOptionData(algorithmTime, baseData, optionChains, packet.Security, sliceFuture))
                                {
                                    continue;
                                }
                            }

                            // special handling of futures data to build the futures chain
                            if (packet.Security.Type == SecurityType.Future)
                            {
                                if (baseData.DataType == MarketDataType.FuturesChain)
                                {
                                    futuresChains[baseData.Symbol] = (FuturesChain)baseData;
                                }
                                else if (!HandleFuturesData(algorithmTime, baseData, futuresChains, packet.Security))
                                {
                                    continue;
                                }
                            }


                            // this is data used to update consolidators
                            consolidatorUpdate.Add(baseData);
                        }

                        // this is the data used set market prices
                        // do not add it if it is a Suspicious tick
                        var tick = baseData as Tick;
                        if (tick != null && tick.Suspicious)
                        {
                            continue;
                        }

                        securityUpdate.Add(baseData);
                    }
                    // include checks for various aux types so we don't have to construct the dictionaries in Slice
                    else if ((delisting = baseData as Delisting) != null)
                    {
                        delistings[symbol] = delisting;
                    }
                    else if ((dividend = baseData as Dividend) != null)
                    {
                        dividends[symbol] = dividend;
                    }
                    else if ((split = baseData as Split) != null)
                    {
                        splits[symbol] = split;
                    }
                    else if ((symbolChange = baseData as SymbolChangedEvent) != null)
                    {
                        // symbol changes is keyed by the requested symbol
                        symbolChanges[packet.Configuration.Symbol] = symbolChange;
                    }
                }

                if (securityUpdate.Count > 0)
                {
                    // check for 'cash securities' if we found valid update data for this symbol
                    // and we need this data to update cash conversion rates, long term we should
                    // have Cash hold onto it's security, then he can update himself, or rather, just
                    // patch through calls to conversion rate to compue it on the fly using Security.Price
                    if (cashSecurities.Contains(packet.Security.Symbol))
                    {
                        foreach (var cashKvp in cashBook)
                        {
                            if (cashKvp.Value.SecuritySymbol == packet.Security.Symbol)
                            {
                                var cashUpdates = new List <BaseData> {
                                    securityUpdate[securityUpdate.Count - 1]
                                };
                                cash.Add(new UpdateData <Cash>(cashKvp.Value, packet.Configuration.Type, cashUpdates));
                            }
                        }
                    }

                    security.Add(new UpdateData <Security>(packet.Security, packet.Configuration.Type, securityUpdate));
                }
                if (consolidatorUpdate.Count > 0)
                {
                    consolidator.Add(new UpdateData <SubscriptionDataConfig>(packet.Configuration, packet.Configuration.Type, consolidatorUpdate));
                }
            }

            slice = new Slice(algorithmTime, allDataForAlgorithm, tradeBars, quoteBars, ticks, optionChains, futuresChains, splits, dividends, delistings, symbolChanges, allDataForAlgorithm.Count > 0);

            return(new TimeSlice(utcDateTime, count, slice, data, cash, security, consolidator, custom, changes));
        }
Beispiel #20
0
        /// <summary>
        /// Creates a new <see cref="TimeSlice"/> for the specified time using the specified data
        /// </summary>
        /// <param name="utcDateTime">The UTC frontier date time</param>
        /// <param name="algorithmTimeZone">The algorithm's time zone, required for computing algorithm and slice time</param>
        /// <param name="cashBook">The algorithm's cash book, required for generating cash update pairs</param>
        /// <param name="data">The data in this <see cref="TimeSlice"/></param>
        /// <param name="changes">The new changes that are seen in this time slice as a result of universe selection</param>
        /// <returns>A new <see cref="TimeSlice"/> containing the specified data</returns>
        public static TimeSlice Create(DateTime utcDateTime, DateTimeZone algorithmTimeZone, CashBook cashBook, List<KeyValuePair<Security, List<BaseData>>> data, SecurityChanges changes)
        {
            int count = 0;
            var security = new List<KeyValuePair<Security, BaseData>>();
            var custom = new List<KeyValuePair<Security, List<BaseData>>>();
            var consolidator = new List<KeyValuePair<SubscriptionDataConfig, List<BaseData>>>();
            var allDataForAlgorithm = new List<BaseData>(data.Count);
            var cash = new List<KeyValuePair<Cash, BaseData>>(cashBook.Count);

            var cashSecurities = new HashSet<Symbol>();
            foreach (var cashItem in cashBook.Values)
            {
                cashSecurities.Add(cashItem.SecuritySymbol);
            }

            Split split;
            Dividend dividend;
            Delisting delisting;
            SymbolChangedEvent symbolChange;

            var algorithmTime = utcDateTime.ConvertFromUtc(algorithmTimeZone);
            var tradeBars = new TradeBars(algorithmTime);
            var ticks = new Ticks(algorithmTime);
            var splits = new Splits(algorithmTime);
            var dividends = new Dividends(algorithmTime);
            var delistings = new Delistings(algorithmTime);
            var symbolChanges = new SymbolChangedEvents(algorithmTime);

            foreach (var kvp in data)
            {
                var list = kvp.Value;
                var symbol = kvp.Key.Symbol;
                
                // keep count of all data points
                if (list.Count == 1 && list[0] is BaseDataCollection)
                {
                    count += ((BaseDataCollection) list[0]).Data.Count;
                }
                else
                {
                    count += list.Count;
                }

                BaseData update = null;
                var consolidatorUpdate = new List<BaseData>(list.Count);
                for (int i = 0; i < list.Count; i++)
                {
                    var baseData = list[i];
                    if (!kvp.Key.SubscriptionDataConfig.IsInternalFeed)
                    {
                        // this is all the data that goes into the algorithm
                        allDataForAlgorithm.Add(baseData);
                        if (kvp.Key.SubscriptionDataConfig.IsCustomData)
                        {
                            // this is all the custom data
                            custom.Add(kvp);
                        }
                    }
                    // don't add internal feed data to ticks/bars objects
                    if (baseData.DataType != MarketDataType.Auxiliary)
                    {
                        if (!kvp.Key.SubscriptionDataConfig.IsInternalFeed)
                        {
                            // populate ticks and tradebars dictionaries with no aux data
                            if (baseData.DataType == MarketDataType.Tick)
                            {
                                List<Tick> ticksList;
                                if (!ticks.TryGetValue(symbol, out ticksList))
                                {
                                    ticksList = new List<Tick> {(Tick) baseData};
                                    ticks[symbol] = ticksList;
                                }
                                ticksList.Add((Tick) baseData);
                            }
                            else if (baseData.DataType == MarketDataType.TradeBar)
                            {
                                tradeBars[symbol] = (TradeBar) baseData;
                            }

                            // this is data used to update consolidators
                            consolidatorUpdate.Add(baseData);
                        }

                        // this is the data used set market prices
                        update = baseData;
                    }
                    // include checks for various aux types so we don't have to construct the dictionaries in Slice
                    else if ((delisting = baseData as Delisting) != null)
                    {
                        delistings[symbol] = delisting;
                    }
                    else if ((dividend = baseData as Dividend) != null)
                    {
                        dividends[symbol] = dividend;
                    }
                    else if ((split = baseData as Split) != null)
                    {
                        splits[symbol] = split;
                    }
                    else if ((symbolChange = baseData as SymbolChangedEvent) != null)
                    {
                        // symbol changes is keyed by the requested symbol
                        symbolChanges[kvp.Key.SubscriptionDataConfig.Symbol] = symbolChange;
                    }
                }

                // check for 'cash securities' if we found valid update data for this symbol
                // and we need this data to update cash conversion rates, long term we should
                // have Cash hold onto it's security, then he can update himself, or rather, just
                // patch through calls to conversion rate to compue it on the fly using Security.Price
                if (update != null && cashSecurities.Contains(kvp.Key.Symbol))
                {
                    foreach (var cashKvp in cashBook)
                    {
                        if (cashKvp.Value.SecuritySymbol == kvp.Key.Symbol)
                        {
                            cash.Add(new KeyValuePair<Cash, BaseData>(cashKvp.Value, update));
                        }
                    }
                }

                security.Add(new KeyValuePair<Security, BaseData>(kvp.Key, update));
                consolidator.Add(new KeyValuePair<SubscriptionDataConfig, List<BaseData>>(kvp.Key.SubscriptionDataConfig, consolidatorUpdate));
            }

            var slice = new Slice(utcDateTime.ConvertFromUtc(algorithmTimeZone), allDataForAlgorithm, tradeBars, ticks, splits, dividends, delistings, symbolChanges, allDataForAlgorithm.Count > 0);

            return new TimeSlice(utcDateTime, count, slice, data, cash, security, consolidator, custom, changes);
        }
Beispiel #21
0
        /// <summary>
        /// Creates a new <see cref="TimeSlice"/> for the specified time using the specified data
        /// </summary>
        /// <param name="utcDateTime">The UTC frontier date time</param>
        /// <param name="data">The data in this <see cref="TimeSlice"/></param>
        /// <param name="changes">The new changes that are seen in this time slice as a result of universe selection</param>
        /// <param name="universeData"></param>
        /// <returns>A new <see cref="TimeSlice"/> containing the specified data</returns>
        public TimeSlice Create(DateTime utcDateTime,
                                List <DataFeedPacket> data,
                                SecurityChanges changes,
                                Dictionary <Universe, BaseDataCollection> universeData)
        {
            int count    = 0;
            var security = new List <UpdateData <ISecurityPrice> >(data.Count);
            List <UpdateData <ISecurityPrice> > custom = null;
            var consolidator            = new List <UpdateData <SubscriptionDataConfig> >(data.Count);
            var allDataForAlgorithm     = new List <BaseData>(data.Count);
            var optionUnderlyingUpdates = new Dictionary <Symbol, BaseData>();

            Split              split;
            Dividend           dividend;
            Delisting          delisting;
            SymbolChangedEvent symbolChange;

            // we need to be able to reference the slice being created in order to define the
            // evaluation of option price models, so we define a 'future' that can be referenced
            // in the option price model evaluation delegates for each contract
            Slice slice       = null;
            var   sliceFuture = new Lazy <Slice>(() => slice);

            var                 algorithmTime = utcDateTime.ConvertFromUtc(_timeZone);
            TradeBars           tradeBars     = null;
            QuoteBars           quoteBars     = null;
            Ticks               ticks         = null;
            Splits              splits        = null;
            Dividends           dividends     = null;
            Delistings          delistings    = null;
            OptionChains        optionChains  = null;
            FuturesChains       futuresChains = null;
            SymbolChangedEvents symbolChanges = null;

            UpdateEmptyCollections(algorithmTime);

            if (universeData.Count > 0)
            {
                // count universe data
                foreach (var kvp in universeData)
                {
                    count += kvp.Value.Data.Count;
                }
            }

            // ensure we read equity data before option data, so we can set the current underlying price
            foreach (var packet in data)
            {
                // filter out packets for removed subscriptions
                if (packet.IsSubscriptionRemoved)
                {
                    continue;
                }

                var list   = packet.Data;
                var symbol = packet.Configuration.Symbol;

                if (list.Count == 0)
                {
                    continue;
                }

                // keep count of all data points
                if (list.Count == 1 && list[0] is BaseDataCollection)
                {
                    var baseDataCollectionCount = ((BaseDataCollection)list[0]).Data.Count;
                    if (baseDataCollectionCount == 0)
                    {
                        continue;
                    }
                    count += baseDataCollectionCount;
                }
                else
                {
                    count += list.Count;
                }

                if (!packet.Configuration.IsInternalFeed && packet.Configuration.IsCustomData)
                {
                    if (custom == null)
                    {
                        custom = new List <UpdateData <ISecurityPrice> >(1);
                    }
                    // This is all the custom data
                    custom.Add(new UpdateData <ISecurityPrice>(packet.Security, packet.Configuration.Type, list, packet.Configuration.IsInternalFeed));
                }

                var securityUpdate          = new List <BaseData>(list.Count);
                var consolidatorUpdate      = new List <BaseData>(list.Count);
                var containsFillForwardData = false;
                for (var i = 0; i < list.Count; i++)
                {
                    var baseData = list[i];
                    if (!packet.Configuration.IsInternalFeed)
                    {
                        // this is all the data that goes into the algorithm
                        allDataForAlgorithm.Add(baseData);
                    }

                    containsFillForwardData |= baseData.IsFillForward;

                    // don't add internal feed data to ticks/bars objects
                    if (baseData.DataType != MarketDataType.Auxiliary)
                    {
                        var tick = baseData as Tick;

                        if (!packet.Configuration.IsInternalFeed)
                        {
                            // populate data dictionaries
                            switch (baseData.DataType)
                            {
                            case MarketDataType.Tick:
                                if (ticks == null)
                                {
                                    ticks = new Ticks(algorithmTime);
                                }
                                ticks.Add(baseData.Symbol, (Tick)baseData);
                                break;

                            case MarketDataType.TradeBar:
                                if (tradeBars == null)
                                {
                                    tradeBars = new TradeBars(algorithmTime);
                                }

                                var      newTradeBar = (TradeBar)baseData;
                                TradeBar existingTradeBar;
                                // if we have an existing bar keep the highest resolution one
                                // e.g Hour and Minute resolution subscriptions for the same symbol
                                // see CustomUniverseWithBenchmarkRegressionAlgorithm
                                if (!tradeBars.TryGetValue(baseData.Symbol, out existingTradeBar) ||
                                    existingTradeBar.Period > newTradeBar.Period)
                                {
                                    tradeBars[baseData.Symbol] = newTradeBar;
                                }
                                break;

                            case MarketDataType.QuoteBar:
                                if (quoteBars == null)
                                {
                                    quoteBars = new QuoteBars(algorithmTime);
                                }

                                var      newQuoteBar = (QuoteBar)baseData;
                                QuoteBar existingQuoteBar;
                                // if we have an existing bar keep the highest resolution one
                                // e.g Hour and Minute resolution subscriptions for the same symbol
                                // see CustomUniverseWithBenchmarkRegressionAlgorithm
                                if (!quoteBars.TryGetValue(baseData.Symbol, out existingQuoteBar) ||
                                    existingQuoteBar.Period > newQuoteBar.Period)
                                {
                                    quoteBars[baseData.Symbol] = newQuoteBar;
                                }
                                break;

                            case MarketDataType.OptionChain:
                                if (optionChains == null)
                                {
                                    optionChains = new OptionChains(algorithmTime);
                                }
                                optionChains[baseData.Symbol] = (OptionChain)baseData;
                                break;

                            case MarketDataType.FuturesChain:
                                if (futuresChains == null)
                                {
                                    futuresChains = new FuturesChains(algorithmTime);
                                }
                                futuresChains[baseData.Symbol] = (FuturesChain)baseData;
                                break;
                            }

                            // this is data used to update consolidators
                            // do not add it if it is a Suspicious tick
                            if (tick == null || !tick.Suspicious)
                            {
                                consolidatorUpdate.Add(baseData);
                            }
                        }

                        // special handling of options data to build the option chain
                        if (symbol.SecurityType.IsOption())
                        {
                            // internal feeds, like open interest, will not create the chain but will update it if it exists
                            // this is because the open interest could arrive at some closed market hours in which there is no other data and we don't
                            // want to generate a chain object in this case
                            if (optionChains == null && !packet.Configuration.IsInternalFeed)
                            {
                                optionChains = new OptionChains(algorithmTime);
                            }

                            if (baseData.DataType == MarketDataType.OptionChain)
                            {
                                optionChains[baseData.Symbol] = (OptionChain)baseData;
                            }
                            else if (optionChains != null && !HandleOptionData(algorithmTime, baseData, optionChains, packet.Security, sliceFuture, optionUnderlyingUpdates))
                            {
                                continue;
                            }
                        }

                        // special handling of futures data to build the futures chain
                        if (symbol.SecurityType == SecurityType.Future)
                        {
                            // internal feeds, like open interest, will not create the chain but will update it if it exists
                            // this is because the open interest could arrive at some closed market hours in which there is no other data and we don't
                            // want to generate a chain object in this case
                            if (futuresChains == null && !packet.Configuration.IsInternalFeed)
                            {
                                futuresChains = new FuturesChains(algorithmTime);
                            }
                            if (baseData.DataType == MarketDataType.FuturesChain)
                            {
                                futuresChains[baseData.Symbol] = (FuturesChain)baseData;
                            }
                            else if (futuresChains != null && !HandleFuturesData(algorithmTime, baseData, futuresChains, packet.Security))
                            {
                                continue;
                            }
                        }

                        // this is the data used set market prices
                        // do not add it if it is a Suspicious tick
                        if (tick != null && tick.Suspicious)
                        {
                            continue;
                        }

                        securityUpdate.Add(baseData);

                        // option underlying security update
                        if (!packet.Configuration.IsInternalFeed)
                        {
                            optionUnderlyingUpdates[symbol] = baseData;
                        }
                    }
                    else if (!packet.Configuration.IsInternalFeed)
                    {
                        // include checks for various aux types so we don't have to construct the dictionaries in Slice
                        if ((delisting = baseData as Delisting) != null)
                        {
                            if (delistings == null)
                            {
                                delistings = new Delistings(algorithmTime);
                            }
                            delistings[symbol] = delisting;
                        }
                        else if ((dividend = baseData as Dividend) != null)
                        {
                            if (dividends == null)
                            {
                                dividends = new Dividends(algorithmTime);
                            }
                            dividends[symbol] = dividend;
                        }
                        else if ((split = baseData as Split) != null)
                        {
                            if (splits == null)
                            {
                                splits = new Splits(algorithmTime);
                            }
                            splits[symbol] = split;
                        }
                        else if ((symbolChange = baseData as SymbolChangedEvent) != null)
                        {
                            if (symbolChanges == null)
                            {
                                symbolChanges = new SymbolChangedEvents(algorithmTime);
                            }
                            // symbol changes is keyed by the requested symbol
                            symbolChanges[packet.Configuration.Symbol] = symbolChange;
                        }
                    }
                }

                if (securityUpdate.Count > 0)
                {
                    security.Add(new UpdateData <ISecurityPrice>(packet.Security, packet.Configuration.Type, securityUpdate, packet.Configuration.IsInternalFeed, containsFillForwardData));
                }
                if (consolidatorUpdate.Count > 0)
                {
                    consolidator.Add(new UpdateData <SubscriptionDataConfig>(packet.Configuration, packet.Configuration.Type, consolidatorUpdate, packet.Configuration.IsInternalFeed, containsFillForwardData));
                }
            }

            slice = new Slice(algorithmTime, allDataForAlgorithm, tradeBars ?? _emptyTradeBars, quoteBars ?? _emptyQuoteBars, ticks ?? _emptyTicks, optionChains ?? _emptyOptionChains, futuresChains ?? _emptyFuturesChains, splits ?? _emptySplits, dividends ?? _emptyDividends, delistings ?? _emptyDelistings, symbolChanges ?? _emptySymbolChangedEvents, allDataForAlgorithm.Count > 0);

            return(new TimeSlice(utcDateTime, count, slice, data, security, consolidator, custom ?? _emptyCustom, changes, universeData));
        }
Beispiel #22
0
        /// <summary>
        /// Creates a new <see cref="TimeSlice"/> for the specified time using the specified data
        /// </summary>
        /// <param name="algorithm">The algorithm we're creating <see cref="TimeSlice"/> instances for</param>
        /// <param name="utcDateTime">The UTC frontier date time</param>
        /// <param name="data">The data in this <see cref="TimeSlice"/></param>
        /// <param name="changes">The new changes that are seen in this time slice as a result of universe selection</param>
        /// <returns>A new <see cref="TimeSlice"/> containing the specified data</returns>
        public static TimeSlice Create(IAlgorithm algorithm, DateTime utcDateTime, List <KeyValuePair <Security, List <BaseData> > > data, SecurityChanges changes)
        {
            int count               = 0;
            var security            = new List <KeyValuePair <Security, BaseData> >();
            var custom              = new List <KeyValuePair <Security, List <BaseData> > >();
            var consolidator        = new List <KeyValuePair <SubscriptionDataConfig, List <BaseData> > >();
            var allDataForAlgorithm = new List <BaseData>(data.Count);
            var cash = new List <KeyValuePair <Cash, BaseData> >(algorithm.Portfolio.CashBook.Count);

            var cashSecurities = new HashSet <string>();

            foreach (var cashItem in algorithm.Portfolio.CashBook.Values)
            {
                cashSecurities.Add(cashItem.SecuritySymbol);
            }

            Split     split;
            Dividend  dividend;
            Delisting delisting;

            var algorithmTime = utcDateTime.ConvertFromUtc(algorithm.TimeZone);
            var tradeBars     = new TradeBars(algorithmTime);
            var ticks         = new Ticks(algorithmTime);
            var splits        = new Splits(algorithmTime);
            var dividends     = new Dividends(algorithmTime);
            var delistings    = new Delistings(algorithmTime);

            foreach (var kvp in data)
            {
                var list   = kvp.Value;
                var symbol = kvp.Key.Symbol;

                // keep count of all data points
                count += list.Count;

                BaseData update             = null;
                var      consolidatorUpdate = new List <BaseData>(list.Count);
                for (int i = list.Count - 1; i > -1; i--)
                {
                    var baseData = list[i];
                    if (!kvp.Key.SubscriptionDataConfig.IsInternalFeed)
                    {
                        // this is all the data that goes into the algorithm
                        allDataForAlgorithm.Add(baseData);
                    }
                    if (kvp.Key.IsDynamicallyLoadedData)
                    {
                        // this is all the custom data
                        custom.Add(kvp);
                    }
                    if (baseData.DataType != MarketDataType.Auxiliary)
                    {
                        // populate ticks and tradebars dictionaries with no aux data
                        if (baseData.DataType == MarketDataType.Tick)
                        {
                            List <Tick> ticksList;
                            if (!ticks.TryGetValue(symbol, out ticksList))
                            {
                                ticksList = new List <Tick> {
                                    (Tick)baseData
                                };
                                ticks[symbol] = ticksList;
                            }
                            ticksList.Add((Tick)baseData);
                        }
                        else if (baseData.DataType == MarketDataType.TradeBar)
                        {
                            tradeBars[symbol] = (TradeBar)baseData;
                        }

                        // this is data used to update consolidators
                        consolidatorUpdate.Add(baseData);
                        if (update == null)
                        {
                            // this is the data used set market prices
                            update = baseData;
                        }
                    }
                    // include checks for various aux types so we don't have to construct the dictionaries in Slice
                    else if ((delisting = baseData as Delisting) != null)
                    {
                        delistings[symbol] = delisting;
                    }
                    else if ((dividend = baseData as Dividend) != null)
                    {
                        dividends[symbol] = dividend;
                    }
                    else if ((split = baseData as Split) != null)
                    {
                        splits[symbol] = split;
                    }
                }

                // check for 'cash securities' if we found valid update data for this symbol
                // and we need this data to update cash conversion rates, long term we should
                // have Cash hold onto it's security, then he can update himself, or rather, just
                // patch through calls to conversion rate to compue it on the fly using Security.Price
                if (update != null && cashSecurities.Contains(kvp.Key.Symbol))
                {
                    foreach (var cashKvp in algorithm.Portfolio.CashBook)
                    {
                        if (cashKvp.Value.SecuritySymbol == kvp.Key.Symbol)
                        {
                            cash.Add(new KeyValuePair <Cash, BaseData>(cashKvp.Value, update));
                        }
                    }
                }

                security.Add(new KeyValuePair <Security, BaseData>(kvp.Key, update));
                consolidator.Add(new KeyValuePair <SubscriptionDataConfig, List <BaseData> >(kvp.Key.SubscriptionDataConfig, consolidatorUpdate));
            }

            var slice = new Slice(utcDateTime.ConvertFromUtc(algorithm.TimeZone), allDataForAlgorithm, tradeBars, ticks, splits, dividends, delistings);

            return(new TimeSlice(utcDateTime, count, slice, data, cash, security, consolidator, custom, changes));
        }
Beispiel #23
0
        /// <summary>
        /// Creates a new <see cref="TimeSlice"/> for the specified time using the specified data
        /// </summary>
        /// <param name="utcDateTime">The UTC frontier date time</param>
        /// <param name="algorithmTimeZone">The algorithm's time zone, required for computing algorithm and slice time</param>
        /// <param name="cashBook">The algorithm's cash book, required for generating cash update pairs</param>
        /// <param name="data">The data in this <see cref="TimeSlice"/></param>
        /// <param name="changes">The new changes that are seen in this time slice as a result of universe selection</param>
        /// <param name="universeData"></param>
        /// <returns>A new <see cref="TimeSlice"/> containing the specified data</returns>
        public static TimeSlice Create(DateTime utcDateTime,
                                       DateTimeZone algorithmTimeZone,
                                       CashBook cashBook,
                                       List <DataFeedPacket> data,
                                       SecurityChanges changes,
                                       Dictionary <Universe, BaseDataCollection> universeData)
        {
            int count                   = 0;
            var security                = new List <UpdateData <Security> >();
            var custom                  = new List <UpdateData <Security> >();
            var consolidator            = new List <UpdateData <SubscriptionDataConfig> >();
            var allDataForAlgorithm     = new List <BaseData>(data.Count);
            var optionUnderlyingUpdates = new Dictionary <Symbol, BaseData>();

            Split              split;
            Dividend           dividend;
            Delisting          delisting;
            SymbolChangedEvent symbolChange;

            // we need to be able to reference the slice being created in order to define the
            // evaluation of option price models, so we define a 'future' that can be referenced
            // in the option price model evaluation delegates for each contract
            Slice slice       = null;
            var   sliceFuture = new Lazy <Slice>(() => slice);

            var algorithmTime = utcDateTime.ConvertFromUtc(algorithmTimeZone);
            var tradeBars     = new TradeBars(algorithmTime);
            var quoteBars     = new QuoteBars(algorithmTime);
            var ticks         = new Ticks(algorithmTime);
            var splits        = new Splits(algorithmTime);
            var dividends     = new Dividends(algorithmTime);
            var delistings    = new Delistings(algorithmTime);
            var optionChains  = new OptionChains(algorithmTime);
            var futuresChains = new FuturesChains(algorithmTime);
            var symbolChanges = new SymbolChangedEvents(algorithmTime);

            if (universeData.Count > 0)
            {
                // count universe data
                foreach (var kvp in universeData)
                {
                    count += kvp.Value.Data.Count;
                }
            }

            // ensure we read equity data before option data, so we can set the current underlying price
            foreach (var packet in data)
            {
                // filter out packets for removed subscriptions
                if (packet.IsSubscriptionRemoved)
                {
                    continue;
                }

                var list   = packet.Data;
                var symbol = packet.Security.Symbol;

                if (list.Count == 0)
                {
                    continue;
                }

                // keep count of all data points
                if (list.Count == 1 && list[0] is BaseDataCollection)
                {
                    var baseDataCollectionCount = ((BaseDataCollection)list[0]).Data.Count;
                    if (baseDataCollectionCount == 0)
                    {
                        continue;
                    }
                    count += baseDataCollectionCount;
                }
                else
                {
                    count += list.Count;
                }

                if (!packet.Configuration.IsInternalFeed && packet.Configuration.IsCustomData)
                {
                    // This is all the custom data
                    custom.Add(new UpdateData <Security>(packet.Security, packet.Configuration.Type, list));
                }

                var securityUpdate     = new List <BaseData>(list.Count);
                var consolidatorUpdate = new List <BaseData>(list.Count);
                for (int i = 0; i < list.Count; i++)
                {
                    var baseData = list[i];
                    if (!packet.Configuration.IsInternalFeed)
                    {
                        // this is all the data that goes into the algorithm
                        allDataForAlgorithm.Add(baseData);
                    }
                    // don't add internal feed data to ticks/bars objects
                    if (baseData.DataType != MarketDataType.Auxiliary)
                    {
                        if (!packet.Configuration.IsInternalFeed)
                        {
                            PopulateDataDictionaries(baseData, ticks, tradeBars, quoteBars, optionChains, futuresChains);

                            // special handling of options data to build the option chain
                            if (packet.Security.Type == SecurityType.Option)
                            {
                                if (baseData.DataType == MarketDataType.OptionChain)
                                {
                                    optionChains[baseData.Symbol] = (OptionChain)baseData;
                                }
                                else if (!HandleOptionData(algorithmTime, baseData, optionChains, packet.Security, sliceFuture, optionUnderlyingUpdates))
                                {
                                    continue;
                                }
                            }

                            // special handling of futures data to build the futures chain
                            if (packet.Security.Type == SecurityType.Future)
                            {
                                if (baseData.DataType == MarketDataType.FuturesChain)
                                {
                                    futuresChains[baseData.Symbol] = (FuturesChain)baseData;
                                }
                                else if (!HandleFuturesData(algorithmTime, baseData, futuresChains, packet.Security))
                                {
                                    continue;
                                }
                            }

                            // this is data used to update consolidators
                            consolidatorUpdate.Add(baseData);
                        }

                        // this is the data used set market prices
                        // do not add it if it is a Suspicious tick
                        var tick = baseData as Tick;
                        if (tick != null && tick.Suspicious)
                        {
                            continue;
                        }

                        securityUpdate.Add(baseData);

                        // option underlying security update
                        if (packet.Security.Symbol.SecurityType == SecurityType.Equity)
                        {
                            optionUnderlyingUpdates[packet.Security.Symbol] = baseData;
                        }
                    }
                    // include checks for various aux types so we don't have to construct the dictionaries in Slice
                    else if ((delisting = baseData as Delisting) != null)
                    {
                        delistings[symbol] = delisting;
                    }
                    else if ((dividend = baseData as Dividend) != null)
                    {
                        dividends[symbol] = dividend;
                    }
                    else if ((split = baseData as Split) != null)
                    {
                        splits[symbol] = split;
                    }
                    else if ((symbolChange = baseData as SymbolChangedEvent) != null)
                    {
                        // symbol changes is keyed by the requested symbol
                        symbolChanges[packet.Configuration.Symbol] = symbolChange;
                    }
                }

                if (securityUpdate.Count > 0)
                {
                    security.Add(new UpdateData <Security>(packet.Security, packet.Configuration.Type, securityUpdate));
                }
                if (consolidatorUpdate.Count > 0)
                {
                    consolidator.Add(new UpdateData <SubscriptionDataConfig>(packet.Configuration, packet.Configuration.Type, consolidatorUpdate));
                }
            }

            slice = new Slice(algorithmTime, allDataForAlgorithm, tradeBars, quoteBars, ticks, optionChains, futuresChains, splits, dividends, delistings, symbolChanges, allDataForAlgorithm.Count > 0);

            return(new TimeSlice(utcDateTime, count, slice, data, security, consolidator, custom, changes, universeData));
        }
Beispiel #24
0
        /// <summary>
        /// Launch the algorithm manager to run this strategy
        /// </summary>
        /// <param name="job">Algorithm job</param>
        /// <param name="algorithm">Algorithm instance</param>
        /// <param name="feed">Datafeed object</param>
        /// <param name="transactions">Transaction manager object</param>
        /// <param name="results">Result handler object</param>
        /// <param name="realtime">Realtime processing object</param>
        /// <param name="token">Cancellation token</param>
        /// <remarks>Modify with caution</remarks>
        public void Run(AlgorithmNodePacket job, IAlgorithm algorithm, IDataFeed feed, ITransactionHandler transactions, IResultHandler results, IRealTimeHandler realtime, CancellationToken token)
        {
            //Initialize:
            _dataPointCount = 0;
            var startingPortfolioValue = algorithm.Portfolio.TotalPortfolioValue;
            var backtestMode           = (job.Type == PacketType.BacktestNode);
            var methodInvokers         = new Dictionary <Type, MethodInvoker>();
            var marginCallFrequency    = TimeSpan.FromMinutes(5);
            var nextMarginCallTime     = DateTime.MinValue;
            var delistingTickets       = new List <OrderTicket>();

            //Initialize Properties:
            _algorithmId    = job.AlgorithmId;
            _algorithmState = AlgorithmStatus.Running;
            _previousTime   = algorithm.StartDate.Date;

            //Create the method accessors to push generic types into algorithm: Find all OnData events:

            // Algorithm 2.0 data accessors
            var hasOnDataTradeBars = AddMethodInvoker <TradeBars>(algorithm, methodInvokers);
            var hasOnDataTicks     = AddMethodInvoker <Ticks>(algorithm, methodInvokers);

            // dividend and split events
            var hasOnDataDividends  = AddMethodInvoker <Dividends>(algorithm, methodInvokers);
            var hasOnDataSplits     = AddMethodInvoker <Splits>(algorithm, methodInvokers);
            var hasOnDataDelistings = AddMethodInvoker <Delistings>(algorithm, methodInvokers);

            // Algorithm 3.0 data accessors
            var hasOnDataSlice = algorithm.GetType().GetMethods()
                                 .Where(x => x.Name == "OnData" && x.GetParameters().Length == 1 && x.GetParameters()[0].ParameterType == typeof(Slice))
                                 .FirstOrDefault(x => x.DeclaringType == algorithm.GetType()) != null;

            //Go through the subscription types and create invokers to trigger the event handlers for each custom type:
            foreach (var config in feed.Subscriptions)
            {
                //If type is a tradebar, combine tradebars and ticks into unified array:
                if (config.Type.Name != "TradeBar" && config.Type.Name != "Tick")
                {
                    //Get the matching method for this event handler - e.g. public void OnData(Quandl data) { .. }
                    var genericMethod = (algorithm.GetType()).GetMethod("OnData", new[] { config.Type });

                    //If we already have this Type-handler then don't add it to invokers again.
                    if (methodInvokers.ContainsKey(config.Type))
                    {
                        continue;
                    }

                    //If we couldnt find the event handler, let the user know we can't fire that event.
                    if (genericMethod == null && !hasOnDataSlice)
                    {
                        algorithm.RunTimeError = new Exception("Data event handler not found, please create a function matching this template: public void OnData(" + config.Type.Name + " data) {  }");
                        _algorithmState        = AlgorithmStatus.RuntimeError;
                        return;
                    }
                    if (genericMethod != null)
                    {
                        methodInvokers.Add(config.Type, genericMethod.DelegateForCallMethod());
                    }
                }
            }

            //Loop over the queues: get a data collection, then pass them all into relevent methods in the algorithm.
            Log.Trace("AlgorithmManager.Run(): Begin DataStream - Start: " + algorithm.StartDate + " Stop: " + algorithm.EndDate);
            foreach (var timeSlice in feed.Bridge.GetConsumingEnumerable(token))
            {
                // reset our timer on each loop
                _currentTimeStepTime = DateTime.UtcNow;

                //Check this backtest is still running:
                if (_algorithmState != AlgorithmStatus.Running)
                {
                    Log.Error(string.Format("AlgorithmManager.Run(): Algorthm state changed to {0} at {1}", _algorithmState, timeSlice.Time));
                    break;
                }

                //Execute with TimeLimit Monitor:
                if (token.IsCancellationRequested)
                {
                    Log.Error("AlgorithmManager.Run(): CancellationRequestion at " + timeSlice.Time);
                    return;
                }

                var time    = timeSlice.Time;
                var newData = timeSlice.Data;

                //If we're in backtest mode we need to capture the daily performance. We do this here directly
                //before updating the algorithm state with the new data from this time step, otherwise we'll
                //produce incorrect samples (they'll take into account this time step's new price values)
                if (backtestMode)
                {
                    //On day-change sample equity and daily performance for statistics calculations
                    if (_previousTime.Date != time.Date)
                    {
                        //Sample the portfolio value over time for chart.
                        results.SampleEquity(_previousTime, Math.Round(algorithm.Portfolio.TotalPortfolioValue, 4));

                        //Check for divide by zero
                        if (startingPortfolioValue == 0m)
                        {
                            results.SamplePerformance(_previousTime.Date, 0);
                        }
                        else
                        {
                            results.SamplePerformance(_previousTime.Date, Math.Round((algorithm.Portfolio.TotalPortfolioValue - startingPortfolioValue) * 100 / startingPortfolioValue, 10));
                        }
                        startingPortfolioValue = algorithm.Portfolio.TotalPortfolioValue;
                    }
                }

                //Update algorithm state after capturing performance from previous day

                //Set the algorithm and real time handler's time
                algorithm.SetDateTime(time);
                realtime.SetTime(algorithm.Time);

                //On each time step push the real time prices to the cashbook so we can have updated conversion rates
                algorithm.Portfolio.CashBook.Update(newData);

                //Update the securities properties: first before calling user code to avoid issues with data
                algorithm.Securities.Update(time, newData);

                // process fill models on the updated data before entering algorithm, applies to all non-market orders
                transactions.ProcessSynchronousEvents();

                if (delistingTickets.Count != 0)
                {
                    for (int i = 0; i < delistingTickets.Count; i++)
                    {
                        var ticket = delistingTickets[i];
                        if (ticket.Status == OrderStatus.Filled)
                        {
                            algorithm.Securities.Remove(ticket.Symbol);
                            delistingTickets.RemoveAt(i--);
                            Log.Trace("AlgorithmManager.Run(): Security removed: " + ticket.Symbol);
                        }
                    }
                }

                //Check if the user's signalled Quit: loop over data until day changes.
                if (algorithm.GetQuit())
                {
                    _algorithmState = AlgorithmStatus.Quit;
                    Log.Trace("AlgorithmManager.Run(): Algorithm quit requested.");
                    break;
                }
                if (algorithm.RunTimeError != null)
                {
                    _algorithmState = AlgorithmStatus.RuntimeError;
                    Log.Trace(string.Format("AlgorithmManager.Run(): Algorithm encountered a runtime error at {0}. Error: {1}", timeSlice.Time, algorithm.RunTimeError));
                    break;
                }

                // perform margin calls, in live mode we can also use realtime to emit these
                if (time >= nextMarginCallTime || (_liveMode && nextMarginCallTime > DateTime.Now))
                {
                    // determine if there are possible margin call orders to be executed
                    bool issueMarginCallWarning;
                    var  marginCallOrders = algorithm.Portfolio.ScanForMarginCall(out issueMarginCallWarning);
                    if (marginCallOrders.Count != 0)
                    {
                        try
                        {
                            // tell the algorithm we're about to issue the margin call
                            algorithm.OnMarginCall(marginCallOrders);
                        }
                        catch (Exception err)
                        {
                            algorithm.RunTimeError = err;
                            _algorithmState        = AlgorithmStatus.RuntimeError;
                            Log.Error("AlgorithmManager.Run(): RuntimeError: OnMarginCall: " + err.Message + " STACK >>> " + err.StackTrace);
                            return;
                        }

                        // execute the margin call orders
                        var executedTickets = algorithm.Portfolio.MarginCallModel.ExecuteMarginCall(marginCallOrders);
                        foreach (var ticket in executedTickets)
                        {
                            algorithm.Error(string.Format("{0} - Executed MarginCallOrder: {1} - Quantity: {2} @ {3}", algorithm.Time, ticket.Symbol, ticket.Quantity, ticket.OrderEvents.Last().FillPrice));
                        }
                    }
                    // we didn't perform a margin call, but got the warning flag back, so issue the warning to the algorithm
                    else if (issueMarginCallWarning)
                    {
                        try
                        {
                            algorithm.OnMarginCallWarning();
                        }
                        catch (Exception err)
                        {
                            algorithm.RunTimeError = err;
                            _algorithmState        = AlgorithmStatus.RuntimeError;
                            Log.Error("AlgorithmManager.Run(): RuntimeError: OnMarginCallWarning: " + err.Message + " STACK >>> " + err.StackTrace);
                        }
                    }

                    nextMarginCallTime = time + marginCallFrequency;
                }

                //Trigger the data events: Invoke the types we have data for:
                var newBars       = new TradeBars(algorithm.Time);
                var newTicks      = new Ticks(algorithm.Time);
                var newDividends  = new Dividends(algorithm.Time);
                var newSplits     = new Splits(algorithm.Time);
                var newDelistings = new Delistings(algorithm.Time);

                //Invoke all non-tradebars, non-ticks methods and build up the TradeBars and Ticks dictionaries
                // --> i == Subscription Configuration Index, so we don't need to compare types.
                foreach (var i in newData.Keys)
                {
                    //Data point and config of this point:
                    var dataPoints = newData[i];
                    var config     = feed.Subscriptions[i];

                    //Keep track of how many data points we've processed
                    _dataPointCount += dataPoints.Count;

                    //We don't want to pump data that we added just for currency conversions
                    if (config.IsInternalFeed)
                    {
                        continue;
                    }

                    //Create TradeBars Unified Data --> OR --> invoke generic data event. One loop.
                    //  Aggregate Dividends and Splits -- invoke portfolio application methods
                    foreach (var dataPoint in dataPoints)
                    {
                        var dividend = dataPoint as Dividend;
                        if (dividend != null)
                        {
                            Log.Trace("AlgorithmManager.Run(): Applying Dividend for " + dividend.Symbol);
                            // if this is a dividend apply to portfolio
                            algorithm.Portfolio.ApplyDividend(dividend);
                            if (hasOnDataDividends)
                            {
                                // and add to our data dictionary to pump into OnData(Dividends data)
                                newDividends.Add(dividend);
                            }
                            continue;
                        }

                        var split = dataPoint as Split;
                        if (split != null)
                        {
                            Log.Trace("AlgorithmManager.Run(): Applying Split for " + split.Symbol);
                            // if this is a split apply to portfolio
                            algorithm.Portfolio.ApplySplit(split);
                            if (hasOnDataSplits)
                            {
                                // and add to our data dictionary to pump into OnData(Splits data)
                                newSplits.Add(split);
                            }
                            continue;
                        }

                        var delisting = dataPoint as Delisting;
                        if (delisting != null)
                        {
                            if (hasOnDataDelistings)
                            {
                                // add to out data dictonary to pump into OnData(Delistings data)
                                newDelistings.Add(delisting);
                            }
                        }

                        //Update registered consolidators for this symbol index
                        try
                        {
                            for (var j = 0; j < config.Consolidators.Count; j++)
                            {
                                config.Consolidators[j].Update(dataPoint);
                            }
                        }
                        catch (Exception err)
                        {
                            algorithm.RunTimeError = err;
                            _algorithmState        = AlgorithmStatus.RuntimeError;
                            Log.Error("AlgorithmManager.Run(): RuntimeError: Consolidators update: " + err.Message);
                            return;
                        }

                        // TRADEBAR -- add to our dictionary
                        if (dataPoint.DataType == MarketDataType.TradeBar)
                        {
                            var bar = dataPoint as TradeBar;
                            if (bar != null)
                            {
                                newBars[bar.Symbol] = bar;
                                continue;
                            }
                        }

                        // TICK -- add to our dictionary
                        if (dataPoint.DataType == MarketDataType.Tick)
                        {
                            var tick = dataPoint as Tick;
                            if (tick != null)
                            {
                                List <Tick> ticks;
                                if (!newTicks.TryGetValue(tick.Symbol, out ticks))
                                {
                                    ticks = new List <Tick>(3);
                                    newTicks.Add(tick.Symbol, ticks);
                                }
                                ticks.Add(tick);
                                continue;
                            }
                        }

                        // if it was nothing else then it must be custom data

                        // CUSTOM DATA -- invoke on data method
                        //Send data into the generic algorithm event handlers
                        try
                        {
                            MethodInvoker methodInvoker;
                            if (methodInvokers.TryGetValue(config.Type, out methodInvoker))
                            {
                                methodInvoker(algorithm, dataPoint);
                            }
                        }
                        catch (Exception err)
                        {
                            algorithm.RunTimeError = err;
                            _algorithmState        = AlgorithmStatus.RuntimeError;
                            Log.Error("AlgorithmManager.Run(): RuntimeError: Custom Data: " + err.Message + " STACK >>> " + err.StackTrace);
                            return;
                        }
                    }
                }

                try
                {
                    // fire off the dividend and split events before pricing events
                    if (hasOnDataDividends && newDividends.Count != 0)
                    {
                        methodInvokers[typeof(Dividends)](algorithm, newDividends);
                    }
                    if (hasOnDataSplits && newSplits.Count != 0)
                    {
                        methodInvokers[typeof(Splits)](algorithm, newSplits);
                    }
                    if (hasOnDataDelistings && newDelistings.Count != 0)
                    {
                        methodInvokers[typeof(Delistings)](algorithm, newDelistings);
                    }
                }
                catch (Exception err)
                {
                    algorithm.RunTimeError = err;
                    _algorithmState        = AlgorithmStatus.RuntimeError;
                    Log.Error("AlgorithmManager.Run(): RuntimeError: Dividends/Splits/Delistings: " + err.Message + " STACK >>> " + err.StackTrace);
                    return;
                }

                // run the delisting logic after firing delisting events
                HandleDelistedSymbols(algorithm, newDelistings, delistingTickets);

                //After we've fired all other events in this second, fire the pricing events:
                try
                {
                    if (hasOnDataTradeBars && newBars.Count > 0)
                    {
                        methodInvokers[typeof(TradeBars)](algorithm, newBars);
                    }
                    if (hasOnDataTicks && newTicks.Count > 0)
                    {
                        methodInvokers[typeof(Ticks)](algorithm, newTicks);
                    }
                }
                catch (Exception err)
                {
                    algorithm.RunTimeError = err;
                    _algorithmState        = AlgorithmStatus.RuntimeError;
                    Log.Error("AlgorithmManager.Run(): RuntimeError: New Style Mode: " + err.Message + " STACK >>> " + err.StackTrace);
                    return;
                }

                // EVENT HANDLER v3.0 -- all data in a single event
                var slice = new Slice(algorithm.Time, newData.Values.SelectMany(x => x),
                                      newBars.Count == 0 ? null : newBars,
                                      newTicks.Count == 0 ? null : newTicks,
                                      newSplits.Count == 0 ? null : newSplits,
                                      newDividends.Count == 0 ? null : newDividends,
                                      newDelistings.Count == 0 ? null : newDelistings
                                      );

                try
                {
                    algorithm.OnData(slice);
                }
                catch (Exception err)
                {
                    algorithm.RunTimeError = err;
                    _algorithmState        = AlgorithmStatus.RuntimeError;
                    Log.Error("AlgorithmManager.Run(): RuntimeError: Slice: " + err.Message + " STACK >>> " + err.StackTrace);
                    return;
                }

                //If its the historical/paper trading models, wait until market orders have been "filled"
                // Manually trigger the event handler to prevent thread switch.
                transactions.ProcessSynchronousEvents();

                //Save the previous time for the sample calculations
                _previousTime = time;

                // Process any required events of the results handler such as sampling assets, equity, or stock prices.
                results.ProcessSynchronousEvents();
            } // End of ForEach feed.Bridge.GetConsumingEnumerable

            // stop timing the loops
            _currentTimeStepTime = DateTime.MinValue;

            //Stream over:: Send the final packet and fire final events:
            Log.Trace("AlgorithmManager.Run(): Firing On End Of Algorithm...");
            try
            {
                algorithm.OnEndOfAlgorithm();
            }
            catch (Exception err)
            {
                _algorithmState        = AlgorithmStatus.RuntimeError;
                algorithm.RunTimeError = new Exception("Error running OnEndOfAlgorithm(): " + err.Message, err.InnerException);
                Log.Error("AlgorithmManager.OnEndOfAlgorithm(): " + err.Message + " STACK >>> " + err.StackTrace);
                return;
            }

            // Process any required events of the results handler such as sampling assets, equity, or stock prices.
            results.ProcessSynchronousEvents(forceProcess: true);

            //Liquidate Holdings for Calculations:
            if (_algorithmState == AlgorithmStatus.Liquidated && _liveMode)
            {
                Log.Trace("AlgorithmManager.Run(): Liquidating algorithm holdings...");
                algorithm.Liquidate();
                results.LogMessage("Algorithm Liquidated");
                results.SendStatusUpdate(job.AlgorithmId, AlgorithmStatus.Liquidated);
            }

            //Manually stopped the algorithm
            if (_algorithmState == AlgorithmStatus.Stopped)
            {
                Log.Trace("AlgorithmManager.Run(): Stopping algorithm...");
                results.LogMessage("Algorithm Stopped");
                results.SendStatusUpdate(job.AlgorithmId, AlgorithmStatus.Stopped);
            }

            //Backtest deleted.
            if (_algorithmState == AlgorithmStatus.Deleted)
            {
                Log.Trace("AlgorithmManager.Run(): Deleting algorithm...");
                results.DebugMessage("Algorithm Id:(" + job.AlgorithmId + ") Deleted by request.");
                results.SendStatusUpdate(job.AlgorithmId, AlgorithmStatus.Deleted);
            }

            //Algorithm finished, send regardless of commands:
            results.SendStatusUpdate(job.AlgorithmId, AlgorithmStatus.Completed);

            //Take final samples:
            results.SampleRange(algorithm.GetChartUpdates());
            results.SampleEquity(_previousTime, Math.Round(algorithm.Portfolio.TotalPortfolioValue, 4));
            results.SamplePerformance(_previousTime, Math.Round((algorithm.Portfolio.TotalPortfolioValue - startingPortfolioValue) * 100 / startingPortfolioValue, 10));
        } // End of Run();
Beispiel #25
0
        /// <summary>
        /// Creates a new <see cref="TimeSlice"/> for the specified time using the specified data
        /// </summary>
        /// <param name="utcDateTime">The UTC frontier date time</param>
        /// <param name="algorithmTimeZone">The algorithm's time zone, required for computing algorithm and slice time</param>
        /// <param name="cashBook">The algorithm's cash book, required for generating cash update pairs</param>
        /// <param name="data">The data in this <see cref="TimeSlice"/></param>
        /// <param name="changes">The new changes that are seen in this time slice as a result of universe selection</param>
        /// <returns>A new <see cref="TimeSlice"/> containing the specified data</returns>
        public static TimeSlice Create(DateTime utcDateTime, DateTimeZone algorithmTimeZone, CashBook cashBook, List <DataFeedPacket> data, SecurityChanges changes)
        {
            int count               = 0;
            var security            = new List <KeyValuePair <Security, BaseData> >();
            var custom              = new List <KeyValuePair <Security, IEnumerable <BaseData> > >();
            var consolidator        = new List <KeyValuePair <SubscriptionDataConfig, List <BaseData> > >();
            var allDataForAlgorithm = new List <BaseData>(data.Count);
            var cash = new List <KeyValuePair <Cash, BaseData> >(cashBook.Count);

            var cashSecurities = new HashSet <Symbol>();

            foreach (var cashItem in cashBook.Values)
            {
                cashSecurities.Add(cashItem.SecuritySymbol);
            }

            Split              split;
            Dividend           dividend;
            Delisting          delisting;
            SymbolChangedEvent symbolChange;

            var algorithmTime = utcDateTime.ConvertFromUtc(algorithmTimeZone);
            var tradeBars     = new TradeBars(algorithmTime);
            var ticks         = new Ticks(algorithmTime);
            var splits        = new Splits(algorithmTime);
            var dividends     = new Dividends(algorithmTime);
            var delistings    = new Delistings(algorithmTime);
            var symbolChanges = new SymbolChangedEvents(algorithmTime);

            foreach (var packet in data)
            {
                var list   = packet.Data;
                var symbol = packet.Security.Symbol;

                // keep count of all data points
                if (list.Count == 1 && list[0] is BaseDataCollection)
                {
                    count += ((BaseDataCollection)list[0]).Data.Count;
                }
                else
                {
                    count += list.Count;
                }

                BaseData update             = null;
                var      consolidatorUpdate = new List <BaseData>(list.Count);
                for (int i = 0; i < list.Count; i++)
                {
                    var baseData = list[i];
                    if (!packet.Security.SubscriptionDataConfig.IsInternalFeed)
                    {
                        // this is all the data that goes into the algorithm
                        allDataForAlgorithm.Add(baseData);
                        if (packet.Security.SubscriptionDataConfig.IsCustomData)
                        {
                            // this is all the custom data
                            custom.Add(new KeyValuePair <Security, IEnumerable <BaseData> >(packet.Security, list));
                        }
                    }
                    // don't add internal feed data to ticks/bars objects
                    if (baseData.DataType != MarketDataType.Auxiliary)
                    {
                        if (!packet.Security.SubscriptionDataConfig.IsInternalFeed)
                        {
                            // populate ticks and tradebars dictionaries with no aux data
                            switch (baseData.DataType)
                            {
                            case MarketDataType.Tick:
                                List <Tick> ticksList;
                                if (!ticks.TryGetValue(symbol, out ticksList))
                                {
                                    ticksList = new List <Tick> {
                                        (Tick)baseData
                                    };
                                    ticks[symbol] = ticksList;
                                }
                                ticksList.Add((Tick)baseData);
                                break;

                            case MarketDataType.TradeBar:
                                tradeBars[symbol] = (TradeBar)baseData;
                                break;
                            }

                            // this is data used to update consolidators
                            consolidatorUpdate.Add(baseData);
                        }

                        // this is the data used set market prices
                        update = baseData;
                    }
                    // include checks for various aux types so we don't have to construct the dictionaries in Slice
                    else if ((delisting = baseData as Delisting) != null)
                    {
                        delistings[symbol] = delisting;
                    }
                    else if ((dividend = baseData as Dividend) != null)
                    {
                        dividends[symbol] = dividend;
                    }
                    else if ((split = baseData as Split) != null)
                    {
                        splits[symbol] = split;
                    }
                    else if ((symbolChange = baseData as SymbolChangedEvent) != null)
                    {
                        // symbol changes is keyed by the requested symbol
                        symbolChanges[packet.Security.SubscriptionDataConfig.Symbol] = symbolChange;
                    }
                }

                // check for 'cash securities' if we found valid update data for this symbol
                // and we need this data to update cash conversion rates, long term we should
                // have Cash hold onto it's security, then he can update himself, or rather, just
                // patch through calls to conversion rate to compue it on the fly using Security.Price
                if (update != null && cashSecurities.Contains(packet.Security.Symbol))
                {
                    foreach (var cashKvp in cashBook)
                    {
                        if (cashKvp.Value.SecuritySymbol == packet.Security.Symbol)
                        {
                            cash.Add(new KeyValuePair <Cash, BaseData>(cashKvp.Value, update));
                        }
                    }
                }

                security.Add(new KeyValuePair <Security, BaseData>(packet.Security, update));
                consolidator.Add(new KeyValuePair <SubscriptionDataConfig, List <BaseData> >(packet.Security.SubscriptionDataConfig, consolidatorUpdate));
            }

            var slice = new Slice(algorithmTime, allDataForAlgorithm, tradeBars, ticks, splits, dividends, delistings, symbolChanges, allDataForAlgorithm.Count > 0);

            return(new TimeSlice(utcDateTime, count, slice, data, cash, security, consolidator, custom, changes));
        }
Beispiel #26
0
        /// <summary>
        /// Creates a new <see cref="TimeSlice"/> for the specified time using the specified data
        /// </summary>
        /// <param name="utcDateTime">The UTC frontier date time</param>
        /// <param name="algorithmTimeZone">The algorithm's time zone, required for computing algorithm and slice time</param>
        /// <param name="cashBook">The algorithm's cash book, required for generating cash update pairs</param>
        /// <param name="data">The data in this <see cref="TimeSlice"/></param>
        /// <param name="changes">The new changes that are seen in this time slice as a result of universe selection</param>
        /// <returns>A new <see cref="TimeSlice"/> containing the specified data</returns>
        public static TimeSlice Create(DateTime utcDateTime, DateTimeZone algorithmTimeZone, CashBook cashBook, List<DataFeedPacket> data, SecurityChanges changes)
        {
            int count = 0;
            var security = new List<UpdateData<Security>>();
            var custom = new List<UpdateData<Security>>();
            var consolidator = new List<UpdateData<SubscriptionDataConfig>>();
            var allDataForAlgorithm = new List<BaseData>(data.Count);
            var cash = new List<UpdateData<Cash>>(cashBook.Count);

            var cashSecurities = new HashSet<Symbol>();
            foreach (var cashItem in cashBook.Values)
            {
                cashSecurities.Add(cashItem.SecuritySymbol);
            }

            Split split;
            Dividend dividend;
            Delisting delisting;
            SymbolChangedEvent symbolChange;

            // we need to be able to reference the slice being created in order to define the
            // evaluation of option price models, so we define a 'future' that can be referenced
            // in the option price model evaluation delegates for each contract
            Slice slice = null;
            var sliceFuture = new Lazy<Slice>(() => slice);

            var algorithmTime = utcDateTime.ConvertFromUtc(algorithmTimeZone);
            var tradeBars = new TradeBars(algorithmTime);
            var quoteBars = new QuoteBars(algorithmTime);
            var ticks = new Ticks(algorithmTime);
            var splits = new Splits(algorithmTime);
            var dividends = new Dividends(algorithmTime);
            var delistings = new Delistings(algorithmTime);
            var optionChains = new OptionChains(algorithmTime);
            var symbolChanges = new SymbolChangedEvents(algorithmTime);

            foreach (var packet in data)
            {
                var list = packet.Data;
                var symbol = packet.Security.Symbol;

                if (list.Count == 0) continue;
                
                // keep count of all data points
                if (list.Count == 1 && list[0] is BaseDataCollection)
                {
                    var baseDataCollectionCount = ((BaseDataCollection)list[0]).Data.Count;
                    if (baseDataCollectionCount == 0)
                    {
                        continue;
                    }
                    count += baseDataCollectionCount;
                }
                else
                {
                    count += list.Count;
                }

                if (!packet.Configuration.IsInternalFeed && packet.Configuration.IsCustomData)
                {
                    // This is all the custom data
                    custom.Add(new UpdateData<Security>(packet.Security, packet.Configuration.Type, list));
                }

                var securityUpdate = new List<BaseData>(list.Count);
                var consolidatorUpdate = new List<BaseData>(list.Count);
                for (int i = 0; i < list.Count; i++)
                {
                    var baseData = list[i];
                    if (!packet.Configuration.IsInternalFeed)
                    {
                        // this is all the data that goes into the algorithm
                        allDataForAlgorithm.Add(baseData);
                    }
                    // don't add internal feed data to ticks/bars objects
                    if (baseData.DataType != MarketDataType.Auxiliary)
                    {
                        if (!packet.Configuration.IsInternalFeed)
                        {
                            PopulateDataDictionaries(baseData, ticks, tradeBars, quoteBars, optionChains);

                            // special handling of options data to build the option chain
                            if (packet.Security.Type == SecurityType.Option)
                            {
                                if (baseData.DataType == MarketDataType.OptionChain)
                                {
                                    optionChains[baseData.Symbol] = (OptionChain) baseData;
                                }
                                else if (!HandleOptionData(algorithmTime, baseData, optionChains, packet.Security, sliceFuture))
                                {
                                    continue;
                                }
                            }

                            // this is data used to update consolidators
                            consolidatorUpdate.Add(baseData);
                        }

                        // this is the data used set market prices
                        securityUpdate.Add(baseData);
                    }
                    // include checks for various aux types so we don't have to construct the dictionaries in Slice
                    else if ((delisting = baseData as Delisting) != null)
                    {
                        delistings[symbol] = delisting;
                    }
                    else if ((dividend = baseData as Dividend) != null)
                    {
                        dividends[symbol] = dividend;
                    }
                    else if ((split = baseData as Split) != null)
                    {
                        splits[symbol] = split;
                    }
                    else if ((symbolChange = baseData as SymbolChangedEvent) != null)
                    {
                        // symbol changes is keyed by the requested symbol
                        symbolChanges[packet.Configuration.Symbol] = symbolChange;
                    }
                }

                if (securityUpdate.Count > 0)
                {
                    // check for 'cash securities' if we found valid update data for this symbol
                    // and we need this data to update cash conversion rates, long term we should
                    // have Cash hold onto it's security, then he can update himself, or rather, just
                    // patch through calls to conversion rate to compue it on the fly using Security.Price
                    if (cashSecurities.Contains(packet.Security.Symbol))
                    {
                        foreach (var cashKvp in cashBook)
                        {
                            if (cashKvp.Value.SecuritySymbol == packet.Security.Symbol)
                            {
                                var cashUpdates = new List<BaseData> {securityUpdate[securityUpdate.Count - 1]};
                                cash.Add(new UpdateData<Cash>(cashKvp.Value, packet.Configuration.Type, cashUpdates));
                            }
                        }
                    }

                    security.Add(new UpdateData<Security>(packet.Security, packet.Configuration.Type, securityUpdate));
                }
                if (consolidatorUpdate.Count > 0)
                {
                    consolidator.Add(new UpdateData<SubscriptionDataConfig>(packet.Configuration, packet.Configuration.Type, consolidatorUpdate));
                }
            }

            slice = new Slice(algorithmTime, allDataForAlgorithm, tradeBars, quoteBars, ticks, optionChains, splits, dividends, delistings, symbolChanges, allDataForAlgorithm.Count > 0);

            return new TimeSlice(utcDateTime, count, slice, data, cash, security, consolidator, custom, changes);
        }