Niggly issue.
I use an unmanaged approach and every now and again my target order throws up the wrong quantity.
It is usually when the order happens on the first tick of the bar - my code automatically adjusts position size and it seems to send out this erroneous second target order. I traced the orders and they are literally milliseconds apart.
Is there anyway to prevent this that someone can share?
Edit I think it may be because of a part fill issue. The unmanaged template puts a target order in there and I wonder if the sum quantity is somehow getting confused.
I reproduce the template code below.
#region ON Execution update protected override void OnExecutionUpdate(Execution execution, string executionId, double price, int quantity, MarketPosition marketPosition, string orderId, DateTime time) { if (longEntry != null && longEntry == execution.Order) { if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.PartFilled || (execution.Order.OrderState == OrderState.Cancelled && execution.Order.Filled > 0)) { // We sum the quantities of each execution making up the entry order sumFilledLong += execution.Quantity; if (State == State.Historical) oco = DateTime.Now.ToString() + CurrentBar + "LongExits"; else oco = GetAtmStrategyUniqueId() + "LongExits"; if (stopLossLong == null && targetLong == null) { SubmitOrderUnmanaged(0, OrderAction.Sell, OrderType.StopMarket, execution.Order.Filled, 0, execution.Order.AverageFillPrice - StopDistance * TickSize, oco, "StopLossLong"); SubmitOrderUnmanaged(0, OrderAction.Sell, OrderType.Limit, execution.Order.Filled, execution.Order.AverageFillPrice + ProfitDistance * TickSize, 0, oco, "TargetLong"); } else { // Submit exit orders for partial fills if (execution.Order.OrderState == OrderState.PartFilled) { ChangeOrder(stopLossLong, execution.Order.Filled, 0, execution.Order.AverageFillPrice - StopDistance * TickSize); ChangeOrder(targetLong, execution.Order.Filled, execution.Order.AverageFillPrice + ProfitDistance * TickSize, 0); } // Update our exit order quantities once orderstate turns to filled and we have seen execution quantities match order quantities else if (execution.Order.OrderState == OrderState.Filled && sumFilledLong == execution.Order.Filled) { // Stop-Loss order for OrderState.Filled ChangeOrder(stopLossLong, execution.Order.Filled, 0, execution.Order.AverageFillPrice - StopDistance * TickSize); ChangeOrder(targetLong, execution.Order.Filled, execution.Order.AverageFillPrice + ProfitDistance * TickSize, 0); } } // Resets the entryOrder object and the sumFilled counter to null / 0 after the order has been filled if (execution.Order.OrderState != OrderState.PartFilled && sumFilledLong == execution.Order.Filled) { longEntry = null; sumFilledLong = 0; } } } if (shortEntry != null && shortEntry == execution.Order) { if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.PartFilled || (execution.Order.OrderState == OrderState.Cancelled && execution.Order.Filled > 0)) { // We sum the quantities of each execution making up the entry order sumFilledShort += execution.Quantity; if (State == State.Historical) oco = DateTime.Now.ToString() + CurrentBar + "ShortExits"; else oco = GetAtmStrategyUniqueId() + "ShortExits"; if (stopLossShort == null && targetShort == null) { SubmitOrderUnmanaged(0, OrderAction.BuyToCover, OrderType.StopMarket, execution.Order.Filled, 0, execution.Order.AverageFillPrice + StopDistance * TickSize, oco, "StopLossShort"); SubmitOrderUnmanaged(0, OrderAction.BuyToCover, OrderType.Limit, execution.Order.Filled, execution.Order.AverageFillPrice - ProfitDistance * TickSize, 0, oco, "TargetShort"); } else { // Submit exit orders for partial fills if (execution.Order.OrderState == OrderState.PartFilled) { ChangeOrder(stopLossShort, execution.Order.Filled, 0, execution.Order.AverageFillPrice + StopDistance * TickSize); ChangeOrder(targetShort, execution.Order.Filled, execution.Order.AverageFillPrice - ProfitDistance * TickSize, 0); } // Update our exit order quantities once orderstate turns to filled and we have seen execution quantities match order quantities else if (execution.Order.OrderState == OrderState.Filled && sumFilledShort == execution.Order.Filled) { // Stop-Loss order for OrderState.Filled ChangeOrder(stopLossShort, execution.Order.Filled, 0, execution.Order.AverageFillPrice + StopDistance * TickSize); ChangeOrder(targetShort, execution.Order.Filled, execution.Order.AverageFillPrice - ProfitDistance * TickSize, 0); } } // Resets the entryOrder object and the sumFilled counter to null / 0 after the order has been filled if (execution.Order.OrderState != OrderState.PartFilled && sumFilledShort == execution.Order.Filled) { shortEntry = null; sumFilledShort = 0; } } } // Reset our stop order and target orders' Order objects after our position is closed. if ((stopLossLong != null && stopLossLong == execution.Order) || (targetLong != null && targetLong == execution.Order)) { if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.PartFilled) { stopLossLong = null; targetLong = null; } } if ((stopLossShort != null && stopLossShort == execution.Order) || (targetShort != null && targetShort == execution.Order)) { if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.PartFilled) { stopLossShort = null; targetShort = null; } } } #endregion
Comment