public void SetHoldings_Short_RoundOff() { var algo = new QCAlgorithm(); algo.AddSecurity(SecurityType.Forex, "EURUSD"); algo.SetCash(100000); algo.SetBrokerageModel(BrokerageName.FxcmBrokerage); algo.Securities[Symbols.EURUSD].TransactionModel = new ConstantFeeTransactionModel(0); Security eurusd = algo.Securities[Symbols.EURUSD]; // Set Price to $26 Update(eurusd, 26); // So -100000/26 = -3846, After Rounding off becomes -3000 var actual = algo.CalculateOrderQuantity(Symbols.EURUSD, -1m); Assert.AreEqual(-3000m, actual); var btcusd = algo.AddCrypto("BTCUSD", market: Market.GDAX); btcusd.TransactionModel = new ConstantFeeTransactionModel(0); // Set Price to $26 Update(btcusd, 26); // So -100000/26 = 3846.153846153846, After Rounding off becomes -3846.15384615, since lot size is 0.00000001 actual = algo.CalculateOrderQuantity(Symbols.BTCUSD, -1m); Assert.AreEqual(-3846.15384615m, actual); }
public void LimitBuyOrderChecksOpenOrders() { _portfolio.SetCash(5000); _btcusd = _algorithm.AddCrypto("BTCUSD"); _btcusd.SetMarketPrice(new Tick { Value = 15000m }); _ethusd = _algorithm.AddCrypto("ETHUSD"); _ethusd.SetMarketPrice(new Tick { Value = 1000m }); _algorithm.SetFinishedWarmingUp(); // BTCUSD buy order decreases available USD (5000 - 1500 = 3500 USD) SubmitLimitOrder(_btcusd.Symbol, 0.1m, 15000m); // ETHUSD buy order decreases available USD (3500 - 3000 = 500 USD) SubmitLimitOrder(_ethusd.Symbol, 3m, 1000m); // 500 USD available, can buy 0.05 BTC at 10000 var order = new LimitOrder(_btcusd.Symbol, 0.05m, 10000m, DateTime.UtcNow); Assert.IsTrue(_buyingPowerModel.HasSufficientBuyingPowerForOrder(_portfolio, _btcusd, order)); // 500 USD available, cannot buy 0.06 BTC at 10000 order = new LimitOrder(_btcusd.Symbol, 0.06m, 10000m, DateTime.UtcNow); Assert.IsFalse(_buyingPowerModel.HasSufficientBuyingPowerForOrder(_portfolio, _btcusd, order)); }
public void AddDataSecurityTickerWithUnderlying(string ticker, Type customDataType, SecurityType securityType, bool securityShouldBeMapped, bool customDataShouldBeMapped) { SymbolCache.Clear(); var qcAlgorithm = new QCAlgorithm(); qcAlgorithm.SubscriptionManager.SetDataManager(new DataManagerStub(qcAlgorithm)); Security asset; switch (securityType) { case SecurityType.Cfd: asset = qcAlgorithm.AddCfd(ticker, Resolution.Daily); break; case SecurityType.Crypto: asset = qcAlgorithm.AddCrypto(ticker, Resolution.Daily); break; case SecurityType.Equity: asset = qcAlgorithm.AddEquity(ticker, Resolution.Daily); break; case SecurityType.Forex: asset = qcAlgorithm.AddForex(ticker, Resolution.Daily); break; case SecurityType.Future: asset = qcAlgorithm.AddFuture(ticker, Resolution.Daily); break; default: throw new Exception($"SecurityType {securityType} is not valid for this test"); } // Aliased value for Futures contains a forward-slash, which causes the // lookup in the SymbolCache to fail if (securityType == SecurityType.Future) { ticker = asset.Symbol.Value; } // Dummy here is meant to try to corrupt the SymbolCache. Ideally, SymbolCache should return non-custom data types with higher priority // in case we want to add two custom data types, but still have them associated with the equity from the cache if we're using it. // This covers the case where two idential data subscriptions are created. var dummy = qcAlgorithm.AddData(customDataType, ticker, Resolution.Daily, qcAlgorithm.SubscriptionManager.Subscriptions.Where(x => x.SecurityType == securityType).First().DataTimeZone); var customData = qcAlgorithm.AddData(customDataType, ticker, Resolution.Daily, qcAlgorithm.SubscriptionManager.Subscriptions.Where(x => x.SecurityType == securityType).First().DataTimeZone); Assert.IsTrue(customData.Symbol.HasUnderlying, $"Custom data added as {ticker} Symbol with SecurityType {securityType} does not have underlying"); Assert.AreEqual(customData.Symbol.Underlying, asset.Symbol, $"Custom data underlying does not match {securityType} Symbol for {ticker}"); var assetSubscription = qcAlgorithm.SubscriptionManager.Subscriptions.Where(x => x.SecurityType == securityType).First(); var customDataSubscription = qcAlgorithm.SubscriptionManager.Subscriptions.Where(x => x.SecurityType == SecurityType.Base).Single(); var assetShouldBeMapped = assetSubscription.TickerShouldBeMapped(); var customShouldBeMapped = customDataSubscription.TickerShouldBeMapped(); if (securityType == SecurityType.Equity) { Assert.AreEqual(securityShouldBeMapped, assetShouldBeMapped); Assert.AreEqual(customDataShouldBeMapped, customShouldBeMapped); Assert.AreNotEqual(assetSubscription, customDataSubscription); if (assetShouldBeMapped == customShouldBeMapped) { Assert.AreEqual(assetSubscription.MappedSymbol, customDataSubscription.MappedSymbol); Assert.AreEqual(asset.Symbol.Value, customData.Symbol.Value.Split('.').First()); } } }
public void AddDataSecurityTickerNoUnderlying(string ticker, Type customDataType, SecurityType securityType, bool securityShouldBeMapped, bool customDataShouldBeMapped) { SymbolCache.Clear(); var qcAlgorithm = new QCAlgorithm(); qcAlgorithm.SubscriptionManager.SetDataManager(new DataManagerStub(qcAlgorithm)); Security asset; switch (securityType) { case SecurityType.Cfd: asset = qcAlgorithm.AddCfd(ticker, Resolution.Daily); break; case SecurityType.Crypto: asset = qcAlgorithm.AddCrypto(ticker, Resolution.Daily); break; case SecurityType.Equity: asset = qcAlgorithm.AddEquity(ticker, Resolution.Daily); break; case SecurityType.Forex: asset = qcAlgorithm.AddForex(ticker, Resolution.Daily); break; case SecurityType.Future: asset = qcAlgorithm.AddFuture(ticker, Resolution.Daily); break; default: throw new Exception($"SecurityType {securityType} is not valid for this test"); } // Dummy here is meant to try to corrupt the SymbolCache. Ideally, SymbolCache should return non-custom data types with higher priority // in case we want to add two custom data types, but still have them associated with the equity from the cache if we're using it. // This covers the case where two idential data subscriptions are created. var dummy = qcAlgorithm.AddData(customDataType, ticker, Resolution.Daily, qcAlgorithm.SubscriptionManager.Subscriptions.Where(x => x.SecurityType == securityType).First().DataTimeZone); var customData = qcAlgorithm.AddData(customDataType, ticker, Resolution.Daily, qcAlgorithm.SubscriptionManager.Subscriptions.Where(x => x.SecurityType == securityType).First().DataTimeZone); // Check to see if we have an underlying symbol when we shouldn't Assert.IsFalse(customData.Symbol.HasUnderlying, $"{customDataType.Name} has underlying symbol for SecurityType {securityType} with ticker {ticker}"); Assert.AreEqual(customData.Symbol.Underlying, null, $"{customDataType.Name} - Custom data underlying Symbol for SecurityType {securityType} is not null"); var assetSubscription = qcAlgorithm.SubscriptionManager.Subscriptions.Where(x => x.SecurityType == securityType).First(); var customDataSubscription = qcAlgorithm.SubscriptionManager.Subscriptions.Where(x => x.SecurityType == SecurityType.Base).Single(); var assetShouldBeMapped = assetSubscription.TickerShouldBeMapped(); var customShouldBeMapped = customDataSubscription.TickerShouldBeMapped(); Assert.AreEqual(securityShouldBeMapped, assetShouldBeMapped); Assert.AreEqual(customDataShouldBeMapped, customShouldBeMapped); Assert.AreNotEqual(assetSubscription, customDataSubscription); if (assetShouldBeMapped == customShouldBeMapped) { // Would fail with CL future without this check because MappedSymbol returns "/CL" for the Future symbol if (assetSubscription.SecurityType == SecurityType.Future) { Assert.AreNotEqual(assetSubscription.MappedSymbol, customDataSubscription.MappedSymbol); Assert.AreNotEqual(asset.Symbol.Value, customData.Symbol.Value.Split('.').First()); } else { Assert.AreEqual(assetSubscription.MappedSymbol, customDataSubscription.MappedSymbol); Assert.AreEqual(asset.Symbol.Value, customData.Symbol.Value.Split('.').First()); } } }
/// <summary> /// Creates and adds a new <see cref="Crypto"/> security to the algorithm /// </summary> /// <param name="ticker">The currency pair</param> /// <param name="resolution">The <see cref="Resolution"/> of market data, Tick, Second, Minute, Hour, or Daily. Default is <see cref="Resolution.Minute"/></param> /// <param name="market">The cfd trading market, <seealso cref="Market"/>. Default value is null and looked up using BrokerageModel.DefaultMarkets in <see cref="AddSecurity{T}"/></param> /// <param name="fillDataForward">If true, returns the last available data even if none in that timeslice. Default is <value>true</value></param> /// <param name="leverage">The requested leverage for this equity. Default is set by <see cref="SecurityInitializer"/></param> /// <returns>The new <see cref="Crypto"/> security</returns> public Crypto AddCrypto(string ticker, Resolution resolution = Resolution.Minute, string market = null, bool fillDataForward = true, decimal leverage = 0m) { return(_algorithm.AddCrypto(ticker, resolution, market, fillDataForward, leverage)); }