Ejemplo n.º 1
0
 public void BrokerageMessage(BrokerageMessageEvent brokerageMessageEvent)
 {
 }
Ejemplo n.º 2
0
        /// <summary>
        /// Connects the client to the broker's remote servers
        /// </summary>
        public override void Connect()
        {
            if (IsConnected)
            {
                return;
            }

            _sockClient.ConnectAsync().SynchronouslyAwaitTask();
            _natsClient.Open();

            _isConnected = true;

            // create new thread to manage disconnections and reconnections
            var connectionMonitorStartedEvent = new AutoResetEvent(false);

            _cancellationTokenSource = new CancellationTokenSource();
            _connectionMonitorThread = new Thread(() =>
            {
                connectionMonitorStartedEvent.Set();

                var nextReconnectionAttemptSeconds = 1;

                try
                {
                    while (!_cancellationTokenSource.IsCancellationRequested)
                    {
                        var isAlive = true;
                        try
                        {
                            isAlive = _sockClient.IsAlive;
                        }
                        catch (Exception)
                        {
                            // ignored
                        }

                        if (isAlive && _connectionLost)
                        {
                            _connectionLost = false;
                            nextReconnectionAttemptSeconds = 1;

                            OnMessage(BrokerageMessageEvent.Reconnected("Connection with Alpaca server restored."));
                        }
                        else if (!isAlive)
                        {
                            if (_connectionLost)
                            {
                                try
                                {
                                    Thread.Sleep(TimeSpan.FromSeconds(nextReconnectionAttemptSeconds));

                                    _sockClient.ConnectAsync().SynchronouslyAwaitTask();
                                }
                                catch (Exception exception)
                                {
                                    // double the interval between attempts (capped to 1 minute)
                                    nextReconnectionAttemptSeconds = Math.Min(nextReconnectionAttemptSeconds * 2, 60);

                                    Log.Error(exception);
                                }
                            }
                            else
                            {
                                _connectionLost = true;

                                OnMessage(
                                    BrokerageMessageEvent.Disconnected(
                                        "Connection with Alpaca server lost. " +
                                        "This could be because of internet connectivity issues. "));
                            }
                        }

                        Thread.Sleep(1000);
                    }
                }
                catch (Exception exception)
                {
                    Log.Error(exception);
                }
            })
            {
                IsBackground = true
            };
            _connectionMonitorThread.Start();

            connectionMonitorStartedEvent.WaitOne();
        }
Ejemplo n.º 3
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
            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);
                        }
                    }
                });
                _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
            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);
                    }
                });
                _connectionMonitorThread.Start();
                while (!_connectionMonitorThread.IsAlive)
                {
                    Thread.Sleep(1);
                }
            }

            // load instruments, accounts, orders, positions
            LoadInstruments();
            if (!EnableOnlyHistoryRequests)
            {
                LoadAccounts();
                LoadOpenOrders();
                LoadOpenPositions();
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Connects the client to the broker's remote servers
        /// </summary>
        public override void Connect()
        {
            if (IsConnected)
            {
                return;
            }

            // Load the list of instruments
            _oandaInstruments = GetInstruments().ToDictionary(x => x.instrument);

            // Register to the event session to receive events.
            _eventsSession = new EventsSession(this, _accountId);
            _eventsSession.DataReceived += OnEventReceived;
            _eventsSession.StartSession();

            _isConnected = true;

            // create new thread to manage disconnections and reconnections
            _cancellationTokenSource = new CancellationTokenSource();
            _connectionMonitorThread = new Thread(() =>
            {
                var nextReconnectionAttemptUtcTime    = DateTime.UtcNow;
                double nextReconnectionAttemptSeconds = 1;

                lock (_lockerConnectionMonitor)
                {
                    _lastHeartbeatUtcTime = DateTime.UtcNow;
                }

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

                        if (!_connectionLost && elapsed > TimeSpan.FromSeconds(20))
                        {
                            _connectionLost = true;
                            nextReconnectionAttemptUtcTime = DateTime.UtcNow.AddSeconds(nextReconnectionAttemptSeconds);

                            OnMessage(BrokerageMessageEvent.Disconnected("Connection with Oanda server lost. " +
                                                                         "This could be because of internet connectivity issues. "));
                        }
                        else if (_connectionLost)
                        {
                            try
                            {
                                if (elapsed <= TimeSpan.FromSeconds(20))
                                {
                                    _connectionLost = false;
                                    nextReconnectionAttemptSeconds = 1;

                                    OnMessage(BrokerageMessageEvent.Reconnected("Connection with Oanda server restored."));
                                }
                                else
                                {
                                    if (DateTime.UtcNow > nextReconnectionAttemptUtcTime)
                                    {
                                        try
                                        {
                                            // check if we have a connection
                                            GetInstruments();

                                            // restore events session
                                            if (_eventsSession != null)
                                            {
                                                _eventsSession.DataReceived -= OnEventReceived;
                                                _eventsSession.StopSession();
                                            }
                                            _eventsSession = new EventsSession(this, _accountId);
                                            _eventsSession.DataReceived += OnEventReceived;
                                            _eventsSession.StartSession();

                                            // restore rates session
                                            List <Symbol> symbolsToSubscribe;
                                            lock (_lockerSubscriptions)
                                            {
                                                symbolsToSubscribe = _subscribedSymbols.ToList();
                                            }
                                            SubscribeSymbols(symbolsToSubscribe);
                                        }
                                        catch (Exception)
                                        {
                                            // double the interval between attempts (capped to 1 minute)
                                            nextReconnectionAttemptSeconds = Math.Min(nextReconnectionAttemptSeconds * 2, 60);
                                            nextReconnectionAttemptUtcTime = DateTime.UtcNow.AddSeconds(nextReconnectionAttemptSeconds);
                                        }
                                    }
                                }
                            }
                            catch (Exception exception)
                            {
                                Log.Error(exception);
                            }
                        }

                        Thread.Sleep(1000);
                    }
                }
                catch (Exception exception)
                {
                    Log.Error(exception);
                }
            });
            _connectionMonitorThread.Start();
            while (!_connectionMonitorThread.IsAlive)
            {
                Thread.Sleep(1);
            }
        }
Ejemplo n.º 5
0
 public virtual void OnBrokerageMessage(BrokerageMessageEvent messageEvent)
 {
     //Algo.OnBrokerageMessage(messageEvent);
 }
Ejemplo n.º 6
0
 /// <summary>
 /// Returns true if the brokerage would allow updating the order as specified by the request
 /// </summary>
 /// <param name="security">The security of the order</param>
 /// <param name="order">The order to be updated</param>
 /// <param name="request">The requested updated to be made to the order</param>
 /// <param name="message">If this function returns false, a brokerage message detailing why the order may not be updated</param>
 /// <returns>True if the brokerage would allow updating the order, false otherwise</returns>
 public bool CanUpdateOrder(Security security, Order order, UpdateOrderRequest request, out BrokerageMessageEvent message)
 {
     using (Py.GIL())
     {
         return(_model.CanUpdateOrder(security, order, out message));
     }
 }
 /// <summary>
 /// Returns true if the brokerage would allow updating the order as specified by the request
 /// </summary>
 /// <param name="security">The security of the order</param>
 /// <param name="order">The order to be updated</param>
 /// <param name="request">The requested updated to be made to the order</param>
 /// <param name="message">If this function returns false, a brokerage message detailing why the order may not be updated</param>
 /// <returns>True if the brokerage would allow updating the order, false otherwise</returns>
 public bool CanUpdateOrder(Security security, Order order, UpdateOrderRequest request, out BrokerageMessageEvent message)
 {
     using (Py.GIL())
     {
         return((_model.CanUpdateOrder(security, order, out message) as PyObject).GetAndDispose <bool>());
     }
 }
Ejemplo n.º 8
0
 /// <summary>
 /// Event invocator for the Message event
 /// </summary>
 /// <param name="e">The error</param>
 public new void OnMessage(BrokerageMessageEvent e)
 {
     base.OnMessage(e);
 }
Ejemplo n.º 9
0
 /// <summary>
 /// Process brokerage message events
 /// </summary>
 /// <param name="brokerageMessageEvent">The brokerage message event</param>
 public virtual void BrokerageMessage(BrokerageMessageEvent brokerageMessageEvent)
 {
     // NOP
 }
Ejemplo n.º 10
0
        /// <summary>
        /// Handles a request to update order properties
        /// </summary>
        private OrderResponse HandleUpdateOrderRequest(UpdateOrderRequest request)
        {
            Order       order;
            OrderTicket ticket;

            if (!_orders.TryGetValue(request.OrderId, out order) || !_orderTickets.TryGetValue(request.OrderId, out ticket))
            {
                Log.Error("BrokerageTransactionHandler.HandleUpdateOrderRequest(): Unable to update order with ID " + request.OrderId);
                return(OrderResponse.UnableToFindOrder(request));
            }

            if (!CanUpdateOrder(order))
            {
                return(OrderResponse.InvalidStatus(request, order));
            }

            // rounds off the order towards 0 to the nearest multiple of lot size
            var security = _algorithm.Securities[order.Symbol];

            order.Quantity = RoundOffOrder(order, security);

            // verify that our current brokerage can actually update the order
            BrokerageMessageEvent message;

            if (!_algorithm.LiveMode && !_algorithm.BrokerageModel.CanUpdateOrder(_algorithm.Securities[order.Symbol], order, request, out message))
            {
                // if we couldn't actually process the order, mark it as invalid and bail
                order.Status = OrderStatus.Invalid;
                if (message == null)
                {
                    message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "InvalidOrder", "BrokerageModel declared unable to update order: " + order.Id);
                }
                var response = OrderResponse.Error(request, OrderResponseErrorCode.BrokerageModelRefusedToUpdateOrder, "OrderID: " + order.Id + " " + message);
                _algorithm.Error(response.ErrorMessage);
                HandleOrderEvent(new OrderEvent(order, _algorithm.UtcTime, 0m, "BrokerageModel declared unable to update order"));
                return(response);
            }

            // modify the values of the order object
            order.ApplyUpdateOrderRequest(request);

            // rounds the order prices
            RoundOrderPrices(order, security);

            ticket.SetOrder(order);

            bool orderUpdated;

            try
            {
                orderUpdated = _brokerage.UpdateOrder(order);
            }
            catch (Exception err)
            {
                Log.Error(err);
                orderUpdated = false;
            }

            if (!orderUpdated)
            {
                // we failed to update the order for some reason
                var errorMessage = "Brokerage failed to update order with id " + request.OrderId;
                _algorithm.Error(errorMessage);
                HandleOrderEvent(new OrderEvent(order, _algorithm.UtcTime, 0m, "Brokerage failed to update order"));
                return(OrderResponse.Error(request, OrderResponseErrorCode.BrokerageFailedToUpdateOrder, errorMessage));
            }

            return(OrderResponse.Success(request));
        }
Ejemplo n.º 11
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);

            // 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();
        }
Ejemplo n.º 12
0
 public override bool CanUpdateOrder(Security security, Order order, UpdateOrderRequest request, out BrokerageMessageEvent message)
 {
     message = new BrokerageMessageEvent(0, 0, "");
     return(false);
 }
Ejemplo n.º 13
0
        /// <summary>
        /// Handles a request to submit a new order
        /// </summary>
        private OrderResponse HandleSubmitOrderRequest(SubmitOrderRequest request)
        {
            OrderTicket ticket;
            var         order = Order.CreateOrder(request);

            // ensure the order is tagged with a currency
            var security = _algorithm.Securities[order.Symbol];

            order.PriceCurrency = security.SymbolProperties.QuoteCurrency;

            // rounds off the order towards 0 to the nearest multiple of lot size
            order.Quantity = RoundOffOrder(order, security);

            if (!_orders.TryAdd(order.Id, order))
            {
                Log.Error("BrokerageTransactionHandler.HandleSubmitOrderRequest(): Unable to add new order, order not processed.");
                return(OrderResponse.Error(request, OrderResponseErrorCode.OrderAlreadyExists, "Cannot process submit request because order with id {0} already exists"));
            }
            if (!_orderTickets.TryGetValue(order.Id, out ticket))
            {
                Log.Error("BrokerageTransactionHandler.HandleSubmitOrderRequest(): Unable to retrieve order ticket, order not processed.");
                return(OrderResponse.UnableToFindOrder(request));
            }

            // rounds the order prices
            RoundOrderPrices(order, security);

            // save current security time and prices
            order.OrderSubmissionData = new OrderSubmissionData(security.GetLastData());

            // update the ticket's internal storage with this new order reference
            ticket.SetOrder(order);

            if (order.Quantity == 0)
            {
                order.Status = OrderStatus.Invalid;
                var response = OrderResponse.ZeroQuantity(request);
                _algorithm.Error(response.ErrorMessage);
                HandleOrderEvent(new OrderEvent(order, _algorithm.UtcTime, 0m, "Unable to add order for zero quantity"));
                return(response);
            }

            // check to see if we have enough money to place the order
            HasSufficientBuyingPowerForOrderResult hasSufficientBuyingPowerResult;

            try
            {
                hasSufficientBuyingPowerResult = security.BuyingPowerModel.HasSufficientBuyingPowerForOrder(_algorithm.Portfolio, security, order);
            }
            catch (Exception err)
            {
                Log.Error(err);
                _algorithm.Error(string.Format("Order Error: id: {0}, Error executing margin models: {1}", order.Id, err.Message));
                HandleOrderEvent(new OrderEvent(order, _algorithm.UtcTime, 0m, "Error executing margin models"));
                return(OrderResponse.Error(request, OrderResponseErrorCode.ProcessingError, "Error in GetSufficientCapitalForOrder"));
            }

            if (!hasSufficientBuyingPowerResult.IsSufficient)
            {
                order.Status = OrderStatus.Invalid;
                var errorMessage = $"Order Error: id: {order.Id}, Insufficient buying power to complete order (Value:{order.GetValue(security).SmartRounding()}), Reason: {hasSufficientBuyingPowerResult.Reason}";
                var response     = OrderResponse.Error(request, OrderResponseErrorCode.InsufficientBuyingPower, errorMessage);
                _algorithm.Error(response.ErrorMessage);
                HandleOrderEvent(new OrderEvent(order, _algorithm.UtcTime, 0m, errorMessage));
                return(response);
            }

            // verify that our current brokerage can actually take the order
            BrokerageMessageEvent message;

            if (!_algorithm.BrokerageModel.CanSubmitOrder(security, order, out message))
            {
                // if we couldn't actually process the order, mark it as invalid and bail
                order.Status = OrderStatus.Invalid;
                if (message == null)
                {
                    message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "InvalidOrder", "BrokerageModel declared unable to submit order: " + order.Id);
                }
                var response = OrderResponse.Error(request, OrderResponseErrorCode.BrokerageModelRefusedToSubmitOrder, "OrderID: " + order.Id + " " + message);
                _algorithm.Error(response.ErrorMessage);
                HandleOrderEvent(new OrderEvent(order, _algorithm.UtcTime, 0m, "BrokerageModel declared unable to submit order"));
                return(response);
            }

            // set the order status based on whether or not we successfully submitted the order to the market
            bool orderPlaced;

            try
            {
                orderPlaced = _brokerage.PlaceOrder(order);
            }
            catch (Exception err)
            {
                Log.Error(err);
                orderPlaced = false;
            }

            if (!orderPlaced)
            {
                // we failed to submit the order, invalidate it
                order.Status = OrderStatus.Invalid;
                var errorMessage = "Brokerage failed to place order: " + order.Id;
                var response     = OrderResponse.Error(request, OrderResponseErrorCode.BrokerageFailedToSubmitOrder, errorMessage);
                _algorithm.Error(response.ErrorMessage);
                HandleOrderEvent(new OrderEvent(order, _algorithm.UtcTime, 0m, "Brokerage failed to place order"));
                return(response);
            }

            return(OrderResponse.Success(request));
        }
Ejemplo n.º 14
0
        private void OnPricingConnectionRestored(object sender, EventArgs e)
        {
            Log.Trace("OnPricingConnectionRestored(): pricing connection restored");

            OnMessage(BrokerageMessageEvent.Reconnected("Pricing connection with Oanda server restored."));
        }
Ejemplo n.º 15
0
        /// <summary>
        /// Connects the client to the broker's remote servers
        /// </summary>
        public override void Connect()
        {
            // Register to the event session to receive events.
            StartTransactionStream();

            _isConnected = true;

            // create new thread to manage disconnections and reconnections
            _cancellationTokenSource = new CancellationTokenSource();
            _connectionMonitorThread = new Thread(() =>
            {
                var nextReconnectionAttemptUtcTime    = DateTime.UtcNow;
                double nextReconnectionAttemptSeconds = 1;

                lock (LockerConnectionMonitor)
                {
                    LastHeartbeatUtcTime = DateTime.UtcNow;
                }

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

                        if (!_connectionLost && elapsed > TimeSpan.FromSeconds(20))
                        {
                            _connectionLost = true;
                            nextReconnectionAttemptUtcTime = DateTime.UtcNow.AddSeconds(nextReconnectionAttemptSeconds);

                            OnMessage(BrokerageMessageEvent.Disconnected("Connection with Oanda server lost. " +
                                                                         "This could be because of internet connectivity issues. "));
                        }
                        else if (_connectionLost)
                        {
                            try
                            {
                                if (elapsed <= TimeSpan.FromSeconds(20))
                                {
                                    _connectionLost = false;
                                    nextReconnectionAttemptSeconds = 1;

                                    OnMessage(BrokerageMessageEvent.Reconnected("Connection with Oanda server restored."));
                                }
                                else
                                {
                                    if (DateTime.UtcNow > nextReconnectionAttemptUtcTime)
                                    {
                                        try
                                        {
                                            // check if we have a connection
                                            GetInstrumentList();

                                            // restore events session
                                            StopTransactionStream();
                                            StartTransactionStream();

                                            // restore rates session
                                            List <Symbol> symbolsToSubscribe;
                                            lock (LockerSubscriptions)
                                            {
                                                symbolsToSubscribe = SubscribedSymbols.ToList();
                                            }
                                            SubscribeSymbols(symbolsToSubscribe);
                                        }
                                        catch (Exception)
                                        {
                                            // double the interval between attempts (capped to 1 minute)
                                            nextReconnectionAttemptSeconds = Math.Min(nextReconnectionAttemptSeconds * 2, 60);
                                            nextReconnectionAttemptUtcTime = DateTime.UtcNow.AddSeconds(nextReconnectionAttemptSeconds);
                                        }
                                    }
                                }
                            }
                            catch (Exception exception)
                            {
                                Log.Error(exception);
                            }
                        }

                        Thread.Sleep(1000);
                    }
                }
                catch (Exception exception)
                {
                    Log.Error(exception);
                }
            })
            {
                IsBackground = true
            };
            _connectionMonitorThread.Start();
            while (!_connectionMonitorThread.IsAlive)
            {
                Thread.Sleep(1);
            }
        }
Ejemplo n.º 16
0
        private void OnTransactionsConnectionRestored(object sender, EventArgs e)
        {
            Log.Trace("OnTransactionsConnectionRestored(): transactions connection restored");

            OnMessage(BrokerageMessageEvent.Reconnected("Transactions connection with Oanda server restored."));
        }
Ejemplo n.º 17
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
            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") ? "Contact [email protected] to enable API access, below is a template email. " + Environment.NewLine +
                    "Email: [email protected] " + Environment.NewLine +
                    "Template: " + Environment.NewLine +
                    "Hello FXCM staff, " + Environment.NewLine +
                    "Please enable Java API for all accounts which are associated with this email address. " + Environment.NewLine +
                    "Also, please respond to this email address once Java API has been enabled, letting me know that the change was done successfully." :
                    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();
            }
        }
Ejemplo n.º 18
0
        /// <summary>
        /// Handles a request to submit a new order
        /// </summary>
        private OrderResponse HandleSubmitOrderRequest(SubmitOrderRequest request)
        {
            OrderTicket ticket;
            var         order = Order.CreateOrder(request);

            if (!_orders.TryAdd(order.Id, order))
            {
                Log.Error("BrokerageTransactionHandler.HandleSubmitOrderRequest(): Unable to add new order, order not processed.");
                return(OrderResponse.Error(request, OrderResponseErrorCode.OrderAlreadyExists, "Cannot process submit request because order with id {0} already exists"));
            }
            if (!_orderTickets.TryGetValue(order.Id, out ticket))
            {
                Log.Error("BrokerageTransactionHandler.HandleSubmitOrderRequest(): Unable to retrieve order ticket, order not processed.");
                return(OrderResponse.UnableToFindOrder(request));
            }

            // update the ticket's internal storage with this new order reference
            ticket.SetOrder(order);

            // check to see if we have enough money to place the order
            bool sufficientCapitalForOrder;

            try
            {
                sufficientCapitalForOrder = _algorithm.Transactions.GetSufficientCapitalForOrder(_algorithm.Portfolio, order);
            }
            catch (Exception err)
            {
                Log.Error(err);
                _algorithm.Error(string.Format("Order Error: id: {0}, Error executing margin models: {1}", order.Id, err.Message));
                return(OrderResponse.Error(request, OrderResponseErrorCode.ProcessingError, "Error in GetSufficientCapitalForOrder"));
            }

            if (!sufficientCapitalForOrder)
            {
                order.Status = OrderStatus.Invalid;
                var security = _algorithm.Securities[order.Symbol];
                var response = OrderResponse.Error(request, OrderResponseErrorCode.InsufficientBuyingPower, string.Format("Order Error: id: {0}, Insufficient buying power to complete order (Value:{1}).", order.Id, order.GetValue(security.Price).SmartRounding()));
                _algorithm.Error(response.ErrorMessage);
                return(response);
            }

            // verify that our current brokerage can actually take the order
            BrokerageMessageEvent message;

            if (!_algorithm.LiveMode && !_algorithm.BrokerageModel.CanSubmitOrder(_algorithm.Securities[order.Symbol], order, out message))
            {
                // if we couldn't actually process the order, mark it as invalid and bail
                order.Status = OrderStatus.Invalid;
                if (message == null)
                {
                    message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "InvalidOrder", "BrokerageModel declared unable to submit order: " + order.Id);
                }
                var response = OrderResponse.Error(request, OrderResponseErrorCode.BrokerageModelRefusedToSubmitOrder, "OrderID: " + order.Id + " " + message);
                _algorithm.Error(response.ErrorMessage);
                return(response);
            }

            // set the order status based on whether or not we successfully submitted the order to the market
            bool orderPlaced;

            try
            {
                orderPlaced = _brokerage.PlaceOrder(order);
            }
            catch (Exception err)
            {
                Log.Error(err);
                orderPlaced = false;
            }

            if (!orderPlaced)
            {
                // we failed to submit the order, invalidate it
                order.Status = OrderStatus.Invalid;
                var errorMessage = "Brokerage failed to place order: " + order.Id;
                var response     = OrderResponse.Error(request, OrderResponseErrorCode.BrokerageFailedToSubmitOrder, errorMessage);
                _algorithm.Error(response.ErrorMessage);
                return(response);
            }

            order.Status = OrderStatus.Submitted;
            return(OrderResponse.Success(request));
        }
Ejemplo n.º 19
0
        /// <summary>
        /// Handles the message
        /// </summary>
        /// <param name="message">The message to be handled</param>
        public void Handle(BrokerageMessageEvent message)
        {
            // based on message type dispatch to result handler
            switch (message.Type)
            {
            case BrokerageMessageType.Information:
                _results.DebugMessage("Brokerage Info: " + message.Message);
                break;

            case BrokerageMessageType.Warning:
                _results.ErrorMessage("Brokerage Warning: " + message.Message);
                _api.SendUserEmail(_job.AlgorithmId, "Brokerage Warning", message.Message);
                break;

            case BrokerageMessageType.Error:
                _results.ErrorMessage("Brokerage Error: " + message.Message);
                _algorithm.RunTimeError = new Exception(message.Message);
                break;

            case BrokerageMessageType.Disconnect:
                _connected = false;
                Log.Trace("DefaultBrokerageMessageHandler.Handle(): Disconnected.");

                // check to see if any non-custom security exchanges are open within the next x minutes
                var open = (from kvp in _algorithm.Securities
                            let security = kvp.Value
                                           where security.Type != SecurityType.Base
                                           let exchange = security.Exchange
                                                          let localTime = _algorithm.UtcTime.ConvertFromUtc(exchange.TimeZone)
                                                                          where exchange.IsOpenDuringBar(localTime, localTime + _openThreshold, security.IsExtendedMarketHours)
                                                                          select security).Any();

                // if any are open then we need to kill the algorithm
                if (open)
                {
                    // wait 15 minutes before killing algorithm
                    StartCheckReconnected(_initialDelay, message);
                }
                else
                {
                    Log.Trace("DefaultBrokerageMessageHandler.Handle(): Disconnect when exchanges are closed, checking back before exchange open.");

                    // if they aren't open, we'll need to check again a little bit before markets open
                    DateTime nextMarketOpenUtc;
                    if (_algorithm.Securities.Count != 0)
                    {
                        nextMarketOpenUtc = (from kvp in _algorithm.Securities
                                             let security = kvp.Value
                                                            where security.Type != SecurityType.Base
                                                            let exchange = security.Exchange
                                                                           let localTime = _algorithm.UtcTime.ConvertFromUtc(exchange.TimeZone)
                                                                                           let marketOpen = exchange.Hours.GetNextMarketOpen(localTime, security.IsExtendedMarketHours)
                                                                                                            let marketOpenUtc = marketOpen.ConvertToUtc(exchange.TimeZone)
                                                                                                                                select marketOpenUtc).Min();
                    }
                    else
                    {
                        // if we have no securities just make next market open an hour from now
                        nextMarketOpenUtc = DateTime.UtcNow.AddHours(1);
                    }

                    var timeUntilNextMarketOpen = nextMarketOpenUtc - DateTime.UtcNow - _openThreshold;

                    // wake up 5 minutes before market open and check if we've reconnected
                    StartCheckReconnected(timeUntilNextMarketOpen, message);
                }
                break;

            case BrokerageMessageType.Reconnect:
                _connected = true;
                Log.Trace("DefaultBrokerageMessageHandler.Handle(): Reconnected.");

                if (_cancellationTokenSource != null && !_cancellationTokenSource.IsCancellationRequested)
                {
                    _cancellationTokenSource.Cancel();
                }
                break;
            }
        }