public void SendFill(MessageFIX4_2 packetFIX) { var clientOrderId = 0L; long.TryParse(packetFIX.ClientOrderId, out clientOrderId); var originalClientOrderId = 0L; long.TryParse(packetFIX.ClientOrderId, out originalClientOrderId); if (debug) { log.Debug("SendFill( " + packetFIX.ClientOrderId + ")"); } var symbolInfo = Factory.Symbol.LookupSymbol(packetFIX.Symbol); var timeZone = new SymbolTimeZone(symbolInfo); SymbolAlgorithm algorithm; if (!TryGetAlgorithm(symbolInfo.BinaryIdentifier, out algorithm)) { log.Info("Fill received but OrderAlgorithm not found for " + symbolInfo + ". Ignoring."); return; } var fillPosition = packetFIX.LastQuantity * SideToSign(packetFIX.Side); if (GetSymbolStatus(symbolInfo)) { CreateOrChangeOrder order; if (OrderStore.TryGetOrderById(clientOrderId, out order)) { TimeStamp executionTime; if (UseLocalFillTime) { executionTime = TimeStamp.UtcNow; } else { executionTime = new TimeStamp(packetFIX.TransactionTime); } var configTime = executionTime; configTime.AddSeconds(timeZone.UtcOffset(executionTime)); var fill = Factory.Utility.PhysicalFill(fillPosition, packetFIX.LastPrice, configTime, executionTime, order.BrokerOrder, false, packetFIX.OrderQuantity, packetFIX.CumulativeQuantity, packetFIX.LeavesQuantity, IsRecovered, true); if (debug) { log.Debug("Sending physical fill: " + fill); } algorithm.OrderAlgorithm.ProcessFill(fill); algorithm.OrderAlgorithm.ProcessOrders(); TrySendStartBroker(symbolInfo, "position sync on fill"); } else { algorithm.OrderAlgorithm.IncreaseActualPosition(fillPosition); log.Notice("Fill id " + packetFIX.ClientOrderId + " not found. Must have been a manual trade."); if (SyncTicks.Enabled) { var tickSync = SyncTicks.GetTickSync(symbolInfo.BinaryIdentifier); tickSync.RemovePhysicalFill(packetFIX.ClientOrderId); } } } }
private CreateOrChangeOrder ConstructCancelOrder(MessageFIX4_2 packet, string clientOrderId) { if (string.IsNullOrEmpty(clientOrderId)) { var message = "Client order id was null or empty. FIX Message is: " + packet; log.Error(message); throw new ApplicationException(message); } var symbol = Factory.Symbol.LookupSymbol(packet.Symbol); var side = OrderSide.Buy; var type = OrderType.None; var logicalId = 0; long clientId; if (!long.TryParse(clientOrderId, out clientId)) { log.Error("original client order id " + clientOrderId + " cannot be converted to long: " + packet); clientId = 0; } var utcCreateTime = new TimeStamp(packet.TimeStamp); var physicalOrder = Factory.Utility.PhysicalOrder( OrderAction.Cancel, OrderState.Active, symbol, side, type, OrderFlags.None, 0D, 0, logicalId, 0, clientId, null, utcCreateTime); if (debug) { log.Debug("Received physical Order: " + physicalOrder); } return(physicalOrder); }
private void FIXRequestSessionStatus(MessageFIX4_2 packet) { if (packet.TradingSessionId != "TSSTATE") { throw new ApplicationException("Expected TSSTATE for trading session id but was: " + packet.TradingSessionId); } if (!packet.TradingSessionRequestId.Contains(sender) || !packet.TradingSessionRequestId.Contains(packet.Sequence.ToString())) { throw new ApplicationException("Expected unique trading session request id but was:" + packet.TradingSessionRequestId); } requestSessionStatus = true; if (onlineNextTime) { ProviderSimulator.SetOrderServerOnline(); onlineNextTime = false; } if (ProviderSimulator.IsOrderServerOnline) { SendSessionStatusOnline(); } else { SendSessionStatus("3"); } onlineNextTime = true; }
private void FIXCreateOrder(MessageFIX4_2 packet) { if (debug) { log.Debug("FIXCreateOrder() for " + packet.Symbol + ". Client id: " + packet.ClientOrderId); } var symbol = Factory.Symbol.LookupSymbol(packet.Symbol); var order = ConstructOrder(packet, packet.ClientOrderId); if (!ProviderSimulator.IsOrderServerOnline) { if (debug) { log.Debug(symbol + ": Rejected " + packet.ClientOrderId + ". Order server offline."); } OnRejectOrder(order, symbol + ": Order Server Offline."); return; } var simulator = simulators[SimulatorType.RejectSymbol]; if (FixFactory != null && simulator.CheckFrequencyAndSymbol(symbol)) { if (debug) { log.Debug("Simulating create order reject of 35=" + packet.MessageType); } OnRejectOrder(order, "Testing reject of create order"); return; } simulator = simulators[SimulatorType.ServerOfflineReject]; if (FixFactory != null && simulator.CheckFrequency()) { if (debug) { log.Debug("Simulating order server offline business reject of 35=" + packet.MessageType); } OnBusinessRejectOrder(packet.ClientOrderId, "Server offline for create order."); ProviderSimulator.SwitchBrokerState("offline", false); ProviderSimulator.SetOrderServerOffline(); return; } if (packet.Symbol == "TestPending") { log.Info("Ignoring FIX order since symbol is " + packet.Symbol); } else { if (string.IsNullOrEmpty(packet.ClientOrderId)) { System.Diagnostics.Debugger.Break(); } ProviderSimulator.CreateOrder(order); ProcessCreateOrder(order); ProviderSimulator.TryProcessAdustments(order); } return; }
private void TryHandlePiggyBackFill(MessageFIX4_2 packetFIX) { if (packetFIX.LastQuantity > 0) { if (debug) { log.Debug("TryHandlePiggyBackFill triggering fill because LastQuantity = " + packetFIX.LastQuantity); } SendFill(packetFIX); } }
private void FIXPositionList(MessageFIX4_2 packet) { var mbtMsg = (FIXMessage4_4)FixFactory.Create(); mbtMsg.SetText("DONE"); mbtMsg.AddHeader("AO"); if (debug) { log.Debug("Sending end of position list: " + mbtMsg); } SendMessage(mbtMsg); }
private void FIXOrderList(MessageFIX4_2 packet) { var mbtMsg = (FIXMessage4_4)FixFactory.Create(); mbtMsg.SetText("END"); mbtMsg.AddHeader("8"); if (debug) { log.Debug("Sending end of order list: " + mbtMsg); } SendMessage(mbtMsg); }
private void BusinessReject(MessageFIX4_2 packetFIX) { var lower = packetFIX.Text.ToLower(); var text = packetFIX.Text; var errorOkay = false; log.Error(packetFIX.Text + " -- Sending EndBroker event."); CancelRecovered(); TrySendEndBroker(); TryEndRecovery(); log.Info(packetFIX.Text + " Sent EndBroker event due to Message:\n" + packetFIX); if (!errorOkay) { string message = "FIX Server reported an error: " + packetFIX.Text + "\n" + packetFIX; throw new ApplicationException(message); } }
public void RejectOrder(MessageFIX4_2 packetFIX) { var clientOrderId = 0L; long.TryParse(packetFIX.ClientOrderId, out clientOrderId); var originalClientOrderId = 0L; long.TryParse(packetFIX.ClientOrderId, out originalClientOrderId); if (packetFIX.Text.Contains("Order Server Offline") || packetFIX.Text.Contains("Trading temporarily unavailable") || packetFIX.Text.Contains("Order Server Not Available")) { CancelRecovered(); TrySendEndBroker(); TryEndRecovery(); } var symbol = Factory.Symbol.LookupSymbol(packetFIX.Symbol); SymbolAlgorithm algorithm; if (TryGetAlgorithm(symbol.BinaryIdentifier, out algorithm)) { if (IsRecovered && algorithm.OrderAlgorithm.RejectRepeatCounter > 0) { var message = "Order Rejected: " + packetFIX.Text + "\n" + packetFIX; log.Warn(message); } var retryImmediately = algorithm.OrderAlgorithm.RejectRepeatCounter < 1; algorithm.OrderAlgorithm.RejectOrder(clientOrderId, IsRecovered, retryImmediately); if (!retryImmediately) { TrySendEndBroker(symbol); } } else { log.Info("RejectOrder but OrderAlgorithm not found for " + symbol + ". Ignoring."); } }
private void CancelRejected(MessageFIX4_2 packetFIX) { var clientOrderId = 0L; long.TryParse(packetFIX.ClientOrderId, out clientOrderId); var originalClientOrderId = 0L; long.TryParse(packetFIX.ClientOrderId, out originalClientOrderId); if (debug && (LogRecovery || !IsRecovery)) { log.Debug("CancelRejected: " + packetFIX); } string orderStatus = packetFIX.OrderStatus; switch (orderStatus) { case "2": //Filled var rejectReason = false; if (packetFIX.Text.Contains("Unknown order") || packetFIX.Text.Contains("Order is completed")) { rejectReason = true; log.Warn("RemoveOriginal=FALSE for: " + packetFIX.Text); //removeOriginal = true; } else { log.Error("Unknown text meesage in CancelReject: " + packetFIX.Text); } CreateOrChangeOrder order; if (OrderStore.TryGetOrderById(clientOrderId, out order)) { var symbol = order.Symbol; SymbolAlgorithm algorithm; if (!TryGetAlgorithm(symbol.BinaryIdentifier, out algorithm)) { log.Info("Cancel rejected but OrderAlgorithm not found for " + symbol + ". Ignoring."); break; } var retryImmediately = true; algorithm.OrderAlgorithm.RejectOrder(clientOrderId, IsRecovered, retryImmediately); } else { if (debug) { log.Debug("Order not found for " + clientOrderId + ". Probably allready filled or canceled."); } } if (!rejectReason && IsRecovered) { var message = "Order Rejected: " + packetFIX.Text + "\n" + packetFIX; var stopping = "The cancel reject error message '" + packetFIX.Text + "' was unrecognized. "; log.Warn(message); log.Error(stopping); } else { if (LogRecovery || !IsRecovery) { log.Info("CancelReject(" + packetFIX.Text + ") Removed cancel order: " + packetFIX.ClientOrderId); } } break; default: throw new ApplicationException("Unknown cancel rejected order status: '" + orderStatus + "'"); } }
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 + "'"); } }
private CreateOrChangeOrder ConstructOrder(MessageFIX4_2 packet, string clientOrderId) { if (string.IsNullOrEmpty(clientOrderId)) { var message = "Client order id was null or empty. FIX Message is: " + packet; log.Error(message); throw new ApplicationException(message); } var symbol = Factory.Symbol.LookupSymbol(packet.Symbol); var side = OrderSide.Buy; switch (packet.Side) { case "1": side = OrderSide.Buy; break; case "2": side = OrderSide.Sell; break; case "5": case "9": side = OrderSide.SellShort; break; } var type = OrderType.BuyLimit; switch (packet.OrderType) { case "1": if (side == OrderSide.Buy) { type = OrderType.BuyMarket; } else { type = OrderType.SellMarket; } break; case "2": if (side == OrderSide.Buy) { type = OrderType.BuyLimit; } else { type = OrderType.SellLimit; } break; default: //throw new LimeException("Unsupported Order Type"); log.Error("Unsupported order type"); return(null); } long clientId; var logicalId = 0; if (!long.TryParse(clientOrderId, out clientId)) { log.Error("original client order id " + clientOrderId + " cannot be converted to long: " + packet); clientId = 0; } //var utcCreateTime = new TimeStamp(packet.TransactionTime); var utcCreateTime = new TimeStamp(packet.TimeStamp); var physicalOrder = Factory.Utility.PhysicalOrder( OrderAction.Create, OrderState.Active, symbol, side, type, OrderFlags.None, packet.Price, packet.OrderQuantity, logicalId, 0, clientId, null, utcCreateTime); if (debug) { log.Debug("Received physical Order: " + physicalOrder); } return(physicalOrder); }
private void FIXCancelOrder(MessageFIX4_2 packet) { var symbol = Factory.Symbol.LookupSymbol(packet.Symbol); if (!ProviderSimulator.IsOrderServerOnline) { throw new LimeException("Order server offline testing for Lime not yet implemeneted"); if (debug) { log.Debug(symbol + ": Cannot cancel order by client id: " + packet.OriginalClientOrderId + ". Order Server Offline."); } OnRejectCancel(packet.Symbol, packet.ClientOrderId, packet.OriginalClientOrderId, symbol + ": Order Server Offline"); return; } var simulator = simulators[SimulatorType.RejectSymbol]; if (FixFactory != null && simulator.CheckFrequencyAndSymbol(symbol)) { if (debug) { log.Debug("Simulating cancel order reject of 35=" + packet.MessageType); } OnRejectCancel(packet.Symbol, packet.ClientOrderId, packet.OriginalClientOrderId, "Testing reject of cancel order."); return; } simulator = simulators[SimulatorType.ServerOfflineReject]; if (FixFactory != null && simulator.CheckFrequency()) { throw new LimeException("Order server offline testing for Lime not yet implemeneted"); if (debug) { log.Debug("Simulating order server offline business reject of 35=" + packet.MessageType); } OnBusinessRejectOrder(packet.ClientOrderId, "Server offline for cancel order."); ProviderSimulator.SwitchBrokerState("offline", false); ProviderSimulator.SetOrderServerOffline(); return; } if (debug) { log.Debug("FIXCancelOrder() for " + packet.Symbol + ". Original client id: " + packet.OriginalClientOrderId); } CreateOrChangeOrder origOrder = null; try { long origClientId; if (!long.TryParse(packet.OriginalClientOrderId, out origClientId)) { log.Error("original client order id " + packet.OriginalClientOrderId + " cannot be converted to long: " + packet); origClientId = 0; } origOrder = ProviderSimulator.GetOrderById(symbol, origClientId); } catch (ApplicationException) { if (debug) { log.Debug(symbol + ": Cannot cancel order by client id: " + packet.OriginalClientOrderId + ". Probably already filled or canceled."); } OnRejectCancel(packet.Symbol, packet.ClientOrderId, packet.OriginalClientOrderId, "No such order"); return; } var cancelOrder = ConstructCancelOrder(packet, packet.ClientOrderId); cancelOrder.OriginalOrder = origOrder; ProviderSimulator.CancelOrder(cancelOrder); ProcessCancelOrder(cancelOrder); ProviderSimulator.TryProcessAdustments(cancelOrder); return; }
private void FIXChangeOrder(MessageFIX4_2 packet) { var symbol = Factory.Symbol.LookupSymbol(packet.Symbol); var order = ConstructOrder(packet, packet.ClientOrderId); if (!ProviderSimulator.IsOrderServerOnline) { throw new LimeException("Order server offline testing for Lime not yet implemeneted"); log.Info(symbol + ": Rejected " + packet.ClientOrderId + ". Order server offline."); OnRejectOrder(order, symbol + ": Order Server Offline."); return; } var simulator = simulators[SimulatorType.RejectSymbol]; if (FixFactory != null && simulator.CheckFrequencyAndSymbol(symbol)) { if (debug) { log.Debug("Simulating create order reject of 35=" + packet.MessageType); } OnRejectOrder(order, "Testing reject of change order."); return; } simulator = simulators[SimulatorType.ServerOfflineReject]; if (FixFactory != null && simulator.CheckFrequency()) { throw new LimeException("Order server offline testing for Lime not yet implemeneted"); if (debug) { log.Debug("Simulating order server offline business reject of 35=" + packet.MessageType); } OnBusinessRejectOrder(packet.ClientOrderId, "Server offline for change order."); ProviderSimulator.SwitchBrokerState("offline", false); ProviderSimulator.SetOrderServerOffline(); return; } CreateOrChangeOrder origOrder = null; if (debug) { log.Debug("FIXChangeOrder() for " + packet.Symbol + ". Client id: " + packet.ClientOrderId + ". Original client id: " + packet.OriginalClientOrderId); } try { long origClientId; if (!long.TryParse(packet.OriginalClientOrderId, out origClientId)) { log.Error("original client order id " + packet.OriginalClientOrderId + " cannot be converted to long: " + packet); origClientId = 0; } origOrder = ProviderSimulator.GetOrderById(symbol, origClientId); } catch (ApplicationException ex) { if (debug) { log.Debug(symbol + ": Rejected " + packet.ClientOrderId + ". Cannot change order: " + packet.OriginalClientOrderId + ". Already filled or canceled. Message: " + ex.Message); } OnRejectOrder(order, symbol + ": Cannot change order. Probably already filled or canceled."); return; } order.OriginalOrder = origOrder; #if VERIFYSIDE if (order.Side != origOrder.Side) { var message = symbol + ": Cannot change " + origOrder.Side + " to " + order.Side; log.Error(message); OnRejectOrder(order, false, message); return; } if (order.Type != origOrder.Type) { var message = symbol + ": Cannot change " + origOrder.Type + " to " + order.Type; log.Error(message); OnRejectOrder(order, false, message); return; } #endif ProviderSimulator.ChangeOrder(order); ProcessChangeOrder(order); }