Esempio n. 1
0
        /// <summary>
        /// Creates a new IBrokerage instance and set ups the environment for the brokerage
        /// </summary>
        /// <param name="job">The job packet to create the brokerage for</param>
        /// <param name="algorithm">The algorithm instance</param>
        /// <returns>A new brokerage instance</returns>
        public override IBrokerage CreateBrokerage(LiveNodePacket job, IAlgorithm algorithm)
        {
            var errors = new List <string>();

            // read values from the brokerage datas
            var useTws                = Config.GetBool("ib-use-tws");
            var port                  = Config.GetInt("ib-port", 4001);
            var host                  = Config.Get("ib-host", "127.0.0.1");
            var twsDirectory          = Config.Get("ib-tws-dir", "C:\\Jts");
            var ibControllerDirectory = Config.Get("ib-controller-dir", "C:\\IBController");

            var account          = Read <string>(job.BrokerageData, "ib-account", errors);
            var userID           = Read <string>(job.BrokerageData, "ib-user-name", errors);
            var password         = Read <string>(job.BrokerageData, "ib-password", errors);
            var agentDescription = Read <AgentDescription>(job.BrokerageData, "ib-agent-description", errors);

            if (errors.Count != 0)
            {
                // if we had errors then we can't create the instance
                throw new Exception(string.Join(Environment.NewLine, errors));
            }

            // launch the IB gateway
            InteractiveBrokersGatewayRunner.Start(ibControllerDirectory, twsDirectory, userID, password, useTws);

            var ib = new InteractiveBrokersBrokerage(algorithm.Transactions, algorithm.Portfolio, account, host, port, agentDescription);

            Composer.Instance.AddPart <IDataQueueHandler>(ib);
            return(ib);
        }
        public void ClientCancelsLimitOrder()
        {
            OrderStatus status = OrderStatus.New;
            var manualResetEvent = new ManualResetEvent(false);

            var ib = new InteractiveBrokersBrokerage();
            ib.Connect();

            ib.OrderEvent += (sender, args) =>
            {
                status = args.Status;
                manualResetEvent.Set();
            };

            // try to sell a single share at a ridiculous price, we'll cancel this later
            var order = new Order("AAPL", SecurityType.Equity, -1, OrderType.Limit, DateTime.UtcNow, 100000);
            ib.PlaceOrder(order);
            manualResetEvent.WaitOne(2500);

            ib.CancelOrder(order);

            manualResetEvent.Reset();
            manualResetEvent.WaitOne(2500);

            Assert.AreEqual(OrderStatus.Canceled, status);
        }
        /// <summary>
        /// Creates a new IBrokerage instance and set ups the environment for the brokerage
        /// </summary>
        /// <param name="job">The job packet to create the brokerage for</param>
        /// <param name="algorithm">The algorithm instance</param>
        /// <returns>A new brokerage instance</returns>
        public override IBrokerage CreateBrokerage(LiveNodePacket job, IAlgorithm algorithm)
        {
            var errors = new List <string>();

            // read values from the brokerage datas
            var port         = Config.GetInt("ib-port", 4001);
            var host         = Config.Get("ib-host", "127.0.0.1");
            var twsDirectory = Config.Get("ib-tws-dir", "C:\\Jts");
            var ibVersion    = Config.Get("ib-version", "974");

            var account          = Read <string>(job.BrokerageData, "ib-account", errors);
            var userId           = Read <string>(job.BrokerageData, "ib-user-name", errors);
            var password         = Read <string>(job.BrokerageData, "ib-password", errors);
            var tradingMode      = Read <string>(job.BrokerageData, "ib-trading-mode", errors);
            var agentDescription = Read <string>(job.BrokerageData, "ib-agent-description", errors);

            var loadExistingHoldings = true;

            if (job.BrokerageData.ContainsKey("load-existing-holdings"))
            {
                loadExistingHoldings = Convert.ToBoolean(job.BrokerageData["load-existing-holdings"]);
            }

            if (errors.Count != 0)
            {
                // if we had errors then we can't create the instance
                throw new Exception(string.Join(Environment.NewLine, errors));
            }

            if (tradingMode.IsNullOrEmpty())
            {
                throw new Exception("No trading mode selected. Please select either 'paper' or 'live' trading.");
            }

            var ib = new InteractiveBrokersBrokerage(
                algorithm,
                algorithm.Transactions,
                algorithm.Portfolio,
                Composer.Instance.GetExportedValueByTypeName <IDataAggregator>(Config.Get("data-aggregator", "QuantConnect.Lean.Engine.DataFeeds.AggregationManager")),
                Composer.Instance.GetExportedValueByTypeName <IMapFileProvider>(Config.Get("map-file-provider", "QuantConnect.Data.Auxiliary.LocalDiskMapFileProvider")),
                account,
                host,
                port,
                twsDirectory,
                ibVersion,
                userId,
                password,
                tradingMode,
                agentDescription,
                loadExistingHoldings);

            Composer.Instance.AddPart <IDataQueueHandler>(ib);

            return(ib);
        }
        public void InitializeBrokerage()
        {
            InteractiveBrokersGatewayRunner.Start(Config.Get("ib-controller-dir"), 
                Config.Get("ib-tws-dir"), 
                Config.Get("ib-user-name"), 
                Config.Get("ib-password"), 
                Config.GetBool("ib-use-tws")
                );

            // grabs account info from configuration
            _interactiveBrokersBrokerage = new InteractiveBrokersBrokerage(new OrderProvider(_orders), new SecurityProvider());
            _interactiveBrokersBrokerage.Connect();
        }
Esempio n. 5
0
        /// <summary>
        /// Creates a new IBrokerage instance and set ups the environment for the brokerage
        /// </summary>
        /// <param name="job">The job packet to create the brokerage for</param>
        /// <param name="algorithm">The algorithm instance</param>
        /// <returns>A new brokerage instance</returns>
        public override IBrokerage CreateBrokerage(LiveNodePacket job, IAlgorithm algorithm)
        {
            var errors = new List <string>();

            // read values from the brokerage datas
            var port         = Config.GetInt("ib-port", 4001);
            var host         = Config.Get("ib-host", "127.0.0.1");
            var twsDirectory = Config.Get("ib-tws-dir", "C:\\Jts");
            var ibVersion    = Config.Get("ib-version", "974");

            var account          = Read <string>(job.BrokerageData, "ib-account", errors);
            var userId           = Read <string>(job.BrokerageData, "ib-user-name", errors);
            var password         = Read <string>(job.BrokerageData, "ib-password", errors);
            var tradingMode      = Read <string>(job.BrokerageData, "ib-trading-mode", errors);
            var agentDescription = Read <string>(job.BrokerageData, "ib-agent-description", errors);

            if (errors.Count != 0)
            {
                // if we had errors then we can't create the instance
                throw new Exception(string.Join(Environment.NewLine, errors));
            }

            if (tradingMode.IsNullOrEmpty())
            {
                throw new Exception("No trading mode selected. Please select either 'paper' or 'live' trading.");
            }

            var ib = new InteractiveBrokersBrokerage(
                algorithm,
                algorithm.Transactions,
                algorithm.Portfolio,
                account,
                host,
                port,
                twsDirectory,
                ibVersion,
                userId,
                password,
                tradingMode,
                agentDescription);

            Composer.Instance.AddPart <IDataQueueHandler>(ib);

            return(ib);
        }
        public void InitializeBrokerage()
        {
            InteractiveBrokersGatewayRunner.Start(Config.Get("ib-controller-dir"), 
                Config.Get("ib-tws-dir"), 
                Config.Get("ib-user-name"), 
                Config.Get("ib-password"),
                Config.Get("ib-trading-mode"),
                Config.GetBool("ib-use-tws")
                );

            // grabs account info from configuration
            var securityProvider = new SecurityProvider();
            securityProvider[Symbols.USDJPY] = new Security(SecurityExchangeHours.AlwaysOpen(TimeZones.NewYork),
                new SubscriptionDataConfig(typeof(TradeBar), Symbols.USDJPY, Resolution.Minute, TimeZones.NewYork, TimeZones.NewYork, false, false, false),
                new Cash(CashBook.AccountCurrency, 0, 1m), SymbolProperties.GetDefault(CashBook.AccountCurrency));

            _interactiveBrokersBrokerage = new InteractiveBrokersBrokerage(new OrderProvider(_orders), securityProvider);
            _interactiveBrokersBrokerage.Connect();
        }
        private static Order AssertOrderOpened(bool orderFilled, QuantConnect.Brokerages.InteractiveBrokers.InteractiveBrokersBrokerage ib, Order order)
        {
            // if the order didn't fill check for it as an open order
            if (!orderFilled)
            {
                // find the right order and return it
                foreach (var openOrder in ib.GetOpenOrders())
                {
                    if (openOrder.BrokerId.Any(id => order.BrokerId.Any(x => x == id)))
                    {
                        return(openOrder);
                    }
                }
                Assert.Fail("The order was not filled and was unable to be located via GetOpenOrders()");
            }

            Assert.Pass("The order was successfully filled!");
            return(null);
        }
        public void GetsTickData()
        {
            InteractiveBrokersGatewayRunner.StartFromConfiguration();
            
            var ib = new InteractiveBrokersBrokerage(new OrderProvider());
            ib.Connect();

            ib.Subscribe(null, new List<Symbol> {Symbols.USDJPY, Symbols.EURGBP});
            
            Thread.Sleep(1000);

            for (int i = 0; i < 10; i++)
            {
                foreach (var tick in ib.GetNextTicks())
                {
                    Console.WriteLine("{0}: {1} - {2} @ {3}", tick.Time, tick.Symbol, tick.Price, ((Tick)tick).Quantity);
                }
            }

            InteractiveBrokersGatewayRunner.Stop();
        }
        public void ClientPlacesLimitOrder()
        {
            bool orderFilled = false;
            var manualResetEvent = new ManualResetEvent(false);
            var ib = new InteractiveBrokersBrokerage();
            ib.Connect();

            decimal aapl = 100m;
            decimal delta = 85.0m; // if we can't get a price then make the delta huge
            ib.OrderEvent += (sender, args) =>
            {
                orderFilled = true;
                aapl = args.FillPrice;
                delta = 0.02m;
                manualResetEvent.Set();
            };

            // get the current market price, couldn't get RequestMarketData to fire tick events
            int id = 0;
            ib.PlaceOrder(new Order("AAPL", SecurityType.Equity, 1, OrderType.Market, DateTime.UtcNow) { Id = ++id });

            manualResetEvent.WaitOne(2000);
            manualResetEvent.Reset();

            // make a box around the current price +- a little

            const int quantity = 1;
            var order = new Order("AAPL", SecurityType.Equity, +quantity, OrderType.Limit, DateTime.Now, aapl - delta) {Id = ++id};
            ib.PlaceOrder(order);

            ib.PlaceOrder(new Order("AAPL", SecurityType.Equity, -quantity, OrderType.Limit, DateTime.Now, aapl + delta) {Id = ++id});

            manualResetEvent.WaitOne(1000);

            var orderFromIB = AssertOrderOpened(orderFilled, ib, order);
            Assert.AreEqual(OrderType.Limit, orderFromIB.Type);
        }
        public void GetsTickData()
        {
            InteractiveBrokersGatewayRunner.StartFromConfiguration();

            var ib = new InteractiveBrokersBrokerage(new OrderMapping());
            ib.Connect();

            ib.Subscribe(null, new Dictionary<SecurityType, List<string>>
            {
                {SecurityType.Forex, new List<string>{"USDJPY", "EURGBP"}}
            });

            Thread.Sleep(1000);

            for (int i = 0; i < 10; i++)
            {
                foreach (var tick in ib.GetNextTicks())
                {
                    Console.WriteLine("{0}: {1} - {2} @ {3}", tick.Time, tick.Symbol, tick.Price, ((Tick)tick).Quantity);
                }
            }

            InteractiveBrokersGatewayRunner.Stop();
        }
Esempio n. 11
0
        /// <summary>
        /// Parses a contract for future with malformed data.
        /// Malformed data usually manifests itself by having "0" assigned to some values
        /// we expect, like the contract's expiry date. The contract is returned by IB
        /// like this, usually due to a high amount of data subscriptions that are active
        /// in an account, surpassing IB's imposed limit. Read more about this here: https://interactivebrokers.github.io/tws-api/rtd_fqa_errors.html#rtd_common_errors_maxmktdata
        ///
        /// We are provided a string in the Symbol in malformed contracts that can be
        /// parsed to construct the clean contract, which is done by this method.
        /// </summary>
        /// <param name="malformedContract">Malformed contract (for futures), i.e. a contract with invalid values ("0") in some of its fields</param>
        /// <param name="symbolPropertiesDatabase">The symbol properties database to use</param>
        /// <returns>Clean Contract for the future</returns>
        /// <remarks>
        /// The malformed contract returns data similar to the following when calling <see cref="InteractiveBrokersBrokerage.GetContractDetails"/>: ES       MAR2021
        /// </remarks>
        public Contract ParseMalformedContractFutureSymbol(Contract malformedContract, SymbolPropertiesDatabase symbolPropertiesDatabase)
        {
            Log.Trace($"InteractiveBrokersSymbolMapper.ParseMalformedContractFutureSymbol(): Parsing malformed contract: {InteractiveBrokersBrokerage.GetContractDescription(malformedContract)} with trading class: \"{malformedContract.TradingClass}\"");

            // capture any character except spaces, match spaces, capture any char except digits, capture digits
            var matches = Regex.Matches(malformedContract.Symbol, @"^(\S*)\s*(\D*)(\d*)");

            var match                   = matches[0].Groups;
            var contractSymbol          = match[1].Value;
            var contractMonthExpiration = DateTime.ParseExact(match[2].Value, "MMM", CultureInfo.CurrentCulture).Month;
            var contractYearExpiration  = match[3].Value;

            var    leanSymbol = GetLeanRootSymbol(contractSymbol);
            string market;

            if (!symbolPropertiesDatabase.TryGetMarket(leanSymbol, SecurityType.Future, out market))
            {
                market = InteractiveBrokersBrokerageModel.DefaultMarketMap[SecurityType.Future];
            }
            var canonicalSymbol   = Symbol.Create(leanSymbol, SecurityType.Future, market);
            var contractMonthYear = new DateTime(int.Parse(contractYearExpiration, CultureInfo.InvariantCulture), contractMonthExpiration, 1);
            // we get the expiration date using the FuturesExpiryFunctions
            var contractExpirationDate = FuturesExpiryFunctions.FuturesExpiryFunction(canonicalSymbol)(contractMonthYear);

            return(new Contract
            {
                Symbol = contractSymbol,
                Multiplier = malformedContract.Multiplier,
                LastTradeDateOrContractMonth = $"{contractExpirationDate:yyyyMMdd}",
                Exchange = malformedContract.Exchange,
                SecType = malformedContract.SecType,
                IncludeExpired = false,
                Currency = malformedContract.Currency
            });
        }
Esempio n. 12
0
        /// <summary>
        /// Parses a contract for options with malformed data.
        /// Malformed data usually manifests itself by having "0" assigned to some values
        /// we expect, like the contract's expiry date. The contract is returned by IB
        /// like this, usually due to a high amount of data subscriptions that are active
        /// in an account, surpassing IB's imposed limit. Read more about this here: https://interactivebrokers.github.io/tws-api/rtd_fqa_errors.html#rtd_common_errors_maxmktdata
        ///
        /// We are provided a string in the Symbol in malformed contracts that can be
        /// parsed to construct the clean contract, which is done by this method.
        /// </summary>
        /// <param name="malformedContract">Malformed contract (for options), i.e. a contract with invalid values ("0") in some of its fields</param>
        /// <param name="exchange">Exchange that the contract's asset lives on/where orders will be routed through</param>
        /// <returns>Clean Contract for the option</returns>
        /// <remarks>
        /// The malformed contract returns data similar to the following when calling <see cref="InteractiveBrokersBrokerage.GetContractDetails"/>:
        /// OPT SPY JUN2021 350 P [SPY 210618P00350000 100] USD 0 0 0
        ///
        /// ... which the contents inside [] follow the pattern:
        ///
        /// [SYMBOL YY_MM_DD_OPTIONRIGHT_STRIKE(divide by 1000) MULTIPLIER]
        /// </remarks>
        public static Contract ParseMalformedContractOptionSymbol(Contract malformedContract, string exchange = "Smart")
        {
            Log.Trace($"InteractiveBrokersSymbolMapper.ParseMalformedContractOptionSymbol(): Parsing malformed contract: {InteractiveBrokersBrokerage.GetContractDescription(malformedContract)} with trading class: \"{malformedContract.TradingClass}\"");

            // we search for the '[ ]' pattern, inside of it we: (capture any character except spaces, match spaces) -> 3 times
            var matches = Regex.Matches(malformedContract.Symbol, @"^.*[\[](\S*)\s*(\S*)\s*(\S*)[\]]");

            var match                 = matches[0].Groups;
            var contractSymbol        = match[1].Value;
            var contractSpecification = match[2].Value;
            var multiplier            = match[3].Value;
            var expiryDate            = "20" + contractSpecification.Substring(0, 6);
            var contractRight         = contractSpecification[6] == 'C' ? IB.RightType.Call : IB.RightType.Put;
            var contractStrike        = long.Parse(contractSpecification.Substring(7), CultureInfo.InvariantCulture) / 1000.0;

            return(new Contract
            {
                Symbol = contractSymbol,
                Multiplier = multiplier,
                LastTradeDateOrContractMonth = expiryDate,
                Right = contractRight,
                Strike = contractStrike,
                Exchange = exchange,
                SecType = malformedContract.SecType,
                IncludeExpired = false,
                Currency = malformedContract.Currency
            });
        }
        private static Order AssertOrderOpened(bool orderFilled, InteractiveBrokersBrokerage ib, Order order)
        {
            // if the order didn't fill check for it as an open order
            if (!orderFilled)
            {
                // find the right order and return it
                foreach (var openOrder in ib.GetOpenOrders())
                {
                    if (openOrder.BrokerId.Any(id => order.BrokerId.Any(x => x == id)))
                    {
                        return openOrder;
                    }
                }
                Assert.Fail("The order was not filled and was unable to be located via GetOpenOrders()");
            }

            Assert.Pass("The order was successfully filled!");
            return null;
        }
Esempio n. 14
0
        /// <summary>
        /// Parses a contract for options with malformed data.
        /// Malformed data usually manifests itself by having "0" assigned to some values
        /// we expect, like the contract's expiry date. The contract is returned by IB
        /// like this, usually due to a high amount of data subscriptions that are active
        /// in an account, surpassing IB's imposed limit. Read more about this here: https://interactivebrokers.github.io/tws-api/rtd_fqa_errors.html#rtd_common_errors_maxmktdata
        ///
        /// We are provided a string in the Symbol in malformed contracts that can be
        /// parsed to construct the clean contract, which is done by this method.
        /// </summary>
        /// <param name="malformedContract">Malformed contract (for options), i.e. a contract with invalid values ("0") in some of its fields</param>
        /// <param name="exchange">Exchange that the contract's asset lives on/where orders will be routed through</param>
        /// <returns>Clean Contract for the option</returns>
        /// <remarks>
        /// The malformed contract returns data similar to the following when calling <see cref="InteractiveBrokersBrokerage.GetContractDetails"/>:
        /// OPT SPY JUN2021 350 P [SPY 210618P00350000 100] USD 0 0 0
        ///
        /// ... which the contents inside [] follow the pattern:
        ///
        /// [SYMBOL YY_MM_DD_OPTIONRIGHT_STRIKE(divide by 1000) MULTIPLIER]
        /// </remarks>
        public static Contract ParseMalformedContractOptionSymbol(Contract malformedContract, string exchange = "Smart")
        {
            Log.Trace($"InteractiveBrokersSymbolMapper.ParseMalformedContractOptionSymbol(): Parsing malformed contract: {InteractiveBrokersBrokerage.GetContractDescription(malformedContract)} with trading class: \"{malformedContract.TradingClass}\"");

            var contractInfoSplit = malformedContract.Symbol.Substring(malformedContract.Symbol.IndexOf('['))
                                    .Replace("[", "")
                                    .Replace("]", "")
                                    .Split(' ');

            var contractSymbol        = contractInfoSplit[0];
            var contractSpecification = contractInfoSplit[1];
            var multiplier            = contractInfoSplit[2];
            var expiryDate            = "20" + contractSpecification.Substring(0, 6);
            var contractRight         = contractSpecification[6] == 'C' ? IB.RightType.Call : IB.RightType.Put;
            var contractStrike        = long.Parse(contractSpecification.Substring(7), CultureInfo.InvariantCulture) / 1000.0;

            return(new Contract
            {
                Symbol = contractSymbol,
                Multiplier = multiplier,
                LastTradeDateOrContractMonth = expiryDate,
                Right = contractRight,
                Strike = contractStrike,
                Exchange = exchange,
                SecType = malformedContract.SecType,
                IncludeExpired = false,
                Currency = malformedContract.Currency
            });
        }
 public void ClientConnects()
 {
     var ib = new InteractiveBrokersBrokerage();
     ib.Connect();
 }
        public void Teardown()
        {
            try
            { // give the tear down a header so we can easily find it in the logs
                Log.Trace("-----");
                Log.Trace("InteractiveBrokersBrokerageTests.Teardown(): Starting teardown...");
                Log.Trace("-----");

                var canceledResetEvent = new ManualResetEvent(false);
                var filledResetEvent = new ManualResetEvent(false);
                _interactiveBrokersBrokerage.OrderStatusChanged += (sender, orderEvent) =>
                {
                    if (orderEvent.Status == OrderStatus.Filled)
                    {
                        filledResetEvent.Set();
                    }
                    if (orderEvent.Status == OrderStatus.Canceled)
                    {
                        canceledResetEvent.Set();
                    }
                };

                // cancel all open orders

                Log.Trace("InteractiveBrokersBrokerageTests.Teardown(): Canceling open orders...");

                var orders = _interactiveBrokersBrokerage.GetOpenOrders();
                foreach (var order in orders)
                {
                    _interactiveBrokersBrokerage.CancelOrder(order);
                    canceledResetEvent.WaitOne(3000);
                    canceledResetEvent.Reset();
                }

                Log.Trace("InteractiveBrokersBrokerageTests.Teardown(): Liquidating open positions...");

                // liquidate all positions
                var holdings = _interactiveBrokersBrokerage.GetAccountHoldings();
                foreach (var holding in holdings.Where(x => x.Quantity != 0))
                {
                    //var liquidate = new MarketOrder(holding.Symbol, (int) -holding.Quantity, DateTime.UtcNow, type: holding.Type);
                    //_interactiveBrokersBrokerage.PlaceOrder(liquidate);
                    //filledResetEvent.WaitOne(3000);
                    //filledResetEvent.Reset();
                }

                var openOrdersText = _interactiveBrokersBrokerage.GetOpenOrders().Select(x => x.Symbol.ToString() + " " + x.Quantity);
                Log.Trace("InteractiveBrokersBrokerageTests.Teardown(): Open orders: " + string.Join(", ", openOrdersText));
                //Assert.AreEqual(0, actualOpenOrderCount, "Failed to verify that there are zero open orders.");

                var holdingsText = _interactiveBrokersBrokerage.GetAccountHoldings().Where(x => x.Quantity != 0).Select(x => x.Symbol.ToString() + " " + x.Quantity);
                Log.Trace("InteractiveBrokersBrokerageTests.Teardown(): Account holdings: " + string.Join(", ", holdingsText));
                //Assert.AreEqual(0, holdingsCount, "Failed to verify that there are zero account holdings.");

                _interactiveBrokersBrokerage.Dispose();
                _interactiveBrokersBrokerage = null;
            }
            finally
            {
                InteractiveBrokersGatewayRunner.Stop();
            }
        }
        public void ClientSellsMarketOrder()
        {
            bool orderFilled = false;
            var manualResetEvent = new ManualResetEvent(false);

            var ib = new InteractiveBrokersBrokerage();
            ib.Connect();

            ib.OrderEvent += (sender, args) =>
            {
                orderFilled = true;
                manualResetEvent.Set();
            };

            // sell a single share
            var order = new Order("AAPL", SecurityType.Equity, -1, OrderType.Market, DateTime.UtcNow);
            ib.PlaceOrder(order);

            manualResetEvent.WaitOne(2500);

            var orderFromIB = AssertOrderOpened(orderFilled, ib, order);
            Assert.AreEqual(OrderType.Market, orderFromIB.Type);
        }
        public void ClientPlacesMarketOrder()
        {
            bool orderFilled = false;
            var manualResetEvent = new ManualResetEvent(false);
            var ib = new InteractiveBrokersBrokerage();
            ib.Connect();

            ib.Client.RequestOpenOrders();

            ib.OrderEvent += (sender, args) =>
            {
                orderFilled = true;
                manualResetEvent.Set();
            };

            const int buyQuantity = 1;
            //ib.PlaceOrder(new Order("AAPL", SecurityType.Equity, buyQuantity, OrderType.Market, DateTime.Now));
            var order = new Order("AAPL", SecurityType.Equity, buyQuantity, OrderType.Market, DateTime.Now);
            ib.PlaceOrder(order);

            manualResetEvent.WaitOne(2500);
            var orderFromIB = AssertOrderOpened(orderFilled, ib, order);
            Assert.AreEqual(OrderType.Market, orderFromIB.Type);
        }
        /// <summary>
        /// Creates a new IBrokerage instance and set ups the environment for the brokerage
        /// </summary>
        /// <param name="job">The job packet to create the brokerage for</param>
        /// <param name="algorithm">The algorithm instance</param>
        /// <returns>A new brokerage instance</returns>
        public override IBrokerage CreateBrokerage(LiveNodePacket job, IAlgorithm algorithm)
        {
            var errors = new List<string>();

            // read values from the brokerage datas
            var useTws = Config.GetBool("ib-use-tws");
            var port = Config.GetInt("ib-port", 4001);
            var host = Config.Get("ib-host", "127.0.0.1");
            var twsDirectory = Config.Get("ib-tws-dir", "C:\\Jts");
            var ibControllerDirectory = Config.Get("ib-controller-dir", "C:\\IBController");

            var account = Read<string>(job.BrokerageData, "ib-account", errors);
            var userID = Read<string>(job.BrokerageData, "ib-user-name", errors);
            var password = Read<string>(job.BrokerageData, "ib-password", errors);
            var agentDescription = Read<AgentDescription>(job.BrokerageData, "ib-agent-description", errors);

            if (errors.Count != 0)
            {
                // if we had errors then we can't create the instance
                throw new Exception(string.Join(Environment.NewLine, errors));
            }
            
            // launch the IB gateway
            InteractiveBrokersGatewayRunner.Start(ibControllerDirectory, twsDirectory, userID, password, useTws);

            var ib = new InteractiveBrokersBrokerage(algorithm.Transactions, algorithm.Portfolio, account, host, port, agentDescription);
            Composer.Instance.AddPart<IDataQueueHandler>(ib);
            return ib;
        }