/// <summary> /// Modifies the state of this order to match the update request /// </summary> /// <param name="request">The request to update this order object</param> public override void ApplyUpdateOrderRequest(UpdateOrderRequest request) { base.ApplyUpdateOrderRequest(request); if (request.StopPrice.HasValue) { StopPrice = request.StopPrice.Value; } }
/// <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 update 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 override bool CanUpdateOrder(Security security, Order order, UpdateOrderRequest request, out BrokerageMessageEvent message) { message = null; if (order.SecurityType == SecurityType.Forex && request.Quantity != null) { return IsForexWithinOrderSizeLimits(order.Symbol.Value, request.Quantity.Value, out message); } return true; }
/// <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 update 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 override bool CanUpdateOrder(Security security, Order order, UpdateOrderRequest request, out BrokerageMessageEvent message) { message = null; // Tradier doesn't allow updating order quantities if (request.Quantity != null && request.Quantity != order.Quantity) { message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "UpdateRejected", "Traider does not support updating order quantities." ); return false; } return true; }
/// <summary> /// Update an order yet to be filled such as stop or limit orders. /// </summary> /// <param name="request">Request detailing how the order should be updated</param> /// <remarks>Does not apply if the order is already fully filled</remarks> public OrderTicket UpdateOrder(UpdateOrderRequest request) { return ProcessRequest(request); }
/// <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); } // 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); 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> /// Update an order yet to be filled such as stop or limit orders. /// </summary> /// <param name="request">Request detailing how the order should be updated</param> /// <remarks>Does not apply if the order is already fully filled</remarks> public OrderTicket UpdateOrder(UpdateOrderRequest request) { OrderTicket ticket; if (!_orderTickets.TryGetValue(request.OrderId, out ticket)) { return OrderTicket.InvalidUpdateOrderId(_algorithm.Transactions, request); } ticket.AddUpdateRequest(request); try { //Update the order from the behaviour var order = GetOrderByIdInternal(request.OrderId); if (order == null) { // can't update an order that doesn't exist! request.SetResponse(OrderResponse.UnableToFindOrder(request)); } else if (order.Status.IsClosed()) { // can't update a completed order request.SetResponse(OrderResponse.InvalidStatus(request, order)); } else if (request.Quantity.HasValue && request.Quantity.Value == 0) { request.SetResponse(OrderResponse.ZeroQuantity(request)); } else if (_algorithm.IsWarmingUp) { request.SetResponse(OrderResponse.WarmingUp(request)); } else { request.SetResponse(OrderResponse.Success(request), OrderRequestStatus.Processing); _orderRequestQueue.Add(request); } } catch (Exception err) { Log.Error(err); request.SetResponse(OrderResponse.Error(request, OrderResponseErrorCode.ProcessingError, err.Message)); } return ticket; }
/// <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); } // modify the values of the order object order.ApplyUpdateOrderRequest(request); 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 order.Status = OrderStatus.Invalid; return OrderResponse.Error(request, OrderResponseErrorCode.BrokerageFailedToUpdateOrder, "Brokerage failed to update order with id " + request.OrderId); } return OrderResponse.Success(request); }
/// <summary> /// Modifies the state of this order to match the update request /// </summary> /// <param name="request">The request to update this order object</param> public virtual void ApplyUpdateOrderRequest(UpdateOrderRequest request) { if (request.OrderId != Id) { throw new ArgumentException("Attempted to apply updates to the incorrect order!"); } if (request.Quantity.HasValue) { Quantity = request.Quantity.Value; } if (request.Tag != null) { Tag = request.Tag; } }
/// <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 update 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 virtual bool CanUpdateOrder(Security security, Order order, UpdateOrderRequest request, out BrokerageMessageEvent message) { message = null; return true; }
/// <summary> /// Creates a new <see cref="OrderTicket"/> that represents trying to update an order for which no ticket exists /// </summary> public static OrderTicket InvalidUpdateOrderId(SecurityTransactionManager transactionManager, UpdateOrderRequest request) { var submit = new SubmitOrderRequest(OrderType.Market, SecurityType.Base, Symbol.Empty, 0, 0, 0, DateTime.MaxValue, request.Tag); submit.SetResponse(OrderResponse.UnableToFindOrder(request)); submit.SetOrderId(request.OrderId); var ticket = new OrderTicket(transactionManager, submit); request.SetResponse(OrderResponse.UnableToFindOrder(request)); ticket.AddUpdateRequest(request); ticket._orderStatusOverride = OrderStatus.Invalid; return(ticket); }
/// <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 update 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 override bool CanUpdateOrder(Security security, Order order, UpdateOrderRequest request, out BrokerageMessageEvent message) { message = null; // validate order quantity if (request.Quantity != null && request.Quantity % 1000 != 0) { message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported", "The order quantity must be a multiple of 1000." ); return false; } // determine direction via the new, updated quantity var newQuantity = request.Quantity ?? order.Quantity; var direction = newQuantity > 0 ? OrderDirection.Buy : OrderDirection.Sell; // use security.Price if null, allows to pass checks var stopPrice = request.StopPrice ?? security.Price; var limitPrice = request.LimitPrice ?? security.Price; return IsValidOrderPrices(security, order.Type, direction, stopPrice, limitPrice, ref message); }