/// <summary> /// Change order execution related parameters. /// </summary> /// <param name="remoteStopLoss">Applicable to open or pending orders only, pass null to skip, decimal.MinValue (or zero) to signify no value.</param> /// <param name="remoteTakeProfit">Applicable to open or pending orders only, pass null to skip, decimal.MinValue (or zero) to signify no value.</param> /// <param name="operationResultMessage">Applicable ONLY to pending order. Pass null otherwise or to leave unchanged.</param> /// <returns></returns> public bool ModifyRemoteParameters(decimal?remoteStopLoss, decimal?remoteTakeProfit, decimal?remoteTargetOpenPrice, out string operationResultMessage) { if (this.IsOpenOrPending == false) { operationResultMessage = "Wrong order state."; return(false); } if (State != OrderStateEnum.Submitted && remoteTargetOpenPrice.HasValue) { operationResultMessage = "Wrong order state for this operation (operation only applicable to pending orders)."; return(false); } if (remoteStopLoss == StopLoss && TakeProfit == remoteTakeProfit) { // remoteTargetOpenPrice only counts if you do it on a pending order. if ((State == OrderStateEnum.Submitted && remoteTargetOpenPrice == OpenPrice) || (State != OrderStateEnum.Submitted)) {// No changes needed. operationResultMessage = "No changes needed."; return(true); } } operationResultMessage = "Session not assigned."; ISourceOrderExecution executionProvider = _executionProvider; string modifiedId; if (executionProvider == null || OrderExecutionProvider.ModifyOrder(Account.Info, this, remoteStopLoss, remoteTakeProfit, remoteTargetOpenPrice, out modifiedId, out operationResultMessage) == false) { return(false); } //lock (this) //{ // //_info.Id = modifiedId; // if (remoteStopLoss.HasValue) // { // _info.StopLoss = remoteStopLoss; // } // if (remoteTakeProfit.HasValue) // { // _info.TakeProfit = remoteTakeProfit; // } // if (remoteTargetOpenPrice.HasValue) // { // _info.OpenPrice = remoteTargetOpenPrice.Value; // } //} //RaiseOrderUpdatedEvent(UpdateTypeEnum.Modified); return(true); }
/// <summary> /// Applicable to pending/delayed orders only. /// </summary> /// <returns></returns> public bool Cancel(out string operationResultMessage) { if (State != OrderStateEnum.Submitted) { operationResultMessage = "Not pending order can not be canceled."; SystemMonitor.OperationError(operationResultMessage); return(false); } string modifiedId; if (OrderExecutionProvider.CancelPendingOrder(Account.Info, this, out modifiedId, out operationResultMessage)) { State = OrderStateEnum.Canceled; //_info.Id = modifiedId; RaiseOrderUpdatedEvent(UpdateTypeEnum.Canceled); return(true); } return(false); }
/// <summary> /// This allows a part of the order to be closed, or all. /// </summary> public bool DecreaseVolume(int volumeDecrease, decimal?allowedSlippage, decimal?desiredPrice, out string operationResultMessage) { if (volumeDecrease == 0) { operationResultMessage = string.Empty; return(true); } if (this.OpenPrice.HasValue == false) { operationResultMessage = "Invalid order open price."; return(false); } if (State != OrderStateEnum.Executed && State != OrderStateEnum.Submitted) { operationResultMessage = "Close/Decrease volume can be done only to open/pending orders."; return(false); } if (volumeDecrease < 0) { operationResultMessage = "Positive volume decrease required."; return(false); } if (CurrentVolume < volumeDecrease) { operationResultMessage = "Misuse of the Order class [Can not close more volume than already open]."; return(false); } decimal operationPrice; bool operationResult = false; ISourceOrderExecution executionProvider = _executionProvider; if (executionProvider == null) { operationResultMessage = "Execution provider not assigned."; return(false); } DateTime closeTime = DateTime.MinValue; string modifiedId; if (_info.Volume == volumeDecrease) {// Close/Cancel order. if (State == OrderStateEnum.Executed) { operationResult = OrderExecutionProvider.CloseOrder(Account.Info, this, allowedSlippage, desiredPrice, out operationPrice, out closeTime, out modifiedId, out operationResultMessage); } else { operationPrice = decimal.MinValue; operationResult = OrderExecutionProvider.CancelPendingOrder(Account.Info, this, out modifiedId, out operationResultMessage); } } else {// Decrease order closeVolume. operationResult = OrderExecutionProvider.DecreaseOrderVolume(Account.Info, this, volumeDecrease, allowedSlippage, desiredPrice, out operationPrice, out modifiedId, out operationResultMessage); } if (operationResult == false) { SystemMonitor.Report("Order volume decrease has failed in executioner."); return(false); } if (string.IsNullOrEmpty(modifiedId)) {// Since the original order has changed its ticket number; and we have failed to establish the new one - we can no longer track it so unregister. SystemMonitor.OperationWarning("Failed to establish new modified order ticket; order will be re-aquired.", TracerItem.PriorityEnum.High); Account.TradeEntities.RemoveOrder(this); return(true); } if (State == OrderStateEnum.Executed) { if (modifiedId != this.Id) { Account.TradeEntities.RemoveOrder(this); OrderInfo newUpdatedInfo = _info; newUpdatedInfo.Id = modifiedId; newUpdatedInfo.Volume = _info.Volume - volumeDecrease; ActiveOrder updatedOrder = new ActiveOrder(_manager, _executionProvider, _quoteProvider, _dataSourceId, Symbol, true); updatedOrder.AdoptInfo(newUpdatedInfo); _executionProvider.TradeEntities.AddOrder(updatedOrder); // Request updated order info for this and new one and remove current one. if (_executionProvider != null && _executionProvider.DefaultAccount != null && string.IsNullOrEmpty(modifiedId) == false) { _executionProvider.BeginOrdersInformationUpdate(_executionProvider.DefaultAccount.Info, new string[] { this.Id, modifiedId }, out operationResultMessage); } } else { _info.Volume = _info.Volume - volumeDecrease; if (_info.Volume == 0) { State = OrderStateEnum.Closed; _info.CloseTime = closeTime; _info.ClosePrice = operationPrice; } } } else if (State == OrderStateEnum.Submitted) { lock (this) { _initialVolume -= volumeDecrease; _info.Volume = _initialVolume; if (_info.Volume == 0) { State = OrderStateEnum.Canceled; } } } if (State == OrderStateEnum.Closed) {// Closed. RaiseOrderUpdatedEvent(UpdateTypeEnum.Closed); } else {// Still open. RaiseOrderUpdatedEvent(UpdateTypeEnum.VolumeChanged); } return(true); }
/// <summary> /// This allows more specific control over the operation. /// </summary> public bool Submit(OrderTypeEnum orderType, int volume, decimal?allowedSlippage, decimal?desiredPrice, decimal?takeProfit, decimal?stopLoss, string comment, out string operationResultMessage) { SystemMonitor.CheckThrow(volume > 0, "Misuse of the Order class."); if (State != OrderStateEnum.Initialized) { operationResultMessage = "Misuse of the Order class [Order not initialized; or Must not place trade, that has already been placed]."; SystemMonitor.Warning(operationResultMessage); return(false); } ISourceOrderExecution executionProvider = _executionProvider; operationResultMessage = "Session not assigned."; if (desiredPrice.HasValue == false) { desiredPrice = OrderInfo.TypeIsBuy(orderType) ? QuoteProvider.Bid : QuoteProvider.Ask; } if (executionProvider == null) {// Placement of order failed. State = OrderStateEnum.Failed; SystemMonitor.Report("Order was not executed [" + operationResultMessage + "]."); return(false); } string id = OrderExecutionProvider.SubmitOrder(Account.Info, this, Symbol, orderType, volume, allowedSlippage, desiredPrice, takeProfit, stopLoss, comment, out operationResultMessage); if (string.IsNullOrEmpty(id)) { State = OrderStateEnum.Failed; SystemMonitor.OperationError("Order was not executed [" + operationResultMessage + "]."); return(false); } lock (this) { _info.Type = orderType; _initialVolume = volume; _info.Id = id; _info.Volume = volume; _info.StopLoss = stopLoss; _info.TakeProfit = takeProfit; State = OrderStateEnum.Submitted; _localOpenTime = DateTime.Now; } Account.TradeEntities.AddOrder(this); if (State == OrderStateEnum.Executed) { RaiseOrderUpdatedEvent(UpdateTypeEnum.Executed); } else { RaiseOrderUpdatedEvent(UpdateTypeEnum.Submitted); } return(true); }