Example #1
0
        /// <summary>
        /// Packs the FIX Message into FIX string.
        /// </summary>
        /// <returns>the FIX Message string.</returns>
        public override string ToString()
        {
            string beginStringField = string.Empty;
            string msgTypeField     = string.Empty;
            string headerFields     = string.Empty;
            string bodyFields       = string.Empty;
            string fieldValue       = string.Empty;

            if (!this.Contains(Tag.BeginString))
            {
                throw new MissingFieldException("FIX BeginString field is missing");
            }
            if (!this.Contains(Tag.MsgType))
            {
                throw new MissingFieldException("FIX MsgType field is missing");
            }

            // Create a stream of bytes from the fields in the FIX message.  Remember that a hashtable -- the underlying data store
            // for the message -- iterates through the fields in a random order.  This is fine for most FIX fields, but some in the
            // header and the trailer must be in a specified order in the packet, so these fields are pulled out of the message
            // during this loop and assembled later into the final message.
            foreach (Field field in this)
            {
                switch (field.Tag)
                {
                case Tag.BeginString:

                    // The 'BeginString' must always be the first field in the message.
                    beginStringField = TagConverter.ConvertTo(Tag.BeginString) + "=" + field.Value.ToString() + FixSeparator.ToString();
                    break;

                case Tag.BodyLength:
                case Tag.CheckSum:
                    // these are calculated below once the FIX string is assembled.
                    break;

                case Tag.MsgType:

                    // The 'MsgType' field is always the third field in the message.
                    string msgTypeValue = MsgTypeConverter.ConvertTo((MsgType)field.Value);
                    msgTypeField = TagConverter.ConvertTo(Tag.MsgType) + "=" + msgTypeValue + FixSeparator.ToString();
                    break;

                //////////////////
                // Header Fields
                //////////////////
                case Tag.PossDupFlag:
                    //case Tag.PossResend:

                    // bool Header Fields
                    headerFields += TagConverter.ConvertTo(field.Tag) + "=" + ((bool)field.Value ? "Y" : "N") + FixSeparator.ToString();
                    break;

                case Tag.SendingTime:
                //case Tag.OnBehalfOfSendingTime:
                case Tag.OrigSendingTime:

                    // DateTime Header Fields.
                    headerFields += TagConverter.ConvertTo(field.Tag) + "=" + ((DateTime)field.Value).ToString("yyyyMMdd-HH:mm:ss") + FixSeparator.ToString();
                    break;

                case Tag.MsgSeqNum:

                    // MsgSeqNum Header Field.
                    headerFields += TagConverter.ConvertTo(field.Tag) + "=" + field.Value.ToString() + FixSeparator.ToString();
                    break;

                case Tag.DeliverToCompID:
                //case Tag.DeliverToLocationID:
                case Tag.DeliverToSubID:
                case Tag.OnBehalfOfCompID:
                //case Tag.OnBehalfOfLocationID:
                case Tag.OnBehalfOfSubID:
                case Tag.SenderCompID:
                //case Tag.SenderLocationID:
                case Tag.SenderSubID:
                case Tag.TargetCompID:
                case Tag.TargetLocationID:
                case Tag.TargetSubID:

                    // ID Header Fields.
                    headerFields += TagConverter.ConvertTo(field.Tag) + "=" + field.Value.ToString() + FixSeparator.ToString();
                    break;

                //////////////////
                // Body Fields
                //////////////////
                // These are the Body Fields ( in alpha order) that require some conversion or business logic.
                // The 'default' case takes care of the rest.
                case Tag.Account:

                    // the Account Body Field is not valid in a cancel message before FIX 4.2
                    if (!this.MsgType.Equals(MsgType.OrderCancelRequest) ||
                        (this.MsgType.Equals(MsgType.OrderCancelRequest) && !this.BeginString.Equals("FIX.4.0") && !this.BeginString.Equals("FIX.4.1")))
                    {
                        if (field.Value != null)
                        {
                            bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + field.Value.ToString() + FixSeparator.ToString();
                        }
                    }
                    break;

                case Tag.BusinessRejectReason:

                    // BusinessRejectReason Body Field
                    fieldValue  = BusinessRejectReasonConverter.ConvertTo((BusinessRejectReason)field.Value);
                    bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + fieldValue + FixSeparator.ToString();
                    break;

                case Tag.CommType:

                    // CommType Body Field
                    fieldValue  = CommTypeConverter.ConvertTo((CommType)field.Value);
                    bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + fieldValue + FixSeparator.ToString();
                    break;

                case Tag.CxlRejReason:

                    // CxlRejReason Body Field.
                    // Only FIX 4.2 and above allow CxlRejReason > 1. (1=CxlRejReason.UnknownOrder).
                    if (this.BeginString.Equals("FIX.4.0") || this.BeginString.Equals("FIX.4.1"))
                    {
                        if ((CxlRejReason)field.Value > CxlRejReason.UnknownOrder)
                        {
                            // default to TooLateToCancel
                            field.Value = CxlRejReason.TooLateToCancel;
                        }
                    }
                    fieldValue  = CxlRejReasonConverter.ConvertTo((CxlRejReason)field.Value);
                    bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + fieldValue + FixSeparator.ToString();
                    break;

                case Tag.CxlRejResponseTo:

                    // the CxlRejResponseTo Body Field is not valid in a cancel-reject message before FIX 4.2
                    if (!this.MsgType.Equals(MsgType.OrderCancelReject) ||
                        (this.MsgType.Equals(MsgType.OrderCancelReject) && !this.BeginString.Equals("FIX.4.0") && !this.BeginString.Equals("FIX.4.1")))
                    {
                        fieldValue  = CxlRejResponseToConverter.ConvertTo((CxlRejResponseTo)field.Value);
                        bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + fieldValue + FixSeparator.ToString();
                    }
                    break;

                case Tag.CxlType:

                    // CxlType Body Field Only for FIX 4.0
                    if (this.BeginString.Equals("FIX.4.0"))
                    {
                        fieldValue  = CxlTypeConverter.ConvertTo((CxlType)field.Value);
                        bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + fieldValue + FixSeparator.ToString();
                    }
                    break;

                case Tag.DiscretionInst:

                    // DiscretionInst Body Field
                    fieldValue  = DiscretionInstConverter.ConvertTo((DiscretionInst)field.Value);
                    bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + fieldValue + FixSeparator.ToString();
                    break;

                case Tag.DKReason:

                    // DKReason Body Field
                    fieldValue  = DKReasonConverter.ConvertTo((DKReason)field.Value);
                    bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + fieldValue + FixSeparator.ToString();
                    break;

                case Tag.EncryptMethod:

                    // EncryptMethod Body Field
                    fieldValue  = EncryptMethodConverter.ConvertTo((EncryptMethod)field.Value);
                    bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + fieldValue + FixSeparator.ToString();
                    break;

                case Tag.ExecTransType:

                    // ExecTransType Body Field
                    fieldValue  = ExecTransTypeConverter.ConvertTo((ExecTransType)field.Value);
                    bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + fieldValue + FixSeparator.ToString();
                    break;

                case Tag.ExecType:

                    // ExecType Body Field - Not valid in FIX 4.0
                    if (!this.BeginString.Equals("FIX.4.0"))
                    {
                        fieldValue  = ExecTypeConverter.ConvertTo((ExecType)field.Value);
                        bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + fieldValue + FixSeparator.ToString();
                    }
                    break;

                case Tag.ExpireTime:

                    // ExpireTime Body Field
                    bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + ((DateTime)field.Value).ToString("yyyyMMdd-HH:mm:ss") + FixSeparator.ToString();
                    break;

                case Tag.GapFillFlag:

                    // GapFillFlag Body Field
                    bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + ((bool)field.Value ? "Y" : "N") + FixSeparator.ToString();
                    break;

                case Tag.HandlInst:

                    // HandlInst Body Field
                    fieldValue  = HandlInstConverter.ConvertTo((HandlInst)field.Value);
                    bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + fieldValue + FixSeparator.ToString();
                    break;

                case Tag.IOINaturalFlag:

                    // IOINaturalFlag Body Field
                    bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + ((bool)field.Value ? "Y" : "N") + FixSeparator.ToString();
                    break;

                case Tag.IOIQltyInd:

                    // IOIQltyInd Body Field
                    fieldValue  = IOIQltyIndConverter.ConvertTo((IOIQltyInd)field.Value);
                    bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + fieldValue + FixSeparator.ToString();
                    break;

                case Tag.IoiQualifierGroup:

                    // Expand the repeating group fields.
                    IoiQualifierGroup ioiQualifierGroup = (IoiQualifierGroup)field.Value;
                    if ((ioiQualifierGroup != null) && (ioiQualifierGroup.Count > 0))
                    {
                        // The 'NoIOIQualifiers' field is only valid for FIX 4.1 and above.
                        if (!this.BeginString.Equals("FIX.4.0"))
                        {
                            // the number of repeating instances goes in the 'NoIOIQualifiers' field.
                            bodyFields += TagConverter.ConvertTo(Tag.NoIOIQualifiers) + "=" + ioiQualifierGroup.Count.ToString() + FixSeparator.ToString();
                        }
                        // Add the qualifiers.
                        foreach (IoiQualifierGroup.Entry entry in ioiQualifierGroup)
                        {
                            fieldValue  = IoiQualifierConverter.ConvertTo(entry.IoiQualifier);
                            bodyFields += TagConverter.ConvertTo(Tag.IOIQualifier) + "=" + fieldValue + FixSeparator.ToString();

                            // FIX 4.0 only supports 1 qualifier.
                            if (this.BeginString.Equals("FIX.4.0"))
                            {
                                break;
                            }
                        }
                    }
                    break;

                // These fields should be part of the repeating group "IoiQualifierGroup",
                // and should NOT be used individually.
                case Tag.NoIOIQualifiers:
                case Tag.IOIQualifier:
                    break;

                case Tag.IOITransType:

                    // IOITransType Body Field
                    fieldValue  = IOITransTypeConverter.ConvertTo((IOITransType)field.Value);
                    bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + fieldValue + FixSeparator.ToString();
                    break;

                case Tag.LastCapacity:

                    // LastCapacity Body Field
                    fieldValue  = LastCapacityConverter.ConvertTo((LastCapacity)field.Value);
                    bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + fieldValue + FixSeparator.ToString();
                    break;

                case Tag.LeavesQty:

                    // LeavesQty Body Field - Not valid in FIX 4.0
                    if (!this.BeginString.Equals("FIX.4.0"))
                    {
                        fieldValue  = field.Value.ToString();
                        bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + fieldValue + FixSeparator.ToString();
                    }
                    break;

                case Tag.MaturityMonthYear:

                    // MaturityMonthYear Body Field
                    bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + ((DateTime)field.Value).ToString("yyyyMM") + FixSeparator.ToString();
                    break;

                case Tag.OpenClose:

                    // OpenClose Body Field
                    fieldValue  = OptionPositionTypeConverter.ConvertTo((OptionPositionType)field.Value);
                    bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + fieldValue + FixSeparator.ToString();
                    break;

                case Tag.OrdRejReason:

                    // OrdRejReason Body Field
                    fieldValue  = OrdRejReasonConverter.ConvertTo((OrdRejReason)field.Value);
                    bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + fieldValue + FixSeparator.ToString();
                    break;

                case Tag.OrdStatus:

                    // the OrdStatus Body Field is not valid in a cancel-reject message before FIX 4.1
                    if (!this.MsgType.Equals(MsgType.OrderCancelReject) ||
                        (this.MsgType.Equals(MsgType.OrderCancelReject) && !this.BeginString.Equals("FIX.4.0")))
                    {
                        fieldValue  = OrdStatusConverter.ConvertTo((OrdStatus)field.Value);
                        bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + fieldValue + FixSeparator.ToString();
                    }
                    break;

                case Tag.OrdType:

                    // OrdType Body Field
                    fieldValue  = OrdTypeConverter.ConvertTo((OrdType)field.Value);
                    bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + fieldValue + FixSeparator.ToString();
                    break;

                case Tag.OrigClOrdID:

                    // the OrigClOrdID Body Field is not valid in cancel-reject or execution report messages before FIX 4.1
                    if ((!this.MsgType.Equals(MsgType.OrderCancelReject) && !this.MsgType.Equals(MsgType.ExecutionReport)) ||
                        (this.MsgType.Equals(MsgType.OrderCancelReject) && !this.BeginString.Equals("FIX.4.0")) ||
                        (this.MsgType.Equals(MsgType.ExecutionReport) && !this.BeginString.Equals("FIX.4.0")))
                    {
                        if (field.Value != null)
                        {
                            bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + field.Value.ToString() + FixSeparator.ToString();
                        }
                    }
                    break;

                case Tag.PutOrCall:

                    // PutOrCall Body Field
                    fieldValue  = OptionTypeConverter.ConvertTo((OptionType)field.Value);
                    bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + fieldValue + FixSeparator.ToString();
                    break;

                case Tag.RefMsgType:

                    // RefMsgType Body Field
                    fieldValue  = MsgTypeConverter.ConvertTo((MsgType)field.Value);
                    bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + fieldValue + FixSeparator.ToString();
                    break;

                case Tag.ResetSeqNumFlag:

                    // ResetSeqNumFlag Body Field
                    bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + ((bool)field.Value ? "Y" : "N") + FixSeparator.ToString();
                    break;

                case Tag.RoutingGroup:

                    // Expand the Routing repeating group fields.
                    RoutingGroup routingGroup = (RoutingGroup)field.Value;
                    if ((routingGroup != null) && (routingGroup.Count > 0))
                    {
                        // the number of repeating instances goes in the 'NoRoutingIDs' field.
                        bodyFields += TagConverter.ConvertTo(Tag.NoRoutingIDs) + "=" + routingGroup.Count.ToString() + FixSeparator.ToString();
                        foreach (RoutingGroup.Entry entry in routingGroup)
                        {
                            // Add the routing type.
                            fieldValue  = RoutingTypeConverter.ConvertTo(entry.RoutingType);
                            bodyFields += TagConverter.ConvertTo(Tag.RoutingType) + "=" + fieldValue + FixSeparator.ToString();

                            // Add the routing ID.
                            bodyFields += TagConverter.ConvertTo(Tag.RoutingID) + "=" + entry.RoutingId + FixSeparator.ToString();
                        }
                    }
                    break;

                // These fields should be part of the repeating group "RoutingGroup",
                // and should NOT be used individually.
                case Tag.NoRoutingIDs:
                case Tag.RoutingID:
                case Tag.RoutingType:
                    break;

                case Tag.SecurityType:

                    // SecurityType Body Field
                    fieldValue  = SecurityTypeConverter.ConvertTo((SecurityType)field.Value);
                    bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + fieldValue + FixSeparator.ToString();
                    break;

                case Tag.SessionRejectReason:

                    // SessionRejectReason Body Field
                    fieldValue  = SessionRejectReasonConverter.ConvertTo((SessionRejectReason)field.Value);
                    bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + fieldValue + FixSeparator.ToString();
                    break;

                case Tag.Side:

                    // Side Body Field
                    fieldValue  = SideConverter.ConvertTo((Side)field.Value);
                    bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + fieldValue + FixSeparator.ToString();
                    break;

                case Tag.TimeInForce:

                    // TimeInForce Body Field
                    fieldValue  = TimeInForceConverter.ConvertTo((TimeInForce)field.Value);
                    bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + fieldValue + FixSeparator.ToString();
                    break;

                case Tag.TransactTime:

                    // the TransactTime Body Field is not valid before FIX 4.2
                    if (!this.BeginString.Equals("FIX.4.0") && !this.BeginString.Equals("FIX.4.1"))
                    {
                        bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + ((DateTime)field.Value).ToString("yyyyMMdd-HH:mm:ss") + FixSeparator.ToString();
                    }
                    break;


                case Tag.ValidUntilTime:

                    // ValidUntilTime Body Field
                    bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + ((DateTime)field.Value).ToString("yyyyMMdd-HH:mm:ss") + FixSeparator.ToString();
                    break;


                default:
                    // Default processing of these types for Tags not in the above list.
                    // Int32 Body Fields
                    // Decimal Body Fields
                    // String Body Fields
                    if (field.Value != null)
                    {
                        bodyFields += TagConverter.ConvertTo(field.Tag) + "=" + field.Value.ToString() + FixSeparator.ToString();
                    }
                    break;
                }
            }

            if (headerFields.Equals(string.Empty))
            {
                throw new MissingFieldException("FIX Header fields are missing");
            }

            // The 'BodyLength' fields must be calculated after the body and part of the header is assembled.
            int    bodyPacketLength = msgTypeField.Length + headerFields.Length + bodyFields.Length;
            string bodyLengthField  = TagConverter.ConvertTo(Tag.BodyLength) + "=" + bodyPacketLength.ToString() + FixSeparator.ToString();

            // Assemble the packet from the component fields.
            string packet = beginStringField + bodyLengthField + msgTypeField + headerFields + bodyFields;

            // The final step in assembling a packet is the calculation of the checksum.  This is the least significant byte of
            // the sum of all the byte values in the packet.
            int checksum = 0;

            foreach (byte messageByte in packet)
            {
                checksum += messageByte;
            }
            string checksumField = TagConverter.ConvertTo(Tag.CheckSum) + "=" + (checksum & 0xFF).ToString("000") + FixSeparator.ToString();

            return(packet + checksumField);
        }
Example #2
0
        /// <summary>
        /// Parses a string to a properly typed value based on the FIX tag.
        /// </summary>
        /// <param name="tag">Determines the datatype of the conversion.</param>
        /// <param name="value">A string representing a value.</param>
        public static object Parse(Tag tag, string value)
        {
            // Use the FIX tag to determine the parsing method and target data type.
            switch (tag)
            {
            case Tag.GapFillFlag:
            case Tag.IOINaturalFlag:
            case Tag.PossDupFlag:
            case Tag.ResetSeqNumFlag:

                // Boolean Values
                return(value == "Y" ? true : false);


            case Tag.BeginSeqNo:
            case Tag.BodyLength:
            case Tag.CheckSum:
            case Tag.EncodedTextLen:
            case Tag.EndSeqNo:
            case Tag.HeartBtInt:
            case Tag.InternalRecordId:
            case Tag.MsgSeqNum:
            case Tag.NewSeqNo:
            case Tag.NextExpectedMsgSeqNum:
            case Tag.NoIOIQualifiers:
            case Tag.NoRoutingIDs:
            case Tag.RawDataLength:
            case Tag.RefSeqNum:

                // Int32 Values
                return(Int32.Parse(value));

            case Tag.AvgPx:
            case Tag.Commission:
            case Tag.CxlQty:
            case Tag.CMSLeavesQty:
            case Tag.CumQty:
            case Tag.DiscretionOffset:
            case Tag.LastPx:
            case Tag.LastShares:
            case Tag.LeavesQty:
            case Tag.MaxFloor:
            case Tag.MinQty:
            case Tag.OrderQty:
            case Tag.PegDifference:
            case Tag.Price:
            case Tag.StopPx:
            case Tag.StrikePrice:

                // Decimal Values
                return(Decimal.Parse(value));

            case Tag.ExpireTime:
            case Tag.OrigSendingTime:
            case Tag.SendingTime:
            case Tag.TransactTime:
            case Tag.ValidUntilTime:

                // DateTime Values
                int year   = Int32.Parse(value.Substring(0, 4));
                int month  = Int32.Parse(value.Substring(4, 2));
                int day    = Int32.Parse(value.Substring(6, 2));
                int hour   = Int32.Parse(value.Substring(9, 2));
                int minute = Int32.Parse(value.Substring(12, 2));
                int second = Int32.Parse(value.Substring(15, 2));
                return(new DateTime(year, month, day, hour, minute, second));

            case Tag.MaturityMonthYear:

                int expYear  = Int32.Parse(value.Substring(0, 4));
                int expMonth = Int32.Parse(value.Substring(4, 2));
                return(new DateTime(expYear, expMonth, 1));

            //enums
            case Tag.BusinessRejectReason: return(BusinessRejectReasonConverter.ConvertFrom(value));

            case Tag.CxlRejReason: return(CxlRejReasonConverter.ConvertFrom(value));

            case Tag.CxlRejResponseTo: return(CxlRejResponseToConverter.ConvertFrom(value));

            case Tag.CxlType: return(CxlTypeConverter.ConvertFrom(value));

            case Tag.CommType: return(CommTypeConverter.ConvertFrom(value));

            case Tag.DiscretionInst: return(DiscretionInstConverter.ConvertFrom(value));

            case Tag.DKReason: return(DKReasonConverter.ConvertFrom(value));

            case Tag.EncryptMethod: return(EncryptMethodConverter.ConvertFrom(value));

            case Tag.ExecTransType: return(ExecTransTypeConverter.ConvertFrom(value));

            case Tag.ExecType: return(ExecTypeConverter.ConvertFrom(value));

            case Tag.HandlInst: return(HandlInstConverter.ConvertFrom(value));

            case Tag.IOIQualifier: return(IoiQualifierConverter.ConvertFrom(value));

            case Tag.IOIQltyInd: return(IOIQltyIndConverter.ConvertFrom(value));

            case Tag.IOITransType: return(IOITransTypeConverter.ConvertFrom(value));

            case Tag.LastCapacity: return(LastCapacityConverter.ConvertFrom(value));

            case Tag.MsgType: return(MsgTypeConverter.ConvertFrom(value));

            case Tag.RefMsgType: return(MsgTypeConverter.ConvertFrom(value));

            case Tag.OpenClose: return(OptionPositionTypeConverter.ConvertFrom(value));

            case Tag.PutOrCall: return(OptionTypeConverter.ConvertFrom(value));

            case Tag.OrdRejReason: return(OrdRejReasonConverter.ConvertFrom(value));

            case Tag.OrdStatus: return(OrdStatusConverter.ConvertFrom(value));

            case Tag.OrdType: return(OrdTypeConverter.ConvertFrom(value));

            case Tag.RoutingType: return(RoutingTypeConverter.ConvertFrom(value));

            case Tag.SecurityType: return(SecurityTypeConverter.ConvertFrom(value));

            case Tag.SessionRejectReason: return(SessionRejectReasonConverter.ConvertFrom(value));

            case Tag.Side: return(SideConverter.ConvertFrom(value));

            case Tag.TimeInForce: return(TimeInForceConverter.ConvertFrom(value));


            default:
                // String Values
                return(value);
            }
        }