UNPKG

fixparser

Version:

FIX.Latest / 5.0 SP2 Parser / AI Agent Trading

409 lines (408 loc) 18.4 kB
import { Field } from '../fields/Field.ts'; import type { RefType, Structure } from '../messagetype/MessageType.ts'; import type { ISpecEnums } from '../spec/SpecEnums.ts'; import type { ISpecFields } from '../spec/SpecFields.ts'; import { type FIXValue } from '../util/util.ts'; type FieldValues = { [tag: string]: any; }; /** * The MessageError object is used by FIXParser validation to * represent detailed error information when validation fails, * including the field, tag, value, expected value, and a * descriptive error message. * * @public */ export type MessageError = { field: RefType | ISpecFields | undefined; name: string | undefined; tag: number; value: FIXValue; expectedValue?: FIXValue; error: string; }; /** * Represents a complete FIX (Financial Information eXchange) message structure. * The message is divided into three main parts: Header, Body, and Trailer. * * @typedef {Object} FIXJSON * @property {Record<string, FIXValue | FIXValue[]>} Header - The header section of the FIX message, which includes metadata such as the sender, target, and timestamp. * @property {Record<string, FIXValue | FIXValue[] | Record<string, FIXValue | FIXValue[]>[]}> Body - The body section of the FIX message, which contains the actual transaction or data being conveyed. It can contain nested groups. * @property {Record<string, FIXValue | FIXValue[]>} Trailer - The trailer section of the FIX message, which typically contains checksum or other closing information. */ type FIXJSON = { Header: Record<string, FIXValue | FIXValue[]>; Body: Record<string, FIXValue | FIXValue[] | Record<string, FIXValue | FIXValue[]>[]>; Trailer: Record<string, FIXValue | FIXValue[]>; }; /** * A FIX message is a standardized electronic communication used in * financial markets to exchange information such as orders, * executions, and market data between trading participants, * following the FIX protocol's predefined structure and rules. * * @public */ export declare class Message { #private; /** The fix version associated with the message. */ fixVersion: string; /** The data fields associated with the message. */ data: Field[]; /** The FIX string representation of the message. */ messageString: string; /** The description of the message. */ description: string; /** The type of the message. */ messageType: string; /** A description of the message type. */ messageTypeDescription: string; /** The sequence number of the message. */ messageSequence: number; /** The structure of the message, can be null if not defined. */ structure: Structure[] | undefined; /** Flag indicating whether the body length is valid. */ bodyLengthValid: boolean; /** Flag indicating whether the checksum is valid. */ checksumValid: boolean; /** The specified checksum value of the message, can be null if not available. */ checksumValue: string | undefined; /** The actual checksum value of the message, can be null if not provided. */ checksumExpected: string | undefined; /** The specified body length of the message, can be null if not available. */ bodyLengthValue: number | undefined; /** The actual body length of the message, can be null if not provided. */ bodyLengthExpected: number | undefined; /** * Creates a new FIX Message instance. * * The constructor initializes the FIX Message with the specified FIX version and optional * custom fields. It processes the fields to set specific FIX tags such as `BeginString`, * `MsgSeqNum`, and `MsgType`, and updates the message accordingly. * * @param {string} [fixVersion=DEFAULT_FIX_VERSION] - The FIX protocol version. Defaults to `DEFAULT_FIX_VERSION`. * @param {...Field} fields - A variable number of `Field` objects that represent individual tags in the FIX message. * Each field object must contain a `tag` and a `value`, where `tag` indicates the field type (e.g., `BeginString`, `MsgSeqNum`, etc.). * * @throws {Error} If the field contains an invalid tag or value type. * * @example * const message = new Message('FIXT.1.1', new Field(FieldType.MsgType, Messages.NewOrderSingle), new Field(Fields.OrderQty, 10000)); * */ constructor(fixVersion?: string, ...fields: Field[]); /** * Adds a single `Field` object to the message data. * * @param {Field} field - The `Field` object to be added. */ addField(field: Field): void; /** * Adds multiple `Field` objects to the message data. * If the field's tag is `MsgType`, it will be added at the beginning of the `data` array. * Otherwise, it will be appended to the end. * * @param {...Field} fields - One or more `Field` objects to be added. */ addFields(...fields: Field[]): void; /** * Removes a field from the message data by its `tag`. * * @param {number} tag - The tag of the field to be removed. */ removeFieldByTag(tag: number): void; /** * Retrieves a single field from the message data by its `tag`. * * @param {number} tag - The tag of the field to be retrieved. * @returns {Field | undefined} The `Field` object if found, otherwise `undefined`. */ getField(tag: number): Field | undefined; /** * Retrieves all fields from the message data that have the specified `tag`. * * @param {number} tag - The tag of the fields to be retrieved. * @returns {Field[]} An array of `Field` objects that match the specified `tag`, or an empty array if no fields match. */ getFields(tag: number): Field[] | undefined; /** * Returns an object containing the name-explain pairs of all fields in the message. * The `name` of each field is used as the key, and the enumeration of the (`value`) is assigned to it. * For example, `MsgType: 'D'` gets assigned `MsgType: 'NewOrderSingle'`, * * @returns {FieldValues} An object where the keys are field names and the values are the explained field values. * @example * console.log(message.getFieldExplains()); * { * '47': 'A', * BeginString: 'FIX42', * BodyLength: 146, * MsgType: 'NewOrderSingle', * MsgSeqNum: 4, * SenderCompID: 'ABC_DEFG01', * SendingTime: '20090323-15:40:29', * TargetCompID: 'CCG', * OnBehalfOfCompID: 'XYZ', * ClOrdID: 'NF 0542/03232009', * Side: 'Buy', * OrderQty: 100, * Symbol: 'CVS', * OrdType: 'Market', * TimeInForce: 'Day', * TransactTime: '20090323-15:40:29', * HandlInst: 'AutomatedExecutionNoIntervention', * SecurityExchange: 'N', * CheckSum: '195' * } */ getFieldExplains(): FieldValues; /** * Returns an object containing the name-value pairs of all fields in the message. * The `name` of each field is used as the key, and the `value` is assigned to it. * * @returns {FieldValues} An object where the keys are field names and the values are field values. * @example * console.log(message.getFieldNameValues()); * { * '47': 'A', * BeginString: 'FIX.4.2', * BodyLength: 146, * MsgType: 'D', * MsgSeqNum: 4, * SenderCompID: 'ABC_DEFG01', * SendingTime: '20090323-15:40:29', * TargetCompID: 'CCG', * OnBehalfOfCompID: 'XYZ', * ClOrdID: 'NF 0542/03232009', * Side: '1', * OrderQty: 100, * Symbol: 'CVS', * OrdType: '1', * TimeInForce: '0', * TransactTime: '20090323-15:40:29', * HandlInst: '1', * SecurityExchange: 'N', * CheckSum: '195' * } */ getFieldNameValues(): FieldValues; /** * Returns an object containing the values of all fields in the message, indexed by their `tag`. * If a tag has multiple fields, the values will be stored in an array. * * @returns {FieldValues} An object where the keys are field tags and the values are field values (or arrays of values). * @example * console.log(message.getFieldValues()); * { * '8': 'FIX.4.2', * '9': 146, * '10': '195', * '11': 'NF 0542/03232009', * '21': '1', * '34': 4, * '35': 'D', * '38': 100, * '40': '1', * '47': 'A', * '49': 'ABC_DEFG01', * '52': '20090323-15:40:29', * '54': '1', * '55': 'CVS', * '56': 'CCG', * '59': '0', * '60': '20090323-15:40:29', * '115': 'XYZ', * '207': 'N' * } */ getFieldValues(): FieldValues; /** * Updates a field in the message data based on its `tag`. * If a field with the same tag exists, it will be replaced with the new `Field` object. * * @param {Field} field - The `Field` object to update in the data. */ setField(field: Field): void; /** * Retrieves the enumeration for a given `tag` and `value` based on the message's `MsgType`. * This method ensures that the `MsgType` field is present and has a value before attempting * to retrieve the corresponding enumeration. * * @param {number} tag - The tag of the field for which the enum is to be retrieved. * @param {FIXValue} value - The value of the field for which the enum is to be retrieved. * @returns {ISpecEnums | undefined} The corresponding enumeration if found, or `undefined` if the `MsgType` field is missing * or has no value, or if no matching enum is found. * * @example * const enumValue = message.getEnum(35, 'D'); * console.log(`Enum: ${enumValue}`); */ getEnum(tag: number, value: FIXValue): ISpecEnums | undefined; /** * Generates a brief Bloomberg-style description of the current message based on its fields, such as `Side`, `OrderQty`, `Symbol`, `Price`, etc. * The description is typically used for a quick summary of an order or trade message, formatted with key field values. * * Depending on the available fields, the method formats and returns a string summarizing the message's main details, * such as quantity, price, symbol, and order type. If certain fields (like `LeavesQty`, `OrderQty`, `Price`, etc.) are not present, * it adjusts the description accordingly. * * @returns {string | null} A brief string description summarizing the message. If no description can be formed, `null` is returned. * * @example * const description = message.getBriefDescription(); * console.log(description); // "100 AAPL LMT @123.45 GTC" */ getBriefDescription(): string | undefined; /** * Validates the body length of the FIX message by comparing the provided value to the actual body length. * The body length is calculated as the difference between the positions of the `MsgType` tag and the `Checksum` tag. * * @param {string} value - The body length value to validate against the calculated body length. * @returns {boolean} `true` if the provided body length matches the calculated body length, otherwise `false`. * * @example * const isValid = message.validateBodyLength('123'); * console.log(isValid); // true if the body length is correct, false otherwise */ validateBodyLength(value: string): boolean; /** * Validates the checksum of the FIX message by comparing the provided checksum value to the calculated checksum. * The checksum is calculated based on the substring of the message string before the `Checksum` tag. * * @param {string} value - The checksum value to validate against the calculated checksum. * @returns {boolean} `true` if the provided checksum matches the calculated checksum, otherwise `false`. * * @example * const isValid = message.validateChecksum('123456'); * console.log(isValid); // true if the checksum is valid, false otherwise */ validateChecksum(value: string): boolean; /** * Recalculates and updates the body length and checksum of the FIX message. * This method is useful when message fields have been modified and the message * needs to be updated with correct length and checksum values. * * The method will: * 1. Calculate the new body length based on the message content * 2. Calculate the new checksum based on the entire message * 3. Update the message's internal state with the new values * * @returns {Object} An object containing the new body length and checksum values * @property {number} bodyLength - The newly calculated body length * @property {string} checksum - The newly calculated checksum * * @example * const message = new Message('FIX.4.4'); * message.addField(new Field(FieldType.OrderQty, 100)); * const { bodyLength, checksum } = message.recalculateMessageLengths(); * console.log(`New body length: ${bodyLength}, New checksum: ${checksum}`); */ recalculateMessageLengths(): { bodyLength: number; checksum: string; }; /** * Validates the structure and content of a given FIX message. * * This method checks the fields in the provided `message` for correct data format, required fields, * and field references (such as `fieldRef`, `groupRef`, `componentRef`). It also validates specific fields * like `BodyLength` and `CheckSum` against expected values. * * The validation process can be constrained to only required fields, based on the `requiredFieldsOnly` flag. * * @param {boolean} [requiredFieldsOnly=true] - If `true`, only required fields (as specified in the message structure) are validated. * Defaults to `true`. * * @returns {MessageError[]} - An array of validation errors. Each error includes details about the field that caused the error, * such as the field's `tag`, `name`, `value`, the error message, and any expected value (if applicable). * * @throws {Error} If any internal validation process fails or an invalid message is encountered. * * @example * const validationErrors = message.validate(); * * if (validationErrors.length > 0) { * validationErrors.forEach(error => { * console.error(`Field ${error.name} (Tag ${error.tag}) has error: ${error.error}`); * }); * } */ validate(requiredFieldsOnly?: boolean): MessageError[]; /** * Encodes the FIX message into a string format based on the current message data, including its header, body, and trailer. * This method first validates the license, then constructs the message by adding fields such as `BeginString`, `BodyLength`, * and `CheckSum`. It also calculates the body length and checksum dynamically, ensuring the message is correctly formatted * according to the FIX protocol. * * @param {string} [separator=SOH] - The separator used to separate fields in the encoded FIX message. Defaults to `SOH` (Start of Header). * @returns {string} The encoded FIX message string, including calculated body length and checksum. * @throws {Error} If the license is invalid, it throws an error with a message indicating no valid license. * * @example * const fixMessage = message.encode(); * console.log(fixMessage); // "8=FIX.4.4|35=D|49=SenderCompID|56=TargetCompID|34=1|10=123" */ encode(separator?: string): string; /** * Converts the current FIX message to a JSON-like structure (FIX JSON), representing the message in a format that mirrors the FIX protocol. * The structure includes three main sections: `Header`, `Body`, and `Trailer`. Each section contains fields and, where applicable, * groups of repeating fields. The method processes the fields in the `data` array and organizes them into these sections, handling * groups, references, and field types appropriately. * * @returns {FIXJSON} The FIX message converted into a structured JSON-like format with `Header`, `Body`, and `Trailer` sections. * * @throws {Error} If the license is invalid, an error is thrown with a message indicating that no valid license is available. * * @example * const fixJson = message.toFIXJSON(); * console.log(fixJson); * // { * // "Header": { * // "BeginString": "FIXT.1.1", * // "MsgType": "NewOrderSingle", * // "SenderCompID": "ABC", * // "TargetCompID": "XYZ" * // }, * // "Body": { * // "OrderQty": 1000, * // "Price": 50.25, * // "Symbol": "AAPL", * // "Side": "Buy" * // }, * // "Trailer": { * // "CheckSum": "123" * // } * // } */ toFIXJSON(): FIXJSON; /** * Creates and returns a new instance of the `Message` class, which is a deep clone of the current `Message` instance. * The cloned instance has the same `fixVersion`, `messageSequence`, and `messageType`, but the `data` array is also cloned to avoid references to the original fields. * * @returns {Message} A new `Message` instance that is a clone of the current one. * * @example * const originalMessage = new Message('FIXT.1.1', field1, field2, field3); * const clonedMessage = originalMessage.clone(); * console.log(clonedMessage); // A new Message instance with the same data as the original */ clone(): Message; /** * Resets the internal state of the `Message` instance to its initial, empty state. * This includes clearing all data fields, resetting various properties to their default values, * and ensuring the message is in a clean state ready for processing. * * This method is typically used when you want to clear the state of the current `Message` object * and prepare it for new data, e.g., when parsing or constructing a new FIX message. * * @private * @returns {void} This method does not return any value. * * @example * const message = new Message('FIX.4.4', field1, field2); * message.reset(); // Clears all properties and prepares the message for a new state */ private reset; } export {};