private void ClosePosition(Order order, pxNetAdapter.Model.Trading.Order pxOrder) { // We need to find the position, if order is long it means we closing a SHORT position pxNetAdapter.Model.Trading.Position pxPosition = order.Long ? m_positions.FirstOrDefault(p => p.Symbol == pxOrder.Symbol && p.Side == pxNetAdapter.Model.Trading.SideEnum.Sell && order.Quantity == p.SellQty) : m_positions.FirstOrDefault(p => p.Symbol == pxOrder.Symbol && p.Side == pxNetAdapter.Model.Trading.SideEnum.Buy && order.Quantity == p.BuyQty); if (pxPosition == null) { m_NTconnection.ProcessEventArgs(new OrderStatusEventArgs(order, NinjaTrader.Cbi.ErrorCode.UnableToSubmitOrder, "Unable to submit order '" + order.OrderId + "': Could not find the Position to close", order.OrderId, pxOrder.Price, order.StopPrice, (int)pxOrder.Quantity, order.AvgFillPrice, order.Filled, OrderState.Rejected, m_NTconnection.Now)); return; } // Calc the pnl double pnl = pxPosition.Side == pxNetAdapter.Model.Trading.SideEnum.Buy ? pxOrder.Price - pxPosition.Price : pxPosition.Price - pxOrder.Price; pnl *= pxOrder.Quantity; pxOrder.PNL = Math.Round(pnl, 2); pxOrder.PNLCurrency = "USD"; m_pxConnector.Send(Trading.ClosePosition(m_token, pxPosition.GUID, pxOrder), res => { if (res.Error != null && !string.IsNullOrEmpty(res.Error.Code)) { m_NTconnection.ProcessEventArgs(new OrderStatusEventArgs(order, NinjaTrader.Cbi.ErrorCode.UnableToSubmitOrder, "Unable to submit order '" + order.OrderId + "': " + res.Error.Message, order.OrderId, pxOrder.Price, order.StopPrice, (int)pxOrder.Quantity, order.AvgFillPrice, order.Filled, OrderState.Rejected, m_NTconnection.Now)); return; } PositionResponseData resData = res.Data as PositionResponseData; if (resData == null || string.IsNullOrEmpty(resData.Position.GUID)) { m_NTconnection.ProcessEventArgs(new OrderStatusEventArgs(order, NinjaTrader.Cbi.ErrorCode.UnableToSubmitOrder, "Unable to submit order '" + order.OrderId + "': Invalid response data" + res.Error.Message, order.OrderId, pxOrder.Price, order.StopPrice, (int)pxOrder.Quantity, order.AvgFillPrice, order.Filled, OrderState.Rejected, m_NTconnection.Now)); return; } m_ntOrderPxOrder[order.OrderId] = resData.Position.GUID; int qty = resData.Position.Side == pxNetAdapter.Model.Trading.SideEnum.Buy ? (int)resData.Position.BuyQty : (int)resData.Position.SellQty; int filled = qty; OrderState state = OrderState.Filled; m_NTconnection.ProcessEventArgs(new OrderStatusEventArgs(order, NinjaTrader.Cbi.ErrorCode.NoError, string.Empty, order.OrderId, resData.Position.Price, order.StopPrice, qty, resData.Position.Price, filled, state, m_NTconnection.Now)); MarketPosition mp = MarketPosition.Flat; m_NTconnection.ProcessEventArgs(new PositionUpdateEventArgs(m_NTconnection, ErrorCode.NoError, "", Operation.Remove, order.Account, order.Instrument, mp, qty, NinjaTrader.Cbi.Currency.UsDollar, resData.Position.Price)); }); }
public void Cancel(Order order) { string orderGUID; if (!m_ntOrderPxOrder.TryGetValue(order.OrderId, out orderGUID) || string.IsNullOrEmpty(orderGUID)) { m_NTconnection.ProcessEventArgs(new OrderStatusEventArgs(order, NinjaTrader.Cbi.ErrorCode.UnableToCancelOrder, "Unable to cancel order '" + order.OrderId + "': Could not find PX order GUID", order.OrderId, order.LimitPrice, order.StopPrice, order.Quantity, order.AvgFillPrice, order.Filled, order.OrderState, m_NTconnection.Now)); return; } Asset asset = GetPxAsset(order.Instrument); if (asset == null) { m_NTconnection.ProcessEventArgs(new OrderStatusEventArgs(order, NinjaTrader.Cbi.ErrorCode.UnableToCancelOrder, "Unable to cancel order '" + order.OrderId + "': Could not convert Instrument to Asset", order.OrderId, order.LimitPrice, order.StopPrice, order.Quantity, order.AvgFillPrice, order.Filled, order.OrderState, m_NTconnection.Now)); return; } if (!m_lastQuotes.ContainsKey(asset.Symbol)) { m_NTconnection.ProcessEventArgs(new OrderStatusEventArgs(order, NinjaTrader.Cbi.ErrorCode.UnableToCancelOrder, "Unable to cancel order '" + order.OrderId + "': No active quote found", order.OrderId, order.LimitPrice, order.StopPrice, order.Quantity, order.AvgFillPrice, order.Filled, order.OrderState, m_NTconnection.Now)); return; } pxNetAdapter.Model.Trading.Order pxOrder = new pxNetAdapter.Model.Trading.Order(); pxOrder.Type = pxNetAdapter.Model.Trading.TypeEnum.Limit; pxOrder.AccountGUID = order.Account.Name; pxOrder.QuoteGUID = m_lastQuotes[asset.Symbol].GUID; m_pxConnector.Send(Trading.ClosePosition(m_token, orderGUID, pxOrder), res => { if (res.Error != null && !string.IsNullOrEmpty(res.Error.Code)) { m_NTconnection.ProcessEventArgs(new OrderStatusEventArgs(order, NinjaTrader.Cbi.ErrorCode.UnableToCancelOrder, "Unable to cancel order '" + order.OrderId + "': " + res.Error.Message, order.OrderId, order.LimitPrice, order.StopPrice, order.Quantity, order.AvgFillPrice, order.Filled, order.OrderState, m_NTconnection.Now)); return; } m_NTconnection.ProcessEventArgs(new OrderStatusEventArgs(order, NinjaTrader.Cbi.ErrorCode.NoError, string.Empty, order.OrderId, order.LimitPrice, order.StopPrice, order.Quantity, order.AvgFillPrice, order.Filled, OrderState.Cancelled, m_NTconnection.Now)); }); m_NTconnection.ProcessEventArgs(new OrderStatusEventArgs(order, NinjaTrader.Cbi.ErrorCode.NoError, string.Empty, order.OrderId, order.LimitPrice, order.StopPrice, order.Quantity, order.AvgFillPrice, order.Filled, OrderState.PendingCancel, m_NTconnection.Now)); }