Example #1
0
        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);
                    }
                }
            }
        }
Example #2
0
        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 + "'");
            }
        }
Example #3
0
        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 + "'");
            }
        }
Example #4
0
        private void OnCreateOrChangeBrokerOrder(CreateOrChangeOrder order, bool resend)
        {
            var fixMsg = (FIXMessage4_2)(resend ? FixFactory.Create(order.Sequence) : FixFactory.Create());

            order.Sequence = fixMsg.Sequence;
            OrderStore.SetOrder(order);
            OrderStore.SetSequences(RemoteSequence, FixFactory.LastSequence);

            if (order.Size > order.Symbol.MaxOrderSize)
            {
                throw new ApplicationException("Order was greater than MaxOrderSize of " + order.Symbol.MaxPositionSize + " for:\n" + order);
            }

            var orderHandler = GetAlgorithm(order.Symbol.BinaryIdentifier);
            var orderSize    = order.Type == OrderType.SellLimit || order.Type == OrderType.SellMarket || order.Type == OrderType.SellStop ? -order.Size : order.Size;

            if (Math.Abs(orderHandler.OrderAlgorithm.ActualPosition + orderSize) > order.Symbol.MaxPositionSize)
            {
                throw new ApplicationException("Order was greater than MaxPositionSize of " + order.Symbol.MaxPositionSize + " for:\n" + order);
            }

            if (debug)
            {
                log.Debug("Adding Order to open order list: " + order);
            }
            if (order.Action == OrderAction.Change)
            {
                var origBrokerOrder = order.OriginalOrder.BrokerOrder;
                fixMsg.SetClientOrderId(order.BrokerOrder.ToString());
                fixMsg.SetOriginalClientOrderId(origBrokerOrder.ToString());
                CreateOrChangeOrder origOrder;
                if (OrderStore.TryGetOrderById(origBrokerOrder, out origOrder))
                {
                    origOrder.ReplacedBy = order;
                    if (debug)
                    {
                        log.Debug("Setting replace property of " + origBrokerOrder + " to " + order.BrokerOrder);
                    }
                }
            }
            else
            {
                fixMsg.SetClientOrderId(order.BrokerOrder.ToString());
            }

            if (order.Action == OrderAction.Change)
            {
                fixMsg.AddHeader("G");
            }
            else
            {
                fixMsg.AddHeader("D");
                if (order.Symbol.Destination.ToLower() == "default")
                {
                    fixMsg.SetDestination(Destination);
                }
                else
                {
                    fixMsg.SetDestination(order.Symbol.Destination);
                }
            }
            fixMsg.SetSymbol(order.Symbol.Symbol);
            fixMsg.SetSide(order.Side == OrderSide.Buy ? 1 : 5);
            switch (order.Type)
            {
            case OrderType.BuyLimit:
                fixMsg.SetOrderType(2);
                fixMsg.SetPrice(order.Price);
                switch (order.Symbol.TimeInForce)
                {
                case TimeInForce.Day:
                    fixMsg.SetTimeInForce(0);
                    break;

                case TimeInForce.GTC:
                    throw new LimeException("Lime does not accept GTC Buy Lime Orders");

                default:
                    throw new ArgumentOutOfRangeException();
                }
                break;

            case OrderType.BuyMarket:
                fixMsg.SetOrderType(1);
                //fixMsg.SetTimeInForce(0);
                break;

            case OrderType.BuyStop:
                // throw new LimeException("Lime does not accept Buy Stop Orders");
                log.Error("Lime: Buy Stops not supproted");
                break;

            case OrderType.SellLimit:
                fixMsg.SetOrderType(2);
                fixMsg.SetPrice(order.Price);
                switch (order.Symbol.TimeInForce)
                {
                case TimeInForce.Day:
                    fixMsg.SetTimeInForce(0);
                    break;

                case TimeInForce.GTC:
                    throw new LimeException("Lime does not accept GTC Buy Lime Orders");

                default:
                    throw new ArgumentOutOfRangeException();
                }
                break;

            case OrderType.SellMarket:
                fixMsg.SetOrderType(1);
                //fixMsg.SetTimeInForce(0);
                break;

            case OrderType.SellStop:
                //throw new LimeException("Lime does not accept Sell Stop Orders");
                log.Error("Lime: Sell Stops not supproted");
                break;

            default:
                throw new LimeException("Unknown OrderType");
            }
            fixMsg.SetOrderQuantity((int)order.Size);
            if (order.Action == OrderAction.Change)
            {
                if (verbose)
                {
                    log.Verbose("Change order: \n" + fixMsg);
                }
            }
            else
            {
                if (verbose)
                {
                    log.Verbose("Create new order: \n" + fixMsg);
                }
            }
            if (resend)
            {
                fixMsg.SetDuplicate(true);
            }
#if NOT_LIME
            fixMsg.SetAccount(AccountNumber);
            fixMsg.SetHandlingInstructions(1);
            fixMsg.SetLocateRequired("N");
            fixMsg.SetTransactTime(order.UtcCreateTime);
            fixMsg.SetOrderCapacity("A");
            fixMsg.SetUserName();
#endif
            fixMsg.SetSendTime(order.UtcCreateTime);
            SendMessage(fixMsg);
        }