public void LinearSearchFindsTwoLegConversions() { var existingSecurities = new List <Security>(0); var potentialSymbols = new List <Symbol> { Symbols.BTCUSD, Symbols.EURUSD }; var subscriptions = new SubscriptionManager(); var dataManager = new DataManagerStub(); subscriptions.SetDataManager(dataManager); var createdSecurities = new List <Security>(); var makeNewSecurity = new Func <Symbol, Security>(symbol => { var security = CreateSecurity(symbol); createdSecurities.Add(security); return(security); }); var currencyConversion = SecurityCurrencyConversion.LinearSearch( "BTC", "EUR", existingSecurities, potentialSymbols, makeNewSecurity); var securities = currencyConversion.ConversionRateSecurities.ToList(); Assert.AreEqual(2, securities.Count); Assert.AreEqual(createdSecurities, securities); Assert.AreEqual(Symbols.BTCUSD, securities[0].Symbol); Assert.AreEqual(Symbols.EURUSD, securities[1].Symbol); }
public void EnsureCurrencyDataFeedMarksIsCurrencyDataFeedForNewSubscriptions() { const int quantity = 100; const decimal conversionRate = 1 / 100m; var cash = new Cash("JPY", quantity, conversionRate); var cashBook = new CashBook(); cashBook.Add("JPY", cash); var subscriptions = new SubscriptionManager(); var dataManager = new DataManagerStub(TimeKeeper); subscriptions.SetDataManager(dataManager); var securities = new SecurityManager(TimeKeeper); securities.Add( Symbols.EURUSD, new Security( SecurityExchangeHours, subscriptions.Add(Symbols.EURUSD, Resolution.Minute, TimeZone, TimeZone), new Cash(cashBook.AccountCurrency, 0, 1m), SymbolProperties.GetDefault(cashBook.AccountCurrency), ErrorCurrencyConverter.Instance, RegisteredSecurityDataTypesProvider.Null, new SecurityCache() ) ); cash.EnsureCurrencyDataFeed(securities, subscriptions, MarketMap, SecurityChanges.None, dataManager.SecurityService, cashBook.AccountCurrency); var config = subscriptions.SubscriptionDataConfigService.GetSubscriptionDataConfigs(Symbols.USDJPY, includeInternalConfigs: true).Single(); Assert.IsTrue(config.IsInternalFeed); }
public void LinearSearchPrefersExistingSecuritiesOverNewOnesOneLeg() { var existingSecurities = new List <Security> { CreateSecurity(Symbols.EURUSD) }; var potentialSymbols = new List <Symbol> { Symbols.EURUSD }; var subscriptions = new SubscriptionManager(); var dataManager = new DataManagerStub(); subscriptions.SetDataManager(dataManager); var createdSecurities = new List <Security>(); var makeNewSecurity = new Func <Symbol, Security>(symbol => { var security = CreateSecurity(symbol); createdSecurities.Add(security); return(security); }); var currencyConversion = SecurityCurrencyConversion.LinearSearch( "EUR", "USD", existingSecurities, potentialSymbols, makeNewSecurity); var securities = currencyConversion.ConversionRateSecurities.ToList(); Assert.AreEqual(1, securities.Count); Assert.AreEqual(0, createdSecurities.Count); Assert.AreEqual(existingSecurities, securities); }
public void NonUsdAccountCurrencyCurrencyDataFeedsGetAdded(string accountCurrency, string quoteCurrency, string baseCurrency, string quoteCurrencySymbol, string baseCurrencySymbol, SecurityType securityType, string market) { var quoteCash = new Cash(quoteCurrency, 100, 1); var baseCash = new Cash(baseCurrency, 100, 1); var cashBook = new CashBook { { quoteCurrency, quoteCash }, { baseCurrency, baseCash } }; var symbol = Symbol.Create(baseCurrency + quoteCurrency, securityType, market); var subscriptions = new SubscriptionManager(); var dataManager = new DataManagerStub(TimeKeeper); subscriptions.SetDataManager(dataManager); var securities = new SecurityManager(TimeKeeper) { { symbol, new Security( SecurityExchangeHours, subscriptions.Add(symbol, Resolution.Minute, TimeZone, TimeZone), new Cash(cashBook.AccountCurrency, 0, 1m), SymbolProperties.GetDefault(cashBook.AccountCurrency), ErrorCurrencyConverter.Instance, RegisteredSecurityDataTypesProvider.Null, new SecurityCache() ) } }; var symbol1 = quoteCash.EnsureCurrencyDataFeed(securities, subscriptions, MarketMap, SecurityChanges.None, dataManager.SecurityService, accountCurrency); Assert.IsNotNull(symbol1); Assert.AreEqual(quoteCurrencySymbol, symbol1.Symbol.Value); var symbol2 = baseCash.EnsureCurrencyDataFeed(securities, subscriptions, MarketMap, SecurityChanges.None, dataManager.SecurityService, accountCurrency); Assert.IsNotNull(symbol2); Assert.AreEqual(baseCurrencySymbol, symbol2.Symbol.Value); }
public void HasErrorWithZeroTotalPortfolioValue(bool hasCashBalance, bool hasHoldings) { var algorithm = new TestAlgorithm(); algorithm.SetHistoryProvider(new BrokerageTransactionHandlerTests.BrokerageTransactionHandlerTests.EmptyHistoryProvider()); var job = GetJob(); job.Brokerage = "TestBrokerage"; var resultHandler = new Mock <IResultHandler>(); var transactionHandler = new Mock <ITransactionHandler>(); var realTimeHandler = new Mock <IRealTimeHandler>(); var brokerage = new Mock <IBrokerage>(); var objectStore = new Mock <IObjectStore>(); brokerage.Setup(x => x.IsConnected).Returns(true); brokerage.Setup(x => x.AccountBaseCurrency).Returns(Currencies.USD); brokerage.Setup(x => x.GetCashBalance()).Returns( hasCashBalance ? new List <CashAmount> { new CashAmount(1000, "USD") } : new List <CashAmount>() ); brokerage.Setup(x => x.GetAccountHoldings()).Returns( hasHoldings ? new List <Holding> { new Holding { Symbol = Symbols.SPY, Quantity = 1, AveragePrice = 100, MarketPrice = 100 } } : new List <Holding>()); brokerage.Setup(x => x.GetOpenOrders()).Returns(new List <Order>()); var setupHandler = new BrokerageSetupHandler(); IBrokerageFactory factory; setupHandler.CreateBrokerage(job, algorithm, out factory); var dataManager = new DataManagerStub(algorithm, new MockDataFeed(), true); Assert.IsTrue(setupHandler.Setup(new SetupHandlerParameters(dataManager.UniverseSelection, algorithm, brokerage.Object, job, resultHandler.Object, transactionHandler.Object, realTimeHandler.Object, objectStore.Object, TestGlobals.DataCacheProvider, TestGlobals.MapFileProvider))); if (!hasCashBalance && !hasHoldings) { Assert.That(algorithm.DebugMessages.Count > 0); Assert.That(algorithm.DebugMessages.Any(x => x.Contains("No cash balances or holdings were found in the brokerage account."))); } }
public void MisalignedBenchmarkAndAlgorithmTimeZones(Resolution resolution, bool useUniverseSubscription = false) { // Verify that if we have algorithm: // - subscribed to a daily resolution via universe or directly // - a benchmark with timezone that is not algorithm time zone // that we post an warning via log that statistics will be affected // Setup a empty algorithm for the test var algorithm = new QCAlgorithm(); var dataManager = new DataManagerStub(algorithm, new MockDataFeed(), liveMode: true); algorithm.SubscriptionManager.SetDataManager(dataManager); if (useUniverseSubscription) { // Change our universe resolution algorithm.UniverseSettings.Resolution = resolution; } else { // subscribe to an equity in our provided resolution algorithm.AddEquity("AAPL", resolution); } // Default benchmark is SPY which is NY TimeZone, // Set timezone to UTC. algorithm.SetTimeZone(DateTimeZone.Utc); algorithm.PostInitialize(); // Verify if our log is there (Should only be there in Daily case) switch (resolution) { case Resolution.Daily: if (algorithm.LogMessages.TryPeek(out string result)) { Assert.IsTrue(result.Contains("Using a security benchmark of a different timezone", StringComparison.InvariantCulture)); } else { Assert.Fail("Warning was not posted"); } break; default: Assert.AreEqual(0, algorithm.LogMessages.Count); break; } }
public void DailySampleValueBasedOnMarketHour(bool extendedMarketHoursEnabled) { var referenceDate = new DateTime(2020, 11, 25); var resultHandler = new LiveTradingResultHandler(); resultHandler.Initialize(new LiveNodePacket(), new QuantConnect.Messaging.Messaging(), new Api.Api(), new BacktestingTransactionHandler()); var algo = new AlgorithmStub(createDataManager: false); algo.SetFinishedWarmingUp(); var dataManager = new DataManagerStub(new TestDataFeed(), algo); algo.SubscriptionManager.SetDataManager(dataManager); var aapl = algo.AddEquity("AAPL", extendedMarketHours: extendedMarketHoursEnabled); algo.PostInitialize(); resultHandler.SetAlgorithm(algo, 100000); resultHandler.OnSecuritiesChanged(SecurityChangesTests.AddedNonInternal(aapl)); // Add values during market hours, should always update algo.Portfolio.CashBook["USD"].AddAmount(1000); algo.Portfolio.InvalidateTotalPortfolioValue(); resultHandler.Sample(referenceDate.AddHours(15)); Assert.IsTrue(resultHandler.Charts.ContainsKey("Strategy Equity")); Assert.AreEqual(1, resultHandler.Charts["Strategy Equity"].Series["Equity"].Values.Count); var currentEquityValue = resultHandler.Charts["Strategy Equity"].Series["Equity"].Values.Last().y; Assert.AreEqual(101000, currentEquityValue); // Add value to portfolio, see if portfolio updates with new sample // will be changed to 'extendedMarketHoursEnabled' = true algo.Portfolio.CashBook["USD"].AddAmount(10000); algo.Portfolio.InvalidateTotalPortfolioValue(); resultHandler.Sample(referenceDate.AddHours(22)); Assert.AreEqual(2, resultHandler.Charts["Strategy Equity"].Series["Equity"].Values.Count); currentEquityValue = resultHandler.Charts["Strategy Equity"].Series["Equity"].Values.Last().y; Assert.AreEqual(extendedMarketHoursEnabled ? 111000 : 101000, currentEquityValue); resultHandler.Exit(); }
public void EnsureCurrencyDataFeedThrowsWithUnsupportedCurrency() { Assert.Throws <ArgumentException>(() => { var book = new CashBook { { Currencies.USD, new Cash(Currencies.USD, 100, 1) }, { "ILS", new Cash("ILS", 0, 0.3m) } }; var subscriptions = new SubscriptionManager(); var dataManager = new DataManagerStub(TimeKeeper); subscriptions.SetDataManager(dataManager); var securities = new SecurityManager(TimeKeeper); // System.ArgumentException: In order to maintain cash in ILS you are required to add a subscription for Forex pair ILSUSD or USDILS book.EnsureCurrencyDataFeeds(securities, subscriptions, MarketMap, SecurityChanges.None, dataManager.SecurityService); }); }
public void EnsureCurrencyDataFeedForCryptoCurrency() { var book = new CashBook { { "USD", new Cash("USD", 100, 1) }, { "BTC", new Cash("BTC", 100, 6000) }, { "LTC", new Cash("LTC", 100, 55) }, { "ETH", new Cash("ETH", 100, 290) }, { "EUR", new Cash("EUR", 100, 1.2m) }, { "JPY", new Cash("JPY", 100, 0.0088m) }, { "XAG", new Cash("XAG", 100, 1275) }, { "XAU", new Cash("XAU", 100, 17) } }; var subscriptions = new SubscriptionManager(); var dataManager = new DataManagerStub(TimeKeeper); subscriptions.SetDataManager(dataManager); var securities = new SecurityManager(TimeKeeper); book.EnsureCurrencyDataFeeds(securities, subscriptions, MarketMap, SecurityChanges.None, dataManager.SecurityService); var symbols = subscriptions.Subscriptions.Select(sdc => sdc.Symbol).ToHashSet(); Assert.IsTrue(symbols.Contains(Symbols.BTCUSD)); Assert.IsTrue(symbols.Contains(Symbols.LTCUSD)); Assert.IsTrue(symbols.Contains(Symbols.ETHUSD)); Assert.IsTrue(symbols.Contains(Symbols.EURUSD)); Assert.IsTrue(symbols.Contains(Symbols.XAGUSD)); Assert.IsTrue(symbols.Contains(Symbols.XAUUSD)); foreach (var cash in book) { Assert.AreEqual("USD", cash.Value.AccountCurrency); } foreach (var subscription in subscriptions.Subscriptions) { Assert.AreEqual( subscription.Symbol.SecurityType == SecurityType.Crypto ? TickType.Trade : TickType.Quote, subscription.TickType); } }
public void UpdateModifiesConversionRate() { const int quantity = 100; const decimal conversionRate = 1 / 100m; var cash = new Cash("GBP", quantity, conversionRate); var cashBook = new CashBook(); cashBook.Add("GBP", cash); var subscriptions = new SubscriptionManager(); var dataManager = new DataManagerStub(TimeKeeper); subscriptions.SetDataManager(dataManager); var securities = new SecurityManager(TimeKeeper); securities.Add( Symbols.GBPUSD, new Security( SecurityExchangeHours, subscriptions.Add(Symbols.GBPUSD, Resolution.Minute, TimeZone, TimeZone), new Cash(cashBook.AccountCurrency, 0, 1m), SymbolProperties.GetDefault(cashBook.AccountCurrency), ErrorCurrencyConverter.Instance, RegisteredSecurityDataTypesProvider.Null, new SecurityCache() ) ); // we need to get subscription index cash.EnsureCurrencyDataFeed(securities, subscriptions, MarketMap, SecurityChanges.None, dataManager.SecurityService, cashBook.AccountCurrency); var last = 1.5m; cash.Update(new Tick(DateTime.Now, Symbols.GBPUSD, last, last * 1.009m, last * 0.009m)); // jpy is inverted, so compare on the inverse Assert.AreEqual(last, cash.ConversionRate); }
public void HasErrorWithZeroTotalPortfolioValue(bool hasCashBalance, bool hasHoldings) { var algorithm = new TestAlgorithm(); algorithm.SetHistoryProvider(new BrokerageTransactionHandlerTests.BrokerageTransactionHandlerTests.EmptyHistoryProvider()); var job = new LiveNodePacket { UserId = 1, ProjectId = 1, DeployId = "1", Brokerage = "TestBrokerage", DataQueueHandler = "none", Controls = new Controls { RamAllocation = 4096 } // no real limit }; var resultHandler = new Mock <IResultHandler>(); var transactionHandler = new Mock <ITransactionHandler>(); var realTimeHandler = new Mock <IRealTimeHandler>(); var brokerage = new Mock <IBrokerage>(); var objectStore = new Mock <IObjectStore>(); brokerage.Setup(x => x.IsConnected).Returns(true); brokerage.Setup(x => x.GetCashBalance()).Returns( hasCashBalance ? new List <CashAmount> { new CashAmount(1000, "USD") } : new List <CashAmount>() ); brokerage.Setup(x => x.GetAccountHoldings()).Returns( hasHoldings ? new List <Holding> { new Holding { Type = SecurityType.Equity, Symbol = Symbols.SPY, Quantity = 1, AveragePrice = 100, MarketPrice = 100 } } : new List <Holding>()); brokerage.Setup(x => x.GetOpenOrders()).Returns(new List <Order>()); var setupHandler = new BrokerageSetupHandler(); IBrokerageFactory factory; setupHandler.CreateBrokerage(job, algorithm, out factory); var dataManager = new DataManagerStub(algorithm, new MockDataFeed(), true); Assert.IsTrue(setupHandler.Setup(new SetupHandlerParameters(dataManager.UniverseSelection, algorithm, brokerage.Object, job, resultHandler.Object, transactionHandler.Object, realTimeHandler.Object, objectStore.Object))); if (hasCashBalance || hasHoldings) { Assert.AreEqual(0, algorithm.DebugMessages.Count); } else { Assert.AreEqual(1, algorithm.DebugMessages.Count); Assert.That(algorithm.DebugMessages.First().Contains("No cash balances or holdings were found in the brokerage account.")); } }