public void BrokerageMessage(BrokerageMessageEvent brokerageMessageEvent) { }
/// <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(); }
/// <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(); } }
/// <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); } }
public virtual void OnBrokerageMessage(BrokerageMessageEvent messageEvent) { //Algo.OnBrokerageMessage(messageEvent); }
/// <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>()); } }
/// <summary> /// Event invocator for the Message event /// </summary> /// <param name="e">The error</param> public new void OnMessage(BrokerageMessageEvent e) { base.OnMessage(e); }
/// <summary> /// Process brokerage message events /// </summary> /// <param name="brokerageMessageEvent">The brokerage message event</param> public virtual void BrokerageMessage(BrokerageMessageEvent brokerageMessageEvent) { // NOP }
/// <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)); }
/// <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(); }
public override bool CanUpdateOrder(Security security, Order order, UpdateOrderRequest request, out BrokerageMessageEvent message) { message = new BrokerageMessageEvent(0, 0, ""); return(false); }
/// <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)); }
private void OnPricingConnectionRestored(object sender, EventArgs e) { Log.Trace("OnPricingConnectionRestored(): pricing connection restored"); OnMessage(BrokerageMessageEvent.Reconnected("Pricing connection with Oanda server restored.")); }
/// <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); } }
private void OnTransactionsConnectionRestored(object sender, EventArgs e) { Log.Trace("OnTransactionsConnectionRestored(): transactions connection restored"); OnMessage(BrokerageMessageEvent.Reconnected("Transactions connection with Oanda server restored.")); }
/// <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(); } }
/// <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)); }
/// <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; } }