protected override IBrokerage CreateBrokerage(IOrderProvider orderProvider, ISecurityProvider securityProvider) { var restClient = new RestClient("https://api.pro.coinbase.com"); var webSocketClient = new WebSocketClientWrapper(); var securities = new SecurityManager(new TimeKeeper(DateTime.UtcNow, TimeZones.NewYork)) { { Symbol, CreateSecurity(Symbol) } }; var transactions = new SecurityTransactionManager(null, securities); transactions.SetOrderProcessor(new FakeOrderProcessor()); var algorithm = new Mock <IAlgorithm>(); algorithm.Setup(a => a.Transactions).Returns(transactions); algorithm.Setup(a => a.BrokerageModel).Returns(new GDAXBrokerageModel()); algorithm.Setup(a => a.Portfolio).Returns(new SecurityPortfolioManager(securities, transactions)); algorithm.Setup(a => a.Securities).Returns(securities); var priceProvider = new Mock <IPriceProvider>(); priceProvider.Setup(a => a.GetLastPrice(It.IsAny <Symbol>())).Returns(1.234m); var aggregator = new AggregationManager(); return(new GDAXBrokerage(Config.Get("gdax-url", "wss://ws-feed.pro.coinbase.com"), webSocketClient, restClient, Config.Get("gdax-api-key"), Config.Get("gdax-api-secret"), Config.Get("gdax-passphrase"), algorithm.Object, priceProvider.Object, aggregator)); }
/// <summary> /// Creates the brokerage under test and connects it /// </summary> /// <param name="orderProvider"></param> /// <param name="securityProvider"></param> /// <returns></returns> protected override IBrokerage CreateBrokerage(IOrderProvider orderProvider, ISecurityProvider securityProvider) { var securities = new SecurityManager(new TimeKeeper(DateTime.UtcNow, TimeZones.NewYork)) { { Symbol, CreateSecurity(Symbol) } }; var transactions = new SecurityTransactionManager(null, securities); transactions.SetOrderProcessor(new FakeOrderProcessor()); var algorithm = new Mock <IAlgorithm>(); algorithm.Setup(a => a.Transactions).Returns(transactions); algorithm.Setup(a => a.BrokerageModel).Returns(new BitfinexBrokerageModel()); algorithm.Setup(a => a.Portfolio).Returns(new SecurityPortfolioManager(securities, transactions)); var priceProvider = new Mock <IPriceProvider>(); priceProvider.Setup(a => a.GetLastPrice(It.IsAny <Symbol>())).Returns(1.234m); return(new BitfinexBrokerage( Config.Get("bitfinex-api-key"), Config.Get("bitfinex-api-secret"), algorithm.Object, priceProvider.Object, new AggregationManager() )); }
/// <summary> /// Creates the brokerage under test and connects it /// </summary> /// <param name="orderProvider"></param> /// <param name="securityProvider"></param> /// <returns></returns> protected override IBrokerage CreateBrokerage(IOrderProvider orderProvider, ISecurityProvider securityProvider) { var securities = new SecurityManager(new TimeKeeper(DateTime.UtcNow, new[] { TimeZones.NewYork })); securities.Add(Symbol, CreateSecurity(Symbol)); var transactions = new SecurityTransactionManager(null, securities); transactions.SetOrderProcessor(new FakeOrderProcessor()); var algorithm = new Mock <IAlgorithm>(); algorithm.Setup(a => a.Transactions).Returns(transactions); algorithm.Setup(a => a.BrokerageModel).Returns(new BitfinexBrokerageModel(AccountType.Margin)); algorithm.Setup(a => a.Portfolio).Returns(new SecurityPortfolioManager(securities, transactions)); var priceProvider = new Mock <IPriceProvider>(); priceProvider.Setup(a => a.GetLastPrice(It.IsAny <Symbol>())).Returns(1.234m); return(new BitfinexBrokerage( Config.Get("bitfinex-url", "wss://api.bitfinex.com/ws"), Config.Get("bitfinex-rest", "https://api.bitfinex.com"), Config.Get("bitfinex-api-key"), Config.Get("bitfinex-api-secret"), algorithm.Object, priceProvider.Object )); }
/// <summary> /// Creates the brokerage under test /// </summary> /// <returns>A connected brokerage instance</returns> protected IBrokerage CreateBrokerage(IOrderProvider orderProvider, ISecurityProvider securityProvider) { var securities = new SecurityManager(new TimeKeeper(DateTime.UtcNow, TimeZones.Kolkata)) { { Symbol, CreateSecurity(Symbol) } }; var transactions = new SecurityTransactionManager(null, securities); transactions.SetOrderProcessor(new FakeOrderProcessor()); var algorithm = new Mock <IAlgorithm>(); algorithm.Setup(a => a.Transactions).Returns(transactions); algorithm.Setup(a => a.BrokerageModel).Returns(new ZerodhaBrokerageModel()); algorithm.Setup(a => a.Portfolio).Returns(new SecurityPortfolioManager(securities, transactions)); var accessToken = Config.Get("zerodha-access-token"); var apiKey = Config.Get("zerodha-api-key"); var tradingSegment = Config.Get("zerodha-trading-segment"); var productType = Config.Get("zerodha-product-type"); var zerodha = new ZerodhaBrokerage(tradingSegment, productType, apiKey, accessToken, algorithm.Object, algorithm.Object.Portfolio, new AggregationManager()); return(zerodha); }
/// <summary> /// Creates the brokerage under test and connects it /// </summary> /// <param name="orderProvider"></param> /// <param name="securityProvider"></param> /// <returns></returns> protected override IBrokerage CreateBrokerage(IOrderProvider orderProvider, ISecurityProvider securityProvider) { var securities = new SecurityManager(new TimeKeeper(DateTime.UtcNow, TimeZones.NewYork)) { { Symbol, CreateSecurity(Symbol) } }; var transactions = new SecurityTransactionManager(null, securities); transactions.SetOrderProcessor(new FakeOrderProcessor()); var algorithm = new Mock <IAlgorithm>(); algorithm.Setup(a => a.Transactions).Returns(transactions); algorithm.Setup(a => a.BrokerageModel).Returns(new BinanceBrokerageModel()); algorithm.Setup(a => a.Portfolio).Returns(new SecurityPortfolioManager(securities, transactions)); var apiKey = Config.Get("binance-api-key"); var apiSecret = Config.Get("binance-api-secret"); _binanceApi = new BinanceRestApiClient( new SymbolPropertiesDatabaseSymbolMapper(Market.Binance), algorithm.Object?.Portfolio, apiKey, apiSecret); return(new BinanceBrokerage( apiKey, apiSecret, algorithm.Object, new AggregationManager(), null )); }
public void ConnectToUserDataStreamIfAlgorithmNotNullAndApiIsCreated() { var securities = new SecurityManager(new TimeKeeper(DateTime.UtcNow, TimeZones.NewYork)); var transactions = new SecurityTransactionManager(null, securities); transactions.SetOrderProcessor(new FakeOrderProcessor()); var algorithm = new Mock <IAlgorithm>(); algorithm.Setup(a => a.Transactions).Returns(transactions); algorithm.Setup(a => a.BrokerageModel).Returns(new BinanceBrokerageModel()); algorithm.Setup(a => a.Portfolio).Returns(new SecurityPortfolioManager(securities, transactions)); using var brokerage = CreateBrokerage(algorithm.Object); Assert.True(brokerage.IsConnected); var _ = brokerage.GetCashBalance(); Assert.True(brokerage.IsConnected); brokerage.Disconnect(); Assert.False(brokerage.IsConnected); }
public void OptimizerResultHandlerTest() { var shadow = new Wrapper(); Type shadowType = shadow.GetType(); var unit = new OptimizerResultHandler(shadow); var flags = BindingFlags.Instance | BindingFlags.NonPublic; var algorithmMock = new Mock <IAlgorithm>(); var securityManager = new SecurityManager(Mock.Of <ITimeKeeper>()); var securityTransactionManager = new SecurityTransactionManager(algorithmMock.Object, securityManager); var orderProcessor = new Mock <IOrderProcessor>(); orderProcessor.Setup(o => o.GetOpenOrders(It.IsAny <Func <Order, bool> >())).Returns(new List <Order>()); securityTransactionManager.SetOrderProcessor(orderProcessor.Object); algorithmMock.Setup(a => a.Portfolio).Returns(new SecurityPortfolioManager(securityManager, securityTransactionManager)); var tradeBuilder = new Mock <ITradeBuilder>(); tradeBuilder.Setup(t => t.ClosedTrades).Returns(new List <QuantConnect.Statistics.Trade>()); algorithmMock.Setup(a => a.TradeBuilder).Returns(tradeBuilder.Object); unit.SetAlgorithm(algorithmMock.Object, 100); shadowType.GetProperty("Algorithm", flags).SetValue(shadow, algorithmMock.Object); securityTransactionManager.TransactionRecord.Add(DateTime.Now, 100); algorithmMock.Setup(s => s.Transactions).Returns(securityTransactionManager); var transactionHandler = new Mock <ITransactionHandler>(); transactionHandler.Setup(v => v.Orders).Returns(new ConcurrentDictionary <int, Order>()); shadowType.GetField("TransactionHandler", flags).SetValue(shadow, transactionHandler.Object); var startTime = shadowType.BaseType.BaseType.GetRuntimeFields().Single(s => s.Name.Contains("StartTime")); startTime.SetValue(shadow, DateTime.Now); var messagingHandler = new MessagingWrapper(); shadowType.GetField("MessagingHandler", flags).SetValue(shadow, messagingHandler); unit.SendFinalResult(); Assert.True((bool)shadowType.BaseType.GetField("ExitTriggered", flags).GetValue(shadow)); transactionHandler.Verify(v => v.Orders); Assert.True(messagingHandler.SendWasCalled); Assert.AreEqual(20, unit.FullResults.Count()); }
private SecurityPortfolioManager GetPortfolio(IOrderProcessor orderProcessor, int quantity) { var securities = new SecurityManager(new TimeKeeper(DateTime.Now, new[] { TimeZones.NewYork })); var transactions = new SecurityTransactionManager(null, securities); transactions.SetOrderProcessor(orderProcessor); var portfolio = new SecurityPortfolioManager(securities, transactions); portfolio.SetCash(quantity); return(portfolio); }
private SecurityPortfolioManager GetPortfolio(IOrderProcessor orderProcessor, int quantity, DateTime time) { var securities = new SecurityManager(new TimeKeeper(time.ConvertToUtc(TimeZones.NewYork), TimeZones.NewYork)); var transactions = new SecurityTransactionManager(null, securities); transactions.SetOrderProcessor(orderProcessor); var portfolio = new SecurityPortfolioManager(securities, transactions); portfolio.SetCash(quantity); portfolio.MarginCallModel = new TestDefaultMarginCallModel(portfolio, new OrderProperties()); return(portfolio); }
public void OptionExercise_NonAccountCurrency() { var algorithm = new QCAlgorithm(); var securities = new SecurityManager(new TimeKeeper(DateTime.Now, TimeZones.NewYork)); var transactions = new SecurityTransactionManager(null, securities); var transactionHandler = new BacktestingTransactionHandler(); var portfolio = new SecurityPortfolioManager(securities, transactions); var EUR = new Cash("EUR", 100 * 192, 10); portfolio.CashBook.Add("EUR", EUR); portfolio.SetCash("USD", 0, 1); algorithm.Securities = securities; transactionHandler.Initialize(algorithm, new BacktestingBrokerage(algorithm), _resultHandler); transactions.SetOrderProcessor(transactionHandler); securities.Add( Symbols.SPY, new Security( SecurityExchangeHours.AlwaysOpen(TimeZones.NewYork), CreateTradeBarConfig(Symbols.SPY), EUR, SymbolProperties.GetDefault(EUR.Symbol), ErrorCurrencyConverter.Instance, RegisteredSecurityDataTypesProvider.Null, new SecurityCache() ) ); securities.Add( Symbols.SPY_C_192_Feb19_2016, new Option( SecurityExchangeHours.AlwaysOpen(TimeZones.NewYork), CreateTradeBarConfig(Symbols.SPY_C_192_Feb19_2016), EUR, new OptionSymbolProperties(new SymbolProperties("EUR", "EUR", 100, 0.01m, 1)), ErrorCurrencyConverter.Instance, RegisteredSecurityDataTypesProvider.Null ) ); securities[Symbols.SPY_C_192_Feb19_2016].Holdings.SetHoldings(1, 1); securities[Symbols.SPY].SetMarketPrice(new Tick { Value = 200 }); transactions.AddOrder(new SubmitOrderRequest(OrderType.OptionExercise, SecurityType.Option, Symbols.SPY_C_192_Feb19_2016, -1, 0, 0, securities.UtcTime, "")); var option = (Option)securities[Symbols.SPY_C_192_Feb19_2016]; var order = (OptionExerciseOrder)transactions.GetOrders(x => true).First(); option.Underlying = securities[Symbols.SPY]; var fills = option.OptionExerciseModel.OptionExercise(option, order).ToList(); Assert.AreEqual(2, fills.Count); Assert.IsFalse(fills[0].IsAssignment); Assert.AreEqual("Automatic Exercise", fills[0].Message); Assert.AreEqual("Option Exercise", fills[1].Message); foreach (var fill in fills) { portfolio.ProcessFill(fill); } // now we have long position in SPY with average price equal to strike var newUnderlyingHoldings = securities[Symbols.SPY].Holdings; // we added 100*192 EUR (strike price) at beginning, all consumed by exercise Assert.AreEqual(0, EUR.Amount); Assert.AreEqual(0, portfolio.CashBook["USD"].Amount); Assert.AreEqual(100, newUnderlyingHoldings.Quantity); Assert.AreEqual(192.0, newUnderlyingHoldings.AveragePrice); // and long call option position has disappeared Assert.AreEqual(0, securities[Symbols.SPY_C_192_Feb19_2016].Holdings.Quantity); }
public void ComputeMarginProperlyShortCoverZeroLong() { const decimal leverage = 2m; const int amount = 1000; const int quantity = (int)(amount * leverage); var securities = new SecurityManager(TimeKeeper); var transactions = new SecurityTransactionManager(securities); var orderProcessor = new OrderProcessor(); transactions.SetOrderProcessor(orderProcessor); var portfolio = new SecurityPortfolioManager(securities, transactions); portfolio.CashBook["USD"].SetAmount(amount); var config = CreateTradeBarDataConfig(SecurityType.Equity, Symbols.AAPL); securities.Add(new Security(SecurityExchangeHours, config, new Cash(CashBook.AccountCurrency, 0, 1m), SymbolProperties.GetDefault(CashBook.AccountCurrency))); var security = securities[Symbols.AAPL]; security.SetLeverage(leverage); var time = DateTime.Now; const decimal sellPrice = 1m; security.SetMarketPrice(new TradeBar(time, Symbols.AAPL, sellPrice, sellPrice, sellPrice, sellPrice, 1)); var order = new MarketOrder(Symbols.AAPL, -quantity, time) { Price = sellPrice }; var fill = new OrderEvent(order, DateTime.UtcNow, 0) { FillPrice = sellPrice, FillQuantity = -quantity }; orderProcessor.AddOrder(order); var request = new SubmitOrderRequest(OrderType.Market, security.Type, security.Symbol, order.Quantity, 0, 0, order.Time, null); request.SetOrderId(0); orderProcessor.AddTicket(new OrderTicket(null, request)); portfolio.ProcessFill(fill); // we shouldn't be able to place a new short order var newOrder = new MarketOrder(Symbols.AAPL, -1, time.AddSeconds(1)) { Price = sellPrice }; var sufficientCapital = transactions.GetSufficientCapitalForOrder(portfolio, newOrder); Assert.IsFalse(sufficientCapital); // we should be able to place cover to zero newOrder = new MarketOrder(Symbols.AAPL, quantity, time.AddSeconds(1)) { Price = sellPrice }; sufficientCapital = transactions.GetSufficientCapitalForOrder(portfolio, newOrder); Assert.IsTrue(sufficientCapital); // now the stock doubles, so we should have negative margin remaining time = time.AddDays(1); const decimal highPrice = sellPrice * 2; security.SetMarketPrice(new TradeBar(time, Symbols.AAPL, highPrice, highPrice, highPrice, highPrice, 1)); // we still shouldn be able to place cover to zero newOrder = new MarketOrder(Symbols.AAPL, quantity, time.AddSeconds(1)) { Price = highPrice }; sufficientCapital = transactions.GetSufficientCapitalForOrder(portfolio, newOrder); Assert.IsTrue(sufficientCapital); // we shouldn't be able to place cover to long newOrder = new MarketOrder(Symbols.AAPL, quantity + 1, time.AddSeconds(1)) { Price = highPrice }; sufficientCapital = transactions.GetSufficientCapitalForOrder(portfolio, newOrder); Assert.IsFalse(sufficientCapital); }
public void MarginComputesProperlyWithMultipleSecurities() { var securities = new SecurityManager(TimeKeeper); var transactions = new SecurityTransactionManager(securities); var orderProcessor = new OrderProcessor(); transactions.SetOrderProcessor(orderProcessor); var portfolio = new SecurityPortfolioManager(securities, transactions); portfolio.CashBook["USD"].SetAmount(1000); portfolio.CashBook.Add("EUR", 1000, 1.1m); portfolio.CashBook.Add("GBP", -1000, 2.0m); var eurCash = portfolio.CashBook["EUR"]; var gbpCash = portfolio.CashBook["GBP"]; var usdCash = portfolio.CashBook["USD"]; var time = DateTime.Now; var config1 = CreateTradeBarDataConfig(SecurityType.Equity, Symbols.AAPL); securities.Add(new Security(SecurityExchangeHours, config1, new Cash(CashBook.AccountCurrency, 0, 1m), SymbolProperties.GetDefault(CashBook.AccountCurrency))); securities[Symbols.AAPL].SetLeverage(2m); securities[Symbols.AAPL].Holdings.SetHoldings(100, 100); securities[Symbols.AAPL].SetMarketPrice(new TradeBar { Time = time, Value = 100 }); //Console.WriteLine("AAPL TMU: " + securities[Symbols.AAPL].MarginModel.GetMaintenanceMargin(securities[Symbols.AAPL])); //Console.WriteLine("AAPL Value: " + securities[Symbols.AAPL].Holdings.HoldingsValue); //Console.WriteLine(); var config2 = CreateTradeBarDataConfig(SecurityType.Forex, Symbols.EURUSD); securities.Add(new QuantConnect.Securities.Forex.Forex(SecurityExchangeHours, usdCash, config2, SymbolProperties.GetDefault(CashBook.AccountCurrency))); securities[Symbols.EURUSD].SetLeverage(100m); securities[Symbols.EURUSD].Holdings.SetHoldings(1.1m, 1000); securities[Symbols.EURUSD].SetMarketPrice(new TradeBar { Time = time, Value = 1.1m }); //Console.WriteLine("EURUSD TMU: " + securities[Symbols.EURUSD].MarginModel.GetMaintenanceMargin(securities[Symbols.EURUSD])); //Console.WriteLine("EURUSD Value: " + securities[Symbols.EURUSD].Holdings.HoldingsValue); //Console.WriteLine(); var config3 = CreateTradeBarDataConfig(SecurityType.Forex, Symbols.EURGBP); securities.Add(new QuantConnect.Securities.Forex.Forex(SecurityExchangeHours, gbpCash, config3, SymbolProperties.GetDefault(gbpCash.Symbol))); securities[Symbols.EURGBP].SetLeverage(100m); securities[Symbols.EURGBP].Holdings.SetHoldings(1m, 1000); securities[Symbols.EURGBP].SetMarketPrice(new TradeBar { Time = time, Value = 1m }); //Console.WriteLine("EURGBP TMU: " + securities[Symbols.EURGBP].MarginModel.GetMaintenanceMargin(securities[Symbols.EURGBP])); //Console.WriteLine("EURGBP Value: " + securities[Symbols.EURGBP].Holdings.HoldingsValue); //Console.WriteLine(); //Console.WriteLine(portfolio.CashBook["USD"]); //Console.WriteLine(portfolio.CashBook["EUR"]); //Console.WriteLine(portfolio.CashBook["GBP"]); //Console.WriteLine("CashBook: " + portfolio.CashBook.TotalValueInAccountCurrency); //Console.WriteLine(); //Console.WriteLine("Total Margin Used: " + portfolio.TotalMarginUsed); //Console.WriteLine("Total Free Margin: " + portfolio.MarginRemaining); //Console.WriteLine("Total Portfolio Value: " + portfolio.TotalPortfolioValue); var acceptedOrder = new MarketOrder(Symbols.AAPL, 101, DateTime.Now) { Price = 100 }; orderProcessor.AddOrder(acceptedOrder); var request = new SubmitOrderRequest(OrderType.Market, acceptedOrder.SecurityType, acceptedOrder.Symbol, acceptedOrder.Quantity, 0, 0, acceptedOrder.Time, null); request.SetOrderId(0); orderProcessor.AddTicket(new OrderTicket(null, request)); var sufficientCapital = transactions.GetSufficientCapitalForOrder(portfolio, acceptedOrder); Assert.IsTrue(sufficientCapital); var rejectedOrder = new MarketOrder(Symbols.AAPL, 102, DateTime.Now) { Price = 100 }; sufficientCapital = transactions.GetSufficientCapitalForOrder(portfolio, rejectedOrder); Assert.IsFalse(sufficientCapital); }
public void ComputeMarginProperlyAsSecurityPriceFluctuates() { const decimal leverage = 1m; const int quantity = (int)(1000 * leverage); var securities = new SecurityManager(TimeKeeper); var transactions = new SecurityTransactionManager(securities); var orderProcessor = new OrderProcessor(); transactions.SetOrderProcessor(orderProcessor); var portfolio = new SecurityPortfolioManager(securities, transactions); portfolio.CashBook["USD"].SetAmount(quantity); var config = CreateTradeBarDataConfig(SecurityType.Equity, Symbols.AAPL); securities.Add(new Security(SecurityExchangeHours, config, new Cash(CashBook.AccountCurrency, 0, 1m), SymbolProperties.GetDefault(CashBook.AccountCurrency))); var security = securities[Symbols.AAPL]; security.SetLeverage(leverage); var time = DateTime.Now; const decimal buyPrice = 1m; security.SetMarketPrice(new TradeBar(time, Symbols.AAPL, buyPrice, buyPrice, buyPrice, buyPrice, 1)); var order = new MarketOrder(Symbols.AAPL, quantity, time) { Price = buyPrice }; var fill = new OrderEvent(order, DateTime.UtcNow, 0) { FillPrice = buyPrice, FillQuantity = quantity }; orderProcessor.AddOrder(order); var request = new SubmitOrderRequest(OrderType.Market, security.Type, security.Symbol, order.Quantity, 0, 0, order.Time, null); request.SetOrderId(0); orderProcessor.AddTicket(new OrderTicket(null, request)); Assert.AreEqual(portfolio.CashBook["USD"].Amount, fill.FillPrice * fill.FillQuantity); portfolio.ProcessFill(fill); Assert.AreEqual(0, portfolio.MarginRemaining); Assert.AreEqual(quantity, portfolio.TotalMarginUsed); Assert.AreEqual(quantity, portfolio.TotalPortfolioValue); // we shouldn't be able to place a trader var newOrder = new MarketOrder(Symbols.AAPL, 1, time.AddSeconds(1)) { Price = buyPrice }; bool sufficientCapital = transactions.GetSufficientCapitalForOrder(portfolio, newOrder); Assert.IsFalse(sufficientCapital); // now the stock doubles, so we should have margin remaining time = time.AddDays(1); const decimal highPrice = buyPrice * 2; security.SetMarketPrice(new TradeBar(time, Symbols.AAPL, highPrice, highPrice, highPrice, highPrice, 1)); Assert.AreEqual(quantity, portfolio.MarginRemaining); Assert.AreEqual(quantity, portfolio.TotalMarginUsed); Assert.AreEqual(quantity * 2, portfolio.TotalPortfolioValue); // we shouldn't be able to place a trader var anotherOrder = new MarketOrder(Symbols.AAPL, 1, time.AddSeconds(1)) { Price = highPrice }; sufficientCapital = transactions.GetSufficientCapitalForOrder(portfolio, anotherOrder); Assert.IsTrue(sufficientCapital); // now the stock plummets, so we should have negative margin remaining time = time.AddDays(1); const decimal lowPrice = buyPrice / 2; security.SetMarketPrice(new TradeBar(time, Symbols.AAPL, lowPrice, lowPrice, lowPrice, lowPrice, 1)); Assert.AreEqual(-quantity / 2m, portfolio.MarginRemaining); Assert.AreEqual(quantity, portfolio.TotalMarginUsed); Assert.AreEqual(quantity / 2m, portfolio.TotalPortfolioValue); // this would not cause a margin call due to leverage = 1 bool issueMarginCallWarning; var marginCallOrders = portfolio.ScanForMarginCall(out issueMarginCallWarning); Assert.IsFalse(issueMarginCallWarning); Assert.AreEqual(0, marginCallOrders.Count); // now change the leverage to test margin call warning and margin call logic security.SetLeverage(leverage * 2); // Stock price increase by minimum variation const decimal newPrice = lowPrice + 0.01m; security.SetMarketPrice(new TradeBar(time, Symbols.AAPL, newPrice, newPrice, newPrice, newPrice, 1)); // this would not cause a margin call, only a margin call warning marginCallOrders = portfolio.ScanForMarginCall(out issueMarginCallWarning); Assert.IsTrue(issueMarginCallWarning); Assert.AreEqual(0, marginCallOrders.Count); // Price drops again to previous low, margin call orders will be issued security.SetMarketPrice(new TradeBar(time, Symbols.AAPL, lowPrice, lowPrice, lowPrice, lowPrice, 1)); order = new MarketOrder(Symbols.AAPL, quantity, time) { Price = buyPrice }; fill = new OrderEvent(order, DateTime.UtcNow, 0) { FillPrice = buyPrice, FillQuantity = quantity }; portfolio.ProcessFill(fill); Assert.AreEqual(0, portfolio.TotalPortfolioValue); marginCallOrders = portfolio.ScanForMarginCall(out issueMarginCallWarning); Assert.IsTrue(issueMarginCallWarning); Assert.AreNotEqual(0, marginCallOrders.Count); Assert.AreEqual(-security.Holdings.Quantity, marginCallOrders[0].Quantity); // we bought twice Assert.GreaterOrEqual(-portfolio.MarginRemaining, security.Price * marginCallOrders[0].Quantity); }