コード例 #1
0
        /// <summary>
        /// Connects the client to the broker's remote servers
        /// </summary>
        public override void Connect()
        {
            if (IsConnected)
            {
                return;
            }

            Log.Trace("FxcmBrokerage.Connect()");

            _cancellationTokenSource = new CancellationTokenSource();

            // create new thread to fire order events in queue
            _orderEventThread = new Thread(() =>
            {
                while (!_cancellationTokenSource.IsCancellationRequested)
                {
                    OrderEvent orderEvent;
                    if (!_orderEventQueue.TryDequeue(out orderEvent))
                    {
                        Thread.Sleep(1);
                        continue;
                    }

                    OnOrderEvent(orderEvent);
                }
            });
            _orderEventThread.Start();
            while (!_orderEventThread.IsAlive)
            {
                Thread.Sleep(1);
            }

            // create the gateway
            _gateway = GatewayFactory.createGateway();

            // register the message listeners with the gateway
            _gateway.registerGenericMessageListener(this);
            _gateway.registerStatusMessageListener(this);

            // create local login properties
            var loginProperties = new FXCMLoginProperties(_userName, _password, _terminal, _server);

            // log in
            _gateway.login(loginProperties);

            // load instruments, accounts, orders, positions
            LoadInstruments();
            LoadAccounts();
            LoadOpenOrders();
            LoadOpenPositions();
        }
コード例 #2
0
ファイル: FxcmBrokerage.cs プロジェクト: stan4git/Lean-1
        /// <summary>
        /// Connects the client to the broker's remote servers
        /// </summary>
        public override void Connect()
        {
            if (IsConnected)
            {
                return;
            }

            Log.Trace("FxcmBrokerage.Connect()");

            _cancellationTokenSource = new CancellationTokenSource();

            // create new thread to fire order events in queue
            if (!EnableOnlyHistoryRequests)
            {
                _orderEventThread = new Thread(() =>
                {
                    while (!_cancellationTokenSource.IsCancellationRequested)
                    {
                        try
                        {
                            OrderEvent orderEvent;
                            if (!_orderEventQueue.TryDequeue(out orderEvent))
                            {
                                Thread.Sleep(1);
                                continue;
                            }

                            OnOrderEvent(orderEvent);
                        }
                        catch (Exception exception)
                        {
                            Log.Error(exception);
                        }
                    }
                })
                {
                    IsBackground = true
                };
                _orderEventThread.Start();
                while (!_orderEventThread.IsAlive)
                {
                    Thread.Sleep(1);
                }
            }

            // create the gateway
            _gateway = GatewayFactory.createGateway();

            // register the message listeners with the gateway
            _gateway.registerGenericMessageListener(this);
            _gateway.registerStatusMessageListener(this);

            // create local login properties
            var loginProperties = new FXCMLoginProperties(_userName, _password, _terminal, _server);

            loginProperties.addProperty(IConnectionManager.APP_INFO, "QuantConnect");

            // log in
            try
            {
                _gateway.login(loginProperties);
            }
            catch (Exception err)
            {
                var message =
                    err.Message.Contains("ORA-20101") ? "Incorrect login credentials" :
                    err.Message.Contains("ORA-20003") ? "API connections are not available on Mini accounts. If you have a standard account contact [email protected] to enable API access" :
                    err.Message;

                _cancellationTokenSource.Cancel();

                throw new BrokerageException(message, err.InnerException);
            }

            // create new thread to manage disconnections and reconnections
            if (!EnableOnlyHistoryRequests)
            {
                _connectionMonitorThread = new Thread(() =>
                {
                    _lastReadyMessageTime = DateTime.UtcNow;

                    try
                    {
                        while (!_cancellationTokenSource.IsCancellationRequested)
                        {
                            TimeSpan elapsed;
                            lock (_lockerConnectionMonitor)
                            {
                                elapsed = DateTime.UtcNow - _lastReadyMessageTime;
                            }

                            if (!_connectionLost && elapsed > TimeSpan.FromSeconds(10))
                            {
                                _connectionLost = true;

                                OnMessage(BrokerageMessageEvent.Disconnected("Connection with FXCM server lost. " +
                                                                             "This could be because of internet connectivity issues. "));
                            }
                            else if (_connectionLost && IsWithinTradingHours())
                            {
                                Log.Trace("FxcmBrokerage.ConnectionMonitorThread(): Attempting reconnection...");

                                try
                                {
                                    // log out
                                    try
                                    {
                                        _gateway.logout();
                                    }
                                    catch (Exception)
                                    {
                                        // ignored
                                    }

                                    // remove the message listeners
                                    _gateway.removeGenericMessageListener(this);
                                    _gateway.removeStatusMessageListener(this);

                                    // register the message listeners with the gateway
                                    _gateway.registerGenericMessageListener(this);
                                    _gateway.registerStatusMessageListener(this);

                                    // log in
                                    _gateway.login(loginProperties);

                                    // load instruments, accounts, orders, positions
                                    LoadInstruments();
                                    if (!EnableOnlyHistoryRequests)
                                    {
                                        LoadAccounts();
                                        LoadOpenOrders();
                                        LoadOpenPositions();
                                    }

                                    _connectionLost = false;

                                    OnMessage(BrokerageMessageEvent.Reconnected("Connection with FXCM server restored."));
                                }
                                catch (Exception exception)
                                {
                                    Log.Trace("FxcmBrokerage.ConnectionMonitorThread(): reconnect failed.");
                                    Log.Error(exception);
                                }
                            }

                            Thread.Sleep(5000);
                        }
                    }
                    catch (Exception exception)
                    {
                        Log.Error(exception);
                    }
                })
                {
                    IsBackground = true
                };
                _connectionMonitorThread.Start();
                while (!_connectionMonitorThread.IsAlive)
                {
                    Thread.Sleep(1);
                }
            }

            // load instruments, accounts, orders, positions
            LoadInstruments();
            if (!EnableOnlyHistoryRequests)
            {
                LoadAccounts();
                LoadOpenOrders();
                LoadOpenPositions();
            }
        }
コード例 #3
0
ファイル: FxcmBrokerage.cs プロジェクト: tzaavi/Lean
        /// <summary>
        /// Connects the client to the broker's remote servers
        /// </summary>
        public override void Connect()
        {
            if (IsConnected)
            {
                return;
            }

            Log.Trace("FxcmBrokerage.Connect()");

            _cancellationTokenSource = new CancellationTokenSource();

            // create new thread to fire order events in queue
            _orderEventThread = new Thread(() =>
            {
                while (!_cancellationTokenSource.IsCancellationRequested)
                {
                    OrderEvent orderEvent;
                    if (!_orderEventQueue.TryDequeue(out orderEvent))
                    {
                        Thread.Sleep(1);
                        continue;
                    }

                    OnOrderEvent(orderEvent);
                }
            });
            _orderEventThread.Start();
            while (!_orderEventThread.IsAlive)
            {
                Thread.Sleep(1);
            }

            // create the gateway
            _gateway = GatewayFactory.createGateway();

            // register the message listeners with the gateway
            _gateway.registerGenericMessageListener(this);
            _gateway.registerStatusMessageListener(this);

            // create local login properties
            var loginProperties = new FXCMLoginProperties(_userName, _password, _terminal, _server);

            // log in
            _gateway.login(loginProperties);

            // create new thread to manage disconnections and reconnections
            _connectionMonitorThread = new Thread(() =>
            {
                _lastReadyMessageTime = DateTime.UtcNow;

                try
                {
                    while (!_cancellationTokenSource.IsCancellationRequested)
                    {
                        TimeSpan elapsed;
                        lock (_lockerConnectionMonitor)
                        {
                            elapsed = DateTime.UtcNow - _lastReadyMessageTime;
                        }

                        if (!_connectionLost && elapsed > TimeSpan.FromSeconds(5))
                        {
                            _connectionLost = true;

                            OnMessage(BrokerageMessageEvent.Disconnected("Connection with FXCM server lost. " +
                                                                         "This could be because of internet connectivity issues. "));
                        }
                        else if (_connectionLost && elapsed <= TimeSpan.FromSeconds(5))
                        {
                            try
                            {
                                _gateway.relogin();

                                _connectionLost = false;

                                OnMessage(BrokerageMessageEvent.Reconnected("Connection with FXCM server restored."));
                            }
                            catch (Exception exception)
                            {
                                Log.Error(exception);
                            }
                        }
                        else if (_connectionError)
                        {
                            try
                            {
                                // log out
                                _gateway.logout();

                                // remove the message listeners
                                _gateway.removeGenericMessageListener(this);
                                _gateway.removeStatusMessageListener(this);

                                // register the message listeners with the gateway
                                _gateway.registerGenericMessageListener(this);
                                _gateway.registerStatusMessageListener(this);

                                // log in
                                _gateway.login(loginProperties);

                                // load instruments, accounts, orders, positions
                                LoadInstruments();
                                LoadAccounts();
                                LoadOpenOrders();
                                LoadOpenPositions();

                                _connectionError = false;
                                _connectionLost  = false;

                                OnMessage(BrokerageMessageEvent.Reconnected("Connection with FXCM server restored."));
                            }
                            catch (Exception exception)
                            {
                                Log.Error(exception);
                            }
                        }

                        Thread.Sleep(5000);
                    }
                }
                catch (Exception exception)
                {
                    Log.Error(exception);
                }
            });
            _connectionMonitorThread.Start();
            while (!_connectionMonitorThread.IsAlive)
            {
                Thread.Sleep(1);
            }

            // load instruments, accounts, orders, positions
            LoadInstruments();
            LoadAccounts();
            LoadOpenOrders();
            LoadOpenPositions();
        }
コード例 #4
0
        public void Run()
        {
            _gateway = GatewayFactory.createGateway();

            // register the generic message listener with the gateway
            _gateway.registerGenericMessageListener(this);

            // register the status message listener with the gateway
            _gateway.registerStatusMessageListener(this);

            // attempt to login with the local login properties
            Console.WriteLine("Logging in...");
            var loginProperties = new FXCMLoginProperties(UserName, Password, Terminal, Server);

            // disable the streaming rates (default automatic subscriptions)
            loginProperties.addProperty(IConnectionManager.__Fields.MSG_FLAGS, IFixDefs.__Fields.CHANNEL_MARKET_DATA.ToString());
            _gateway.login(loginProperties);
            Console.WriteLine("Logged in.\n");

            // get instrument list
            Console.WriteLine("Requesting trading session status...");
            lock (_locker)
            {
                _currentRequest = _gateway.requestTradingSessionStatus();
                Console.WriteLine("\tRequestId = {0}\n", _currentRequest);
            }
            _requestTradingSessionStatusEvent.WaitOne();
            Console.WriteLine("Instruments: {0}\n", _securities.Count);
            foreach (var pair in _securities)
            {
                var security = pair.Value;

                Console.WriteLine(security.getSymbol() + " " +
                                  security.getCurrency() + " " +
                                  security.getFXCMSubscriptionStatus() + " " +
                                  security.getRoundLot() + " " +
                                  security.getContractMultiplier() + " " +
                                  security.getFXCMMinQuantity() + " " +
                                  security.getFXCMMaxQuantity() + " " +
                                  security.getFXCMSymPointSize() + " " +
                                  security.getFactor() + " " +
                                  security.getFXCMSymPrecision() + " " +
                                  security.getProduct() + " " +
                                  security.getFXCMProductID() + " " +
                                  (security.getFXCMProductID() == IFixValueDefs.__Fields.FXCMPRODUCTID_FOREX ? "Forex" : "CFD"));
            }
            Console.WriteLine();

            // get account list
            Console.WriteLine("Requesting account list...");
            lock (_locker)
            {
                _currentRequest = _gateway.requestAccounts();
                Console.WriteLine("\tRequestId = {0}\n", _currentRequest);
            }
            _requestAccountListEvent.WaitOne();
            Console.WriteLine("Accounts: {0}\n", _accounts.Count);

            // use first account
            var accountId = _accounts.Keys.First();

            // we are unable to continue if Hedging enabled
            if (_accounts[accountId].getParties().getFXCMPositionMaintenance() == "Y")
            {
                throw new NotSupportedException("The Lean engine does not support accounts with Hedging enabled. Please contact FXCM support to disable Hedging and try again.");
            }

            // get open order list
            Console.WriteLine("Requesting open order list...");
            lock (_locker)
            {
                _currentRequest = _gateway.requestOpenOrders();
                Console.WriteLine("\tRequestId = {0}\n", _currentRequest);
            }
            _requestOrderEvent.WaitOne();
            Console.WriteLine("Open orders: {0}\n", _orders.Keys.Count);

            // cancel all open orders
            if (_orders.Keys.Count > 0)
            {
                Console.WriteLine("Cancelling open orders...");
                foreach (var order in _orders.Values.ToList())
                {
                    Console.WriteLine("Cancelling order {0}...", order.getOrderID());
                    var request = MessageGenerator.generateOrderCancelRequest("", order.getOrderID(), order.getSide(), order.getAccount());
                    lock (_locker)
                    {
                        _currentRequest = _gateway.sendMessage(request);
                        Console.WriteLine("\tRequestId = {0}\n", _currentRequest);
                    }
                    _requestOrderEvent.WaitOne();
                    Console.WriteLine("Order {0} cancelled.", order.getOrderID());
                }
                _orders.Clear();
                Console.WriteLine("Open orders cancelled.\n");
            }

            // get open position list
            Console.WriteLine("Requesting open position list...");
            lock (_locker)
            {
                _currentRequest = _gateway.requestOpenPositions();
                Console.WriteLine("\tRequestId = {0}\n", _currentRequest);
            }
            _requestPositionListEvent.WaitOne();
            Console.WriteLine("Open position list complete.\n");

            // get closed position list
            Console.WriteLine("Requesting closed position list...");
            lock (_currentRequest)
            {
                _currentRequest = _gateway.requestClosedPositions();
                Console.WriteLine("\tRequestId = {0}\n", _currentRequest);
            }
            _requestPositionListEvent.WaitOne();
            Console.WriteLine("Closed position list complete.\n");

            // get current quotes for the instrument
            if (_securities.ContainsKey(Symbol))
            {
                Console.WriteLine("Requesting market data for " + Symbol + "...");
                var request = new MarketDataRequest();
                request.setMDEntryTypeSet(MarketDataRequest.MDENTRYTYPESET_ALL);
                request.setSubscriptionRequestType(SubscriptionRequestTypeFactory.SNAPSHOT);
                request.addRelatedSymbol(_securities[Symbol]);
                lock (_locker)
                {
                    _currentRequest = _gateway.sendMessage(request);
                    Console.WriteLine("\tRequestId = {0}\n", _currentRequest);
                }
                _requestMarketDataEvent.WaitOne();
                Console.WriteLine(Symbol + " - Bid: {0} Ask: {1}\n", _rates[Symbol].getBidClose(), _rates[Symbol].getAskClose());
            }

            // submit limit order
            Console.WriteLine("Submitting limit order...");
            var limitOrderRequest = MessageGenerator.generateOpenOrder(0.7, accountId, 10000, SideFactory.BUY, Symbol, "");

            limitOrderRequest.setOrdType(OrdTypeFactory.LIMIT);
            limitOrderRequest.setTimeInForce(TimeInForceFactory.GOOD_TILL_CANCEL);
            lock (_locker)
            {
                _currentRequest = _gateway.sendMessage(limitOrderRequest);
                Console.WriteLine("\tRequestId = {0}\n", _currentRequest);
            }
            _requestOrderEvent.WaitOne();
            Console.WriteLine("Limit order submitted.\n");

            var limitOrder = _orderRequests[_currentRequest];

            // update limit order
            Console.WriteLine("Updating limit order...");
            var orderReplaceRequest = MessageGenerator.generateOrderReplaceRequest("", limitOrder.getOrderID(), limitOrder.getSide(), limitOrder.getOrdType(), 0.8, limitOrder.getAccount());

            lock (_locker)
            {
                _currentRequest = _gateway.sendMessage(orderReplaceRequest);
                Console.WriteLine("\tRequestId = {0}\n", _currentRequest);
            }
            _requestOrderEvent.WaitOne();
            Console.WriteLine("Limit order updated.\n");

            // cancel limit order
            Console.WriteLine("Cancelling limit order...");
            var orderCancelRequest = MessageGenerator.generateOrderCancelRequest("", limitOrder.getOrderID(), limitOrder.getSide(), limitOrder.getAccount());

            lock (_locker)
            {
                _currentRequest = _gateway.sendMessage(orderCancelRequest);
                Console.WriteLine("\tRequestId = {0}\n", _currentRequest);
            }
            _requestOrderEvent.WaitOne();
            Console.WriteLine("Limit order cancelled.\n");

            // submit stop market order
            Console.WriteLine("Submitting stop market order...");
            var stopMarketOrderRequest = MessageGenerator.generateOpenOrder(0.7, accountId, 10000, SideFactory.SELL, Symbol, "");

            stopMarketOrderRequest.setOrdType(OrdTypeFactory.STOP);
            stopMarketOrderRequest.setTimeInForce(TimeInForceFactory.GOOD_TILL_CANCEL);
            lock (_locker)
            {
                _currentRequest = _gateway.sendMessage(stopMarketOrderRequest);
                Console.WriteLine("\tRequestId = {0}\n", _currentRequest);
            }
            _requestOrderEvent.WaitOne();
            Console.WriteLine("Stop market order submitted.\n");

            var stopMarketOrder = _orderRequests[_currentRequest];

            // cancel stop market order
            Console.WriteLine("Cancelling stop market order...");
            orderCancelRequest = MessageGenerator.generateOrderCancelRequest("", stopMarketOrder.getOrderID(), stopMarketOrder.getSide(), stopMarketOrder.getAccount());
            lock (_locker)
            {
                _currentRequest = _gateway.sendMessage(orderCancelRequest);
                Console.WriteLine("\tRequestId = {0}\n", _currentRequest);
            }
            _requestOrderEvent.WaitOne();
            Console.WriteLine("Stop market order cancelled.\n");

            // submit stop limit order
            Console.WriteLine("Submitting stop limit order...");
            var stopLimitOrderRequest = MessageGenerator.generateOpenOrder(0.7, accountId, 10000, SideFactory.SELL, Symbol, "");

            stopLimitOrderRequest.setOrdType(OrdTypeFactory.STOP_LIMIT);
            stopLimitOrderRequest.setStopPx(0.695);
            stopLimitOrderRequest.setTimeInForce(TimeInForceFactory.GOOD_TILL_CANCEL);
            lock (_locker)
            {
                _currentRequest = _gateway.sendMessage(stopLimitOrderRequest);
                Console.WriteLine("\tRequestId = {0}\n", _currentRequest);
            }
            _requestOrderEvent.WaitOne();
            Console.WriteLine("Stop limit order submitted.\n");

            var stopLimitOrder = _orderRequests[_currentRequest];

            // cancel stop limit order
            Console.WriteLine("Cancelling stop limit order...");
            orderCancelRequest = MessageGenerator.generateOrderCancelRequest("", stopLimitOrder.getOrderID(), stopLimitOrder.getSide(), stopLimitOrder.getAccount());
            lock (_locker)
            {
                _currentRequest = _gateway.sendMessage(orderCancelRequest);
                Console.WriteLine("\tRequestId = {0}\n", _currentRequest);
            }
            _requestOrderEvent.WaitOne();
            Console.WriteLine("Stop limit order cancelled.\n");

            // submit market order (buy)
            Console.WriteLine("Submitting buy market order...");
            var buyOrder = MessageGenerator.generateMarketOrder(accountId, 10000, SideFactory.BUY, Symbol, "");

            lock (_locker)
            {
                _currentRequest = _gateway.sendMessage(buyOrder);
                Console.WriteLine("\tRequestId = {0}\n", _currentRequest);
            }
            _requestOrderEvent.WaitOne();
            Console.WriteLine("Buy market order submitted.\n");

            // submit market order (sell)
            Console.WriteLine("Submitting sell market order...");
            var sellOrder = MessageGenerator.generateMarketOrder(accountId, 10000, SideFactory.SELL, Symbol, "");

            lock (_locker)
            {
                _currentRequest = _gateway.sendMessage(sellOrder);
                Console.WriteLine("\tRequestId = {0}\n", _currentRequest);
            }
            _requestOrderEvent.WaitOne();
            Console.WriteLine("Sell market order submitted.\n");

            Console.WriteLine();
            Console.WriteLine("Press Return to Logout and exit.\n");
            Console.ReadKey();

            // log out
            Console.WriteLine("Logging out...");
            _gateway.logout();
            Console.WriteLine("Logged out.");

            // remove the generic message listener, stop listening to updates
            _gateway.removeGenericMessageListener(this);

            // remove the status message listener, stop listening to status changes
            _gateway.removeStatusMessageListener(this);
        }
コード例 #5
0
        /// <summary>
        /// Get historical data enumerable for a single symbol, type and resolution given this start and end time (in UTC).
        /// </summary>
        /// <param name="symbol">Symbol for the data we're looking for.</param>
        /// <param name="resolution">Resolution of the data request</param>
        /// <param name="startUtc">Start time of the data in UTC</param>
        /// <param name="endUtc">End time of the data in UTC</param>
        /// <returns>Enumerable of base data for this symbol</returns>
        public IEnumerable <BaseData> Get(Symbol symbol, Resolution resolution, DateTime startUtc, DateTime endUtc)
        {
            if (!_symbolMapper.IsKnownLeanSymbol(symbol))
            {
                throw new ArgumentException("Invalid symbol requested: " + symbol.Value);
            }

            if (symbol.ID.SecurityType != SecurityType.Forex && symbol.ID.SecurityType != SecurityType.Cfd)
            {
                throw new NotSupportedException("SecurityType not available: " + symbol.ID.SecurityType);
            }

            if (endUtc <= startUtc)
            {
                throw new ArgumentException("The end date must be greater than the start date.");
            }

            Console.WriteLine("Logging in...");

            // create the gateway
            _gateway = GatewayFactory.createGateway();

            // register the message listeners with the gateway
            _gateway.registerGenericMessageListener(this);
            _gateway.registerStatusMessageListener(this);

            // create local login properties
            var loginProperties = new FXCMLoginProperties(_userName, _password, _terminal, _server);

            // log in
            _gateway.login(loginProperties);

            // initialize session
            RequestTradingSessionStatus();

            Console.WriteLine("Downloading {0} data from {1} to {2}...", resolution, startUtc.ToString("yyyyMMdd HH:mm:ss"), endUtc.ToString("yyyyMMdd HH:mm:ss"));

            // Find best FXCM parameters
            var interval = FxcmBrokerage.ToFxcmInterval(resolution);

            var totalTicks = (endUtc - startUtc).Ticks;

            // download data
            var totalBaseData = new List <BaseData>();

            var end = endUtc;

            do //
            {
                //show progress
                progressBar(Math.Abs((end - endUtc).Ticks), totalTicks, Console.WindowWidth / 2, '█');
                _currentBaseData.Clear();

                var mdr = new MarketDataRequest();
                mdr.setSubscriptionRequestType(SubscriptionRequestTypeFactory.SNAPSHOT);
                mdr.setResponseFormat(IFixMsgTypeDefs.__Fields.MSGTYPE_FXCMRESPONSE);
                mdr.setFXCMTimingInterval(interval);
                mdr.setMDEntryTypeSet(MarketDataRequest.MDENTRYTYPESET_ALL);

                mdr.setFXCMStartDate(new UTCDate(FxcmBrokerage.ToJavaDateUtc(startUtc)));
                mdr.setFXCMStartTime(new UTCTimeOnly(FxcmBrokerage.ToJavaDateUtc(startUtc)));
                mdr.setFXCMEndDate(new UTCDate(FxcmBrokerage.ToJavaDateUtc(end)));
                mdr.setFXCMEndTime(new UTCTimeOnly(FxcmBrokerage.ToJavaDateUtc(end)));
                mdr.addRelatedSymbol(_fxcmInstruments[_symbolMapper.GetBrokerageSymbol(symbol)]);


                AutoResetEvent autoResetEvent;
                lock (_locker)
                {
                    _currentRequest = _gateway.sendMessage(mdr);
                    autoResetEvent  = new AutoResetEvent(false);
                    _mapRequestsToAutoResetEvents[_currentRequest] = autoResetEvent;
                }
                if (!autoResetEvent.WaitOne(1000 * 5))
                {
                    // no response, exit
                    break;
                }

                // Add data
                totalBaseData.InsertRange(0, _currentBaseData.Where(x => x.Time.Date >= startUtc.Date));

                if (end != _currentBaseData[0].Time)
                {
                    // new end date = first datapoint date.
                    end = _currentBaseData[0].Time;
                }
                else
                {
                    break;
                }
            } while (end > startUtc);


            Console.WriteLine("\nLogging out...");

            // log out
            _gateway.logout();

            // remove the message listeners
            _gateway.removeGenericMessageListener(this);
            _gateway.removeStatusMessageListener(this);

            return(totalBaseData.ToList());
        }
コード例 #6
0
        /// <summary>
        /// Get historical data enumerable for a single symbol, type and resolution given this start and end time (in UTC).
        /// </summary>
        /// <param name="symbol">Symbol for the data we're looking for.</param>
        /// <param name="type">Security type</param>
        /// <param name="resolution">Resolution of the data request</param>
        /// <param name="startUtc">Start time of the data in UTC</param>
        /// <param name="endUtc">End time of the data in UTC</param>
        /// <returns>Enumerable of base data for this symbol</returns>
        public IEnumerable <BaseData> Get(Symbol symbol, SecurityType type, Resolution resolution, DateTime startUtc, DateTime endUtc)
        {
            if (!_instruments.ContainsKey(symbol.Value))
            {
                throw new ArgumentException("Invalid symbol requested: " + symbol.Value);
            }

            if (resolution == Resolution.Tick)
            {
                throw new NotSupportedException("Resolution not available: " + resolution);
            }

            if (type != SecurityType.Forex && type != SecurityType.Cfd)
            {
                throw new NotSupportedException("SecurityType not available: " + type);
            }

            if (endUtc < startUtc)
            {
                throw new ArgumentException("The end date must be greater or equal than the start date.");
            }

            Console.WriteLine("Logging in...");

            // create the gateway
            _gateway = GatewayFactory.createGateway();

            // register the message listeners with the gateway
            _gateway.registerGenericMessageListener(this);
            _gateway.registerStatusMessageListener(this);

            // create local login properties
            var loginProperties = new FXCMLoginProperties(_userName, _password, _terminal, _server);

            // log in
            _gateway.login(loginProperties);

            // initialize session
            RequestTradingSessionStatus();

            Console.WriteLine("Downloading data from {0} to {1}...", startUtc.ToShortDateString(), endUtc.ToShortDateString());

            // download bars
            var totalBars = new List <TradeBar>();

            // calculate the maximum time span for one request (using 10-second bars)
            const int maxBarsPerRequest  = 300;
            var       timeSpanPerRequest = TimeSpan.FromSeconds(maxBarsPerRequest * 10);

            var start = startUtc;
            var end   = startUtc + timeSpanPerRequest;

            // request loop
            while (start < endUtc.AddDays(1))
            {
                _currentBars.Clear();

                var mdr = new MarketDataRequest();
                mdr.setSubscriptionRequestType(SubscriptionRequestTypeFactory.SNAPSHOT);
                mdr.setResponseFormat(IFixMsgTypeDefs.__Fields.MSGTYPE_FXCMRESPONSE);
                mdr.setFXCMTimingInterval(FXCMTimingIntervalFactory.SEC10);
                mdr.setMDEntryTypeSet(MarketDataRequest.MDENTRYTYPESET_ALL);

                mdr.setFXCMStartDate(new UTCDate(ToJavaDateUtc(start)));
                mdr.setFXCMStartTime(new UTCTimeOnly(ToJavaDateUtc(start)));
                mdr.setFXCMEndDate(new UTCDate(ToJavaDateUtc(end)));
                mdr.setFXCMEndTime(new UTCTimeOnly(ToJavaDateUtc(end)));
                mdr.addRelatedSymbol(_fxcmInstruments[_mapInstrumentSymbols[symbol]]);

                AutoResetEvent autoResetEvent;
                lock (_locker)
                {
                    _currentRequest = _gateway.sendMessage(mdr);
                    autoResetEvent  = new AutoResetEvent(false);
                    _mapRequestsToAutoResetEvents[_currentRequest] = autoResetEvent;
                }
                if (!autoResetEvent.WaitOne(1000))
                {
                    // no response, continue loop
                    start = end.AddSeconds(10);
                    // if saturday, fast-forward to sunday
                    if (start.DayOfWeek == DayOfWeek.Saturday)
                    {
                        start = start.AddDays(1);
                    }
                    end = start + timeSpanPerRequest;
                    continue;
                }

                var lastBarTime = _currentBars[_currentBars.Count - 1].Time;
                if (lastBarTime < start)
                {
                    // no more data available, exit loop
                    break;
                }

                // add bars received
                totalBars.AddRange(_currentBars.Where(x => x.Time.Date <= endUtc.Date));

                // calculate time span for next request
                start = lastBarTime.AddSeconds(10);
                end   = start + timeSpanPerRequest;

                if (start >= DateTime.UtcNow)
                {
                    // data in the future not available, exit loop
                    break;
                }
            }

            Console.WriteLine("Logging out...");

            // log out
            _gateway.logout();

            // remove the message listeners
            _gateway.removeGenericMessageListener(this);
            _gateway.removeStatusMessageListener(this);

            switch (resolution)
            {
            case Resolution.Second:
                foreach (var bar in totalBars)
                {
                    yield return(bar);
                }
                break;

            case Resolution.Minute:
            case Resolution.Hour:
            case Resolution.Daily:
                foreach (var bar in AggregateBars(symbol, totalBars, resolution.ToTimeSpan()))
                {
                    yield return(bar);
                }
                break;
            }
        }