fixparser
Version:
FIX.Latest / 5.0 SP2 Parser / AI Agent Trading
123 lines (117 loc) • 5.94 kB
text/typescript
import {
ExecType,
FIXServer,
Field,
Fields,
LicenseManager,
type Message,
Messages,
OrdStatus,
Side,
type TlsOptions,
} from 'fixparser/FIXServer';
const initializeConnection = async () => {
// NOTE: This feature requires a FIXParser Pro license
await LicenseManager.setLicenseKey(process.env.FIXPARSER_LICENSE_KEY);
const tlsOptions = {
minVersion: 'TLSv1.3',
cert: `-----BEGIN CERTIFICATE-----
MIIDazCCAlOgAwIBAgIUAq3bE3+GehnCjrl6M74Ik6qjrVMwDQYJKoZIhvcNAQEL
BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yNTAxMjcyMTQ4MzlaFw00NTAx
MjIyMTQ4MzlaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB
AQUAA4IBDwAwggEKAoIBAQCIS+66TMfEgfm23isscqJ/8rGUUvP0NLqmCvCDBfeA
SeLjOAdNkLO+XnIbPgXPx5RmvNZuk8NrXwDAS5zbZCngbFyS3HQFRxokj/6uH0Bi
dLXaaVHZHXnMmUglaN21dav1wOPTD4IM5pTCIGs4k7fS7zJCQK8/GunAZbv0TLVd
+Cb9NdD/q4qyJKTRxm8QREWXMlJPZCPO48xqNMAtVC2ywGk7UueQu1UPH/uiOtV0
GpW339eRodSYrHOXbwwNk0K5xyHHXVISs+iXIJ1nUlRVUzHkIQCQXK+Fdn5iIqRN
MjnUDvMndqheWDmO64ISTPddnR1v/Ly5Ftwv1v8TaJ85AgMBAAGjUzBRMB0GA1Ud
DgQWBBRI9AX+Nm/RHncJZQktGhvIw5tJ+TAfBgNVHSMEGDAWgBRI9AX+Nm/RHncJ
ZQktGhvIw5tJ+TAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBb
ph8nB374X7EdLHZI4Ulj3itszcSmCeWqS3+x3WZLOnLZUzmbqpoxohqtWapTcD8n
eJ41ZMo/5FFC20/ywMl2i51ofGBupeAXwy9euFna9/JmYWaSf1OmE5AFNAWqmQIK
qHppaphAHjHRpLRO+tp6ezVAFmgXaKk2b09FChZolOorjuPP/7DpcWtwUG9esJHY
LwMaEBMRu37SZCJEoUDDj0wKl7+QQwlAcvXqIsvFxanvdxQn0Q62k1qLa5lMNGtp
DhUtJAY2zkWxFsbGpMcN3B9SxdZO9aZWjbyvsa54D7/EZqTzucDsOt4JNGWwX8x4
BCFxH2tIR7zcDgGRVDE3
-----END CERTIFICATE-----`,
key: `-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCIS+66TMfEgfm2
3isscqJ/8rGUUvP0NLqmCvCDBfeASeLjOAdNkLO+XnIbPgXPx5RmvNZuk8NrXwDA
S5zbZCngbFyS3HQFRxokj/6uH0BidLXaaVHZHXnMmUglaN21dav1wOPTD4IM5pTC
IGs4k7fS7zJCQK8/GunAZbv0TLVd+Cb9NdD/q4qyJKTRxm8QREWXMlJPZCPO48xq
NMAtVC2ywGk7UueQu1UPH/uiOtV0GpW339eRodSYrHOXbwwNk0K5xyHHXVISs+iX
IJ1nUlRVUzHkIQCQXK+Fdn5iIqRNMjnUDvMndqheWDmO64ISTPddnR1v/Ly5Ftwv
1v8TaJ85AgMBAAECggEAAKG1B7qKsGbec2xja17w2i3YUbzSLqecQ1bq48KQOuOI
M9H9R6zfYdA/66sCHZDHx7OdBihHHw93R/qVKSVZ49VlTcu5zCRABXauBcEZ3CCq
83MhZmzJR2IzQ476YMiTfT//H3MPAO/ER7FBqfTNKVnMevS7igviuVe1Exhmjv9M
yBqDmaqxzv9UeacuX/7fqhAcO6A4euODpLgUyGPBdcpwExdG1OLruWsRD/oG8VY6
2ZvQ0CPLusiN7rMem5mRt1GmW2zhHbZaAa960LVy/ikHD6A9k3O0nYYRMtbmOWOn
I0DRZSWTkG3DR7/sD6F5zw8UL25NYTuJFYl/K8fc8QKBgQC9TQz/W05mniLo3SZ7
KxG1s2Wphp4DxufLsbM6EXdzQ09adQyGzHaqtG5bycL54ed8wJgp7EShDBX4RX6U
rg4iMgBipC2S/N9EIBZ7Dg3P0Mayvfqd3+qrg32CWqc0mLIep4k9XkSsWffsghSx
XO7MVRiRnWAaawYxFiDpTHBz6QKBgQC4UeMz1PhtI4cfeJgpsEeiSk4eRJOGc01D
79bYegSehZ9RL04DjgIEazccmIB5eprZ43BSR5SrHyOwAnjeb+Gxxmz4avm1hqYl
fq6QbBlgpk5FQSNHyBgD2DfcNxSs+YWbaT6mgkjZeJRCzhZLMWLLYswSoAGehyYu
FklodWFO0QKBgDEooDZ0BKEbcd9dBtA3eArigoUKo2BBuBIqnGt4+7cgBKxt9wnO
cQaVgo8tjweLRa0c6qcAZzYXSGFH0r5TkPIKYBU9o2QnbOdpGc1s8eNEyUTDlyCG
dI+DvwUp+3/qI19YjIg2QcksN/jgMvV4N78yXgX6g2l434vBvlw3cIB5AoGALzt8
t1mJ153VEHF8vKIZmTLlVchI7Zk6YYBiU9LgwCaJruoqWarYRX2b/83sjjSm3dL0
g4EoTbmLEZ1wj7+n3EB2yCnRl3zLsqwF26h30FaNlB2fBtP1o3aSyfGrcK/4Vtzf
WxfjxyapB318JQSgxnGozdUG1TLYy9KWORhrOSECgYAfyo+EynjQIwM0IkMqLA/3
JvyGxVXv886rjT3wibUATaRfR0ZTfGql+Tszr/fB60M4UqlBN7JRzWFuBLCh7IN/
Ks9adwa81pZEJ3kIkCGewK2fG5lTwEbaJpf2hw/Jf2FYwsp0uI/0O7NgVWDid8sx
tswAkG7yU9ZI15CXgOhekg==
-----END PRIVATE KEY-----`,
rejectUnauthorized: false,
};
const fixServer = new FIXServer();
fixServer.createServer({
host: 'localhost',
port: 9878,
protocol: 'tls-tcp',
sender: 'SERVER',
target: 'CLIENT',
tlsOptions: tlsOptions as TlsOptions,
onOpen: () => console.log('Open'),
onClose: () => console.log('Disconnected'),
onMessage: (message: Message) => {
console.log('server received message', message.description, message.messageString);
// Respond with ExecutionReport
if (message.messageType === Messages.NewOrderSingle) {
sendExecutionReport(message);
}
},
});
const sendExecutionReport = (message: Message) => {
const executionReport = fixServer.createMessage(
new Field(Fields.MsgType, Messages.ExecutionReport),
new Field(Fields.MsgSeqNum, fixServer.getNextTargetMsgSeqNum()),
new Field(Fields.SenderCompID, 'SERVER'),
new Field(Fields.SendingTime, fixServer.getTimestamp()),
new Field(Fields.TargetCompID, 'CLIENT'),
new Field(Fields.AvgPx, message.getField(Fields.Price) ? message.getField(Fields.Price)?.value : 0),
new Field(
Fields.ClOrdID,
message.getField(Fields.ClOrdID) ? message.getField(Fields.ClOrdID)?.value : 'N/A',
),
new Field(Fields.CumQty, message.getField(Fields.OrderQty) ? message.getField(Fields.OrderQty)?.value : 0),
new Field(Fields.Symbol, message.getField(Fields.Symbol) ? message.getField(Fields.Symbol)?.value : 'N/A'),
new Field(Fields.LastPx, message.getField(Fields.Price) ? message.getField(Fields.Price)?.value : 0),
new Field(Fields.OrderID, 55),
new Field(
Fields.OrderQty,
message.getField(Fields.OrderQty) ? message.getField(Fields.OrderQty)?.value : 0,
),
new Field(Fields.OrdStatus, OrdStatus.Filled),
new Field(Fields.Side, Side.Buy),
new Field(Fields.ExecType, ExecType.Trade),
new Field(Fields.LeavesQty, 0),
);
const messages = fixServer.parse(executionReport.encode());
console.log('sending message', messages[0].description, messages[0].messageString.replace(/\x01/g, '|'));
fixServer.send(executionReport);
};
};
initializeConnection().catch((err) => console.error('Error initializing connection:', err));