private SymbolAlgorithm CreateAlgorithm(long symbol) { SymbolAlgorithm symbolAlgorithm; lock ( orderAlgorithmsLocker) { if (!orderAlgorithms.TryGetValue(symbol, out symbolAlgorithm)) { var symbolInfo = Factory.Symbol.LookupSymbol(symbol); var orderCache = Factory.Engine.LogicalOrderCache(symbolInfo, false); var algorithm = Factory.Utility.OrderAlgorithm("limefix", symbolInfo, this, orderCache, OrderStore); algorithm.EnableSyncTicks = SyncTicks.Enabled; symbolAlgorithm = new SymbolAlgorithm { OrderAlgorithm = algorithm }; orderAlgorithms.Add(symbol, symbolAlgorithm); algorithm.OnProcessFill = ProcessFill; } } return(symbolAlgorithm); }
private void ExecutionReport(MessageFIX4_2 packetFIX) { var clientOrderId = 0L; long.TryParse(packetFIX.ClientOrderId, out clientOrderId); var originalClientOrderId = 0L; long.TryParse(packetFIX.ClientOrderId, out originalClientOrderId); if (packetFIX.Text == "END") { throw new ApplicationException("Unexpected END in FIX Text field. Never sent a 35=AF message."); } SymbolAlgorithm algorithm = null; SymbolInfo symbolInfo = packetFIX.Symbol != null?Factory.Symbol.LookupSymbol(packetFIX.Symbol) : null; if (symbolInfo != null) { TryGetAlgorithm(symbolInfo.BinaryIdentifier, out algorithm); } string orderStatus = packetFIX.OrderStatus; switch (orderStatus) { case "0": // New if (debug && (LogRecovery || !IsRecovery)) { log.Debug("ExecutionReport New: " + packetFIX); } if (algorithm == null) { log.Info("New order but OrderAlgorithm not found for " + symbolInfo + ". Ignoring."); break; } CreateOrChangeOrder order = null; OrderStore.TryGetOrderById(clientOrderId, out order); if (order != null && symbolInfo.FixSimulationType == FIXSimulationType.BrokerHeldStopOrder) // Stop Order { if (order.Type == OrderType.BuyStop || order.Type == OrderType.SellStop) { if (debug) { log.Debug("New order message for Forex Stop: " + packetFIX); } break; } } algorithm.OrderAlgorithm.ConfirmCreate(clientOrderId, IsRecovered); TrySendStartBroker(symbolInfo, "sync on confirm cancel"); OrderStore.SetSequences(RemoteSequence, FixFactory.LastSequence); break; case "1": // Partial if (debug && (LogRecovery || !IsRecovery)) { log.Debug("ExecutionReport Partial: " + packetFIX); } //UpdateOrder(packetFIX, OrderState.Active, null); SendFill(packetFIX); OrderStore.SetSequences(RemoteSequence, FixFactory.LastSequence); break; case "2": // Filled if (debug && (LogRecovery || !IsRecovery)) { log.Debug("ExecutionReport Filled: " + packetFIX); } if (packetFIX.CumulativeQuantity < packetFIX.LastQuantity) { log.Warn("Ignoring message due to CumQty " + packetFIX.CumulativeQuantity + " less than " + packetFIX.LastQuantity + ". This is a workaround for a MBT FIX server which sends an extra invalid fill message on occasion."); break; } SendFill(packetFIX); OrderStore.SetSequences(RemoteSequence, FixFactory.LastSequence); break; case "5": // Replaced if (debug && (LogRecovery || !IsRecovery)) { log.Debug("ExecutionReport Replaced: " + packetFIX); } if (algorithm == null) { log.Info("ConfirmChange but OrderAlgorithm not found for " + symbolInfo + ". Ignoring."); break; } algorithm.OrderAlgorithm.ConfirmChange(clientOrderId, IsRecovered); TrySendStartBroker(symbolInfo, "sync on confirm change"); OrderStore.SetSequences(RemoteSequence, FixFactory.LastSequence); break; case "4": // Canceled if (debug && (LogRecovery || !IsRecovery)) { log.Debug("ExecutionReport Canceled: " + packetFIX); } if (algorithm == null) { log.Info("Order Canceled but OrderAlgorithm not found for " + symbolInfo + ". Ignoring."); break; } if (clientOrderId != 0) { algorithm.OrderAlgorithm.ConfirmCancel(clientOrderId, IsRecovered); TrySendStartBroker(symbolInfo, "sync on confirm cancel"); } else if (originalClientOrderId != 0) { algorithm.OrderAlgorithm.ConfirmCancel(originalClientOrderId, IsRecovered); TrySendStartBroker(symbolInfo, "sync on confirm cancel orig order"); } OrderStore.SetSequences(RemoteSequence, FixFactory.LastSequence); break; case "6": // Pending Cancel if (debug && (LogRecovery || !IsRecovery)) { log.Debug("ExecutionReport Pending Cancel: " + packetFIX); } if (!string.IsNullOrEmpty(packetFIX.Text) && packetFIX.Text.Contains("multifunction order")) { if (debug && (LogRecovery || IsRecovered)) { log.Debug("Pending cancel of multifunction order, so removing " + packetFIX.ClientOrderId + " and " + packetFIX.OriginalClientOrderId); } if (clientOrderId != 0L) { OrderStore.RemoveOrder(clientOrderId); } if (originalClientOrderId != 0L) { OrderStore.RemoveOrder(originalClientOrderId); } break; } OrderStore.SetSequences(RemoteSequence, FixFactory.LastSequence); TryHandlePiggyBackFill(packetFIX); break; case "8": // Rejected if (debug && (LogRecovery || !IsRecovery)) { log.Debug("ExecutionReport Reject: " + packetFIX); } RejectOrder(packetFIX); break; case "9": // Suspended if (debug && (LogRecovery || !IsRecovery)) { log.Debug("ExecutionReport Suspended: " + packetFIX); } OrderStore.SetSequences(RemoteSequence, FixFactory.LastSequence); break; case "A": // PendingNew if (debug && (LogRecovery || !IsRecovery)) { log.Debug("ExecutionReport Pending New: " + packetFIX); } if (algorithm == null) { log.Info("PendingNew but OrderAlgorithm not found for " + symbolInfo + ". Ignoring."); break; } OrderStore.TryGetOrderById(clientOrderId, out order); if (order != null && symbolInfo.FixSimulationType == FIXSimulationType.BrokerHeldStopOrder && (order.Type == OrderType.BuyStop || order.Type == OrderType.SellStop)) { if (packetFIX.ExecutionType == "D") // Restated { if (debug) { log.Debug("Ignoring restated message 150=D for Forex stop execution report 39=A."); } } else { algorithm.OrderAlgorithm.ConfirmCreate(originalClientOrderId, IsRecovered); } } else { algorithm.OrderAlgorithm.ConfirmActive(originalClientOrderId, IsRecovered); } TrySendStartBroker(symbolInfo, "sync on confirm cancel orig order"); OrderStore.SetSequences(RemoteSequence, FixFactory.LastSequence); break; case "E": // Pending Replace if (debug && (LogRecovery || !IsRecovery)) { log.Debug("ExecutionReport Pending Replace: " + packetFIX); } OrderStore.SetSequences(RemoteSequence, FixFactory.LastSequence); TryHandlePiggyBackFill(packetFIX); break; case "R": // Resumed. if (debug && (LogRecovery || !IsRecovery)) { log.Debug("ExecutionReport Resumed: " + packetFIX); } OrderStore.SetSequences(RemoteSequence, FixFactory.LastSequence); //UpdateOrder(packetFIX, OrderState.Active, null); // Ignore break; default: throw new ApplicationException("Unknown order status: '" + orderStatus + "'"); } }