/// <summary> /// For backtesting returns the index source for a date /// For live trading will return the source url to use, not using the index mechanism /// </summary> /// <param name="config">Configuration object</param> /// <param name="date">Date of this source file</param> /// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param> /// <returns>The <see cref="SubscriptionDataSource"/> instance to use</returns> public override SubscriptionDataSource GetSource(SubscriptionDataConfig config, DateTime date, bool isLiveMode) { if (isLiveMode) { if (!Tiingo.IsAuthCodeSet) { throw new InvalidOperationException("TiingoNews API token has to be set using Tiingo.SetAuthCode(). See https://api.tiingo.com/about/pricing"); } var tiingoTicker = TiingoSymbolMapper.GetTiingoTicker(config.Symbol); var url = Invariant($"https://api.tiingo.com/tiingo/news?tickers={tiingoTicker}&startDate={date:yyyy-MM-dd}&token={Tiingo.AuthCode}&sortBy=crawlDate"); return(new SubscriptionDataSource(url, SubscriptionTransportMedium.Rest, FileFormat.Collection)); } var source = Path.Combine( Globals.DataFolder, "alternative", "tiingo", $"{config.MappedSymbol.ToLowerInvariant()}", $"{date.ToStringInvariant(DateFormat.EightCharacter)}.csv" ); return(new SubscriptionDataSource(source, SubscriptionTransportMedium.LocalFile, FileFormat.Index)); }
/// <summary> /// Helper method to deserialize a single json Tiingo news /// </summary> /// <param name="token">The json token containing the Tiingo news to deserialize</param> /// <returns>The deserialized <see cref="TiingoNews"/> instance</returns> public static TiingoNews DeserializeNews(JToken token) { // just in case we add some default values for these var title = token["title"]?.ToString() ?? ""; var source = token["source"]?.ToString() ?? ""; var url = token["url"]?.ToString() ?? ""; var tags = token["tags"]?.ToObject <List <string> >() ?? new List <string>(); var description = token["description"]?.ToString() ?? ""; var publishedDate = GetDateTime(token["publishedDate"]); var crawlDate = GetDateTime(token["crawlDate"]); var articleID = token["id"].ToString(); var tickers = token["tickers"]; // 'time' is QC time which could be crawl time or published data + offset (see converter) this is not present in live // which will use 'crawlDate' var time = GetDateTime(token["time"], defaultValue: crawlDate); var symbols = new List <Symbol>(); foreach (var tiingoTicker in tickers) { var rawTicker = tiingoTicker.ToString(); if (rawTicker.Contains(" ") || rawTicker.Contains("|")) { Log.Trace($"TiingoNewsJsonConverter.DeserializeNews(): Article ID {articleID}, ignoring ticker [{rawTicker}] because it contains space or pipe character."); continue; } var ticker = TiingoSymbolMapper.GetLeanTicker(rawTicker); var sid = SecurityIdentifier.GenerateEquity( ticker, // for now we suppose USA market QuantConnect.Market.USA, // we use the news date to resolve the map file to use mappingResolveDate: publishedDate); symbols.Add(new Symbol(sid, ticker)); } var dataPoint = new TiingoNews { ArticleID = articleID, CrawlDate = crawlDate, Description = description, PublishedDate = publishedDate, Time = time, Source = source, Tags = tags, Symbols = symbols, Url = url, Title = title }; return(dataPoint); }
/// <summary> /// Return the URL string source of the file. This will be converted to a stream /// </summary> /// <param name="config">Configuration object</param> /// <param name="date">Date of this source file</param> /// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param> /// <returns>String URL of source file.</returns> public override SubscriptionDataSource GetSource(SubscriptionDataConfig config, DateTime date, bool isLiveMode) { DateTime startDate; if (!_startDates.TryGetValue(config.Symbol.Value, out startDate)) { startDate = date; _startDates.TryAdd(config.Symbol.Value, startDate); } var tiingoTicker = TiingoSymbolMapper.GetTiingoTicker(config.Symbol); var source = Invariant($"https://api.tiingo.com/tiingo/daily/{tiingoTicker}/prices?startDate={startDate:yyyy-MM-dd}&token={Tiingo.AuthCode}"); return(new SubscriptionDataSource(source, SubscriptionTransportMedium.RemoteFile, FileFormat.Collection)); }
/// <summary> /// Helper method to deserialize a single json Tiingo news /// </summary> /// <param name="token">The json token containing the Tiingo news to deserialize</param> /// <returns>The deserialized <see cref="TiingoNewsData"/> instance</returns> public static TiingoNewsData DeserializeNews(JToken token) { // just in case we add some default values for these var title = token["title"]?.ToString() ?? ""; var source = token["source"]?.ToString() ?? ""; var url = token["url"]?.ToString() ?? ""; var tags = token["tags"]?.ToObject <List <string> >() ?? new List <string>(); var description = token["description"]?.ToString() ?? ""; var publishedDate = GetDateTime(token["publishedDate"]); var crawlDate = GetDateTime(token["crawlDate"]); var articleID = token["id"].ToString(); var tickers = token["tickers"]; var symbols = new List <Symbol>(); foreach (var tiingoTicker in tickers) { var ticker = TiingoSymbolMapper.GetLeanTicker(tiingoTicker.ToString()); var sid = SecurityIdentifier.GenerateEquity( ticker, // for now we suppose USA market QuantConnect.Market.USA, // we use the news date to resolve the map file to use mappingResolveDate: publishedDate); symbols.Add(new Symbol(sid, ticker)); } var dataPoint = new TiingoNewsData { ArticleID = articleID, CrawlDate = crawlDate, Description = description, PublishedDate = publishedDate, Time = publishedDate, Source = source, Tags = tags, Symbols = symbols, Url = url, Title = title }; return(dataPoint); }