public void GetInitialMarginRequirement(decimal quantity)
        {
            var algorithm = new QCAlgorithm();

            algorithm.SubscriptionManager.SetDataManager(new DataManagerStub(algorithm));
            var ticker = QuantConnect.Securities.Futures.Financials.EuroDollar;

            const decimal price            = 1.2345m;
            var           time             = new DateTime(2013, 1, 1);
            var           futureSecurity   = algorithm.AddFuture(ticker);
            var           buyingPowerModel = new TestFutureMarginModel();

            futureSecurity.SetMarketPrice(new Tick {
                Value = price, Time = time
            });
            futureSecurity.Holdings.SetHoldings(1.5m, quantity);

            var initialMargin = buyingPowerModel.GetInitialMarginRequirement(futureSecurity, futureSecurity.Holdings.AbsoluteQuantity);

            Assert.IsTrue(initialMargin > 0);
            var overnightMargin = Math.Abs(buyingPowerModel.GetMaintenanceMargin(futureSecurity));

            // initial margin is greater than the maintenance margin
            Assert.Greater(initialMargin, overnightMargin);
        }
        private static Security InitAndGetSecurity(QCAlgorithm algo, decimal fee, SecurityType securityType = SecurityType.Equity, string symbol = "SPY", DateTime?time = null)
        {
            algo.SubscriptionManager.SetDataManager(new DataManagerStub(algo));
            Security security;

            if (securityType == SecurityType.Equity)
            {
                security = algo.AddEquity(symbol);
                _symbol  = security.Symbol;
            }
            else if (securityType == SecurityType.Option)
            {
                security = algo.AddOption(symbol);
                _symbol  = security.Symbol;
            }
            else if (securityType == SecurityType.Future)
            {
                security = algo.AddFuture(symbol == "SPY" ? "ES" : symbol);
                _symbol  = security.Symbol;
            }
            else
            {
                throw new Exception("SecurityType not implemented");
            }

            security.FeeModel = new ConstantFeeModel(fee);
            Update(security, 25, time);
            return(security);
        }
示例#3
0
        private static Security InitAndGetSecurity(QCAlgorithm algo, decimal fee, SecurityType securityType = SecurityType.Equity, string symbol = "SPY")
        {
            algo.SubscriptionManager.SetDataManager(new DataManagerStub(algo));
            Security security;

            if (securityType == SecurityType.Equity)
            {
                security = algo.AddEquity(symbol);
                _symbol  = security.Symbol;
            }
            else if (securityType == SecurityType.Option)
            {
                security = algo.AddOption(symbol);
                _symbol  = security.Symbol;
            }
            else if (securityType == SecurityType.Future)
            {
                security = algo.AddFuture(symbol);
                _symbol  = security.Symbol;
            }
            else
            {
                throw new Exception("SecurityType not implemented");
            }

            security.TransactionModel = new ConstantFeeTransactionModel(fee);
            Update(algo.Portfolio.CashBook, security, 25);
            return(security);
        }
        public void PortfolioStatusPositionWhenPriceIncreases()
        {
            var algorithm = new QCAlgorithm();

            algorithm.SubscriptionManager.SetDataManager(new DataManagerStub(algorithm));

            var ticker         = QuantConnect.Securities.Futures.Financials.EuroDollar;
            var futureSecurity = algorithm.AddFuture(ticker);

            futureSecurity.BuyingPowerModel = GetModel(futureSecurity, out _futureMarginModel);
            futureSecurity.Holdings.SetHoldings(20, 100);
            Update(futureSecurity, 20, algorithm);

            var marginUsed = algorithm.Portfolio.TotalMarginUsed;

            Assert.IsTrue(marginUsed > 0);
            Assert.IsTrue(algorithm.Portfolio.TotalPortfolioValue > 0);
            Assert.IsTrue(algorithm.Portfolio.MarginRemaining > 0);

            // Increase from $20 to $40
            Update(futureSecurity, 40, algorithm);

            var expected = (40 - 20) * 100 * futureSecurity.SymbolProperties.ContractMultiplier - 1.85m * 100;

            Assert.AreEqual(futureSecurity.Holdings.UnrealizedProfit, expected);

            // we have a massive win because of futures leverage
            Assert.IsTrue(algorithm.Portfolio.TotalPortfolioValue > 0);
            Assert.IsTrue(algorithm.Portfolio.MarginRemaining > 0);

            // margin used didn't change because for futures it relies on the maintenance margin
            Assert.AreEqual(marginUsed, algorithm.Portfolio.TotalMarginUsed);
        }
        public void GetMaintenanceMargin(decimal quantity)
        {
            var algorithm = new QCAlgorithm();

            algorithm.SubscriptionManager.SetDataManager(new DataManagerStub(algorithm));
            var ticker = QuantConnect.Securities.Futures.Financials.EuroDollar;

            const decimal price            = 1.2345m;
            var           time             = new DateTime(2013, 1, 1);
            var           futureSecurity   = algorithm.AddFuture(ticker);
            var           buyingPowerModel = GetModel(futureSecurity, out _futureMarginModel);

            futureSecurity.SetMarketPrice(new Tick {
                Value = price, Time = time
            });
            futureSecurity.Holdings.SetHoldings(1.5m, quantity);

            var res = buyingPowerModel.GetMaintenanceMargin(futureSecurity);

            Assert.AreEqual(_futureMarginModel.MaintenanceOvernightMarginRequirement * futureSecurity.Holdings.AbsoluteQuantity, res);

            // We increase the quantity * 2, maintenance margin should DOUBLE
            futureSecurity.Holdings.SetHoldings(1.5m, quantity * 2);
            res = buyingPowerModel.GetMaintenanceMargin(futureSecurity);
            Assert.AreEqual(_futureMarginModel.MaintenanceOvernightMarginRequirement * futureSecurity.Holdings.AbsoluteQuantity, res);
        }
        public void GetInitialMarginRequiredForOrder(decimal quantity)
        {
            var algorithm = new QCAlgorithm();

            algorithm.SubscriptionManager.SetDataManager(new DataManagerStub(algorithm));
            var ticker = QuantConnect.Securities.Futures.Financials.EuroDollar;

            const decimal price            = 1.2345m;
            var           time             = new DateTime(2013, 1, 1);
            var           futureSecurity   = algorithm.AddFuture(ticker);
            var           buyingPowerModel = GetModel(futureSecurity, out _futureMarginModel);

            futureSecurity.SetMarketPrice(new Tick {
                Value = price, Time = time
            });
            futureSecurity.Holdings.SetHoldings(1.5m, quantity);

            var initialMargin = buyingPowerModel.GetInitialMarginRequiredForOrder(
                new InitialMarginRequiredForOrderParameters(algorithm.Portfolio.CashBook,
                                                            futureSecurity,
                                                            new MarketOrder(futureSecurity.Symbol, quantity, algorithm.UtcTime))).Value;

            var initialMarginExpected = buyingPowerModel.GetInitialMarginRequirement(futureSecurity, quantity);

            Assert.AreEqual(initialMarginExpected
                            + 18.50m * Math.Sign(quantity), // fees -> 10 quantity * 1.85
                            initialMargin);
        }
        public void NonAccountCurrency_GetMaintenanceMarginRequirement()
        {
            var algorithm = new QCAlgorithm();

            algorithm.SubscriptionManager.SetDataManager(new DataManagerStub(algorithm));
            algorithm.Portfolio.SetAccountCurrency("EUR");
            algorithm.Portfolio.SetCash(10000);
            algorithm.Portfolio.SetCash(Currencies.USD, 0, 0.88m);

            // For this symbol we dont have history
            var ticker = QuantConnect.Securities.Futures.Financials.EuroDollar;

            const decimal price          = 1.2345m;
            var           time           = new DateTime(2013, 1, 1);
            var           futureSecurity = algorithm.AddFuture(ticker);

            futureSecurity.SetMarketPrice(new Tick {
                Value = price, Time = time
            });
            futureSecurity.Holdings.SetHoldings(1.5m, 1);

            var buyingPowerModel = new FutureMarginModel();
            // 625 overnight / (1.5 price * 1 quantity * 0.88 rate * 2500 multiplier) ~= 0.18939
            var res = buyingPowerModel.GetMaintenanceMarginRequirement(futureSecurity);

            Assert.AreEqual(0.18939, (double)res, 0.00001);
        }
        public void HasSufficientBuyingPowerForOrderInvalidTargets(decimal target)
        {
            var algorithm = new QCAlgorithm();

            algorithm.SetFinishedWarmingUp();
            algorithm.SubscriptionManager.SetDataManager(new DataManagerStub(algorithm));
            var orderProcessor = new FakeOrderProcessor();

            algorithm.Transactions.SetOrderProcessor(orderProcessor);

            var ticker         = QuantConnect.Securities.Futures.Financials.EuroDollar;
            var futureSecurity = algorithm.AddFuture(ticker);

            // set closed market for simpler math
            futureSecurity.Exchange.SetLocalDateTimeFrontier(new DateTime(2020, 2, 1));
            Update(futureSecurity, 100, algorithm);
            var model = GetModel(futureSecurity, out _futureMarginModel, algorithm.Portfolio);

            var quantity = algorithm.CalculateOrderQuantity(futureSecurity.Symbol, target);
            var request  = GetOrderRequest(futureSecurity.Symbol, quantity);

            request.SetOrderId(0);
            orderProcessor.AddTicket(new OrderTicket(algorithm.Transactions, request));

            var result = model.HasSufficientBuyingPowerForOrder(new HasSufficientBuyingPowerForOrderParameters(
                                                                    algorithm.Portfolio,
                                                                    futureSecurity,
                                                                    // we get the maximum target value 1/-1 and add a lot size it shouldn't be a valid order
                                                                    new MarketOrder(futureSecurity.Symbol, quantity + futureSecurity.SymbolProperties.LotSize * Math.Sign(quantity), DateTime.UtcNow)));

            Assert.IsFalse(result.IsSufficient);
        }
        public void MarginRequirementsChangeWithDate()
        {
            var algorithm = new QCAlgorithm();

            algorithm.SubscriptionManager.SetDataManager(new DataManagerStub(algorithm));

            var ticker         = QuantConnect.Securities.Futures.Financials.EuroDollar;
            var futureSecurity = algorithm.AddFuture(ticker);
            var model          = futureSecurity.BuyingPowerModel as FutureMarginModel;

            Update(futureSecurity, 100, algorithm, new DateTime(2001, 01, 07));
            var initial     = model.InitialOvernightMarginRequirement;
            var maintenance = model.MaintenanceOvernightMarginRequirement;

            Assert.AreEqual(810, initial);
            Assert.AreEqual(600, maintenance);

            // date previous to margin change
            Update(futureSecurity, 100, algorithm, new DateTime(2001, 12, 10));
            Assert.AreEqual(810, initial);
            Assert.AreEqual(600, maintenance);

            // new margins!
            Update(futureSecurity, 100, algorithm, new DateTime(2001, 12, 11));
            Assert.AreEqual(945, model.InitialOvernightMarginRequirement);
            Assert.AreEqual(700, model.MaintenanceOvernightMarginRequirement);
        }
        public void IntradayVersusOvernightMargins(decimal target)
        {
            var algorithm = new QCAlgorithm();

            algorithm.SetFinishedWarmingUp();
            algorithm.SubscriptionManager.SetDataManager(new DataManagerStub(algorithm));
            var orderProcessor = new FakeOrderProcessor();

            algorithm.Transactions.SetOrderProcessor(orderProcessor);

            var ticker         = QuantConnect.Securities.Futures.Financials.EuroDollar;
            var futureSecurity = algorithm.AddFuture(ticker);
            var lotSize        = futureSecurity.SymbolProperties.LotSize;

            Update(futureSecurity, 100, algorithm);
            var model = GetModel(futureSecurity, out _futureMarginModel, algorithm.Portfolio);

            // Close market
            futureSecurity.Exchange.SetLocalDateTimeFrontier(new DateTime(2020, 2, 1));

            var quantityClosedMarket = algorithm.CalculateOrderQuantity(futureSecurity.Symbol, target);

            Assert.AreEqual(quantityClosedMarket.DiscretelyRoundBy(lotSize), quantityClosedMarket,
                            "Calculated order quantity was not whole number multiple of the lot size"
                            );
            var request = GetOrderRequest(futureSecurity.Symbol, quantityClosedMarket);

            request.SetOrderId(0);
            orderProcessor.AddTicket(new OrderTicket(algorithm.Transactions, request));

            Assert.IsTrue(model.HasSufficientBuyingPowerForOrder(
                              new HasSufficientBuyingPowerForOrderParameters(algorithm.Portfolio,
                                                                             futureSecurity,
                                                                             new MarketOrder(futureSecurity.Symbol, quantityClosedMarket, DateTime.UtcNow))).IsSufficient);

            var initialOvernight     = _futureMarginModel.InitialOvernightMarginRequirement;
            var maintenanceOvernight = _futureMarginModel.MaintenanceOvernightMarginRequirement;

            // Open market
            futureSecurity.Exchange.SetLocalDateTimeFrontier(new DateTime(2020, 2, 3));

            var fourtyPercentQuantity = (quantityClosedMarket * 0.4m).DiscretelyRoundBy(lotSize);

            futureSecurity.Holdings.SetHoldings(100, fourtyPercentQuantity);

            var halfQuantity = (quantityClosedMarket / 2).DiscretelyRoundBy(lotSize);

            Assert.IsTrue(model.HasSufficientBuyingPowerForOrder(
                              new HasSufficientBuyingPowerForOrderParameters(algorithm.Portfolio,
                                                                             futureSecurity,
                                                                             new MarketOrder(futureSecurity.Symbol, halfQuantity, DateTime.UtcNow))).IsSufficient);

            Assert.Greater(initialOvernight, _futureMarginModel.InitialIntradayMarginRequirement);
            Assert.Greater(maintenanceOvernight, _futureMarginModel.MaintenanceIntradayMarginRequirement);
        }
        public void ClosingSoonIntradayClosedMarketMargins(decimal target)
        {
            var algorithm = new QCAlgorithm();

            algorithm.SetFinishedWarmingUp();
            algorithm.SubscriptionManager.SetDataManager(new DataManagerStub(algorithm));
            var orderProcessor = new FakeOrderProcessor();

            algorithm.Transactions.SetOrderProcessor(orderProcessor);

            var ticker         = QuantConnect.Securities.Futures.Financials.EuroDollar;
            var futureSecurity = algorithm.AddFuture(ticker);

            Update(futureSecurity, 100, algorithm);
            var localTime  = new DateTime(2020, 2, 3);
            var utcTime    = localTime.ConvertToUtc(futureSecurity.Exchange.TimeZone);
            var timeKeeper = new TimeKeeper(utcTime, futureSecurity.Exchange.TimeZone);
            var model      = GetModel(futureSecurity, out _futureMarginModel, algorithm.Portfolio);

            // this is important
            _futureMarginModel.EnableIntradayMargins = true;

            // Open market
            futureSecurity.Exchange.SetLocalDateTimeFrontier(localTime);

            var quantity = algorithm.CalculateOrderQuantity(futureSecurity.Symbol, target);
            var request  = GetOrderRequest(futureSecurity.Symbol, quantity);

            request.SetOrderId(0);
            orderProcessor.AddTicket(new OrderTicket(algorithm.Transactions, request));

            Assert.IsTrue(model.HasSufficientBuyingPowerForOrder(
                              new HasSufficientBuyingPowerForOrderParameters(algorithm.Portfolio,
                                                                             futureSecurity,
                                                                             new MarketOrder(futureSecurity.Symbol, quantity, DateTime.UtcNow))).IsSufficient);

            // Closing soon market
            futureSecurity.Exchange.SetLocalDateTimeFrontier(new DateTime(2020, 2, 3, 15, 50, 0));

            Assert.IsFalse(model.HasSufficientBuyingPowerForOrder(
                               new HasSufficientBuyingPowerForOrderParameters(algorithm.Portfolio,
                                                                              futureSecurity,
                                                                              new MarketOrder(futureSecurity.Symbol, quantity, DateTime.UtcNow))).IsSufficient);
            Assert.IsTrue(futureSecurity.Exchange.ExchangeOpen);
            Assert.IsTrue(futureSecurity.Exchange.ClosingSoon);

            // Close market
            futureSecurity.Exchange.SetLocalDateTimeFrontier(new DateTime(2020, 2, 1));
            Assert.IsFalse(futureSecurity.Exchange.ExchangeOpen);

            Assert.IsFalse(model.HasSufficientBuyingPowerForOrder(
                               new HasSufficientBuyingPowerForOrderParameters(algorithm.Portfolio,
                                                                              futureSecurity,
                                                                              new MarketOrder(futureSecurity.Symbol, quantity, DateTime.UtcNow))).IsSufficient);
        }
示例#12
0
        public void Setup()
        {
            var algo                = new QCAlgorithm();
            var settings            = new UniverseSettings(Resolution.Second, 1, true, false, TimeSpan.Zero);
            var timeKeeper          = new TimeKeeper(new DateTime(2015, 12, 07));
            var subscriptionManager = new SubscriptionManager(timeKeeper);
            var securityInitializer = SecurityInitializer.Null;

            _canonicalSecurity    = algo.AddFuture(RootGold);
            _futuresChainUniverse = new FuturesChainUniverse(_canonicalSecurity, settings, subscriptionManager, securityInitializer);
        }
        public void SetLeverageThrowsException(int leverage)
        {
            var algorithm = new QCAlgorithm();

            algorithm.SubscriptionManager.SetDataManager(new DataManagerStub(algorithm));

            var ticker         = QuantConnect.Securities.Futures.Financials.EuroDollar;
            var futureSecurity = algorithm.AddFuture(ticker);

            Assert.Throws <InvalidOperationException>(() => futureSecurity.BuyingPowerModel.SetLeverage(futureSecurity, leverage));
        }
示例#14
0
        public void AddFutureOptionAddsUniverseSelectionModel()
        {
            var algo = new QCAlgorithm();

            algo.SubscriptionManager.SetDataManager(new DataManagerStub(algo));

            var underlying = algo.AddFuture("ES", Resolution.Minute, Market.CME);

            underlying.SetFilter(0, 365);

            algo.AddFutureOption(underlying.Symbol, _ => _);
            Assert.IsTrue(algo.UniverseSelection is OptionChainedUniverseSelectionModel);
        }
        public void GetMaximumOrderQuantityForTargetBuyingPower_ThrowsForInvalidTarget(decimal target)
        {
            var algorithm = new QCAlgorithm();

            algorithm.SubscriptionManager.SetDataManager(new DataManagerStub(algorithm));

            var ticker         = QuantConnect.Securities.Futures.Financials.EuroDollar;
            var futureSecurity = algorithm.AddFuture(ticker);

            Assert.Throws <InvalidOperationException>(() => futureSecurity.BuyingPowerModel.GetMaximumOrderQuantityForTargetBuyingPower(
                                                          new GetMaximumOrderQuantityForTargetBuyingPowerParameters(algorithm.Portfolio,
                                                                                                                    futureSecurity,
                                                                                                                    target)));
        }
        public void GetLeverage()
        {
            var algorithm = new QCAlgorithm();

            algorithm.SubscriptionManager.SetDataManager(new DataManagerStub(algorithm));

            var ticker         = QuantConnect.Securities.Futures.Financials.EuroDollar;
            var futureSecurity = algorithm.AddFuture(ticker);

            Update(futureSecurity, 100, algorithm);
            var leverage = futureSecurity.BuyingPowerModel.GetLeverage(futureSecurity);

            Assert.AreEqual(1, leverage);
        }
示例#17
0
        public void SubscriptionHistoryRequestWithDifferentDataMappingMode()
        {
            var dataMappingModes = GetAllDataMappingModes();
            var historyStart     = new DateTime(2013, 10, 6);
            var historyEnd       = new DateTime(2014, 1, 1);
            var resolution       = Resolution.Daily;

            _algorithm = GetAlgorithm(historyEnd);
            var symbol = _algorithm.AddFuture(Futures.Indices.SP500EMini, resolution, dataMappingMode: dataMappingModes.First()).Symbol;

            var historyResults = dataMappingModes
                                 .Select(x => _algorithm.History(new [] { symbol }, historyStart, historyEnd, resolution, dataMappingMode: x).ToList())
                                 .ToList();

            CheckThatHistoryResultsHaveEqualBarCount(historyResults);

            // Check that all history results have a mapping date at some point in the history
            HashSet <DateTime> mappingDates = new HashSet <DateTime>();

            for (int i = 0; i < historyResults.Count; i++)
            {
                var underlying    = historyResults[i].First().Bars.Keys.First().Underlying;
                int mappingsCount = 0;

                foreach (var slice in historyResults[i])
                {
                    var dataUnderlying = slice.Bars.Keys.First().Underlying;
                    if (dataUnderlying != underlying)
                    {
                        underlying = dataUnderlying;
                        mappingsCount++;
                        mappingDates.Add(slice.Time.Date);
                    }
                }

                if (mappingsCount == 0)
                {
                    throw new Exception($"History results for {dataMappingModes[i]} data mapping mode did not contain any mappings");
                }
            }

            if (mappingDates.Count < dataMappingModes.Length)
            {
                throw new Exception($"History results should have had different mapping dates for each data mapping mode");
            }

            CheckThatHistoryResultsHaveDifferentClosePrices(historyResults, dataMappingModes.Length,
                                                            $"History results close prices should have been different for each data mapping mode at each time");
        }
        public void IntradayVersusOvernightMargins(decimal target)
        {
            var algorithm = new QCAlgorithm();

            algorithm.SetFinishedWarmingUp();
            algorithm.SubscriptionManager.SetDataManager(new DataManagerStub(algorithm));
            var orderProcessor = new FakeOrderProcessor();

            algorithm.Transactions.SetOrderProcessor(orderProcessor);

            var ticker         = QuantConnect.Securities.Futures.Financials.EuroDollar;
            var futureSecurity = algorithm.AddFuture(ticker);

            Update(futureSecurity, 100, algorithm);
            var model = futureSecurity.BuyingPowerModel as FutureMarginModel;

            // Close market
            futureSecurity.Exchange.SetLocalDateTimeFrontier(new DateTime(2020, 2, 1));

            var quantityClosedMarket = algorithm.CalculateOrderQuantity(futureSecurity.Symbol, target);
            var request = GetOrderRequest(futureSecurity.Symbol, quantityClosedMarket);

            request.SetOrderId(0);
            orderProcessor.AddTicket(new OrderTicket(algorithm.Transactions, request));

            Assert.IsTrue(model.HasSufficientBuyingPowerForOrder(
                              new HasSufficientBuyingPowerForOrderParameters(algorithm.Portfolio,
                                                                             futureSecurity,
                                                                             new MarketOrder(futureSecurity.Symbol, quantityClosedMarket, DateTime.UtcNow))).IsSufficient);

            var initialOvernight     = model.InitialOvernightMarginRequirement;
            var maintenanceOvernight = model.MaintenanceOvernightMarginRequirement;

            // Open market
            futureSecurity.Exchange.SetLocalDateTimeFrontier(new DateTime(2020, 2, 3));

            futureSecurity.Holdings.SetHoldings(100, quantityClosedMarket * 0.4m);

            Assert.IsTrue(model.HasSufficientBuyingPowerForOrder(
                              new HasSufficientBuyingPowerForOrderParameters(algorithm.Portfolio,
                                                                             futureSecurity,
                                                                             new MarketOrder(futureSecurity.Symbol, quantityClosedMarket / 2, DateTime.UtcNow))).IsSufficient);

            Assert.Greater(initialOvernight, model.InitialIntradayMarginRequirement);
            Assert.Greater(maintenanceOvernight, model.MaintenanceIntradayMarginRequirement);
        }
示例#19
0
        public void AddOptionWithUnderlyingFuture()
        {
            // Adds an option containing a Future as its underlying Symbol.
            // This is an essential step in enabling custom derivatives
            // based on any asset class provided to Option. This test
            // checks the ability to create Future Options.
            var algo = new QCAlgorithm();

            algo.SubscriptionManager.SetDataManager(new DataManagerStub(algo));

            var underlying = algo.AddFuture("ES", Resolution.Minute, Market.CME);

            underlying.SetFilter(0, 365);

            var futureOption = algo.AddOption(underlying.Symbol, Resolution.Minute);

            Assert.IsTrue(futureOption.Symbol.HasUnderlying);
            Assert.AreEqual(underlying.Symbol, futureOption.Symbol.Underlying);
        }
        public void GetMaximumOrderQuantityForTargetBuyingPower_WithHoldingsInverseDirection(decimal target)
        {
            var algorithm = new QCAlgorithm();

            algorithm.SetFinishedWarmingUp();
            algorithm.SubscriptionManager.SetDataManager(new DataManagerStub(algorithm));
            var orderProcessor = new FakeOrderProcessor();

            algorithm.Transactions.SetOrderProcessor(orderProcessor);

            var ticker         = QuantConnect.Securities.Futures.Financials.EuroDollar;
            var futureSecurity = algorithm.AddFuture(ticker);

            // set closed market for simpler math
            futureSecurity.Exchange.SetLocalDateTimeFrontier(new DateTime(2020, 2, 1));
            futureSecurity.Holdings.SetHoldings(100, 10 * -1 * Math.Sign(target));
            Update(futureSecurity, 100, algorithm);

            var model = GetModel(futureSecurity, out _futureMarginModel, algorithm.Portfolio);

            futureSecurity.BuyingPowerModel = _futureMarginModel;

            var quantity = algorithm.CalculateOrderQuantity(futureSecurity.Symbol, target);

            var expected = (algorithm.Portfolio.TotalPortfolioValue * Math.Abs(target) + Math.Abs(model.GetInitialMarginRequirement(futureSecurity, futureSecurity.Holdings.Quantity)))
                           / _futureMarginModel.InitialOvernightMarginRequirement - 1 * Math.Abs(target); // -1 fees

            expected -= expected % futureSecurity.SymbolProperties.LotSize;
            Log.Trace($"Expected {expected}");

            Assert.AreEqual(expected * Math.Sign(target), quantity);

            var request = GetOrderRequest(futureSecurity.Symbol, quantity);

            request.SetOrderId(0);
            orderProcessor.AddTicket(new OrderTicket(algorithm.Transactions, request));

            Assert.IsTrue(model.HasSufficientBuyingPowerForOrder(
                              new HasSufficientBuyingPowerForOrderParameters(algorithm.Portfolio,
                                                                             futureSecurity,
                                                                             new MarketOrder(futureSecurity.Symbol, expected * Math.Sign(target), DateTime.UtcNow))).IsSufficient);
        }
        public void NonAccountCurrency_GetBuyingPower(decimal nonAccountCurrencyCash)
        {
            var algorithm = new QCAlgorithm();

            algorithm.SubscriptionManager.SetDataManager(new DataManagerStub(algorithm));
            algorithm.Portfolio.SetAccountCurrency("EUR");
            algorithm.Portfolio.SetCash(10000);
            algorithm.Portfolio.SetCash(Currencies.USD, nonAccountCurrencyCash, 0.88m);

            // For this symbol we dont have history
            var ticker = QuantConnect.Securities.Futures.Financials.EuroDollar;

            var futureSecurity = algorithm.AddFuture(ticker);

            var buyingPowerModel = new FutureMarginModel();
            var quantity         = buyingPowerModel.GetBuyingPower(new BuyingPowerParameters(
                                                                       algorithm.Portfolio, futureSecurity, OrderDirection.Buy));

            Assert.AreEqual(10000m + algorithm.Portfolio.CashBook[Currencies.USD].ValueInAccountCurrency,
                            quantity.Value);
        }
        public void GetMaximumOrderQuantityForTargetBuyingPower_TwoStep(decimal target)
        {
            var algorithm = new QCAlgorithm();

            algorithm.SetFinishedWarmingUp();
            algorithm.SubscriptionManager.SetDataManager(new DataManagerStub(algorithm));
            var orderProcessor = new FakeOrderProcessor();

            algorithm.Transactions.SetOrderProcessor(orderProcessor);

            var ticker         = QuantConnect.Securities.Futures.Financials.EuroDollar;
            var futureSecurity = algorithm.AddFuture(ticker);

            futureSecurity.BuyingPowerModel = GetModel(futureSecurity, out _futureMarginModel, algorithm.Portfolio);
            // set closed market for simpler math
            futureSecurity.Exchange.SetLocalDateTimeFrontier(new DateTime(2020, 2, 1));
            Update(futureSecurity, 100, algorithm);
            var expectedFinalQuantity = algorithm.CalculateOrderQuantity(futureSecurity.Symbol, target);

            var quantity = algorithm.CalculateOrderQuantity(futureSecurity.Symbol, target / 2);

            futureSecurity.Holdings.SetHoldings(100, quantity);
            algorithm.Portfolio.InvalidateTotalPortfolioValue();

            var quantity2 = algorithm.CalculateOrderQuantity(futureSecurity.Symbol, target);

            var request = GetOrderRequest(futureSecurity.Symbol, quantity2);

            request.SetOrderId(0);
            orderProcessor.AddTicket(new OrderTicket(algorithm.Transactions, request));

            Assert.IsTrue(futureSecurity.BuyingPowerModel.HasSufficientBuyingPowerForOrder(
                              new HasSufficientBuyingPowerForOrderParameters(algorithm.Portfolio,
                                                                             futureSecurity,
                                                                             new MarketOrder(futureSecurity.Symbol, quantity2, DateTime.UtcNow))).IsSufficient);

            // two step operation is the same as 1 step
            Assert.AreEqual(expectedFinalQuantity, quantity + quantity2);
        }
        public void MarginUsedForPositionWhenPriceIncreases(decimal quantity)
        {
            var algorithm = new QCAlgorithm();

            algorithm.SubscriptionManager.SetDataManager(new DataManagerStub(algorithm));

            var ticker         = QuantConnect.Securities.Futures.Financials.EuroDollar;
            var futureSecurity = algorithm.AddFuture(ticker);

            futureSecurity.Holdings.SetHoldings(20, quantity);
            Update(futureSecurity, 20, algorithm);

            var marginForPosition = futureSecurity.BuyingPowerModel.GetReservedBuyingPowerForPosition(
                new ReservedBuyingPowerForPositionParameters(futureSecurity)).AbsoluteUsedBuyingPower;

            // Increase from $20 to $40
            Update(futureSecurity, 40, algorithm);

            var marginForPositionAfter = futureSecurity.BuyingPowerModel.GetReservedBuyingPowerForPosition(
                new ReservedBuyingPowerForPositionParameters(futureSecurity)).AbsoluteUsedBuyingPower;

            Assert.AreEqual(marginForPosition, marginForPositionAfter);
        }
示例#24
0
        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());
                }
            }
        }
示例#25
0
        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());
                }
            }
        }
示例#26
0
文件: QuantBook.cs 项目: yuzhucu/Lean
 /// <summary>
 /// Creates and adds a new <see cref="Future"/> security to the algorithm
 /// </summary>
 /// <param name="symbol">The futures contract symbol</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 futures market, <seealso cref="Market"/>. Default is value 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="Future"/> security</returns>
 public Future AddFuture(string symbol, Resolution resolution = Resolution.Minute, string market = null, bool fillDataForward = true, decimal leverage = 0m)
 {
     return(_algorithm.AddFuture(symbol, resolution, market, fillDataForward, leverage));
 }