Example #1
0
 // this event fires whenever we have changes to our universe
 public override void OnSecuritiesChanged(SecurityChanges changes)
 {
     _changes = changes;
     Log($"OnSecuritiesChanged({UtcTime:o}):: {changes}");
 }
        // this event fires whenever we have changes to our universe
        public override void OnSecuritiesChanged(SecurityChanges changes)
        {
            _changes = changes;

            if (changes.AddedSecurities.Count > 0)
            {
                Debug("Securities added: " + string.Join(",", changes.AddedSecurities.Select(x => x.Symbol.Value)));
            }
            if (changes.RemovedSecurities.Count > 0)
            {
                Debug("Securities removed: " + string.Join(",", changes.RemovedSecurities.Select(x => x.Symbol.Value)));
            }
        }
        /// <summary>
        /// Primary entry point.
        /// </summary>
        public void Run()
        {
            IsActive = true;

            // we want to emit to the bridge minimally once a second since the data feed is
            // the heartbeat of the application, so this value will contain a second after
            // the last emit time, and if we pass this time, we'll emit even with no data
            var nextEmit = DateTime.MinValue;

            try
            {
                while (!_cancellationTokenSource.IsCancellationRequested)
                {
                    // perform sleeps to wake up on the second?
                    _frontierUtc = _timeProvider.GetUtcNow();
                    _frontierTimeProvider.SetCurrentTime(_frontierUtc);

                    var data = new List <DataFeedPacket>();
                    foreach (var subscription in Subscriptions)
                    {
                        var config = subscription.Configuration;
                        var packet = new DataFeedPacket(subscription.Security, config);

                        // dequeue data that is time stamped at or before this frontier
                        while (subscription.MoveNext() && subscription.Current != null)
                        {
                            var clone = subscription.Current.Clone(subscription.Current.IsFillForward);
                            clone.Time = clone.Time.RoundDownInTimeZone(config.Increment, config.ExchangeTimeZone, config.DataTimeZone);
                            packet.Add(clone);
                        }

                        // if we have data, add it to be added to the bridge
                        if (packet.Count > 0)
                        {
                            data.Add(packet);
                        }

                        // we have new universe data to select based on
                        if (subscription.IsUniverseSelectionSubscription && packet.Count > 0)
                        {
                            var universe = subscription.Universe;

                            // always wait for other thread to sync up
                            if (!_bridge.WaitHandle.WaitOne(Timeout.Infinite, _cancellationTokenSource.Token))
                            {
                                break;
                            }

                            // assume that if the first item is a base data collection then the enumerator handled the aggregation,
                            // otherwise, load all the the data into a new collection instance
                            var collection = packet.Data[0] as BaseDataCollection ?? new BaseDataCollection(_frontierUtc, config.Symbol, packet.Data);

                            _changes += _universeSelection.ApplyUniverseSelection(universe, _frontierUtc, collection);
                        }
                    }

                    // check for cancellation
                    if (_cancellationTokenSource.IsCancellationRequested)
                    {
                        return;
                    }

                    // emit on data or if we've elapsed a full second since last emit
                    if (data.Count != 0 || _frontierUtc >= nextEmit)
                    {
                        _bridge.Add(TimeSlice.Create(_frontierUtc, _algorithm.TimeZone, _algorithm.Portfolio.CashBook, data, _changes), _cancellationTokenSource.Token);

                        // force emitting every second
                        nextEmit = _frontierUtc.RoundDown(Time.OneSecond).Add(Time.OneSecond);
                    }

                    // reset our security changes
                    _changes = SecurityChanges.None;

                    // take a short nap
                    Thread.Sleep(1);
                }
            }
            catch (Exception err)
            {
                Log.Error(err);
                _algorithm.RunTimeError = err;
                _algorithm.Status       = AlgorithmStatus.RuntimeError;

                // send last empty packet list before terminating,
                // so the algorithm manager has a chance to detect the runtime error
                // and exit showing the correct error instead of a timeout
                nextEmit = _frontierUtc.RoundDown(Time.OneSecond).Add(Time.OneSecond);

                if (!_cancellationTokenSource.IsCancellationRequested)
                {
                    _bridge.Add(
                        TimeSlice.Create(nextEmit, _algorithm.TimeZone, _algorithm.Portfolio.CashBook, new List <DataFeedPacket>(), SecurityChanges.None),
                        _cancellationTokenSource.Token);
                }
            }

            Log.Trace("LiveTradingDataFeed.Run(): Exited thread.");
            IsActive = false;
        }
 // this event fires whenever we have changes to our universe
 public override void OnSecuritiesChanged(SecurityChanges changes)
 {
     _changes = changes;
 }
Example #5
0
 public void OnSecuritiesChanged(SecurityChanges changes)
 {
 }
        /// <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;
                            }

                            // special handling of options data to build the option chain
                            if (symbol.SecurityType == SecurityType.Option)
                            {
                                if (optionChains == null)
                                {
                                    optionChains = new OptionChains(algorithmTime);
                                }

                                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 (symbol.SecurityType == SecurityType.Future)
                            {
                                if (futuresChains == null)
                                {
                                    futuresChains = new FuturesChains(algorithmTime);
                                }
                                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
                            // do not add it if it is a Suspicious tick
                            if (tick == null || !tick.Suspicious)
                            {
                                consolidatorUpdate.Add(baseData);
                            }
                        }

                        // 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 &&
                            symbol.SecurityType == SecurityType.Equity)
                        {
                            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));
        }
Example #7
0
 /// <summary>
 /// Event fired each time the we add/remove securities from the data feed
 /// </summary>
 /// <param name="changes">Object containing AddedSecurities and RemovedSecurities</param>
 public override void OnSecuritiesChanged(SecurityChanges changes)
 {
     _changes = changes;
     Log(Time + " " + changes);
 }
Example #8
0
 /// <summary>
 /// Adds and removes the security changes to/from the collection
 /// </summary>
 /// <param name="securities">The securities collection to be updated with the changes</param>
 /// <param name="changes">The changes to be applied to the securities collection</param>
 public static void UpdateCollection(ICollection <Security> securities, SecurityChanges changes)
 {
     Update(changes, securities.Add, removed => securities.Remove(removed));
 }
Example #9
0
 /// <summary>
 /// Adds and removes the security changes to/from the collection
 /// </summary>
 /// <param name="securities">The securities collection to be updated with the changes</param>
 /// <param name="changes">The changes to be applied to the securities collection</param>
 /// <param name="valueFactory">Delegate used to create instances of <typeparamref name="TValue"/> from a <see cref="Security"/> object</param>
 public static void UpdateCollection <TValue>(ICollection <TValue> securities, SecurityChanges changes, Func <Security, TValue> valueFactory)
 {
     Update(changes, added => securities.Add(valueFactory(added)), removed => securities.Remove(valueFactory(removed)));
 }
Example #10
0
 /// <summary>
 /// Initializes a new <see cref="TimeSlice"/> containing the specified data
 /// </summary>
 public TimeSlice(DateTime time, int dataPointCount, Slice slice, List <KeyValuePair <Security, List <BaseData> > > data, List <KeyValuePair <Cash, BaseData> > cashBookUpdateData, List <KeyValuePair <Security, BaseData> > securitiesUpdateData, List <KeyValuePair <SubscriptionDataConfig, List <BaseData> > > consolidatorUpdateData, List <KeyValuePair <Security, List <BaseData> > > customData, SecurityChanges securityChanges)
 {
     Time                   = time;
     Data                   = data;
     Slice                  = slice;
     CustomData             = customData;
     DataPointCount         = dataPointCount;
     CashBookUpdateData     = cashBookUpdateData;
     SecuritiesUpdateData   = securitiesUpdateData;
     ConsolidatorUpdateData = consolidatorUpdateData;
     SecurityChanges        = securityChanges;
 }
Example #11
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));
        }
Example #12
0
        /// <summary>
        /// Ensures that we have a data feed to convert this currency into the base currency.
        /// This will add a <see cref="SubscriptionDataConfig"/> and create a <see cref="Security"/> at the lowest resolution if one is not found.
        /// </summary>
        /// <param name="securities">The security manager</param>
        /// <param name="subscriptions">The subscription manager used for searching and adding subscriptions</param>
        /// <param name="marketMap">The market map that decides which market the new security should be in</param>
        /// <param name="changes">Will be used to consume <see cref="SecurityChanges.AddedSecurities"/></param>
        /// <param name="securityService">Will be used to create required new <see cref="Security"/></param>
        /// <param name="accountCurrency">The account currency</param>
        /// <param name="defaultResolution">The default resolution to use for the internal subscriptions</param>
        /// <returns>Returns the added <see cref="SubscriptionDataConfig"/>, otherwise null</returns>
        public SubscriptionDataConfig EnsureCurrencyDataFeed(SecurityManager securities,
                                                             SubscriptionManager subscriptions,
                                                             IReadOnlyDictionary <SecurityType, string> marketMap,
                                                             SecurityChanges changes,
                                                             ISecurityService securityService,
                                                             string accountCurrency,
                                                             Resolution defaultResolution = Resolution.Minute
                                                             )
        {
            // this gets called every time we add securities using universe selection,
            // so must of the time we've already resolved the value and don't need to again
            if (ConversionRateSecurity != null)
            {
                return(null);
            }

            if (Symbol == accountCurrency)
            {
                ConversionRateSecurity = null;
                _isBaseCurrency        = true;
                ConversionRate         = 1.0m;
                return(null);
            }

            // we require a security that converts this into the base currency
            string normal             = Symbol + accountCurrency;
            string invert             = accountCurrency + Symbol;
            var    securitiesToSearch = securities.Select(kvp => kvp.Value)
                                        .Concat(changes.AddedSecurities)
                                        .Where(s => s.Type == SecurityType.Forex || s.Type == SecurityType.Cfd || s.Type == SecurityType.Crypto);

            foreach (var security in securitiesToSearch)
            {
                if (security.Symbol.Value == normal)
                {
                    ConversionRateSecurity = security;
                    return(null);
                }
                if (security.Symbol.Value == invert)
                {
                    ConversionRateSecurity = security;
                    _invertRealTimePrice   = true;
                    return(null);
                }
            }

            // if we've made it here we didn't find a security, so we'll need to add one

            // Create a SecurityType to Market mapping with the markets from SecurityManager members
            var markets = securities.Select(x => x.Key)
                          .GroupBy(x => x.SecurityType)
                          .ToDictionary(x => x.Key, y => y.Select(symbol => symbol.ID.Market).ToHashSet());

            if (markets.ContainsKey(SecurityType.Cfd) && !markets.ContainsKey(SecurityType.Forex))
            {
                markets.Add(SecurityType.Forex, markets[SecurityType.Cfd]);
            }
            if (markets.ContainsKey(SecurityType.Forex) && !markets.ContainsKey(SecurityType.Cfd))
            {
                markets.Add(SecurityType.Cfd, markets[SecurityType.Forex]);
            }

            var forexEntries  = GetAvailableSymbolPropertiesDatabaseEntries(SecurityType.Forex, marketMap, markets);
            var cfdEntries    = GetAvailableSymbolPropertiesDatabaseEntries(SecurityType.Cfd, marketMap, markets);
            var cryptoEntries = GetAvailableSymbolPropertiesDatabaseEntries(SecurityType.Crypto, marketMap, markets);

            var potentialEntries = forexEntries
                                   .Concat(cfdEntries)
                                   .Concat(cryptoEntries)
                                   .ToList();

            if (!potentialEntries.Any(x =>
                                      Symbol == x.Key.Symbol.Substring(0, x.Key.Symbol.Length - x.Value.QuoteCurrency.Length) ||
                                      Symbol == x.Value.QuoteCurrency))
            {
                // currency not found in any tradeable pair
                Log.Error($"No tradeable pair was found for currency {Symbol}, conversion rate to account currency ({accountCurrency}) will be set to zero.");
                ConversionRateSecurity = null;
                ConversionRate         = 0m;
                return(null);
            }

            var potentials = potentialEntries
                             .Select(x => QuantConnect.Symbol.Create(x.Key.Symbol, x.Key.SecurityType, x.Key.Market));

            var minimumResolution = subscriptions.Subscriptions.Select(x => x.Resolution).DefaultIfEmpty(defaultResolution).Min();

            foreach (var symbol in potentials)
            {
                if (symbol.Value == normal || symbol.Value == invert)
                {
                    _invertRealTimePrice = symbol.Value == invert;
                    var securityType = symbol.ID.SecurityType;

                    // use the first subscription defined in the subscription manager
                    var type       = subscriptions.LookupSubscriptionConfigDataTypes(securityType, minimumResolution, false).First();
                    var objectType = type.Item1;
                    var tickType   = type.Item2;

                    // set this as an internal feed so that the data doesn't get sent into the algorithm's OnData events
                    var config = subscriptions.SubscriptionDataConfigService.Add(symbol,
                                                                                 minimumResolution,
                                                                                 fillForward: true,
                                                                                 extendedMarketHours: false,
                                                                                 isInternalFeed: true,
                                                                                 subscriptionDataTypes: new List <Tuple <Type, TickType> > {
                        new Tuple <Type, TickType>(objectType, tickType)
                    }).First();

                    var security = securityService.CreateSecurity(symbol,
                                                                  config,
                                                                  addToSymbolCache: false);

                    ConversionRateSecurity = security;
                    securities.Add(config.Symbol, security);
                    Log.Trace($"Cash.EnsureCurrencyDataFeed(): Adding {symbol.Value} for cash {Symbol} currency feed");
                    return(config);
                }
            }

            // Special case for crypto markets without direct pairs (They wont be found by the above)
            // This allows us to add cash for "StableCoins" that are 1-1 with our account currency without needing a conversion security.
            // Check out the StableCoinsWithoutPairs static var for those that are missing their 1-1 conversion pairs
            if (Currencies.StableCoinsWithoutPairs.Contains(QuantConnect.Symbol.Create(normal, SecurityType.Crypto, marketMap[SecurityType.Crypto])))
            {
                ConversionRateSecurity = null;
                ConversionRate         = 1.0m;
                return(null);
            }

            // if this still hasn't been set then it's an error condition
            throw new ArgumentException($"In order to maintain cash in {Symbol} you are required to add a " +
                                        $"subscription for Forex pair {Symbol}{accountCurrency} or {accountCurrency}{Symbol}"
                                        );
        }
Example #13
0
 /// <summary>
 /// Checks the current subscriptions and adds necessary currency pair feeds to provide real time conversion data
 /// </summary>
 public void EnsureCurrencyDataFeeds(SecurityChanges securityChanges)
 {
     _currencySubscriptionDataConfigManager.EnsureCurrencySubscriptionDataConfigs(securityChanges);
 }
Example #14
0
 /// <summary>
 /// Securities changed, detects if we've got new additions to the universe
 /// so that we don't try to trade every loop
 /// </summary>
 public void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
 {
     _hasAdded = changes.AddedSecurities.Count != 0;
 }
Example #15
0
        /// <summary>
        /// Main routine for datafeed analysis.
        /// </summary>
        /// <remarks>This is a hot-thread and should be kept extremely lean. Modify with caution.</remarks>
        public void Run()
        {
            var frontier = DateTime.MaxValue;

            try
            {
                // compute initial frontier time
                frontier = GetInitialFrontierTime();

                Log.Trace(string.Format("FileSystemDataFeed.Run(): Begin: {0} UTC", frontier));
                // continue to loop over each subscription, enqueuing data in time order
                while (!_cancellationTokenSource.IsCancellationRequested)
                {
                    // each time step reset our security changes
                    _changes = SecurityChanges.None;
                    var earlyBirdTicks = long.MaxValue;
                    var data           = new List <KeyValuePair <Security, List <BaseData> > >();

                    // we union subscriptions with itself so if subscriptions changes on the first
                    // iteration we will pick up those changes in the union call, this is used in
                    // universe selection. an alternative is to extract this into a method and check
                    // to see if changes != SecurityChanges.None, and re-run all subscriptions again,
                    // This was added as quick fix due to an issue found in universe selection regression alg
                    foreach (var subscription in Subscriptions.Union(Subscriptions))
                    {
                        if (subscription.EndOfStream)
                        {
                            // remove finished subscriptions
                            Subscription sub;
                            _subscriptions.TryRemove(new SymbolSecurityType(subscription), out sub);
                            continue;
                        }

                        var cache = new KeyValuePair <Security, List <BaseData> >(subscription.Security, new List <BaseData>());
                        data.Add(cache);

                        var configuration      = subscription.Configuration;
                        var offsetProvider     = subscription.OffsetProvider;
                        var currentOffsetTicks = offsetProvider.GetOffsetTicks(frontier);
                        while (subscription.Current.EndTime.Ticks - currentOffsetTicks <= frontier.Ticks)
                        {
                            // we want bars rounded using their subscription times, we make a clone
                            // so we don't interfere with the enumerator's internal logic
                            var clone = subscription.Current.Clone(subscription.Current.IsFillForward);
                            clone.Time = clone.Time.ExchangeRoundDown(configuration.Increment, subscription.Security.Exchange.Hours, configuration.ExtendedMarketHours);
                            cache.Value.Add(clone);
                            if (!subscription.MoveNext())
                            {
                                Log.Trace("FileSystemDataFeed.Run(): Finished subscription: " + subscription.Security.Symbol + " at " + frontier + " UTC");
                                break;
                            }
                        }

                        // we have new universe data to select based on
                        if (subscription.IsUniverseSelectionSubscription && cache.Value.Count > 0)
                        {
                            var universe = subscription.Universe;

                            // always wait for other thread
                            if (!Bridge.Wait(Timeout.Infinite, _cancellationTokenSource.Token))
                            {
                                break;
                            }

                            OnUniverseSelection(universe, frontier, configuration, cache.Value);
                        }

                        if (subscription.Current != null)
                        {
                            // take the earliest between the next piece of data or the next tz discontinuity
                            earlyBirdTicks = Math.Min(earlyBirdTicks, Math.Min(subscription.Current.EndTime.Ticks - currentOffsetTicks, offsetProvider.GetNextDiscontinuity()));
                        }
                    }

                    if (earlyBirdTicks == long.MaxValue)
                    {
                        if (_changes == SecurityChanges.None)
                        {
                            // there's no more data to pull off, we're done
                            break;
                        }
                    }

                    // enqueue our next time slice and set the frontier for the next
                    Bridge.Add(TimeSlice.Create(frontier, _algorithm.TimeZone, _algorithm.Portfolio.CashBook, data, _changes), _cancellationTokenSource.Token);

                    // never go backwards in time, so take the max between early birds and the current frontier
                    frontier = new DateTime(Math.Max(earlyBirdTicks, frontier.Ticks), DateTimeKind.Utc);
                }

                if (!_cancellationTokenSource.IsCancellationRequested)
                {
                    Bridge.CompleteAdding();
                }
            }
            catch (Exception err)
            {
                Log.Error("FileSystemDataFeed.Run(): Encountered an error: " + err.Message);
                if (!_cancellationTokenSource.IsCancellationRequested)
                {
                    Bridge.CompleteAdding();
                    _cancellationTokenSource.Cancel();
                }
            }
            finally
            {
                Log.Trace(string.Format("FileSystemDataFeed.Run(): Data Feed Completed at {0} UTC", frontier));

                //Close up all streams:
                foreach (var subscription in Subscriptions)
                {
                    subscription.Dispose();
                }

                Log.Trace("FileSystemDataFeed.Run(): Ending Thread... ");
                IsActive = false;
            }
        }
Example #16
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="synchronizer">Instance which implements <see cref="ISynchronizer"/>. Used to stream the data</param>
        /// <param name="transactions">Transaction manager object</param>
        /// <param name="results">Result handler object</param>
        /// <param name="realtime">Realtime processing object</param>
        /// <param name="leanManager">ILeanManager implementation that is updated periodically with the IAlgorithm instance</param>
        /// <param name="alphas">Alpha handler used to process algorithm generated insights</param>
        /// <param name="token">Cancellation token</param>
        /// <remarks>Modify with caution</remarks>
        public void Run(AlgorithmNodePacket job, IAlgorithm algorithm, ISynchronizer synchronizer, ITransactionHandler transactions, IResultHandler results, IRealTimeHandler realtime, ILeanManager leanManager, IAlphaHandler alphas, CancellationToken token)
        {
            //Initialize:
            DataPoints = 0;
            _algorithm = algorithm;

            var backtestMode            = (job.Type == PacketType.BacktestNode);
            var methodInvokers          = new Dictionary <Type, MethodInvoker>();
            var marginCallFrequency     = TimeSpan.FromMinutes(5);
            var nextMarginCallTime      = DateTime.MinValue;
            var settlementScanFrequency = TimeSpan.FromMinutes(30);
            var nextSettlementScanTime  = DateTime.MinValue;
            var time = algorithm.StartDate.Date;

            var pendingDelistings = new List <Delisting>();
            var splitWarnings     = new List <Split>();

            //Initialize Properties:
            AlgorithmId = job.AlgorithmId;

            //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 hasOnDataQuoteBars    = AddMethodInvoker <QuoteBars>(algorithm, methodInvokers);
            var hasOnDataOptionChains = AddMethodInvoker <OptionChains>(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);
            var hasOnDataSymbolChangedEvents = AddMethodInvoker <SymbolChangedEvents>(algorithm, methodInvokers);

            //Go through the subscription types and create invokers to trigger the event handlers for each custom type:
            foreach (var config in algorithm.SubscriptionManager.Subscriptions)
            {
                //If type is a custom feed, check for a dedicated event handler
                if (config.IsCustomData)
                {
                    //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 (genericMethod != null)
                    {
                        methodInvokers.Add(config.Type, genericMethod.DelegateForCallMethod());
                    }
                }
            }

            // Schedule a daily event for sampling at midnight every night
            algorithm.Schedule.On("Daily Sampling", algorithm.Schedule.DateRules.EveryDay(),
                                  algorithm.Schedule.TimeRules.Midnight, () =>
            {
                results.Sample(algorithm.UtcTime);
            });

            //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} Time: {algorithm.Time} Warmup: {algorithm.IsWarmingUp}");
            foreach (var timeSlice in Stream(algorithm, synchronizer, results, token))
            {
                // reset our timer on each loop
                TimeLimit.StartNewTimeStep();

                //Check this backtest is still running:
                if (_algorithm.Status != AlgorithmStatus.Running && _algorithm.RunTimeError == null)
                {
                    Log.Error($"AlgorithmManager.Run(): Algorithm state changed to {_algorithm.Status} at {timeSlice.Time.ToStringInvariant()}");
                    break;
                }

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

                // Update the ILeanManager
                leanManager.Update();

                time        = timeSlice.Time;
                DataPoints += timeSlice.DataPointCount;

                if (backtestMode && algorithm.Portfolio.TotalPortfolioValue <= 0)
                {
                    var logMessage = "AlgorithmManager.Run(): Portfolio value is less than or equal to zero, stopping algorithm.";
                    Log.Error(logMessage);
                    results.SystemDebugMessage(logMessage);
                    break;
                }

                // If backtesting/warmup, we need to check if there are realtime events in the past
                // which didn't fire because at the scheduled times there was no data (i.e. markets closed)
                // and fire them with the correct date/time.
                realtime.ScanPastEvents(time);

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

                // the time pulse are just to advance algorithm time, lets shortcut the loop here
                if (timeSlice.IsTimePulse)
                {
                    continue;
                }

                // Update the current slice before firing scheduled events or any other task
                algorithm.SetCurrentSlice(timeSlice.Slice);

                if (timeSlice.Slice.SymbolChangedEvents.Count != 0)
                {
                    if (hasOnDataSymbolChangedEvents)
                    {
                        methodInvokers[typeof(SymbolChangedEvents)](algorithm, timeSlice.Slice.SymbolChangedEvents);
                    }
                    foreach (var symbol in timeSlice.Slice.SymbolChangedEvents.Keys)
                    {
                        // cancel all orders for the old symbol
                        foreach (var ticket in transactions.GetOpenOrderTickets(x => x.Symbol == symbol))
                        {
                            ticket.Cancel("Open order cancelled on symbol changed event");
                        }
                    }
                }

                if (timeSlice.SecurityChanges != SecurityChanges.None)
                {
                    foreach (var security in timeSlice.SecurityChanges.AddedSecurities)
                    {
                        security.IsTradable = true;

                        // uses TryAdd, so don't need to worry about duplicates here
                        algorithm.Securities.Add(security);
                    }

                    var activeSecurities = algorithm.UniverseManager.ActiveSecurities;
                    foreach (var security in timeSlice.SecurityChanges.RemovedSecurities)
                    {
                        if (!activeSecurities.ContainsKey(security.Symbol))
                        {
                            security.IsTradable = false;
                        }
                    }

                    leanManager.OnSecuritiesChanged(timeSlice.SecurityChanges);
                    realtime.OnSecuritiesChanged(timeSlice.SecurityChanges);
                    results.OnSecuritiesChanged(timeSlice.SecurityChanges);
                }

                //Update the securities properties: first before calling user code to avoid issues with data
                foreach (var update in timeSlice.SecuritiesUpdateData)
                {
                    var security = update.Target;

                    security.Update(update.Data, update.DataType, update.ContainsFillForwardData);

                    if (!update.IsInternalConfig)
                    {
                        // Send market price updates to the TradeBuilder
                        algorithm.TradeBuilder.SetMarketPrice(security.Symbol, security.Price);
                    }
                }

                //Update the securities properties with any universe data
                if (timeSlice.UniverseData.Count > 0)
                {
                    foreach (var kvp in timeSlice.UniverseData)
                    {
                        foreach (var data in kvp.Value.Data)
                        {
                            Security security;
                            if (algorithm.Securities.TryGetValue(data.Symbol, out security))
                            {
                                security.Cache.StoreData(new[] { data }, data.GetType());
                            }
                        }
                    }
                }

                // poke each cash object to update from the recent security data
                foreach (var cash in algorithm.Portfolio.CashBook.Values.Where(x => x.CurrencyConversion != null))
                {
                    cash.Update();
                }

                // security prices got updated
                algorithm.Portfolio.InvalidateTotalPortfolioValue();

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

                // fire real time events after we've updated based on the new data
                realtime.SetTime(timeSlice.Time);

                // process split warnings for options
                ProcessSplitSymbols(algorithm, splitWarnings, pendingDelistings);

                //Check if the user's signalled Quit: loop over data until day changes.
                if (_algorithm.Status != AlgorithmStatus.Running && _algorithm.RunTimeError == null)
                {
                    Log.Error($"AlgorithmManager.Run(): Algorithm state changed to {_algorithm.Status} at {timeSlice.Time.ToStringInvariant()}");
                    break;
                }
                if (algorithm.RunTimeError != null)
                {
                    Log.Error($"AlgorithmManager.Run(): Stopping, encountered a runtime error at {algorithm.UtcTime} UTC.");
                    return;
                }

                // perform margin calls, in live mode we can also use realtime to emit these
                if (time >= nextMarginCallTime || (_liveMode && nextMarginCallTime > DateTime.UtcNow))
                {
                    // determine if there are possible margin call orders to be executed
                    bool issueMarginCallWarning;
                    var  marginCallOrders = algorithm.Portfolio.MarginCallModel.GetMarginCallOrders(out issueMarginCallWarning);
                    if (marginCallOrders.Count != 0)
                    {
                        var executingMarginCall = false;
                        try
                        {
                            // tell the algorithm we're about to issue the margin call
                            algorithm.OnMarginCall(marginCallOrders);

                            executingMarginCall = true;

                            // execute the margin call orders
                            var executedTickets = algorithm.Portfolio.MarginCallModel.ExecuteMarginCall(marginCallOrders);
                            foreach (var ticket in executedTickets)
                            {
                                algorithm.Error($"{algorithm.Time.ToStringInvariant()} - Executed MarginCallOrder: {ticket.Symbol} - " +
                                                $"Quantity: {ticket.Quantity.ToStringInvariant()} @ {ticket.AverageFillPrice.ToStringInvariant()}"
                                                );
                            }
                        }
                        catch (Exception err)
                        {
                            algorithm.SetRuntimeError(err, executingMarginCall ? "Portfolio.MarginCallModel.ExecuteMarginCall" : "OnMarginCall");
                            return;
                        }
                    }
                    // 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.SetRuntimeError(err, "OnMarginCallWarning");
                            return;
                        }
                    }

                    nextMarginCallTime = time + marginCallFrequency;
                }

                // perform check for settlement of unsettled funds
                if (time >= nextSettlementScanTime || (_liveMode && nextSettlementScanTime > DateTime.UtcNow))
                {
                    algorithm.Portfolio.ScanForCashSettlement(algorithm.UtcTime);

                    nextSettlementScanTime = time + settlementScanFrequency;
                }

                // before we call any events, let the algorithm know about universe changes
                if (timeSlice.SecurityChanges != SecurityChanges.None)
                {
                    try
                    {
                        var algorithmSecurityChanges = new SecurityChanges(timeSlice.SecurityChanges)
                        {
                            // by default for user code we want to filter out custom securities
                            FilterCustomSecurities = true,
                            // by default for user code we want to filter out internal securities
                            FilterInternalSecurities = true
                        };

                        algorithm.OnSecuritiesChanged(algorithmSecurityChanges);
                        algorithm.OnFrameworkSecuritiesChanged(algorithmSecurityChanges);
                    }
                    catch (Exception err)
                    {
                        algorithm.SetRuntimeError(err, "OnSecuritiesChanged");
                        return;
                    }
                }

                // apply dividends
                foreach (var dividend in timeSlice.Slice.Dividends.Values)
                {
                    Log.Debug($"AlgorithmManager.Run(): {algorithm.Time}: Applying Dividend: {dividend}");

                    Security security = null;
                    if (_liveMode && algorithm.Securities.TryGetValue(dividend.Symbol, out security))
                    {
                        Log.Trace($"AlgorithmManager.Run(): {algorithm.Time}: Pre-Dividend: {dividend}. " +
                                  $"Security Holdings: {security.Holdings.Quantity} Account Currency Holdings: " +
                                  $"{algorithm.Portfolio.CashBook[algorithm.AccountCurrency].Amount}");
                    }

                    var mode = algorithm.SubscriptionManager.SubscriptionDataConfigService
                               .GetSubscriptionDataConfigs(dividend.Symbol)
                               .DataNormalizationMode();

                    // apply the dividend event to the portfolio
                    algorithm.Portfolio.ApplyDividend(dividend, _liveMode, mode);

                    if (_liveMode && security != null)
                    {
                        Log.Trace($"AlgorithmManager.Run(): {algorithm.Time}: Post-Dividend: {dividend}. Security " +
                                  $"Holdings: {security.Holdings.Quantity} Account Currency Holdings: " +
                                  $"{algorithm.Portfolio.CashBook[algorithm.AccountCurrency].Amount}");
                    }
                }

                // apply splits
                foreach (var split in timeSlice.Slice.Splits.Values)
                {
                    try
                    {
                        // only process split occurred events (ignore warnings)
                        if (split.Type != SplitType.SplitOccurred)
                        {
                            continue;
                        }

                        Log.Debug($"AlgorithmManager.Run(): {algorithm.Time}: Applying Split for {split.Symbol}");

                        Security security = null;
                        if (_liveMode && algorithm.Securities.TryGetValue(split.Symbol, out security))
                        {
                            Log.Trace($"AlgorithmManager.Run(): {algorithm.Time}: Pre-Split for {split}. Security Price: {security.Price} Holdings: {security.Holdings.Quantity}");
                        }

                        var mode = algorithm.SubscriptionManager.SubscriptionDataConfigService
                                   .GetSubscriptionDataConfigs(split.Symbol)
                                   .DataNormalizationMode();

                        // apply the split event to the portfolio
                        algorithm.Portfolio.ApplySplit(split, _liveMode, mode);

                        if (_liveMode && security != null)
                        {
                            Log.Trace($"AlgorithmManager.Run(): {algorithm.Time}: Post-Split for {split}. Security Price: {security.Price} Holdings: {security.Holdings.Quantity}");
                        }

                        // apply the split to open orders as well in raw mode, all other modes are split adjusted
                        if (_liveMode || mode == DataNormalizationMode.Raw)
                        {
                            // in live mode we always want to have our order match the order at the brokerage, so apply the split to the orders
                            var openOrders = transactions.GetOpenOrderTickets(ticket => ticket.Symbol == split.Symbol);
                            algorithm.BrokerageModel.ApplySplit(openOrders.ToList(), split);
                        }
                    }
                    catch (Exception err)
                    {
                        algorithm.SetRuntimeError(err, "Split event");
                        return;
                    }
                }

                //Update registered consolidators for this symbol index
                try
                {
                    if (timeSlice.ConsolidatorUpdateData.Count > 0)
                    {
                        var timeKeeper = algorithm.TimeKeeper;
                        foreach (var update in timeSlice.ConsolidatorUpdateData)
                        {
                            var localTime     = timeKeeper.GetLocalTimeKeeper(update.Target.ExchangeTimeZone).LocalTime;
                            var consolidators = update.Target.Consolidators;
                            foreach (var consolidator in consolidators)
                            {
                                foreach (var dataPoint in update.Data)
                                {
                                    // only push data into consolidators on the native, subscribed to resolution
                                    if (EndTimeIsInNativeResolution(update.Target, dataPoint.EndTime))
                                    {
                                        consolidator.Update(dataPoint);
                                    }
                                }

                                // scan for time after we've pumped all the data through for this consolidator
                                consolidator.Scan(localTime);
                            }
                        }
                    }
                }
                catch (Exception err)
                {
                    algorithm.SetRuntimeError(err, "Consolidators update");
                    return;
                }

                // fire custom event handlers
                foreach (var update in timeSlice.CustomData)
                {
                    MethodInvoker methodInvoker;
                    if (!methodInvokers.TryGetValue(update.DataType, out methodInvoker))
                    {
                        continue;
                    }

                    try
                    {
                        foreach (var dataPoint in update.Data)
                        {
                            if (update.DataType.IsInstanceOfType(dataPoint))
                            {
                                methodInvoker(algorithm, dataPoint);
                            }
                        }
                    }
                    catch (Exception err)
                    {
                        algorithm.SetRuntimeError(err, "Custom Data");
                        return;
                    }
                }

                try
                {
                    // fire off the dividend and split events before pricing events
                    if (hasOnDataDividends && timeSlice.Slice.Dividends.Count != 0)
                    {
                        methodInvokers[typeof(Dividends)](algorithm, timeSlice.Slice.Dividends);
                    }
                    if (hasOnDataSplits && timeSlice.Slice.Splits.Count != 0)
                    {
                        methodInvokers[typeof(Splits)](algorithm, timeSlice.Slice.Splits);
                    }
                    if (hasOnDataDelistings && timeSlice.Slice.Delistings.Count != 0)
                    {
                        methodInvokers[typeof(Delistings)](algorithm, timeSlice.Slice.Delistings);
                    }
                }
                catch (Exception err)
                {
                    algorithm.SetRuntimeError(err, "Dividends/Splits/Delistings");
                    return;
                }

                // Only track pending delistings in non-live mode.
                if (!algorithm.LiveMode)
                {
                    // Keep this up to date even though we don't process delistings here anymore
                    foreach (var delisting in timeSlice.Slice.Delistings.Values)
                    {
                        if (delisting.Type == DelistingType.Warning)
                        {
                            // Store our delistings warnings because they are still used by ProcessSplitSymbols above
                            pendingDelistings.Add(delisting);
                        }
                        else
                        {
                            // If we have an actual delisting event, remove it from pending delistings
                            var index = pendingDelistings.FindIndex(x => x.Symbol == delisting.Symbol);
                            if (index != -1)
                            {
                                pendingDelistings.RemoveAt(index);
                            }
                        }
                    }
                }

                // run split logic after firing split events
                HandleSplitSymbols(timeSlice.Slice.Splits, splitWarnings);

                //After we've fired all other events in this second, fire the pricing events:
                try
                {
                    if (hasOnDataTradeBars && timeSlice.Slice.Bars.Count > 0)
                    {
                        methodInvokers[typeof(TradeBars)](algorithm, timeSlice.Slice.Bars);
                    }
                    if (hasOnDataQuoteBars && timeSlice.Slice.QuoteBars.Count > 0)
                    {
                        methodInvokers[typeof(QuoteBars)](algorithm, timeSlice.Slice.QuoteBars);
                    }
                    if (hasOnDataOptionChains && timeSlice.Slice.OptionChains.Count > 0)
                    {
                        methodInvokers[typeof(OptionChains)](algorithm, timeSlice.Slice.OptionChains);
                    }
                    if (hasOnDataTicks && timeSlice.Slice.Ticks.Count > 0)
                    {
                        methodInvokers[typeof(Ticks)](algorithm, timeSlice.Slice.Ticks);
                    }
                }
                catch (Exception err)
                {
                    algorithm.SetRuntimeError(err, "methodInvokers");
                    return;
                }

                try
                {
                    if (timeSlice.Slice.HasData)
                    {
                        // EVENT HANDLER v3.0 -- all data in a single event
                        algorithm.OnData(timeSlice.Slice);
                    }

                    // always turn the crank on this method to ensure universe selection models function properly on day changes w/out data
                    algorithm.OnFrameworkData(timeSlice.Slice);
                }
                catch (Exception err)
                {
                    algorithm.SetRuntimeError(err, "OnData");
                    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();

                // sample alpha charts now that we've updated time/price information and after transactions
                // are processed so that insights closed because of new order based insights get updated
                alphas.ProcessSynchronousEvents();

                // send the alpha statistics to the result handler for storage/transmit with the result packets
                results.SetAlphaRuntimeStatistics(alphas.RuntimeStatistics);

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

                // poke the algorithm at the end of each time step
                algorithm.OnEndOfTimeStep();
            } // End of ForEach feed.Bridge.GetConsumingEnumerable

            // stop timing the loops
            TimeLimit.StopEnforcingTimeLimit();

            //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)
            {
                algorithm.SetRuntimeError(err, "OnEndOfAlgorithm");
                return;
            }

            // final processing now that the algorithm has completed
            alphas.ProcessSynchronousEvents();

            // send the final alpha statistics to the result handler for storage/transmit with the result packets
            results.SetAlphaRuntimeStatistics(alphas.RuntimeStatistics);

            // 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 (_algorithm.Status == AlgorithmStatus.Liquidated && _liveMode)
            {
                Log.Trace("AlgorithmManager.Run(): Liquidating algorithm holdings...");
                algorithm.Liquidate();
                results.LogMessage("Algorithm Liquidated");
                results.SendStatusUpdate(AlgorithmStatus.Liquidated);
            }

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

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

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

            //Take final samples:
            results.Sample(time);
        } // End of Run();
 public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
 {
 }
Example #18
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)
                        {
                            PopulateDataDictionaries(baseData, ticks, tradeBars);

                            // 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));
        }
Example #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 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);

            // ensure we read equity data before option data, so we can set the current underlying price
            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, 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));
        }
Example #20
0
        public void OrdersAreSubmittedWhenRequiredForTargetsToExecute(
            Language language,
            double[] historicalPrices,
            decimal lastVolume,
            int expectedOrdersSubmitted,
            decimal expectedTotalQuantity)
        {
            var actualOrdersSubmitted = new List <SubmitOrderRequest>();

            var time            = new DateTime(2018, 8, 2, 16, 0, 0);
            var historyProvider = new Mock <IHistoryProvider>();

            historyProvider.Setup(m => m.GetHistory(It.IsAny <IEnumerable <HistoryRequest> >(), It.IsAny <DateTimeZone>()))
            .Returns(historicalPrices.Select((x, i) =>
                                             new Slice(time.AddMinutes(i),
                                                       new List <BaseData>
            {
                new TradeBar
                {
                    Time   = time.AddMinutes(i),
                    Symbol = Symbols.AAPL,
                    Open   = Convert.ToDecimal(x),
                    High   = Convert.ToDecimal(x),
                    Low    = Convert.ToDecimal(x),
                    Close  = Convert.ToDecimal(x),
                    Volume = 100m
                }
            })));

            var algorithm = new QCAlgorithm();

            algorithm.SubscriptionManager.SetDataManager(new DataManagerStub(algorithm));
            algorithm.SetPandasConverter();
            algorithm.SetHistoryProvider(historyProvider.Object);
            algorithm.SetDateTime(time.AddMinutes(5));

            var security = algorithm.AddEquity(Symbols.AAPL.Value);

            security.SetMarketPrice(new TradeBar {
                Value = 250, Volume = lastVolume
            });

            algorithm.SetFinishedWarmingUp();

            var orderProcessor = new Mock <IOrderProcessor>();

            orderProcessor.Setup(m => m.Process(It.IsAny <SubmitOrderRequest>()))
            .Returns((SubmitOrderRequest request) => new OrderTicket(algorithm.Transactions, request))
            .Callback((SubmitOrderRequest request) => actualOrdersSubmitted.Add(request));
            orderProcessor.Setup(m => m.GetOpenOrders(It.IsAny <Func <Order, bool> >()))
            .Returns(new List <Order>());
            algorithm.Transactions.SetOrderProcessor(orderProcessor.Object);

            var model = GetExecutionModel(language);

            algorithm.SetExecution(model);

            var changes = new SecurityChanges(new[] { security }, Enumerable.Empty <Security>());

            model.OnSecuritiesChanged(algorithm, changes);

            algorithm.History(new List <Symbol> {
                security.Symbol
            }, historicalPrices.Length, Resolution.Minute)
            .PushThroughConsolidators(symbol => algorithm.Securities[symbol].Subscriptions.Single(s => s.TickType == LeanData.GetCommonTickType(SecurityType.Equity)).Consolidators.First());

            var targets = new IPortfolioTarget[] { new PortfolioTarget(security.Symbol, 10) };

            model.Execute(algorithm, targets);

            Assert.AreEqual(expectedOrdersSubmitted, actualOrdersSubmitted.Count);
            Assert.AreEqual(expectedTotalQuantity, actualOrdersSubmitted.Sum(x => x.Quantity));

            if (actualOrdersSubmitted.Count == 1)
            {
                var request = actualOrdersSubmitted[0];
                Assert.AreEqual(expectedTotalQuantity, request.Quantity);
                Assert.AreEqual(algorithm.UtcTime, request.Time);
            }
        }
Example #21
0
 /// <summary>
 /// Event fired each time the we add/remove securities from the data feed
 /// </summary>
 /// <param name="algorithm">The algorithm instance that experienced the change in securities</param>
 /// <param name="changes">The security additions and removals from the algorithm</param>
 public override void OnSecuritiesChanged(QCAlgorithmFramework algorithm, SecurityChanges changes)
 {
     // Get removed symbol and invalidate them in the insight collection
     _removedSymbols = changes.RemovedSecurities.Select(x => x.Symbol).ToList();
     _insightCollection.Clear(_removedSymbols.ToArray());
 }
 /// <summary>
 /// Event fired each time the we add/remove securities from the data feed
 /// </summary>
 /// <param name="changes"></param>
 public override void OnSecuritiesChanged(SecurityChanges changes)
 {
     // each time our securities change we'll be notified here
     _changes = changes;
 }
Example #23
0
 /// <summary>
 /// Checks the current subscriptions and adds necessary currency pair feeds to provide real time conversion data
 /// </summary>
 public void EnsureCurrencyDataFeeds(SecurityChanges securityChanges)
 {
     _currencySubscriptionDataConfigManager.EnsureCurrencySubscriptionDataConfigs(securityChanges, _algorithm.BrokerageModel);
 }
Example #24
0
        /// <summary>
        /// Primary entry point.
        /// </summary>
        public void Run()
        {
            IsActive = true;

            // we want to emit to the bridge minimally once a second since the data feed is
            // the heartbeat of the application, so this value will contain a second after
            // the last emit time, and if we pass this time, we'll emit even with no data
            var nextEmit = DateTime.MinValue;

            try
            {
                while (!_cancellationTokenSource.IsCancellationRequested)
                {
                    // perform sleeps to wake up on the second?
                    _frontierUtc = _timeProvider.GetUtcNow();
                    _frontierTimeProvider.SetCurrentTime(_frontierUtc);

                    var data = new List <KeyValuePair <Security, List <BaseData> > >();
                    foreach (var kvp in _subscriptions)
                    {
                        var subscription = kvp.Value;

                        var cache = new KeyValuePair <Security, List <BaseData> >(subscription.Security, new List <BaseData>());

                        // dequeue data that is time stamped at or before this frontier
                        while (subscription.MoveNext() && subscription.Current != null)
                        {
                            cache.Value.Add(subscription.Current);
                        }

                        // if we have data, add it to be added to the bridge
                        if (cache.Value.Count > 0)
                        {
                            data.Add(cache);
                        }

                        // we have new universe data to select based on
                        if (subscription.IsUniverseSelectionSubscription && cache.Value.Count > 0)
                        {
                            var universe = subscription.Universe;

                            // always wait for other thread to sync up
                            if (!_bridge.WaitHandle.WaitOne(Timeout.Infinite, _cancellationTokenSource.Token))
                            {
                                break;
                            }

                            // assume that if the first item is a base data collection then the enumerator handled the aggregation,
                            // otherwise, load all the the data into a new collection instance
                            var collection = cache.Value[0] as BaseDataCollection ?? new BaseDataCollection(_frontierUtc, subscription.Configuration.Symbol, cache.Value);

                            _changes += _universeSelection.ApplyUniverseSelection(universe, _frontierUtc, collection);
                        }
                    }

                    // check for cancellation
                    if (_cancellationTokenSource.IsCancellationRequested)
                    {
                        return;
                    }

                    // emit on data or if we've elapsed a full second since last emit
                    if (data.Count != 0 || _frontierUtc >= nextEmit)
                    {
                        _bridge.Add(TimeSlice.Create(_frontierUtc, _algorithm.TimeZone, _algorithm.Portfolio.CashBook, data, _changes), _cancellationTokenSource.Token);

                        // force emitting every second
                        nextEmit = _frontierUtc.RoundDown(Time.OneSecond).Add(Time.OneSecond);
                    }

                    // reset our security changes
                    _changes = SecurityChanges.None;

                    // take a short nap
                    Thread.Sleep(1);
                }
            }
            catch (Exception err)
            {
                Log.Error(err);
                _algorithm.RunTimeError = err;
            }

            Log.Trace("LiveTradingDataFeed.Run(): Exited thread.");
            IsActive = false;
        }
Example #25
0
        public void AddAlphaModel(Language language)
        {
            IAlphaModel model;
            IAlphaModel model2 = null;
            IAlphaModel model3 = null;

            if (!TryCreateModel(language, out model) ||
                !TryCreateModel(language, out model2) ||
                !TryCreateModel(language, out model3))
            {
                Assert.Ignore($"Ignore {GetType().Name}: Could not create {language} model.");
            }

            // Set the alpha model
            _algorithm.SetAlpha(model);
            _algorithm.AddAlpha(model2);
            _algorithm.AddAlpha(model3);
            _algorithm.SetUniverseSelection(new ManualUniverseSelectionModel());

            var changes = new SecurityChanges(AddedSecurities, RemovedSecurities);

            _algorithm.OnFrameworkSecuritiesChanged(changes);

            var actualInsights = new List <Insight>();

            _algorithm.InsightsGenerated += (s, e) => actualInsights.AddRange(e.Insights);

            var expectedInsights = ExpectedInsights().ToList();

            var consolidators = _algorithm.Securities.SelectMany(kvp => kvp.Value.Subscriptions).SelectMany(x => x.Consolidators);
            var slices        = CreateSlices();

            foreach (var slice in slices.ToList())
            {
                _algorithm.SetDateTime(slice.Time);

                foreach (var symbol in slice.Keys)
                {
                    var data = slice[symbol];
                    _algorithm.Securities[symbol].SetMarketPrice(data);

                    foreach (var consolidator in consolidators)
                    {
                        consolidator.Update(data);
                    }
                }

                _algorithm.OnFrameworkData(slice);
            }

            Assert.AreEqual(expectedInsights.Count * 3, actualInsights.Count);

            for (var i = 0; i < actualInsights.Count; i = i + 3)
            {
                var expected = expectedInsights[i / 3];
                for (int j = i; j < 3; j++)
                {
                    var actual = actualInsights[j];
                    Assert.AreEqual(expected.Symbol, actual.Symbol);
                    Assert.AreEqual(expected.Type, actual.Type);
                    Assert.AreEqual(expected.Direction, actual.Direction);
                    Assert.AreEqual(expected.Period, actual.Period);
                    Assert.AreEqual(expected.Magnitude, actual.Magnitude);
                    Assert.AreEqual(expected.Confidence, actual.Confidence);
                }
            }
        }
Example #26
0
 public void OnSecuritiesChanged(SecurityChanges changes)
 {
     Algo.OnSecuritiesChanged(changes);
 }
        //Data Event Handler: New data arrives here. "TradeBars" type is a dictionary of strings so you can access it by symbol.
        public void OnData(TradeBars data)
        {
            // if we have no changes, do nothing
            if (_changes == SecurityChanges.None) return;

            // liquidate removed securities
            foreach (var security in _changes.RemovedSecurities)
            {
                if (security.Invested)
                {
                    Liquidate(security.Symbol);
                    Debug("Liquidated Stock: " + security.Symbol.Value);
                }
            }

            // we want 50% allocation in each security in our universe
            foreach (var security in _changes.AddedSecurities)
            {
                SetHoldings(security.Symbol, 0.5m);
                Debug("Purchased Stock: " + security.Symbol.Value);
            }

            _changes = SecurityChanges.None;
        }
Example #28
0
 public void OnFrameworkSecuritiesChanged(SecurityChanges changes)
 {
     Algo.OnFrameworkSecuritiesChanged(changes);
 }
        public override void OnSecuritiesChanged(SecurityChanges changes)
        {
            _optionCount += changes.AddedSecurities.Count(security => security.Symbol.SecurityType == SecurityType.Option);

            Log($"{GetStatusLog()} CHANGES: {changes}");
        }
 public override void OnSecuritiesChanged(SecurityChanges changes)
 {
     Debug($"{Time}-{changes}");
 }
Example #31
0
 /// <summary>
 /// Event fired each time the we add/remove securities from the data feed
 /// </summary>
 /// <param name="algorithm">The algorithm instance that experienced the change in securities</param>
 /// <param name="changes">The security additions and removals from the algorithm</param>
 public void OnSecuritiesChanged(QCAlgorithmFramework algorithm, SecurityChanges changes)
 {
 }
Example #32
0
        /// <summary>
        /// Ensures that we have a data feed to convert this currency into the base currency.
        /// This will add a <see cref="SubscriptionDataConfig"/> and create a <see cref="Security"/> at the lowest resolution if one is not found.
        /// </summary>
        /// <param name="securities">The security manager</param>
        /// <param name="subscriptions">The subscription manager used for searching and adding subscriptions</param>
        /// <param name="marketMap">The market map that decides which market the new security should be in</param>
        /// <param name="changes">Will be used to consume <see cref="SecurityChanges.AddedSecurities"/></param>
        /// <param name="securityService">Will be used to create required new <see cref="Security"/></param>
        /// <param name="accountCurrency">The account currency</param>
        /// <param name="defaultResolution">The default resolution to use for the internal subscriptions</param>
        /// <returns>Returns the added <see cref="SubscriptionDataConfig"/>, otherwise null</returns>
        public List <SubscriptionDataConfig> EnsureCurrencyDataFeed(SecurityManager securities,
                                                                    SubscriptionManager subscriptions,
                                                                    IReadOnlyDictionary <SecurityType, string> marketMap,
                                                                    SecurityChanges changes,
                                                                    ISecurityService securityService,
                                                                    string accountCurrency,
                                                                    Resolution defaultResolution = Resolution.Minute
                                                                    )
        {
            // this gets called every time we add securities using universe selection,
            // so must of the time we've already resolved the value and don't need to again
            if (CurrencyConversion != null)
            {
                return(null);
            }

            if (Symbol == accountCurrency)
            {
                _isBaseCurrency    = true;
                CurrencyConversion = null;
                ConversionRate     = 1.0m;
                return(null);
            }

            // existing securities
            var securitiesToSearch = securities.Select(kvp => kvp.Value)
                                     .Concat(changes.AddedSecurities)
                                     .Where(s => s.Type == SecurityType.Forex || s.Type == SecurityType.Cfd || s.Type == SecurityType.Crypto);

            // Create a SecurityType to Market mapping with the markets from SecurityManager members
            var markets = securities.Select(x => x.Key)
                          .GroupBy(x => x.SecurityType)
                          .ToDictionary(x => x.Key, y => y.Select(symbol => symbol.ID.Market).ToHashSet());

            if (markets.ContainsKey(SecurityType.Cfd) && !markets.ContainsKey(SecurityType.Forex))
            {
                markets.Add(SecurityType.Forex, markets[SecurityType.Cfd]);
            }
            if (markets.ContainsKey(SecurityType.Forex) && !markets.ContainsKey(SecurityType.Cfd))
            {
                markets.Add(SecurityType.Cfd, markets[SecurityType.Forex]);
            }

            var forexEntries  = GetAvailableSymbolPropertiesDatabaseEntries(SecurityType.Forex, marketMap, markets);
            var cfdEntries    = GetAvailableSymbolPropertiesDatabaseEntries(SecurityType.Cfd, marketMap, markets);
            var cryptoEntries = GetAvailableSymbolPropertiesDatabaseEntries(SecurityType.Crypto, marketMap, markets);

            var potentialEntries = forexEntries
                                   .Concat(cfdEntries)
                                   .Concat(cryptoEntries)
                                   .ToList();

            if (!potentialEntries.Any(x =>
                                      Symbol == x.Key.Symbol.Substring(0, x.Key.Symbol.Length - x.Value.QuoteCurrency.Length) ||
                                      Symbol == x.Value.QuoteCurrency))
            {
                // currency not found in any tradeable pair
                Log.Error($"No tradeable pair was found for currency {Symbol}, conversion rate to account currency ({accountCurrency}) will be set to zero.");
                CurrencyConversion = null;
                ConversionRate     = 0m;
                return(null);
            }

            // Special case for crypto markets without direct pairs (They wont be found by the above)
            // This allows us to add cash for "StableCoins" that are 1-1 with our account currency without needing a conversion security.
            // Check out the StableCoinsWithoutPairs static var for those that are missing their 1-1 conversion pairs
            if (marketMap.TryGetValue(SecurityType.Crypto, out var market)
                &&
                (Currencies.IsStableCoinWithoutPair(Symbol + accountCurrency, market) ||
                 Currencies.IsStableCoinWithoutPair(accountCurrency + Symbol, market)))
            {
                CurrencyConversion = null;
                ConversionRate     = 1.0m;
                return(null);
            }

            var requiredSecurities = new List <SubscriptionDataConfig>();

            var potentials = potentialEntries
                             .Select(x => QuantConnect.Symbol.Create(x.Key.Symbol, x.Key.SecurityType, x.Key.Market));

            var minimumResolution = subscriptions.Subscriptions.Select(x => x.Resolution).DefaultIfEmpty(defaultResolution).Min();

            var makeNewSecurity = new Func <Symbol, Security>(symbol =>
            {
                var securityType = symbol.ID.SecurityType;

                // use the first subscription defined in the subscription manager
                var type       = subscriptions.LookupSubscriptionConfigDataTypes(securityType, minimumResolution, false).First();
                var objectType = type.Item1;
                var tickType   = type.Item2;

                // set this as an internal feed so that the data doesn't get sent into the algorithm's OnData events
                var config = subscriptions.SubscriptionDataConfigService.Add(symbol,
                                                                             minimumResolution,
                                                                             fillForward: true,
                                                                             extendedMarketHours: false,
                                                                             isInternalFeed: true,
                                                                             subscriptionDataTypes: new List <Tuple <Type, TickType> >
                {
                    new Tuple <Type, TickType>(objectType, tickType)
                }).First();

                var newSecurity = securityService.CreateSecurity(symbol,
                                                                 config,
                                                                 addToSymbolCache: false);

                Log.Trace($"Cash.EnsureCurrencyDataFeed(): Adding {symbol.Value} for cash {Symbol} currency feed");

                securities.Add(symbol, newSecurity);
                requiredSecurities.Add(config);

                return(newSecurity);
            });

            CurrencyConversion = SecurityCurrencyConversion.LinearSearch(Symbol,
                                                                         accountCurrency,
                                                                         securitiesToSearch.ToList(),
                                                                         potentials,
                                                                         makeNewSecurity);

            return(requiredSecurities);
        }