I have a decent order management algo here for my unmanaged system which takes fills and issues stops/targets. However, once in a blue moon I encounter an issue with my "unique lableling" methodology which results in having a position that doesn't get matched stops/targets.
To start, entry orders are issued a "unique identifier" based on the instrument and time entered. I believe the problem stems from near-simultaneous executions which receive identical entry names:
if (BarsInProgress == 0 && !noTrading) { // First, cancel any outstanding entry orders: if (CurrentBar > barNumberOfOrder && entryOrder != null) { CancelOrder(entryOrder); // Need to reset entryOrder to null in the order update: entryOrder = null; } if (Signal == 1) { newPosition = Instrument.FullName + "_" + "Long_" + Time[0]; entryOrder = SubmitOrder(0, OrderAction.Buy, OrderType.Limit, positionSize, Instrument.MasterInstrument.Round2TickSize(CRG.LongLimitEntryPrice), 0, entryOrders.Count.ToString(), newPosition); } if (Signal == -1) { newPosition = Instrument.FullName + "_" + "Short_" + Time[0]; entryOrder = SubmitOrder(0, OrderAction.SellShort, OrderType.Limit, positionSize, Instrument.MasterInstrument.Round2TickSize(CRG.ShortLimitEntryPrice), 0, entryOrders.Count.ToString(), newPosition); } if (entryOrder != null) { // Add the entry order's token to the token array: entryOrderTokens.Add(entryOrder.Token); // Add the entry order to the entryOrder array: entryOrders.Add(entryOrder); entryOrder = null; // Here, we assign barNumberOfOrder the CurrentBar, so we can check how many bars pass after our order is placed. barNumberOfOrder = CurrentBar; } }
protected override void OnExecution(IExecution execution) { try { // First, loop through the entry orders to see if this execution is linked to an entry order: if (entryOrders.Count !=0) { for (int i = entryOrders.Count - 1; i >= 0; i --) { // Create a temporary entry order container: IOrder localEntryOrder = entryOrders[i]; // If the execution token matches the token to the entry order we were looking for: if (localEntryOrder.Token == execution.Order.Token) { //Print(execution.ToString()); // Is the order filled/partially filled OR has the order been cancelled & filled? //if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.PartFilled || (execution.Order.OrderState == OrderState.Cancelled && execution.Order.Filled > 0)) if (execution.Order.OrderState == OrderState.Filled || (execution.Order.OrderState == OrderState.Cancelled && execution.Order.Filled > 0)) //if (execution.Order.OrderState == OrderState.Filled) { if (Position.MarketPosition == MarketPosition.Long) { targetExitPrice = Position.AvgPrice + CRG.TargetExit; trailingStopPrice = Position.AvgPrice - CRG.StopExit; stopOrder = SubmitOrder(0, OrderAction.Sell, OrderType.Stop, execution.Order.Quantity, 0, trailingStopPrice, execution.Order.Name, "Stop Order"); targetOrder = SubmitOrder(0, OrderAction.Sell, OrderType.Limit, execution.Order.Quantity, targetExitPrice, 0, execution.Order.Name, "Target Order"); } if (Position.MarketPosition == MarketPosition.Short) { targetExitPrice = Position.AvgPrice - CRG.TargetExit; trailingStopPrice = Position.AvgPrice + CRG.StopExit; stopOrder = SubmitOrder(0, OrderAction.BuyToCover, OrderType.Stop, execution.Order.Quantity, 0, trailingStopPrice, execution.Order.Name, "Stop Order"); targetOrder = SubmitOrder(0, OrderAction.BuyToCover, OrderType.Limit, execution.Order.Quantity, targetExitPrice, 0, execution.Order.Name, "Target Order"); } // Add stop order to the stop order list if (stopOrder != null) { stopOrders.Add(stopOrder); stopOrder = null; } // Add target order to the target order list. if (targetOrder != null) { targetOrders.Add(targetOrder); targetOrder = null; } // Resets the entryOrder object to null after the order has been filled or partially filled //if (execution.Order.OrderState != OrderState.PartFilled) if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.Cancelled) { entryOrders.RemoveAt(i); entryOrder = null; } } } } } // Second, loop through the target orders to see if this execution is linked to a target order: if (targetOrders.Count != 0) { for (int i = targetOrders.Count - 1; i >= 0; i --) { IOrder localTargetOrder = targetOrders[i]; // If the execution token matches the token to the entry order we were looking for: if (localTargetOrder.Token == execution.Order.Token) { // Is the order filled/partially filled OR has the order been cancelled & filled? //if (execution.Order.OrderState == OrderState.Filled || (execution.Order.OrderState == OrderState.Cancelled && execution.Order.Filled > 0)) if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.Cancelled) { //CancelOrder(targetOrders[i]); targetOrders.RemoveAt(i); } } } } // Third, loop through the stop orders to see if this execution is linked to a stop order: if (stopOrders.Count != 0) { for (int i = stopOrders.Count - 1; i >= 0; i --) { IOrder localStopOrder = stopOrders[i]; // If the execution token matches the token to the entry order we were looking for: if (localStopOrder.Token == execution.Order.Token) { // Is the order filled/partially filled OR has the order been cancelled & filled? //if (execution.Order.OrderState == OrderState.Filled || (execution.Order.OrderState == OrderState.Cancelled && execution.Order.Filled > 0)) if (execution.Order.OrderState == OrderState.Filled || execution.Order.OrderState == OrderState.Cancelled) { //CancelOrder(stopOrders[i]); stopOrders.RemoveAt(i); } } } } } catch (Exception ex) { Debug.WriteLine(ex); } }
Thanks-
CG
PS I have left just a few details out in terms of the code but everything needed for the positioning algo is there -
Comment