/// <summary> /// AddData<typeparam name="T"/> a new user defined data source, requiring only the minimum config options. /// </summary> /// <param name="symbol">Key/Symbol for data</param> /// <param name="resolution">Resolution of the Data Required</param> /// <param name="timeZone">Specifies the time zone of the raw data</param> /// <param name="fillDataForward">When no data available on a tradebar, return the last data that was generated</param> /// <param name="leverage">Custom leverage per security</param> /// <remarks>Generic type T must implement base data</remarks> public void AddData <T>(Symbol symbol, Resolution resolution, DateTimeZone timeZone, bool fillDataForward = false, decimal leverage = 1.0m) where T : BaseData, new() { if (_locked) { return; } //Add this to the data-feed subscriptions var config = SubscriptionManager.Add(typeof(T), SecurityType.Base, symbol, resolution, "usa", timeZone, true, fillDataForward, true, false); var exchangeHours = _exchangeHoursProvider.GetExchangeHours(config); //Add this new generic data as a tradeable security: var security = new Security(exchangeHours, config, leverage); Securities.Add(symbol, security); }
/// <summary> /// Ensures that we have a data feed to conver this currency into the base currency. /// This will add a subscription 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="exchangeHoursProvider">A security exchange hours provider instance used to resolve exchange hours for new subscriptions</param> public void EnsureCurrencyDataFeed(SecurityManager securities, SubscriptionManager subscriptions, SecurityExchangeHoursProvider exchangeHoursProvider) { if (Symbol == CashBook.AccountCurrency) { SecuritySymbol = string.Empty; _isBaseCurrency = true; ConversionRate = 1.0m; return; } if (subscriptions.Count == 0) { throw new InvalidOperationException("Unable to add cash when no subscriptions are present. Please add subscriptions in the Initialize() method."); } // we require a subscription that converts this into the base currency string normal = Symbol + CashBook.AccountCurrency; string invert = CashBook.AccountCurrency + Symbol; foreach (var config in subscriptions.Subscriptions.Where(config => config.SecurityType == SecurityType.Forex)) { if (config.Symbol == normal) { SecuritySymbol = config.Symbol; return; } if (config.Symbol == invert) { SecuritySymbol = config.Symbol; _invertRealTimePrice = true; return; } } // get the market from the first Forex subscription string market = (from config in subscriptions.Subscriptions where config.SecurityType == SecurityType.Forex select config.Market).FirstOrDefault() ?? "fxcm"; // if we've made it here we didn't find a subscription, so we'll need to add one var currencyPairs = Forex.Forex.CurrencyPairs; var minimumResolution = subscriptions.Subscriptions.Min(x => x.Resolution); var objectType = minimumResolution == Resolution.Tick ? typeof (Tick) : typeof (TradeBar); foreach (var symbol in currencyPairs) { if (symbol == normal || symbol == invert) { _invertRealTimePrice = symbol == invert; var exchangeHours = exchangeHoursProvider.GetExchangeHours(market, symbol, SecurityType.Forex); // set this as an internal feed so that the data doesn't get sent into the algorithm's OnData events var config = subscriptions.Add(objectType, SecurityType.Forex, symbol, minimumResolution, market, exchangeHours.TimeZone, true, false, true); var security = new Forex.Forex(this, config, 1m); SecuritySymbol = config.Symbol; securities.Add(symbol, security); Log.Trace("Cash.EnsureCurrencyDataFeed(): Adding " + symbol + " for cash " + Symbol + " currency feed"); return; } } // if this still hasn't been set then it's an error condition throw new ArgumentException(string.Format("In order to maintain cash in {0} you are required to add a subscription for Forex pair {0}{1} or {1}{0}", Symbol, CashBook.AccountCurrency)); }
/// <summary> /// Set a required SecurityType-symbol and resolution for algorithm /// </summary> /// <param name="securityType">SecurityType Enum: Equity, Commodity, FOREX or Future</param> /// <param name="symbol">Symbol Representation of the MarketType, e.g. AAPL</param> /// <param name="resolution">Resolution of the MarketType required: MarketData, Second or Minute</param> /// <param name="market">The market the requested security belongs to, such as 'usa' or 'fxcm'</param> /// <param name="fillDataForward">If true, returns the last available data even if none in that timeslice.</param> /// <param name="leverage">leverage for this security</param> /// <param name="extendedMarketHours">ExtendedMarketHours send in data from 4am - 8pm, not used for FOREX</param> public void AddSecurity(SecurityType securityType, string symbol, Resolution resolution, string market, bool fillDataForward, decimal leverage, bool extendedMarketHours) { try { if (_locked) { throw new Exception("Algorithm.AddSecurity(): Cannot add another security after algorithm running."); } symbol = symbol.ToUpper(); //If it hasn't been set, use some defaults based on the portfolio type: if (leverage <= 0) { switch (securityType) { case SecurityType.Equity: leverage = 2; //Cash Ac. = 1, RegT Std = 2 or PDT = 4. break; case SecurityType.Forex: leverage = 50; break; } } if (market == null) { // set default values if (securityType == SecurityType.Forex) { market = "fxcm"; } else if (securityType == SecurityType.Equity) { market = "usa"; } else { market = "usa"; } } //Add the symbol to Data Manager -- generate unified data streams for algorithm events var exchangeHours = _exchangeHoursProvider.GetExchangeHours(market, symbol, securityType); var config = SubscriptionManager.Add(securityType, symbol, resolution, market, exchangeHours.TimeZone, fillDataForward, extendedMarketHours); Security security; switch (config.SecurityType) { case SecurityType.Equity: security = new Equity(exchangeHours, config, leverage, false); break; case SecurityType.Forex: // decompose the symbol into each currency pair string baseCurrency, quoteCurrency; QuantConnect.Securities.Forex.Forex.DecomposeCurrencyPair(symbol, out baseCurrency, out quoteCurrency); if (!Portfolio.CashBook.ContainsKey(baseCurrency)) { // since we have none it's safe to say the conversion is zero Portfolio.CashBook.Add(baseCurrency, 0, 0); } if (!Portfolio.CashBook.ContainsKey(quoteCurrency)) { // since we have none it's safe to say the conversion is zero Portfolio.CashBook.Add(quoteCurrency, 0, 0); } security = new Forex(exchangeHours, Portfolio.CashBook[quoteCurrency], config, leverage, false); break; default: case SecurityType.Base: security = new Security(exchangeHours, config, leverage, false); break; } //Add the symbol to Securities Manager -- manage collection of portfolio entities for easy access. Securities.Add(config.Symbol, security); } catch (Exception err) { Error("Algorithm.AddSecurity(): " + err.Message); } }