TimelordUK / jspurefix

native typescript FIX engine
MIT License
58 stars 27 forks source link

Support alphabetic currency codes #12

Closed NiklasZ closed 3 years ago

NiklasZ commented 3 years ago

Hi there,

I'm interacting with a FIX 4.2 acceptor that uses the alphabetic currencies for the Currency(15) tag. From what I understand from the protocol, it should allow both numeric and alphabetic codes (see https://www.onixs.biz/fix-dictionary/4.2/app_a.html).

However, jspurefix only seems to support the numeric variant. I initially worked around this when sending messages by overriding library types with

type FlexibleCurrencyCode = {
  Currency?: string | number;
};

and that works for sending messages:

8=FIX.4.2|9=000269|35=D|49=redacted|56=redacted|34=6|57=|52=20210127-17:23:56.820|11=cf4c77ca-e9f7-4ec2-b0b4-84cb14c71f0a|1=redacted|21=2|100=SMART|55=AAPL|48=US0378331005|22=4|167=CS|207=XNGS|54=1|60=20210127-17:23:49.949|38=100|40=1|15=USD|59=6|168=20210127-17:23:56|126=20210127-22:59:59|204=0|10=033|

But in the response, the currency is parsed from "USD" to 0, which breaks the logic.

  protected async onApplicationMsg(msgType: string, view: MsgView): Promise<void> {
    try {
      const fixObject = view.toObject();
      this.logger.info({ fixObject }, 'processing FIX message');
// Some other logic here
    } catch (error) {
      this.logger.error({ error }, 'Message handling failed.');
    }
  }

The response message:

8=FIX.4.2|9=000331|35=8|34=000029|43=N|52=20210127-17:35:00.037|49=redacted|56=redacted|11=f49a0549-165b-47ed-91c1-f81d1465b959|17=00002b0c.6010f513.01.01|150=2|20=0|39=2|48=US0378331005|22=4|55=AAPL|38=50|44=0.00|32=50|30=XNYS|31=144.48|14=50|151=0|6=144.48|54=1|37=00000942.00004691.6010f828.0001|1=redacted|167=CS|60=20210127-17:35:00.037|40=1|59=6|15=USD|10=020|

Object resulting from view.toObject():

{
    "severity": "INFO",
    "time": 1611768900088,
    "name": "redacted",
    "service": "FixAdapter",
    "fixObject": {
        "StandardHeader": {
            "BeginString": "FIX.4.2",
            "BodyLength": 331,
            "MsgType": "8",
            "SenderCompID": "redacted",
            "TargetCompID": "redacted",
            "MsgSeqNum": 29,
            "PossDupFlag": false,
            "SendingTime": "2021-01-27T17:35:00.037Z"
        },
        "OrderID": "00000942.00004691.6010f828.0001",
        "ClOrdID": "f49a0549-165b-47ed-91c1-f81d1465b959",
        "ExecID": "00002b0c.6010f513.01.01",
        "ExecTransType": "0",
        "ExecType": "2",
        "OrdStatus": "2",
        "Account": "redacted",
        "Symbol": "AAPL",
        "SecurityID": "US0378331005",
        "IDSource": "4",
        "SecurityType": "CS",
        "Side": "1",
        "OrderQty": 50,
        "OrdType": "1",
        "Price": 0,
        "Currency": 0,
        "TimeInForce": "6",
        "LastShares": 50,
        "LastPx": 144.48,
        "LastMkt": "XNYS",
        "LeavesQty": 0,
        "CumQty": 50,
        "AvgPx": 144.48,
        "TransactTime": "2021-01-27T17:35:00.037Z",
        "StandardTrailer": {
            "CheckSum": "020"
        }
    },
    "msg": "processing FIX message"
}
TimelordUK commented 3 years ago

thanks I will take a look

On Thu, 28 Jan 2021 at 10:17, NiklasZ notifications@github.com wrote:

Hi there,

I'm interacting with a FIX 4.2 acceptor that uses the alphabetic currencies for the Currency(15) tag. From what I understand from the protocol, it should allow both numeric and alphabetic codes (see https://www.onixs.biz/fix-dictionary/4.2/app_a.html).

However, jspurefix only seems to support the numeric variant. I initially worked around this when sending messages by overriding library types with

type FlexibleCurrencyCode = { Currency?: string | number;};

and that works for sending messages:

8=FIX.4.2|9=000269|35=D|49=redacted|56=redacted|34=6|57=|52=20210127-17:23:56.820|11=cf4c77ca-e9f7-4ec2-b0b4-84cb14c71f0a|1=redacted|21=2|100=SMART|55=AAPL|48=US0378331005|22=4|167=CS|207=XNGS|54=1|60=20210127-17:23:49.949|38=100|40=1|15=USD|59=6|168=20210127-17:23:56|126=20210127-22:59:59|204=0|10=033|

But in the response, the currency is parsed from "USD" to 0, which breaks the logic.

protected async onApplicationMsg(msgType: string, view: MsgView): Promise { try { const fixObject = view.toObject(); this.logger.info({ fixObject }, 'processing FIX message'); } catch (error) { this.logger.error({ error }, 'Message handling failed.'); } }

The response message:

8=FIX.4.2|9=000331|35=8|34=000029|43=N|52=20210127-17:35:00.037|49=redacted|56=redacted|11=f49a0549-165b-47ed-91c1-f81d1465b959|17=00002b0c.6010f513.01.01|150=2|20=0|39=2|48=US0378331005|22=4|55=AAPL|38=50|44=0.00|32=50|30=XNYS|31=144.48|14=50|151=0|6=144.48|54=1|37=00000942.00004691.6010f828.0001|1=redacted|167=CS|60=20210127-17:35:00.037|40=1|59=6|15=USD|10=020|

Object resulting from view.toObject():

{ "severity": "INFO", "time": 1611768900088, "name": "redacted", "service": "FixAdapter", "fixObject": { "StandardHeader": { "BeginString": "FIX.4.2", "BodyLength": 331, "MsgType": "8", "SenderCompID": "redacted", "TargetCompID": "redacted", "MsgSeqNum": 29, "PossDupFlag": false, "SendingTime": "2021-01-27T17:35:00.037Z" }, "OrderID": "00000942.00004691.6010f828.0001", "ClOrdID": "f49a0549-165b-47ed-91c1-f81d1465b959", "ExecID": "00002b0c.6010f513.01.01", "ExecTransType": "0", "ExecType": "2", "OrdStatus": "2", "Account": "redacted", "Symbol": "AAPL", "SecurityID": "US0378331005", "IDSource": "4", "SecurityType": "CS", "Side": "1", "OrderQty": 50, "OrdType": "1", "Price": 0, "Currency": 0, "TimeInForce": "6", "LastShares": 50, "LastPx": 144.48, "LastMkt": "XNYS", "LeavesQty": 0, "CumQty": 50, "AvgPx": 144.48, "TransactTime": "2021-01-27T17:35:00.037Z", "StandardTrailer": { "CheckSum": "020" } }, "msg": "processing FIX message" }

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/TimelordUK/jspurefix/issues/12, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABXWJG2NOXYJHVCDPLETCSLS4E2R7ANCNFSM4WWZITSA .

TimelordUK commented 3 years ago

otherwise look for field in ts\jspurefix\data\fix_repo\FIX.4.2\Base

and change the definition in this file and see if the message is then parsed correctly - i.e. if you are using the repo based dictionary

NiklasZ commented 3 years ago

Ah right, I should have maybe mentioned that. Yes, I'm using the repo's dictionary with the following 2 config values:

    protocol: 'ascii',
    dictionary: 'repo42',
NiklasZ commented 3 years ago

Yup it worked when I changed the Currency in node_modules/jspurefix/data/fix_repo/FIX.4.2/Base/Fields.xml to a String type:

    </Field>
    <Field added="FIX.2.7">
        <Tag>15</Tag>
        <Name>Currency</Name>
        <Type>String</Type>
        <NotReqXML>1</NotReqXML>
        <Description>Identifies currency used for price. Absence of this field is interpreted as the default for the security. It is recommended that systems provide the currency value whenever possible. See Appendix A: Valid Currency Codes for information on obtaining valid values.</Description>
    </Field>
NiklasZ commented 3 years ago

Thanks for the help :smiley:

TimelordUK commented 3 years ago

I will take a further look into it - the Currency seems to have a base defintion of string in repo implying something is not right. In any case at least this gets you up and running, i will report back.

TimelordUK commented 3 years ago

https://github.com/TimelordUK/jspurefix/tree/1.0.17

should now be resolved in 1.0.17

NiklasZ commented 3 years ago

Just tested it with our setup and can confirm it is working:

8=FIX.4.2|9=000324|35=8|34=000003|43=N|52=20210211-09:55:39.816|49=redacted|56=redacted|11=38ab5187-63ab-4de3-8365-b0eb6f81b7de|17=18065.1613037339.1|150=0|20=0|39=0|55=AAPL|38=10|44=0.00|32=0|31=0.00|14=0|151=10|6=0|54=1|37=000009a5.00004691.6024be4e.0001|1=redacted|167=CS|60=20210211-09:55:39.816|40=1|109=redacted|59=6|15=USD|126=20210211-22:59:59|10=024|

converts into

fixObject: {
      "StandardHeader": {
        "BeginString": "FIX.4.2",
        "BodyLength": 324,
        "MsgType": "8",
        "SenderCompID": "redacted",
        "TargetCompID": "redacted",
        "MsgSeqNum": 3,
        "PossDupFlag": false,
        "SendingTime": "2021-02-11T09:55:39.816Z"
      },
      "OrderID": "000009a5.00004691.6024be4e.0001",
      "ClOrdID": "38ab5187-63ab-4de3-8365-b0eb6f81b7de",
      "ClientID": "redacted",
      "ExecID": "18065.1613037339.1",
      "ExecTransType": "0",
      "ExecType": "0",
      "OrdStatus": "0",
      "Account": "redacted",
      "Symbol": "AAPL",
      "SecurityType": "CS",
      "Side": "1",
      "OrderQty": 10,
      "OrdType": "1",
      "Price": 0,
      "Currency": "USD",
      "TimeInForce": "6",
      "ExpireTime": "2021-02-11T22:59:59.000Z",
      "LastShares": 0,
      "LastPx": 0,
      "LeavesQty": 10,
      "CumQty": 0,
      "AvgPx": 0,
      "TransactTime": "2021-02-11T09:55:39.816Z",
      "StandardTrailer": {
        "CheckSum": "024"
      }
    }

Thanks for the fix :pray: