fixparser 8.1.1 → 8.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cjs/FIXParser.js +2 -2
- package/build/cjs/FIXParserBrowser.js +2 -2
- package/build/cjs/FIXServer.js +2 -2
- package/build/esm/FIXParser.mjs +2 -2
- package/build/esm/FIXParserBrowser.mjs +2 -2
- package/build/esm/FIXServer.mjs +2 -2
- package/examples/example_parse_message.ts +8 -0
- package/examples/example_quickfix_client1.ts +116 -0
- package/examples/example_quickfix_client1_continuous.ts +161 -0
- package/examples/example_quickfix_executor.ts +68 -0
- package/examples/example_tcp_client.ts +77 -0
- package/examples/example_tcp_client_resendrequest.ts +96 -0
- package/examples/example_tcp_ctrader.ts +86 -0
- package/examples/example_tcp_server.ts +55 -0
- package/examples/example_tls-tcp_client.ts +133 -0
- package/examples/example_tls-tcp_server.ts +112 -0
- package/examples/example_ws_client.ts +77 -0
- package/examples/example_ws_server.ts +91 -0
- package/examples/run-example.ts +28 -0
- package/package.json +2 -2
package/build/cjs/FIXParser.js
CHANGED
|
@@ -239507,7 +239507,7 @@ var missingOrEmpty = (value) => {
|
|
|
239507
239507
|
return value == null || value.length === 0;
|
|
239508
239508
|
};
|
|
239509
239509
|
var LicenseManager = class _LicenseManager {
|
|
239510
|
-
static #RELEASE_INFORMATION = "
|
|
239510
|
+
static #RELEASE_INFORMATION = "MTczODY5NzM0OTAwNA==";
|
|
239511
239511
|
static #licenseKey;
|
|
239512
239512
|
static #licenseKeyId = void 0;
|
|
239513
239513
|
static #licenseExpiry = void 0;
|
|
@@ -239765,7 +239765,7 @@ var uuidv4 = () => {
|
|
|
239765
239765
|
// src/util/util.ts
|
|
239766
239766
|
var version = {
|
|
239767
239767
|
version: "0.0.0",
|
|
239768
|
-
build: "2025-02-04T19:
|
|
239768
|
+
build: "2025-02-04T19:29:09.004Z"
|
|
239769
239769
|
};
|
|
239770
239770
|
var parseFixVersion = (version2) => {
|
|
239771
239771
|
return FIX_VERSIONS[version2] ?? version2;
|
|
@@ -235883,7 +235883,7 @@ var missingOrEmpty = (value) => {
|
|
|
235883
235883
|
return value == null || value.length === 0;
|
|
235884
235884
|
};
|
|
235885
235885
|
var LicenseManager = class _LicenseManager {
|
|
235886
|
-
static #RELEASE_INFORMATION = "
|
|
235886
|
+
static #RELEASE_INFORMATION = "MTczODY5NzM0OTAwNA==";
|
|
235887
235887
|
static #licenseKey;
|
|
235888
235888
|
static #licenseKeyId = void 0;
|
|
235889
235889
|
static #licenseExpiry = void 0;
|
|
@@ -236141,7 +236141,7 @@ var uuidv4 = () => {
|
|
|
236141
236141
|
// src/util/util.ts
|
|
236142
236142
|
var version = {
|
|
236143
236143
|
version: "0.0.0",
|
|
236144
|
-
build: "2025-02-04T19:
|
|
236144
|
+
build: "2025-02-04T19:29:09.004Z"
|
|
236145
236145
|
};
|
|
236146
236146
|
var parseFixVersion = (version2) => {
|
|
236147
236147
|
return FIX_VERSIONS[version2] ?? version2;
|
package/build/cjs/FIXServer.js
CHANGED
|
@@ -239511,7 +239511,7 @@ var missingOrEmpty = (value) => {
|
|
|
239511
239511
|
return value == null || value.length === 0;
|
|
239512
239512
|
};
|
|
239513
239513
|
var LicenseManager = class _LicenseManager {
|
|
239514
|
-
static #RELEASE_INFORMATION = "
|
|
239514
|
+
static #RELEASE_INFORMATION = "MTczODY5NzM0OTAwNA==";
|
|
239515
239515
|
static #licenseKey;
|
|
239516
239516
|
static #licenseKeyId = void 0;
|
|
239517
239517
|
static #licenseExpiry = void 0;
|
|
@@ -239769,7 +239769,7 @@ var uuidv4 = () => {
|
|
|
239769
239769
|
// src/util/util.ts
|
|
239770
239770
|
var version = {
|
|
239771
239771
|
version: "0.0.0",
|
|
239772
|
-
build: "2025-02-04T19:
|
|
239772
|
+
build: "2025-02-04T19:29:09.004Z"
|
|
239773
239773
|
};
|
|
239774
239774
|
var parseFixVersion = (version2) => {
|
|
239775
239775
|
return FIX_VERSIONS[version2] ?? version2;
|
package/build/esm/FIXParser.mjs
CHANGED
|
@@ -238804,7 +238804,7 @@ var missingOrEmpty = (value) => {
|
|
|
238804
238804
|
return value == null || value.length === 0;
|
|
238805
238805
|
};
|
|
238806
238806
|
var LicenseManager = class _LicenseManager {
|
|
238807
|
-
static #RELEASE_INFORMATION = "
|
|
238807
|
+
static #RELEASE_INFORMATION = "MTczODY5NzM0OTAwNA==";
|
|
238808
238808
|
static #licenseKey;
|
|
238809
238809
|
static #licenseKeyId = void 0;
|
|
238810
238810
|
static #licenseExpiry = void 0;
|
|
@@ -239062,7 +239062,7 @@ var uuidv4 = () => {
|
|
|
239062
239062
|
// src/util/util.ts
|
|
239063
239063
|
var version = {
|
|
239064
239064
|
version: "0.0.0",
|
|
239065
|
-
build: "2025-02-04T19:
|
|
239065
|
+
build: "2025-02-04T19:29:09.004Z"
|
|
239066
239066
|
};
|
|
239067
239067
|
var parseFixVersion = (version2) => {
|
|
239068
239068
|
return FIX_VERSIONS[version2] ?? version2;
|
|
@@ -235161,7 +235161,7 @@ var missingOrEmpty = (value) => {
|
|
|
235161
235161
|
return value == null || value.length === 0;
|
|
235162
235162
|
};
|
|
235163
235163
|
var LicenseManager = class _LicenseManager {
|
|
235164
|
-
static #RELEASE_INFORMATION = "
|
|
235164
|
+
static #RELEASE_INFORMATION = "MTczODY5NzM0OTAwNA==";
|
|
235165
235165
|
static #licenseKey;
|
|
235166
235166
|
static #licenseKeyId = void 0;
|
|
235167
235167
|
static #licenseExpiry = void 0;
|
|
@@ -235419,7 +235419,7 @@ var uuidv4 = () => {
|
|
|
235419
235419
|
// src/util/util.ts
|
|
235420
235420
|
var version = {
|
|
235421
235421
|
version: "0.0.0",
|
|
235422
|
-
build: "2025-02-04T19:
|
|
235422
|
+
build: "2025-02-04T19:29:09.004Z"
|
|
235423
235423
|
};
|
|
235424
235424
|
var parseFixVersion = (version2) => {
|
|
235425
235425
|
return FIX_VERSIONS[version2] ?? version2;
|
package/build/esm/FIXServer.mjs
CHANGED
|
@@ -238808,7 +238808,7 @@ var missingOrEmpty = (value) => {
|
|
|
238808
238808
|
return value == null || value.length === 0;
|
|
238809
238809
|
};
|
|
238810
238810
|
var LicenseManager = class _LicenseManager {
|
|
238811
|
-
static #RELEASE_INFORMATION = "
|
|
238811
|
+
static #RELEASE_INFORMATION = "MTczODY5NzM0OTAwNA==";
|
|
238812
238812
|
static #licenseKey;
|
|
238813
238813
|
static #licenseKeyId = void 0;
|
|
238814
238814
|
static #licenseExpiry = void 0;
|
|
@@ -239066,7 +239066,7 @@ var uuidv4 = () => {
|
|
|
239066
239066
|
// src/util/util.ts
|
|
239067
239067
|
var version = {
|
|
239068
239068
|
version: "0.0.0",
|
|
239069
|
-
build: "2025-02-04T19:
|
|
239069
|
+
build: "2025-02-04T19:29:09.004Z"
|
|
239070
239070
|
};
|
|
239071
239071
|
var parseFixVersion = (version2) => {
|
|
239072
239072
|
return FIX_VERSIONS[version2] ?? version2;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { FIXParser } from 'fixparser';
|
|
2
|
+
|
|
3
|
+
const fixParser = new FIXParser();
|
|
4
|
+
const fixString: string =
|
|
5
|
+
'8=FIX.4.2\x019=145\x0135=D\x0134=4\x0149=ABC_DEFG01\x0152=20090323-15:40:29\x0156=CCG\x01115=XYZ\x0111=NF 0542/03232009\x0154=1\x0138=100\x0155=CVS\x0140=1\x0159=0\x0147=A\x0160=20090323-15:40:29\x0121=1\x01207=N\x0110=139\x01';
|
|
6
|
+
const message = fixParser.parse(fixString);
|
|
7
|
+
console.log(JSON.stringify(message, null, 4));
|
|
8
|
+
console.log(message[0].getBriefDescription());
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This example will connect to the C++ QuickFIX engine.
|
|
3
|
+
* Clone https://github.com/quickfix/quickfix
|
|
4
|
+
* build and run ./bin/run_executor_cpp.sh.
|
|
5
|
+
*
|
|
6
|
+
* FIX session flow:
|
|
7
|
+
* Initiator (us) connects over TCP to port 5001 on the QuickFIX server.
|
|
8
|
+
* Upon connection, we send a Logon message. QuickFIX responds to the Logon message.
|
|
9
|
+
* Next, we send a NewOrderSingle. QuickFIX responds with a ExecutionReport.
|
|
10
|
+
* Next, we send a Logout request message. QuickFIX responds with a Logout response message.
|
|
11
|
+
* Session is closed.
|
|
12
|
+
*/
|
|
13
|
+
import {
|
|
14
|
+
ConsoleLogTransport,
|
|
15
|
+
EncryptMethod,
|
|
16
|
+
FIXParser,
|
|
17
|
+
Field,
|
|
18
|
+
Fields,
|
|
19
|
+
HandlInst,
|
|
20
|
+
LicenseManager,
|
|
21
|
+
type Message,
|
|
22
|
+
Messages,
|
|
23
|
+
type Options,
|
|
24
|
+
OrdType,
|
|
25
|
+
ResetSeqNumFlag,
|
|
26
|
+
Side,
|
|
27
|
+
TimeInForce,
|
|
28
|
+
} from 'fixparser';
|
|
29
|
+
|
|
30
|
+
// NOTE: This feature requires a FIXParser Pro license
|
|
31
|
+
LicenseManager.setLicenseKey('<your license here>');
|
|
32
|
+
|
|
33
|
+
const fixParser = new FIXParser();
|
|
34
|
+
const SENDER = 'CLIENT2';
|
|
35
|
+
const TARGET = 'EXECUTOR';
|
|
36
|
+
const CONNECT_PARAMS: Options = {
|
|
37
|
+
host: 'localhost',
|
|
38
|
+
port: 5001,
|
|
39
|
+
protocol: 'tcp',
|
|
40
|
+
sender: SENDER,
|
|
41
|
+
target: TARGET,
|
|
42
|
+
fixVersion: 'FIX.4.4',
|
|
43
|
+
logging: true,
|
|
44
|
+
logOptions: {
|
|
45
|
+
name: SENDER,
|
|
46
|
+
level: 'info',
|
|
47
|
+
format: 'json',
|
|
48
|
+
transport: new ConsoleLogTransport({ format: 'console' }),
|
|
49
|
+
},
|
|
50
|
+
onOpen: () => {
|
|
51
|
+
console.log('Open');
|
|
52
|
+
sendLogon();
|
|
53
|
+
sendOrder(32768);
|
|
54
|
+
sendLogout();
|
|
55
|
+
},
|
|
56
|
+
onMessage: (message: Message) =>
|
|
57
|
+
console.log('received message', message.description, message.messageString.replace(/\x01/g, '|')),
|
|
58
|
+
onClose: () => {
|
|
59
|
+
console.log('Disconnected');
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const sendLogon = () => {
|
|
64
|
+
const logon = fixParser.createMessage(
|
|
65
|
+
new Field(Fields.MsgType, Messages.Logon),
|
|
66
|
+
new Field(Fields.MsgSeqNum, fixParser.getNextTargetMsgSeqNum()),
|
|
67
|
+
new Field(Fields.SenderCompID, SENDER),
|
|
68
|
+
new Field(Fields.SendingTime, fixParser.getTimestamp()),
|
|
69
|
+
new Field(Fields.TargetCompID, TARGET),
|
|
70
|
+
new Field(Fields.ResetSeqNumFlag, ResetSeqNumFlag.Yes),
|
|
71
|
+
new Field(Fields.EncryptMethod, EncryptMethod.None),
|
|
72
|
+
new Field(Fields.HeartBtInt, 10),
|
|
73
|
+
);
|
|
74
|
+
const messages = fixParser.parse(logon.encode());
|
|
75
|
+
console.log('sending message', messages[0].description, messages[0].messageString);
|
|
76
|
+
fixParser.send(logon);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
const sendLogout = () => {
|
|
80
|
+
const logout = fixParser.createMessage(
|
|
81
|
+
new Field(Fields.MsgType, Messages.Logout),
|
|
82
|
+
new Field(Fields.SenderCompID, SENDER),
|
|
83
|
+
new Field(Fields.TargetCompID, TARGET),
|
|
84
|
+
new Field(Fields.MsgSeqNum, fixParser.getNextTargetMsgSeqNum()),
|
|
85
|
+
new Field(Fields.SendingTime, fixParser.getTimestamp()),
|
|
86
|
+
new Field(Fields.Text, 'Logout request'),
|
|
87
|
+
);
|
|
88
|
+
const messages = fixParser.parse(logout.encode());
|
|
89
|
+
console.log('sending message', messages[0].description, messages[0].messageString);
|
|
90
|
+
fixParser.send(logout);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const sendOrder = (orderId: number) => {
|
|
94
|
+
const newOrderSingle = fixParser.createMessage(
|
|
95
|
+
new Field(Fields.MsgType, Messages.NewOrderSingle),
|
|
96
|
+
new Field(Fields.MsgSeqNum, fixParser.getNextTargetMsgSeqNum()),
|
|
97
|
+
new Field(Fields.SenderCompID, SENDER),
|
|
98
|
+
new Field(Fields.TargetCompID, TARGET),
|
|
99
|
+
new Field(Fields.SendingTime, fixParser.getTimestamp()),
|
|
100
|
+
new Field(Fields.ClOrdID, String(orderId).padStart(4, '0')),
|
|
101
|
+
new Field(Fields.Side, Side.Buy),
|
|
102
|
+
new Field(Fields.Symbol, 'MSFT'),
|
|
103
|
+
new Field(Fields.OrderQty, 10000),
|
|
104
|
+
new Field(Fields.Price, 100),
|
|
105
|
+
new Field(Fields.OrdType, OrdType.Limit),
|
|
106
|
+
new Field(Fields.HandlInst, HandlInst.ManualOrder),
|
|
107
|
+
new Field(Fields.TimeInForce, TimeInForce.Day),
|
|
108
|
+
new Field(Fields.Text, 'NewOrderSingle'),
|
|
109
|
+
new Field(Fields.TransactTime, fixParser.getTimestamp()),
|
|
110
|
+
);
|
|
111
|
+
const messages = fixParser.parse(newOrderSingle.encode());
|
|
112
|
+
console.log('sending message', messages[0].description, messages[0].messageString.replace(/\x01/g, '|'));
|
|
113
|
+
fixParser.send(newOrderSingle);
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
fixParser.connect(CONNECT_PARAMS);
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This example will connect to the C++ QuickFIX engine.
|
|
3
|
+
* Clone https://github.com/quickfix/quickfix
|
|
4
|
+
* build and run ./bin/run_executor_cpp.sh.
|
|
5
|
+
*
|
|
6
|
+
* FIX session flow:
|
|
7
|
+
* Initiator (us) connects over TCP to port 5001 on the QuickFIX server.
|
|
8
|
+
* Upon connection, we send a Logon message. QuickFIX responds to the Logon message.
|
|
9
|
+
* Next, we send several NewOrderSingle at random intervals. QuickFIX responds with ExecutionReports.
|
|
10
|
+
* This demonstrates a continuous connection with random order intervals and session management messages.
|
|
11
|
+
*/
|
|
12
|
+
import {
|
|
13
|
+
EncryptMethod,
|
|
14
|
+
FIXParser,
|
|
15
|
+
Field,
|
|
16
|
+
Fields,
|
|
17
|
+
HandlInst,
|
|
18
|
+
LicenseManager,
|
|
19
|
+
type Message,
|
|
20
|
+
Messages,
|
|
21
|
+
MsgType,
|
|
22
|
+
type Options,
|
|
23
|
+
OrdType,
|
|
24
|
+
ResetSeqNumFlag,
|
|
25
|
+
Side,
|
|
26
|
+
TimeInForce,
|
|
27
|
+
} from 'fixparser';
|
|
28
|
+
|
|
29
|
+
// NOTE: This feature requires a FIXParser Pro license
|
|
30
|
+
LicenseManager.setLicenseKey('<your license here>');
|
|
31
|
+
|
|
32
|
+
let randomIterator = 0;
|
|
33
|
+
const timeBasedRandom = (min: number, max: number): number => {
|
|
34
|
+
const timeNow = Date.now() % 1000;
|
|
35
|
+
randomIterator++;
|
|
36
|
+
let x = timeNow ^ randomIterator;
|
|
37
|
+
x ^= x << 21;
|
|
38
|
+
x ^= x >>> 35;
|
|
39
|
+
x ^= x << 4;
|
|
40
|
+
const timeBasedRandom = Math.abs(x % (max - min + 1));
|
|
41
|
+
return min + timeBasedRandom;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const getRandomNumber = (min = 0, max = 65535): number => {
|
|
45
|
+
return timeBasedRandom(min, max);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const getRandomEnumValue = <T>(enumObj: T): T[keyof T] => {
|
|
49
|
+
const enumValues = Object.values(enumObj);
|
|
50
|
+
const randomIndex = timeBasedRandom(0, enumValues.length - 1);
|
|
51
|
+
return enumValues[randomIndex];
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
let sentOrders = 0;
|
|
55
|
+
let orderInterval: NodeJS.Timeout;
|
|
56
|
+
const fixParser = new FIXParser();
|
|
57
|
+
const SENDER = 'CLIENT2';
|
|
58
|
+
const TARGET = 'EXECUTOR';
|
|
59
|
+
const CONNECT_PARAMS: Options = {
|
|
60
|
+
host: 'localhost',
|
|
61
|
+
port: 5001,
|
|
62
|
+
protocol: 'tcp',
|
|
63
|
+
sender: SENDER,
|
|
64
|
+
target: TARGET,
|
|
65
|
+
fixVersion: 'FIX.4.4',
|
|
66
|
+
logging: false,
|
|
67
|
+
logOptions: {
|
|
68
|
+
name: SENDER,
|
|
69
|
+
level: 'info',
|
|
70
|
+
format: 'json',
|
|
71
|
+
},
|
|
72
|
+
onOpen: () => {
|
|
73
|
+
console.log('Open');
|
|
74
|
+
sendLogon();
|
|
75
|
+
},
|
|
76
|
+
onMessage: (message: Message) => {
|
|
77
|
+
switch (message.messageType) {
|
|
78
|
+
case MsgType.Reject: {
|
|
79
|
+
console.log(
|
|
80
|
+
`\x1b[31mReceived ${message.description}: ${message.getField(58)?.value} (referencing tag ${message.getField(371)?.value})\x1b[0m`,
|
|
81
|
+
);
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
case MsgType.Logon: {
|
|
85
|
+
console.log(`\x1b[34mReceived ${message.description}\x1b[0m`);
|
|
86
|
+
const startInterval = () => {
|
|
87
|
+
const numOrders = getRandomNumber(3, 50);
|
|
88
|
+
const pauseMs = getRandomNumber(100, 15000);
|
|
89
|
+
orderInterval = setInterval(() => {
|
|
90
|
+
const randomOrderId = getRandomNumber();
|
|
91
|
+
sendOrder(randomOrderId);
|
|
92
|
+
|
|
93
|
+
if (sentOrders % numOrders === 0) {
|
|
94
|
+
clearInterval(orderInterval);
|
|
95
|
+
console.log(
|
|
96
|
+
`-----------------> pausing for ${pauseMs / 1000} s (sent ${numOrders} orders)...`,
|
|
97
|
+
);
|
|
98
|
+
setTimeout(() => {
|
|
99
|
+
console.log('-----------------> restarting...');
|
|
100
|
+
sentOrders = 0;
|
|
101
|
+
startInterval();
|
|
102
|
+
}, pauseMs);
|
|
103
|
+
}
|
|
104
|
+
}, 5);
|
|
105
|
+
};
|
|
106
|
+
startInterval();
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
case MsgType.ExecutionReport: {
|
|
110
|
+
console.log(
|
|
111
|
+
`\x1b[32mReceived ${message.description}: ${JSON.stringify(message.toFIXJSON(), null, 4)})\x1b[0m`,
|
|
112
|
+
);
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
default: {
|
|
116
|
+
console.log(`\x1b[36mReceived unhandled message: ${message.description}\x1b[0m`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
onClose: () => {
|
|
121
|
+
console.log('Disconnected');
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const sendLogon = () => {
|
|
126
|
+
const logon = fixParser.createMessage(
|
|
127
|
+
new Field(Fields.MsgType, Messages.Logon),
|
|
128
|
+
new Field(Fields.MsgSeqNum, fixParser.getNextTargetMsgSeqNum()),
|
|
129
|
+
new Field(Fields.SenderCompID, SENDER),
|
|
130
|
+
new Field(Fields.SendingTime, fixParser.getTimestamp()),
|
|
131
|
+
new Field(Fields.TargetCompID, TARGET),
|
|
132
|
+
new Field(Fields.ResetSeqNumFlag, ResetSeqNumFlag.Yes),
|
|
133
|
+
new Field(Fields.EncryptMethod, EncryptMethod.None),
|
|
134
|
+
new Field(Fields.HeartBtInt, 10),
|
|
135
|
+
);
|
|
136
|
+
fixParser.send(logon);
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const sendOrder = (orderId: number) => {
|
|
140
|
+
const newOrderSingle = fixParser.createMessage(
|
|
141
|
+
new Field(Fields.MsgType, Messages.NewOrderSingle),
|
|
142
|
+
new Field(Fields.MsgSeqNum, fixParser.getNextTargetMsgSeqNum()),
|
|
143
|
+
new Field(Fields.SenderCompID, SENDER),
|
|
144
|
+
new Field(Fields.TargetCompID, TARGET),
|
|
145
|
+
new Field(Fields.SendingTime, fixParser.getTimestamp()),
|
|
146
|
+
new Field(Fields.ClOrdID, String(orderId).padStart(4, '0')),
|
|
147
|
+
new Field(Fields.Side, getRandomEnumValue(Side)),
|
|
148
|
+
new Field(Fields.Symbol, 'MSFT'),
|
|
149
|
+
new Field(Fields.OrderQty, getRandomNumber(1, 100000)),
|
|
150
|
+
new Field(Fields.Price, getRandomNumber(100, 500)),
|
|
151
|
+
new Field(Fields.OrdType, OrdType.Limit),
|
|
152
|
+
new Field(Fields.HandlInst, getRandomEnumValue(HandlInst)),
|
|
153
|
+
new Field(Fields.TimeInForce, getRandomEnumValue(TimeInForce)),
|
|
154
|
+
new Field(Fields.Text, `New Order ${orderId}`),
|
|
155
|
+
new Field(Fields.TransactTime, fixParser.getTimestamp()),
|
|
156
|
+
);
|
|
157
|
+
fixParser.send(newOrderSingle);
|
|
158
|
+
sentOrders++;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
fixParser.connect(CONNECT_PARAMS);
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This example will connect to the C++ QuickFIX engine.
|
|
3
|
+
* Clone https://github.com/quickfix/quickfix
|
|
4
|
+
* build and run ./bin/run_tradeclient.sh.
|
|
5
|
+
*
|
|
6
|
+
* FIX session flow:
|
|
7
|
+
* Initiator (us) connects over TCP to port 5001.
|
|
8
|
+
* Upon connection, QuickFIX sends a Logon message. We respond to the Logon message.
|
|
9
|
+
* You can send orders from QuickFIX. We respond with a ExecutionReport.
|
|
10
|
+
*/
|
|
11
|
+
import {
|
|
12
|
+
ExecType,
|
|
13
|
+
FIXServer,
|
|
14
|
+
Field,
|
|
15
|
+
Fields,
|
|
16
|
+
LicenseManager,
|
|
17
|
+
type Message,
|
|
18
|
+
Messages,
|
|
19
|
+
OrdStatus,
|
|
20
|
+
} from 'fixparser/FIXServer';
|
|
21
|
+
|
|
22
|
+
// NOTE: This feature requires a FIXParser Pro license
|
|
23
|
+
LicenseManager.setLicenseKey('<your license here>');
|
|
24
|
+
|
|
25
|
+
const SENDER: string = 'EXECUTOR';
|
|
26
|
+
const TARGET: string = 'CLIENT1';
|
|
27
|
+
|
|
28
|
+
const fixServer = new FIXServer();
|
|
29
|
+
fixServer.createServer({
|
|
30
|
+
host: 'localhost',
|
|
31
|
+
port: 5001,
|
|
32
|
+
sender: SENDER,
|
|
33
|
+
target: TARGET,
|
|
34
|
+
onOpen: () => console.log('Open'),
|
|
35
|
+
onMessage: (message: Message) => {
|
|
36
|
+
console.log('server received message', message.description, message.messageString.replace(/\x01/g, '|'));
|
|
37
|
+
// Respond with ExecutionReport
|
|
38
|
+
if (message.messageType === Messages.NewOrderSingle) {
|
|
39
|
+
sendExecutionReport(message);
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
onClose: () => console.log('Disconnected'),
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const sendExecutionReport = (message: Message) => {
|
|
46
|
+
const executionReport = fixServer.createMessage(
|
|
47
|
+
new Field(Fields.MsgType, Messages.ExecutionReport),
|
|
48
|
+
new Field(Fields.MsgSeqNum, fixServer.getNextTargetMsgSeqNum()),
|
|
49
|
+
new Field(Fields.SenderCompID, SENDER),
|
|
50
|
+
new Field(Fields.SendingTime, fixServer.getTimestamp()),
|
|
51
|
+
new Field(Fields.TargetCompID, TARGET),
|
|
52
|
+
new Field(Fields.AvgPx, message.getField(Fields.Price) ? message.getField(Fields.Price)?.value : 0),
|
|
53
|
+
new Field(Fields.ClOrdID, message.getField(Fields.ClOrdID) ? message.getField(Fields.ClOrdID)?.value : 'N/A'),
|
|
54
|
+
new Field(Fields.ExecID, message.getField(Fields.ClOrdID) ? message.getField(Fields.ClOrdID)?.value : 'N/A'),
|
|
55
|
+
new Field(Fields.ExecType, ExecType.New),
|
|
56
|
+
new Field(Fields.CumQty, message.getField(Fields.OrderQty) ? message.getField(Fields.OrderQty)?.value : 0),
|
|
57
|
+
new Field(Fields.Symbol, message.getField(Fields.Symbol) ? message.getField(Fields.Symbol)?.value : 'N/A'),
|
|
58
|
+
new Field(Fields.LastPx, message.getField(Fields.Price) ? message.getField(Fields.Price)?.value : 0),
|
|
59
|
+
new Field(Fields.OrderID, message.getField(Fields.ClOrdID) ? message.getField(Fields.ClOrdID)?.value : 'N/A'),
|
|
60
|
+
new Field(Fields.OrderQty, message.getField(Fields.OrderQty) ? message.getField(Fields.OrderQty)?.value : 0),
|
|
61
|
+
new Field(Fields.OrdStatus, OrdStatus.Filled),
|
|
62
|
+
new Field(Fields.Side, message.getField(Fields.Side) ? message.getField(Fields.Side)?.value : 'N/A'),
|
|
63
|
+
new Field(Fields.LeavesQty, 0),
|
|
64
|
+
);
|
|
65
|
+
const messages = fixServer.parse(executionReport.encode());
|
|
66
|
+
console.log('sending message', messages[0].description, messages[0].messageString.replace(/\x01/g, '|'));
|
|
67
|
+
fixServer.send(executionReport);
|
|
68
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EncryptMethod,
|
|
3
|
+
FIXParser,
|
|
4
|
+
Field,
|
|
5
|
+
Fields,
|
|
6
|
+
HandlInst,
|
|
7
|
+
LicenseManager,
|
|
8
|
+
type Message,
|
|
9
|
+
Messages,
|
|
10
|
+
OrdType,
|
|
11
|
+
ResetSeqNumFlag,
|
|
12
|
+
Side,
|
|
13
|
+
TimeInForce,
|
|
14
|
+
} from 'fixparser';
|
|
15
|
+
|
|
16
|
+
const fixParser = new FIXParser();
|
|
17
|
+
const SENDER = 'CLIENT';
|
|
18
|
+
const TARGET = 'SERVER';
|
|
19
|
+
|
|
20
|
+
// NOTE: This feature requires a FIXParser Pro license
|
|
21
|
+
LicenseManager.setLicenseKey('<your license here>');
|
|
22
|
+
|
|
23
|
+
fixParser.connect({
|
|
24
|
+
host: 'localhost',
|
|
25
|
+
port: 9878,
|
|
26
|
+
protocol: 'tcp',
|
|
27
|
+
sender: SENDER,
|
|
28
|
+
target: TARGET,
|
|
29
|
+
fixVersion: 'FIX.4.4',
|
|
30
|
+
logging: true,
|
|
31
|
+
onOpen: () => {
|
|
32
|
+
console.log('Open');
|
|
33
|
+
sendLogon();
|
|
34
|
+
setInterval(() => {
|
|
35
|
+
sendOrder();
|
|
36
|
+
}, 500);
|
|
37
|
+
},
|
|
38
|
+
onMessage: (message: Message) => console.log('received message', message.description, message.messageString),
|
|
39
|
+
onClose: () => console.log('Disconnected'),
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
const sendLogon = () => {
|
|
43
|
+
const logon = fixParser.createMessage(
|
|
44
|
+
new Field(Fields.MsgType, Messages.Logon),
|
|
45
|
+
new Field(Fields.MsgSeqNum, fixParser.getNextTargetMsgSeqNum()),
|
|
46
|
+
new Field(Fields.SenderCompID, SENDER),
|
|
47
|
+
new Field(Fields.SendingTime, fixParser.getTimestamp()),
|
|
48
|
+
new Field(Fields.TargetCompID, TARGET),
|
|
49
|
+
new Field(Fields.ResetSeqNumFlag, ResetSeqNumFlag.Yes),
|
|
50
|
+
new Field(Fields.EncryptMethod, EncryptMethod.None),
|
|
51
|
+
new Field(Fields.HeartBtInt, 10),
|
|
52
|
+
);
|
|
53
|
+
const messages = fixParser.parse(logon.encode());
|
|
54
|
+
console.log('sending message', messages[0].description, messages[0].messageString);
|
|
55
|
+
fixParser.send(logon);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const sendOrder = () => {
|
|
59
|
+
const order = fixParser.createMessage(
|
|
60
|
+
new Field(Fields.MsgType, Messages.NewOrderSingle),
|
|
61
|
+
new Field(Fields.MsgSeqNum, fixParser.getNextTargetMsgSeqNum()),
|
|
62
|
+
new Field(Fields.SenderCompID, SENDER),
|
|
63
|
+
new Field(Fields.SendingTime, fixParser.getTimestamp()),
|
|
64
|
+
new Field(Fields.TargetCompID, TARGET),
|
|
65
|
+
new Field(Fields.ClOrdID, '11223344'),
|
|
66
|
+
new Field(Fields.HandlInst, HandlInst.AutomatedExecutionNoIntervention),
|
|
67
|
+
new Field(Fields.OrderQty, '123'),
|
|
68
|
+
new Field(Fields.TransactTime, fixParser.getTimestamp()),
|
|
69
|
+
new Field(Fields.OrdType, OrdType.Market),
|
|
70
|
+
new Field(Fields.Side, Side.Buy),
|
|
71
|
+
new Field(Fields.Symbol, '700.HK'),
|
|
72
|
+
new Field(Fields.TimeInForce, TimeInForce.Day),
|
|
73
|
+
);
|
|
74
|
+
const messages = fixParser.parse(order.encode());
|
|
75
|
+
console.log('sending message', messages[0].description, messages[0].messageString.replace(/\x01/g, '|'));
|
|
76
|
+
fixParser.send(order);
|
|
77
|
+
};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EncryptMethod,
|
|
3
|
+
FIXParser,
|
|
4
|
+
Field,
|
|
5
|
+
Fields,
|
|
6
|
+
HandlInst,
|
|
7
|
+
LicenseManager,
|
|
8
|
+
type Message,
|
|
9
|
+
Messages,
|
|
10
|
+
OrdType,
|
|
11
|
+
ResetSeqNumFlag,
|
|
12
|
+
Side,
|
|
13
|
+
TimeInForce,
|
|
14
|
+
} from 'fixparser';
|
|
15
|
+
|
|
16
|
+
// NOTE: This feature requires a FIXParser Pro license
|
|
17
|
+
LicenseManager.setLicenseKey('<your license here>');
|
|
18
|
+
|
|
19
|
+
const fixParser = new FIXParser();
|
|
20
|
+
const SENDER = 'CLIENT';
|
|
21
|
+
const TARGET = 'SERVER';
|
|
22
|
+
|
|
23
|
+
fixParser.connect({
|
|
24
|
+
host: 'localhost',
|
|
25
|
+
port: 9878,
|
|
26
|
+
protocol: 'tcp',
|
|
27
|
+
sender: SENDER,
|
|
28
|
+
target: TARGET,
|
|
29
|
+
fixVersion: 'FIX.4.4',
|
|
30
|
+
logging: true,
|
|
31
|
+
onOpen: () => {
|
|
32
|
+
console.log('Open');
|
|
33
|
+
sendLogon();
|
|
34
|
+
|
|
35
|
+
// Send some orders
|
|
36
|
+
sendOrders();
|
|
37
|
+
|
|
38
|
+
// Ask to Resend
|
|
39
|
+
setTimeout(() => {
|
|
40
|
+
const resendRequest = fixParser.createMessage(
|
|
41
|
+
new Field(Fields.MsgType, Messages.ResendRequest),
|
|
42
|
+
new Field(Fields.MsgSeqNum, fixParser.getNextTargetMsgSeqNum()),
|
|
43
|
+
new Field(Fields.SenderCompID, SENDER),
|
|
44
|
+
new Field(Fields.SendingTime, fixParser.getTimestamp()),
|
|
45
|
+
new Field(Fields.TargetCompID, TARGET),
|
|
46
|
+
new Field(Fields.BeginSeqNo, 4),
|
|
47
|
+
new Field(Fields.EndSeqNo, 7),
|
|
48
|
+
);
|
|
49
|
+
const messages = fixParser.parse(resendRequest.encode());
|
|
50
|
+
console.log('sending message', messages[0].description, messages[0].messageString.replace(/\x01/g, '|'));
|
|
51
|
+
fixParser.send(resendRequest);
|
|
52
|
+
}, 10000);
|
|
53
|
+
},
|
|
54
|
+
onMessage: (message: Message) => console.log('received message', message.description, message.messageString),
|
|
55
|
+
onClose: () => console.log('Disconnected'),
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const sendLogon = () => {
|
|
59
|
+
const logon = fixParser.createMessage(
|
|
60
|
+
new Field(Fields.MsgType, Messages.Logon),
|
|
61
|
+
new Field(Fields.MsgSeqNum, fixParser.getNextTargetMsgSeqNum()),
|
|
62
|
+
new Field(Fields.SenderCompID, SENDER),
|
|
63
|
+
new Field(Fields.SendingTime, fixParser.getTimestamp()),
|
|
64
|
+
new Field(Fields.TargetCompID, TARGET),
|
|
65
|
+
new Field(Fields.ResetSeqNumFlag, ResetSeqNumFlag.Yes),
|
|
66
|
+
new Field(Fields.EncryptMethod, EncryptMethod.None),
|
|
67
|
+
new Field(Fields.HeartBtInt, 60),
|
|
68
|
+
);
|
|
69
|
+
const messages = fixParser.parse(logon.encode());
|
|
70
|
+
console.log('sending message', messages[0].description, messages[0].messageString);
|
|
71
|
+
fixParser.send(logon);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const sendOrders = () => {
|
|
75
|
+
['order1', 'order2', 'order3', 'order4', 'order5', 'order6'].forEach((orderId: string, index: number) => {
|
|
76
|
+
const order = fixParser.createMessage(
|
|
77
|
+
new Field(Fields.MsgType, Messages.NewOrderSingle),
|
|
78
|
+
new Field(Fields.MsgSeqNum, fixParser.getNextTargetMsgSeqNum()),
|
|
79
|
+
new Field(Fields.SenderCompID, SENDER),
|
|
80
|
+
new Field(Fields.SendingTime, fixParser.getTimestamp()),
|
|
81
|
+
new Field(Fields.TargetCompID, TARGET),
|
|
82
|
+
new Field(Fields.ClOrdID, orderId),
|
|
83
|
+
new Field(Fields.HandlInst, HandlInst.AutomatedExecutionNoIntervention),
|
|
84
|
+
new Field(Fields.OrderQty, 1000 * index),
|
|
85
|
+
new Field(Fields.Price, 300 * index),
|
|
86
|
+
new Field(Fields.TransactTime, fixParser.getTimestamp()),
|
|
87
|
+
new Field(Fields.OrdType, OrdType.Market),
|
|
88
|
+
new Field(Fields.Side, Side.Buy),
|
|
89
|
+
new Field(Fields.Symbol, `${(index + 1) * 100}.HK`),
|
|
90
|
+
new Field(Fields.TimeInForce, TimeInForce.Day),
|
|
91
|
+
);
|
|
92
|
+
const messages = fixParser.parse(order.encode());
|
|
93
|
+
console.log('sending message', messages[0].description, messages[0].messageString.replace(/\x01/g, '|'));
|
|
94
|
+
fixParser.send(order);
|
|
95
|
+
});
|
|
96
|
+
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EncryptMethod,
|
|
3
|
+
FIXParser,
|
|
4
|
+
Field,
|
|
5
|
+
Fields,
|
|
6
|
+
LicenseManager,
|
|
7
|
+
MDEntryType,
|
|
8
|
+
MDUpdateType,
|
|
9
|
+
type Message,
|
|
10
|
+
Messages,
|
|
11
|
+
ResetSeqNumFlag,
|
|
12
|
+
} from 'fixparser';
|
|
13
|
+
|
|
14
|
+
// NOTE: This feature requires a FIXParser Pro license
|
|
15
|
+
LicenseManager.setLicenseKey('<your license here>');
|
|
16
|
+
|
|
17
|
+
const fixParser = new FIXParser();
|
|
18
|
+
|
|
19
|
+
const SENDER = 'ctrader.xxxxxxx';
|
|
20
|
+
const TARGET = 'CSERVER';
|
|
21
|
+
const CTRADER_PASSWORD = 'xxxxxxxxxxxx';
|
|
22
|
+
const CTRADER_SERVER = 'xxxxxxxxxxxx'; // e.g. h47.p.ctrader.com
|
|
23
|
+
const CTRADER_PORT = 5201; // 5211 SSL, 5201 Plain Text
|
|
24
|
+
|
|
25
|
+
let countReq = 0;
|
|
26
|
+
|
|
27
|
+
fixParser.connect({
|
|
28
|
+
host: CTRADER_SERVER,
|
|
29
|
+
port: CTRADER_PORT,
|
|
30
|
+
protocol: 'tcp',
|
|
31
|
+
sender: SENDER,
|
|
32
|
+
target: TARGET,
|
|
33
|
+
fixVersion: 'FIX.4.4',
|
|
34
|
+
onOpen: () => {
|
|
35
|
+
console.log('Open');
|
|
36
|
+
sendLogon();
|
|
37
|
+
sendMarketDataRequest();
|
|
38
|
+
},
|
|
39
|
+
onMessage: (message: Message) => console.log('received message', message.description, message.messageString),
|
|
40
|
+
onError: (error?: Error) => console.log('error', error),
|
|
41
|
+
onClose: () => console.log('Disconnected'),
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const sendLogon = () => {
|
|
45
|
+
const logon = fixParser.createMessage(
|
|
46
|
+
new Field(Fields.MsgType, Messages.Logon),
|
|
47
|
+
new Field(Fields.BeginString, 'FIX.4.4'),
|
|
48
|
+
new Field(Fields.MsgSeqNum, fixParser.getNextTargetMsgSeqNum()),
|
|
49
|
+
new Field(Fields.SenderCompID, SENDER),
|
|
50
|
+
new Field(Fields.SendingTime, fixParser.getTimestamp()),
|
|
51
|
+
new Field(Fields.TargetCompID, TARGET),
|
|
52
|
+
new Field(Fields.SenderSubID, 'QUOTE'),
|
|
53
|
+
new Field(Fields.ResetSeqNumFlag, ResetSeqNumFlag.Yes),
|
|
54
|
+
new Field(Fields.RawData, CTRADER_PASSWORD),
|
|
55
|
+
new Field(Fields.EncryptMethod, EncryptMethod.None),
|
|
56
|
+
new Field(Fields.HeartBtInt, 10),
|
|
57
|
+
);
|
|
58
|
+
const messages = fixParser.parse(logon.encode());
|
|
59
|
+
console.log('sending message', messages[0].description, messages[0].messageString);
|
|
60
|
+
fixParser.send(logon);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// for sending market data request to cTrader's FIX API server
|
|
64
|
+
const sendMarketDataRequest = () => {
|
|
65
|
+
const quote = fixParser.createMessage(
|
|
66
|
+
new Field(Fields.MsgType, Messages.MarketDataRequest),
|
|
67
|
+
new Field(Fields.BeginString, 'FIX.4.4'),
|
|
68
|
+
new Field(Fields.SenderCompID, SENDER),
|
|
69
|
+
new Field(Fields.MsgSeqNum, fixParser.getNextTargetMsgSeqNum()),
|
|
70
|
+
new Field(Fields.TargetCompID, TARGET),
|
|
71
|
+
new Field(Fields.SendingTime, fixParser.getTimestamp()),
|
|
72
|
+
new Field(Fields.MarketDepth, 0),
|
|
73
|
+
new Field(Fields.MDUpdateType, MDUpdateType.FullRefresh),
|
|
74
|
+
new Field(Fields.NoRelatedSym, 2),
|
|
75
|
+
new Field(Fields.Symbol, 1), // for cTrader's own symbol system, 1 for EURUSD
|
|
76
|
+
new Field(Fields.Symbol, 2), // 2 for GBPUSD
|
|
77
|
+
new Field(Fields.MDReqID, ++countReq),
|
|
78
|
+
new Field(Fields.SubscriptionRequestType, 1),
|
|
79
|
+
new Field(Fields.NoMDEntryTypes, 2),
|
|
80
|
+
new Field(Fields.MDEntryType, MDEntryType.Bid),
|
|
81
|
+
new Field(Fields.MDEntryType, MDEntryType.Offer),
|
|
82
|
+
);
|
|
83
|
+
const messages = fixParser.parse(quote.encode());
|
|
84
|
+
console.log('sending message', messages[0].description, messages[0].messageString.replace(/\x01/g, '|'));
|
|
85
|
+
fixParser.send(quote);
|
|
86
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ExecType,
|
|
3
|
+
FIXServer,
|
|
4
|
+
Field,
|
|
5
|
+
Fields,
|
|
6
|
+
LicenseManager,
|
|
7
|
+
type Message,
|
|
8
|
+
Messages,
|
|
9
|
+
OrdStatus,
|
|
10
|
+
Side,
|
|
11
|
+
} from 'fixparser/FIXServer';
|
|
12
|
+
|
|
13
|
+
// NOTE: This feature requires a FIXParser Pro license
|
|
14
|
+
LicenseManager.setLicenseKey('<your license here>');
|
|
15
|
+
|
|
16
|
+
const fixServer = new FIXServer();
|
|
17
|
+
fixServer.createServer({
|
|
18
|
+
host: 'localhost',
|
|
19
|
+
port: 9878,
|
|
20
|
+
sender: 'SERVER',
|
|
21
|
+
target: 'CLIENT',
|
|
22
|
+
onOpen: () => console.log('Open'),
|
|
23
|
+
onClose: () => console.log('Disconnected'),
|
|
24
|
+
onMessage: (message: Message) => {
|
|
25
|
+
console.log('server received message', message.description, message.messageString);
|
|
26
|
+
// Respond with ExecutionReport
|
|
27
|
+
if (message.messageType === Messages.NewOrderSingle) {
|
|
28
|
+
sendExecutionReport(message);
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const sendExecutionReport = (message: Message) => {
|
|
34
|
+
const executionReport = fixServer.createMessage(
|
|
35
|
+
new Field(Fields.MsgType, Messages.ExecutionReport),
|
|
36
|
+
new Field(Fields.MsgSeqNum, fixServer.getNextTargetMsgSeqNum()),
|
|
37
|
+
new Field(Fields.SenderCompID, 'SERVER'),
|
|
38
|
+
new Field(Fields.SendingTime, fixServer.getTimestamp()),
|
|
39
|
+
new Field(Fields.TargetCompID, 'CLIENT'),
|
|
40
|
+
new Field(Fields.AvgPx, message.getField(Fields.Price) ? message.getField(Fields.Price)?.value : 0),
|
|
41
|
+
new Field(Fields.ClOrdID, message.getField(Fields.ClOrdID) ? message.getField(Fields.ClOrdID)?.value : 'N/A'),
|
|
42
|
+
new Field(Fields.CumQty, message.getField(Fields.OrderQty) ? message.getField(Fields.OrderQty)?.value : 0),
|
|
43
|
+
new Field(Fields.Symbol, message.getField(Fields.Symbol) ? message.getField(Fields.Symbol)?.value : 'N/A'),
|
|
44
|
+
new Field(Fields.LastPx, message.getField(Fields.Price) ? message.getField(Fields.Price)?.value : 0),
|
|
45
|
+
new Field(Fields.OrderID, 55),
|
|
46
|
+
new Field(Fields.OrderQty, message.getField(Fields.OrderQty) ? message.getField(Fields.OrderQty)?.value : 0),
|
|
47
|
+
new Field(Fields.OrdStatus, OrdStatus.Filled),
|
|
48
|
+
new Field(Fields.Side, Side.Buy),
|
|
49
|
+
new Field(Fields.ExecType, ExecType.Trade),
|
|
50
|
+
new Field(Fields.LeavesQty, 0),
|
|
51
|
+
);
|
|
52
|
+
const messages = fixServer.parse(executionReport.encode());
|
|
53
|
+
console.log('sending message', messages[0].description, messages[0].messageString.replace(/\x01/g, '|'));
|
|
54
|
+
fixServer.send(executionReport);
|
|
55
|
+
};
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type ConnectionOptions,
|
|
3
|
+
EncryptMethod,
|
|
4
|
+
FIXParser,
|
|
5
|
+
Field,
|
|
6
|
+
Fields,
|
|
7
|
+
HandlInst,
|
|
8
|
+
LicenseManager,
|
|
9
|
+
type Message,
|
|
10
|
+
Messages,
|
|
11
|
+
OrdType,
|
|
12
|
+
ResetSeqNumFlag,
|
|
13
|
+
Side,
|
|
14
|
+
TimeInForce,
|
|
15
|
+
} from 'fixparser';
|
|
16
|
+
|
|
17
|
+
const fixParser = new FIXParser();
|
|
18
|
+
const SENDER = 'CLIENT';
|
|
19
|
+
const TARGET = 'SERVER';
|
|
20
|
+
|
|
21
|
+
const tlsOptions = {
|
|
22
|
+
minVersion: 'TLSv1.3',
|
|
23
|
+
cert: `-----BEGIN CERTIFICATE-----
|
|
24
|
+
MIIDazCCAlOgAwIBAgIUAq3bE3+GehnCjrl6M74Ik6qjrVMwDQYJKoZIhvcNAQEL
|
|
25
|
+
BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
|
|
26
|
+
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yNTAxMjcyMTQ4MzlaFw00NTAx
|
|
27
|
+
MjIyMTQ4MzlaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
|
|
28
|
+
HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB
|
|
29
|
+
AQUAA4IBDwAwggEKAoIBAQCIS+66TMfEgfm23isscqJ/8rGUUvP0NLqmCvCDBfeA
|
|
30
|
+
SeLjOAdNkLO+XnIbPgXPx5RmvNZuk8NrXwDAS5zbZCngbFyS3HQFRxokj/6uH0Bi
|
|
31
|
+
dLXaaVHZHXnMmUglaN21dav1wOPTD4IM5pTCIGs4k7fS7zJCQK8/GunAZbv0TLVd
|
|
32
|
+
+Cb9NdD/q4qyJKTRxm8QREWXMlJPZCPO48xqNMAtVC2ywGk7UueQu1UPH/uiOtV0
|
|
33
|
+
GpW339eRodSYrHOXbwwNk0K5xyHHXVISs+iXIJ1nUlRVUzHkIQCQXK+Fdn5iIqRN
|
|
34
|
+
MjnUDvMndqheWDmO64ISTPddnR1v/Ly5Ftwv1v8TaJ85AgMBAAGjUzBRMB0GA1Ud
|
|
35
|
+
DgQWBBRI9AX+Nm/RHncJZQktGhvIw5tJ+TAfBgNVHSMEGDAWgBRI9AX+Nm/RHncJ
|
|
36
|
+
ZQktGhvIw5tJ+TAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBb
|
|
37
|
+
ph8nB374X7EdLHZI4Ulj3itszcSmCeWqS3+x3WZLOnLZUzmbqpoxohqtWapTcD8n
|
|
38
|
+
eJ41ZMo/5FFC20/ywMl2i51ofGBupeAXwy9euFna9/JmYWaSf1OmE5AFNAWqmQIK
|
|
39
|
+
qHppaphAHjHRpLRO+tp6ezVAFmgXaKk2b09FChZolOorjuPP/7DpcWtwUG9esJHY
|
|
40
|
+
LwMaEBMRu37SZCJEoUDDj0wKl7+QQwlAcvXqIsvFxanvdxQn0Q62k1qLa5lMNGtp
|
|
41
|
+
DhUtJAY2zkWxFsbGpMcN3B9SxdZO9aZWjbyvsa54D7/EZqTzucDsOt4JNGWwX8x4
|
|
42
|
+
BCFxH2tIR7zcDgGRVDE3
|
|
43
|
+
-----END CERTIFICATE-----`,
|
|
44
|
+
key: `-----BEGIN PRIVATE KEY-----
|
|
45
|
+
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCIS+66TMfEgfm2
|
|
46
|
+
3isscqJ/8rGUUvP0NLqmCvCDBfeASeLjOAdNkLO+XnIbPgXPx5RmvNZuk8NrXwDA
|
|
47
|
+
S5zbZCngbFyS3HQFRxokj/6uH0BidLXaaVHZHXnMmUglaN21dav1wOPTD4IM5pTC
|
|
48
|
+
IGs4k7fS7zJCQK8/GunAZbv0TLVd+Cb9NdD/q4qyJKTRxm8QREWXMlJPZCPO48xq
|
|
49
|
+
NMAtVC2ywGk7UueQu1UPH/uiOtV0GpW339eRodSYrHOXbwwNk0K5xyHHXVISs+iX
|
|
50
|
+
IJ1nUlRVUzHkIQCQXK+Fdn5iIqRNMjnUDvMndqheWDmO64ISTPddnR1v/Ly5Ftwv
|
|
51
|
+
1v8TaJ85AgMBAAECggEAAKG1B7qKsGbec2xja17w2i3YUbzSLqecQ1bq48KQOuOI
|
|
52
|
+
M9H9R6zfYdA/66sCHZDHx7OdBihHHw93R/qVKSVZ49VlTcu5zCRABXauBcEZ3CCq
|
|
53
|
+
83MhZmzJR2IzQ476YMiTfT//H3MPAO/ER7FBqfTNKVnMevS7igviuVe1Exhmjv9M
|
|
54
|
+
yBqDmaqxzv9UeacuX/7fqhAcO6A4euODpLgUyGPBdcpwExdG1OLruWsRD/oG8VY6
|
|
55
|
+
2ZvQ0CPLusiN7rMem5mRt1GmW2zhHbZaAa960LVy/ikHD6A9k3O0nYYRMtbmOWOn
|
|
56
|
+
I0DRZSWTkG3DR7/sD6F5zw8UL25NYTuJFYl/K8fc8QKBgQC9TQz/W05mniLo3SZ7
|
|
57
|
+
KxG1s2Wphp4DxufLsbM6EXdzQ09adQyGzHaqtG5bycL54ed8wJgp7EShDBX4RX6U
|
|
58
|
+
rg4iMgBipC2S/N9EIBZ7Dg3P0Mayvfqd3+qrg32CWqc0mLIep4k9XkSsWffsghSx
|
|
59
|
+
XO7MVRiRnWAaawYxFiDpTHBz6QKBgQC4UeMz1PhtI4cfeJgpsEeiSk4eRJOGc01D
|
|
60
|
+
79bYegSehZ9RL04DjgIEazccmIB5eprZ43BSR5SrHyOwAnjeb+Gxxmz4avm1hqYl
|
|
61
|
+
fq6QbBlgpk5FQSNHyBgD2DfcNxSs+YWbaT6mgkjZeJRCzhZLMWLLYswSoAGehyYu
|
|
62
|
+
FklodWFO0QKBgDEooDZ0BKEbcd9dBtA3eArigoUKo2BBuBIqnGt4+7cgBKxt9wnO
|
|
63
|
+
cQaVgo8tjweLRa0c6qcAZzYXSGFH0r5TkPIKYBU9o2QnbOdpGc1s8eNEyUTDlyCG
|
|
64
|
+
dI+DvwUp+3/qI19YjIg2QcksN/jgMvV4N78yXgX6g2l434vBvlw3cIB5AoGALzt8
|
|
65
|
+
t1mJ153VEHF8vKIZmTLlVchI7Zk6YYBiU9LgwCaJruoqWarYRX2b/83sjjSm3dL0
|
|
66
|
+
g4EoTbmLEZ1wj7+n3EB2yCnRl3zLsqwF26h30FaNlB2fBtP1o3aSyfGrcK/4Vtzf
|
|
67
|
+
WxfjxyapB318JQSgxnGozdUG1TLYy9KWORhrOSECgYAfyo+EynjQIwM0IkMqLA/3
|
|
68
|
+
JvyGxVXv886rjT3wibUATaRfR0ZTfGql+Tszr/fB60M4UqlBN7JRzWFuBLCh7IN/
|
|
69
|
+
Ks9adwa81pZEJ3kIkCGewK2fG5lTwEbaJpf2hw/Jf2FYwsp0uI/0O7NgVWDid8sx
|
|
70
|
+
tswAkG7yU9ZI15CXgOhekg==a
|
|
71
|
+
-----END PRIVATE KEY-----`,
|
|
72
|
+
rejectUnauthorized: false,
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// NOTE: This feature requires a FIXParser Pro license
|
|
76
|
+
LicenseManager.setLicenseKey('<your license here>');
|
|
77
|
+
|
|
78
|
+
fixParser.connect({
|
|
79
|
+
host: 'localhost',
|
|
80
|
+
port: 9878,
|
|
81
|
+
protocol: 'tls-tcp',
|
|
82
|
+
sender: SENDER,
|
|
83
|
+
target: TARGET,
|
|
84
|
+
fixVersion: 'FIX.4.4',
|
|
85
|
+
tlsOptions: tlsOptions as ConnectionOptions,
|
|
86
|
+
logging: true,
|
|
87
|
+
onOpen: () => {
|
|
88
|
+
console.log('Open');
|
|
89
|
+
sendLogon();
|
|
90
|
+
setInterval(() => {
|
|
91
|
+
sendOrder();
|
|
92
|
+
}, 500);
|
|
93
|
+
},
|
|
94
|
+
onMessage: (message: Message) => console.log('received message', message.description, message.messageString),
|
|
95
|
+
onClose: () => console.log('Disconnected'),
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const sendLogon = () => {
|
|
99
|
+
const logon = fixParser.createMessage(
|
|
100
|
+
new Field(Fields.MsgType, Messages.Logon),
|
|
101
|
+
new Field(Fields.MsgSeqNum, fixParser.getNextTargetMsgSeqNum()),
|
|
102
|
+
new Field(Fields.SenderCompID, SENDER),
|
|
103
|
+
new Field(Fields.SendingTime, fixParser.getTimestamp()),
|
|
104
|
+
new Field(Fields.TargetCompID, TARGET),
|
|
105
|
+
new Field(Fields.ResetSeqNumFlag, ResetSeqNumFlag.Yes),
|
|
106
|
+
new Field(Fields.EncryptMethod, EncryptMethod.None),
|
|
107
|
+
new Field(Fields.HeartBtInt, 10),
|
|
108
|
+
);
|
|
109
|
+
const messages = fixParser.parse(logon.encode());
|
|
110
|
+
console.log('sending message', messages[0].description, messages[0].messageString);
|
|
111
|
+
fixParser.send(logon);
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const sendOrder = () => {
|
|
115
|
+
const order = fixParser.createMessage(
|
|
116
|
+
new Field(Fields.MsgType, Messages.NewOrderSingle),
|
|
117
|
+
new Field(Fields.MsgSeqNum, fixParser.getNextTargetMsgSeqNum()),
|
|
118
|
+
new Field(Fields.SenderCompID, SENDER),
|
|
119
|
+
new Field(Fields.SendingTime, fixParser.getTimestamp()),
|
|
120
|
+
new Field(Fields.TargetCompID, TARGET),
|
|
121
|
+
new Field(Fields.ClOrdID, '11223344'),
|
|
122
|
+
new Field(Fields.HandlInst, HandlInst.AutomatedExecutionNoIntervention),
|
|
123
|
+
new Field(Fields.OrderQty, '123'),
|
|
124
|
+
new Field(Fields.TransactTime, fixParser.getTimestamp()),
|
|
125
|
+
new Field(Fields.OrdType, OrdType.Market),
|
|
126
|
+
new Field(Fields.Side, Side.Buy),
|
|
127
|
+
new Field(Fields.Symbol, '700.HK'),
|
|
128
|
+
new Field(Fields.TimeInForce, TimeInForce.Day),
|
|
129
|
+
);
|
|
130
|
+
const messages = fixParser.parse(order.encode());
|
|
131
|
+
console.log('sending message', messages[0].description, messages[0].messageString.replace(/\x01/g, '|'));
|
|
132
|
+
fixParser.send(order);
|
|
133
|
+
};
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ExecType,
|
|
3
|
+
FIXServer,
|
|
4
|
+
Field,
|
|
5
|
+
Fields,
|
|
6
|
+
LicenseManager,
|
|
7
|
+
type Message,
|
|
8
|
+
Messages,
|
|
9
|
+
OrdStatus,
|
|
10
|
+
Side,
|
|
11
|
+
type TlsOptions,
|
|
12
|
+
} from 'fixparser/FIXServer';
|
|
13
|
+
|
|
14
|
+
const tlsOptions = {
|
|
15
|
+
minVersion: 'TLSv1.3',
|
|
16
|
+
cert: `-----BEGIN CERTIFICATE-----
|
|
17
|
+
MIIDazCCAlOgAwIBAgIUAq3bE3+GehnCjrl6M74Ik6qjrVMwDQYJKoZIhvcNAQEL
|
|
18
|
+
BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
|
|
19
|
+
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yNTAxMjcyMTQ4MzlaFw00NTAx
|
|
20
|
+
MjIyMTQ4MzlaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
|
|
21
|
+
HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB
|
|
22
|
+
AQUAA4IBDwAwggEKAoIBAQCIS+66TMfEgfm23isscqJ/8rGUUvP0NLqmCvCDBfeA
|
|
23
|
+
SeLjOAdNkLO+XnIbPgXPx5RmvNZuk8NrXwDAS5zbZCngbFyS3HQFRxokj/6uH0Bi
|
|
24
|
+
dLXaaVHZHXnMmUglaN21dav1wOPTD4IM5pTCIGs4k7fS7zJCQK8/GunAZbv0TLVd
|
|
25
|
+
+Cb9NdD/q4qyJKTRxm8QREWXMlJPZCPO48xqNMAtVC2ywGk7UueQu1UPH/uiOtV0
|
|
26
|
+
GpW339eRodSYrHOXbwwNk0K5xyHHXVISs+iXIJ1nUlRVUzHkIQCQXK+Fdn5iIqRN
|
|
27
|
+
MjnUDvMndqheWDmO64ISTPddnR1v/Ly5Ftwv1v8TaJ85AgMBAAGjUzBRMB0GA1Ud
|
|
28
|
+
DgQWBBRI9AX+Nm/RHncJZQktGhvIw5tJ+TAfBgNVHSMEGDAWgBRI9AX+Nm/RHncJ
|
|
29
|
+
ZQktGhvIw5tJ+TAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBb
|
|
30
|
+
ph8nB374X7EdLHZI4Ulj3itszcSmCeWqS3+x3WZLOnLZUzmbqpoxohqtWapTcD8n
|
|
31
|
+
eJ41ZMo/5FFC20/ywMl2i51ofGBupeAXwy9euFna9/JmYWaSf1OmE5AFNAWqmQIK
|
|
32
|
+
qHppaphAHjHRpLRO+tp6ezVAFmgXaKk2b09FChZolOorjuPP/7DpcWtwUG9esJHY
|
|
33
|
+
LwMaEBMRu37SZCJEoUDDj0wKl7+QQwlAcvXqIsvFxanvdxQn0Q62k1qLa5lMNGtp
|
|
34
|
+
DhUtJAY2zkWxFsbGpMcN3B9SxdZO9aZWjbyvsa54D7/EZqTzucDsOt4JNGWwX8x4
|
|
35
|
+
BCFxH2tIR7zcDgGRVDE3
|
|
36
|
+
-----END CERTIFICATE-----`,
|
|
37
|
+
key: `-----BEGIN PRIVATE KEY-----
|
|
38
|
+
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCIS+66TMfEgfm2
|
|
39
|
+
3isscqJ/8rGUUvP0NLqmCvCDBfeASeLjOAdNkLO+XnIbPgXPx5RmvNZuk8NrXwDA
|
|
40
|
+
S5zbZCngbFyS3HQFRxokj/6uH0BidLXaaVHZHXnMmUglaN21dav1wOPTD4IM5pTC
|
|
41
|
+
IGs4k7fS7zJCQK8/GunAZbv0TLVd+Cb9NdD/q4qyJKTRxm8QREWXMlJPZCPO48xq
|
|
42
|
+
NMAtVC2ywGk7UueQu1UPH/uiOtV0GpW339eRodSYrHOXbwwNk0K5xyHHXVISs+iX
|
|
43
|
+
IJ1nUlRVUzHkIQCQXK+Fdn5iIqRNMjnUDvMndqheWDmO64ISTPddnR1v/Ly5Ftwv
|
|
44
|
+
1v8TaJ85AgMBAAECggEAAKG1B7qKsGbec2xja17w2i3YUbzSLqecQ1bq48KQOuOI
|
|
45
|
+
M9H9R6zfYdA/66sCHZDHx7OdBihHHw93R/qVKSVZ49VlTcu5zCRABXauBcEZ3CCq
|
|
46
|
+
83MhZmzJR2IzQ476YMiTfT//H3MPAO/ER7FBqfTNKVnMevS7igviuVe1Exhmjv9M
|
|
47
|
+
yBqDmaqxzv9UeacuX/7fqhAcO6A4euODpLgUyGPBdcpwExdG1OLruWsRD/oG8VY6
|
|
48
|
+
2ZvQ0CPLusiN7rMem5mRt1GmW2zhHbZaAa960LVy/ikHD6A9k3O0nYYRMtbmOWOn
|
|
49
|
+
I0DRZSWTkG3DR7/sD6F5zw8UL25NYTuJFYl/K8fc8QKBgQC9TQz/W05mniLo3SZ7
|
|
50
|
+
KxG1s2Wphp4DxufLsbM6EXdzQ09adQyGzHaqtG5bycL54ed8wJgp7EShDBX4RX6U
|
|
51
|
+
rg4iMgBipC2S/N9EIBZ7Dg3P0Mayvfqd3+qrg32CWqc0mLIep4k9XkSsWffsghSx
|
|
52
|
+
XO7MVRiRnWAaawYxFiDpTHBz6QKBgQC4UeMz1PhtI4cfeJgpsEeiSk4eRJOGc01D
|
|
53
|
+
79bYegSehZ9RL04DjgIEazccmIB5eprZ43BSR5SrHyOwAnjeb+Gxxmz4avm1hqYl
|
|
54
|
+
fq6QbBlgpk5FQSNHyBgD2DfcNxSs+YWbaT6mgkjZeJRCzhZLMWLLYswSoAGehyYu
|
|
55
|
+
FklodWFO0QKBgDEooDZ0BKEbcd9dBtA3eArigoUKo2BBuBIqnGt4+7cgBKxt9wnO
|
|
56
|
+
cQaVgo8tjweLRa0c6qcAZzYXSGFH0r5TkPIKYBU9o2QnbOdpGc1s8eNEyUTDlyCG
|
|
57
|
+
dI+DvwUp+3/qI19YjIg2QcksN/jgMvV4N78yXgX6g2l434vBvlw3cIB5AoGALzt8
|
|
58
|
+
t1mJ153VEHF8vKIZmTLlVchI7Zk6YYBiU9LgwCaJruoqWarYRX2b/83sjjSm3dL0
|
|
59
|
+
g4EoTbmLEZ1wj7+n3EB2yCnRl3zLsqwF26h30FaNlB2fBtP1o3aSyfGrcK/4Vtzf
|
|
60
|
+
WxfjxyapB318JQSgxnGozdUG1TLYy9KWORhrOSECgYAfyo+EynjQIwM0IkMqLA/3
|
|
61
|
+
JvyGxVXv886rjT3wibUATaRfR0ZTfGql+Tszr/fB60M4UqlBN7JRzWFuBLCh7IN/
|
|
62
|
+
Ks9adwa81pZEJ3kIkCGewK2fG5lTwEbaJpf2hw/Jf2FYwsp0uI/0O7NgVWDid8sx
|
|
63
|
+
tswAkG7yU9ZI15CXgOhekg==
|
|
64
|
+
-----END PRIVATE KEY-----`,
|
|
65
|
+
rejectUnauthorized: false,
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
// NOTE: This feature requires a FIXParser Pro license
|
|
69
|
+
LicenseManager.setLicenseKey('<your license here>');
|
|
70
|
+
|
|
71
|
+
const fixServer = new FIXServer();
|
|
72
|
+
fixServer.createServer({
|
|
73
|
+
host: 'localhost',
|
|
74
|
+
port: 9878,
|
|
75
|
+
protocol: 'tls-tcp',
|
|
76
|
+
sender: 'SERVER',
|
|
77
|
+
target: 'CLIENT',
|
|
78
|
+
tlsOptions: tlsOptions as TlsOptions,
|
|
79
|
+
onOpen: () => console.log('Open'),
|
|
80
|
+
onClose: () => console.log('Disconnected'),
|
|
81
|
+
onMessage: (message: Message) => {
|
|
82
|
+
console.log('server received message', message.description, message.messageString);
|
|
83
|
+
// Respond with ExecutionReport
|
|
84
|
+
if (message.messageType === Messages.NewOrderSingle) {
|
|
85
|
+
sendExecutionReport(message);
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const sendExecutionReport = (message: Message) => {
|
|
91
|
+
const executionReport = fixServer.createMessage(
|
|
92
|
+
new Field(Fields.MsgType, Messages.ExecutionReport),
|
|
93
|
+
new Field(Fields.MsgSeqNum, fixServer.getNextTargetMsgSeqNum()),
|
|
94
|
+
new Field(Fields.SenderCompID, 'SERVER'),
|
|
95
|
+
new Field(Fields.SendingTime, fixServer.getTimestamp()),
|
|
96
|
+
new Field(Fields.TargetCompID, 'CLIENT'),
|
|
97
|
+
new Field(Fields.AvgPx, message.getField(Fields.Price) ? message.getField(Fields.Price)?.value : 0),
|
|
98
|
+
new Field(Fields.ClOrdID, message.getField(Fields.ClOrdID) ? message.getField(Fields.ClOrdID)?.value : 'N/A'),
|
|
99
|
+
new Field(Fields.CumQty, message.getField(Fields.OrderQty) ? message.getField(Fields.OrderQty)?.value : 0),
|
|
100
|
+
new Field(Fields.Symbol, message.getField(Fields.Symbol) ? message.getField(Fields.Symbol)?.value : 'N/A'),
|
|
101
|
+
new Field(Fields.LastPx, message.getField(Fields.Price) ? message.getField(Fields.Price)?.value : 0),
|
|
102
|
+
new Field(Fields.OrderID, 55),
|
|
103
|
+
new Field(Fields.OrderQty, message.getField(Fields.OrderQty) ? message.getField(Fields.OrderQty)?.value : 0),
|
|
104
|
+
new Field(Fields.OrdStatus, OrdStatus.Filled),
|
|
105
|
+
new Field(Fields.Side, Side.Buy),
|
|
106
|
+
new Field(Fields.ExecType, ExecType.Trade),
|
|
107
|
+
new Field(Fields.LeavesQty, 0),
|
|
108
|
+
);
|
|
109
|
+
const messages = fixServer.parse(executionReport.encode());
|
|
110
|
+
console.log('sending message', messages[0].description, messages[0].messageString.replace(/\x01/g, '|'));
|
|
111
|
+
fixServer.send(executionReport);
|
|
112
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import {
|
|
2
|
+
EncryptMethod,
|
|
3
|
+
FIXParser,
|
|
4
|
+
Field,
|
|
5
|
+
Fields,
|
|
6
|
+
HandlInst,
|
|
7
|
+
LicenseManager,
|
|
8
|
+
type Message,
|
|
9
|
+
Messages,
|
|
10
|
+
OrdType,
|
|
11
|
+
ResetSeqNumFlag,
|
|
12
|
+
Side,
|
|
13
|
+
TimeInForce,
|
|
14
|
+
} from 'fixparser';
|
|
15
|
+
|
|
16
|
+
// NOTE: This feature requires a FIXParser Pro license
|
|
17
|
+
LicenseManager.setLicenseKey('<your license here>');
|
|
18
|
+
|
|
19
|
+
const fixParser = new FIXParser();
|
|
20
|
+
const SENDER = 'BANZAI';
|
|
21
|
+
const TARGET = 'EXEC';
|
|
22
|
+
|
|
23
|
+
fixParser.connect({
|
|
24
|
+
host: 'localhost',
|
|
25
|
+
port: 9900,
|
|
26
|
+
protocol: 'websocket',
|
|
27
|
+
sender: SENDER,
|
|
28
|
+
target: TARGET,
|
|
29
|
+
fixVersion: 'FIX.4.4',
|
|
30
|
+
onOpen: () => {
|
|
31
|
+
console.log('Open');
|
|
32
|
+
sendLogon();
|
|
33
|
+
setInterval(() => {
|
|
34
|
+
sendOrder();
|
|
35
|
+
}, 500);
|
|
36
|
+
},
|
|
37
|
+
onMessage: (message: Message) => console.log('received message', message.description, message.messageString),
|
|
38
|
+
onClose: () => console.log('Disconnected'),
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const sendLogon = () => {
|
|
42
|
+
const logon = fixParser.createMessage(
|
|
43
|
+
new Field(Fields.MsgType, Messages.Logon),
|
|
44
|
+
new Field(Fields.MsgSeqNum, fixParser.getNextTargetMsgSeqNum()),
|
|
45
|
+
new Field(Fields.SenderCompID, SENDER),
|
|
46
|
+
new Field(Fields.SendingTime, fixParser.getTimestamp()),
|
|
47
|
+
new Field(Fields.TargetCompID, TARGET),
|
|
48
|
+
new Field(Fields.ResetSeqNumFlag, ResetSeqNumFlag.Yes),
|
|
49
|
+
new Field(Fields.EncryptMethod, EncryptMethod.None),
|
|
50
|
+
new Field(Fields.HeartBtInt, 10),
|
|
51
|
+
);
|
|
52
|
+
const messages = fixParser.parse(logon.encode());
|
|
53
|
+
console.log('sending message', messages[0].description, messages[0].messageString);
|
|
54
|
+
fixParser.send(logon);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const sendOrder = () => {
|
|
58
|
+
const order = fixParser.createMessage(
|
|
59
|
+
new Field(Fields.MsgType, Messages.NewOrderSingle),
|
|
60
|
+
new Field(Fields.MsgSeqNum, fixParser.getNextTargetMsgSeqNum()),
|
|
61
|
+
new Field(Fields.SenderCompID, SENDER),
|
|
62
|
+
new Field(Fields.SendingTime, fixParser.getTimestamp()),
|
|
63
|
+
new Field(Fields.TargetCompID, TARGET),
|
|
64
|
+
new Field(Fields.ClOrdID, '11223344'),
|
|
65
|
+
new Field(Fields.HandlInst, HandlInst.AutomatedExecutionNoIntervention),
|
|
66
|
+
new Field(Fields.OrderQty, 10000),
|
|
67
|
+
new Field(Fields.AvgPx, 100),
|
|
68
|
+
new Field(Fields.TransactTime, fixParser.getTimestamp()),
|
|
69
|
+
new Field(Fields.OrdType, OrdType.Market),
|
|
70
|
+
new Field(Fields.Side, Side.Buy),
|
|
71
|
+
new Field(Fields.Symbol, '700.HK'),
|
|
72
|
+
new Field(Fields.TimeInForce, TimeInForce.Day),
|
|
73
|
+
);
|
|
74
|
+
const messages = fixParser.parse(order.encode());
|
|
75
|
+
console.log('sending message', messages[0].description, messages[0].messageString.replace(/\x01/g, '|'));
|
|
76
|
+
fixParser.send(order);
|
|
77
|
+
};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ExecType,
|
|
3
|
+
FIXServer,
|
|
4
|
+
Field,
|
|
5
|
+
Fields,
|
|
6
|
+
HandlInst,
|
|
7
|
+
LicenseManager,
|
|
8
|
+
type Message,
|
|
9
|
+
Messages,
|
|
10
|
+
OrdStatus,
|
|
11
|
+
OrdType,
|
|
12
|
+
Side,
|
|
13
|
+
TimeInForce,
|
|
14
|
+
} from 'fixparser/FIXServer';
|
|
15
|
+
|
|
16
|
+
// NOTE: This feature requires a FIXParser Pro license
|
|
17
|
+
LicenseManager.setLicenseKey('<your license here>');
|
|
18
|
+
|
|
19
|
+
const SENDER = 'EXEC';
|
|
20
|
+
const TARGET = 'BANZAI';
|
|
21
|
+
const fixServer = new FIXServer();
|
|
22
|
+
let intervalId: ReturnType<typeof setInterval> | null = null;
|
|
23
|
+
|
|
24
|
+
fixServer.createServer({
|
|
25
|
+
host: 'localhost',
|
|
26
|
+
port: 9900,
|
|
27
|
+
protocol: 'websocket',
|
|
28
|
+
sender: 'EXEC',
|
|
29
|
+
target: 'BANZAI',
|
|
30
|
+
onOpen: () => {
|
|
31
|
+
console.log('Open');
|
|
32
|
+
clearInterval(intervalId!);
|
|
33
|
+
intervalId = setInterval(() => {
|
|
34
|
+
sendOrder();
|
|
35
|
+
}, 5000);
|
|
36
|
+
},
|
|
37
|
+
onMessage: (message: Message) => {
|
|
38
|
+
console.log('server received message', message.description, message.messageString);
|
|
39
|
+
// Respond with ExecutionReport
|
|
40
|
+
if (message.messageType === Messages.NewOrderSingle) {
|
|
41
|
+
sendExecutionReport(message);
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
onClose: () => {
|
|
45
|
+
console.log('Disconnected');
|
|
46
|
+
clearInterval(intervalId!);
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const sendOrder = () => {
|
|
51
|
+
const order = fixServer.createMessage(
|
|
52
|
+
new Field(Fields.MsgType, Messages.NewOrderSingle),
|
|
53
|
+
new Field(Fields.MsgSeqNum, fixServer.setNextTargetMsgSeqNum(fixServer.getNextTargetMsgSeqNum() + 1)),
|
|
54
|
+
new Field(Fields.SenderCompID, SENDER),
|
|
55
|
+
new Field(Fields.SendingTime, fixServer.getTimestamp()),
|
|
56
|
+
new Field(Fields.TargetCompID, TARGET),
|
|
57
|
+
new Field(Fields.ClOrdID, '11223344'),
|
|
58
|
+
new Field(Fields.HandlInst, HandlInst.AutomatedExecutionNoIntervention),
|
|
59
|
+
new Field(Fields.OrderQty, '123'),
|
|
60
|
+
new Field(Fields.TransactTime, fixServer.getTimestamp()),
|
|
61
|
+
new Field(Fields.OrdType, OrdType.Market),
|
|
62
|
+
new Field(Fields.Side, Side.Buy),
|
|
63
|
+
new Field(Fields.Symbol, '700.HK'),
|
|
64
|
+
new Field(Fields.TimeInForce, TimeInForce.Day),
|
|
65
|
+
);
|
|
66
|
+
const messages = fixServer.parse(order.encode());
|
|
67
|
+
console.log('sending message', messages[0].description, messages[0].messageString.replace(/\x01/g, '|'));
|
|
68
|
+
fixServer.send(order);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const sendExecutionReport = (message: Message) => {
|
|
72
|
+
const executionReport = fixServer.createMessage(
|
|
73
|
+
new Field(Fields.MsgType, Messages.ExecutionReport),
|
|
74
|
+
new Field(Fields.MsgSeqNum, fixServer.getNextTargetMsgSeqNum()),
|
|
75
|
+
new Field(Fields.SenderCompID, 'SERVER'),
|
|
76
|
+
new Field(Fields.SendingTime, fixServer.getTimestamp()),
|
|
77
|
+
new Field(Fields.TargetCompID, 'CLIENT'),
|
|
78
|
+
new Field(Fields.AvgPx, message.getField(Fields.Price) ? message.getField(Fields.Price)?.value : 0),
|
|
79
|
+
new Field(Fields.ClOrdID, message.getField(Fields.ClOrdID) ? message.getField(Fields.ClOrdID)?.value : 'N/A'),
|
|
80
|
+
new Field(Fields.CumQty, message.getField(Fields.OrderQty) ? message.getField(Fields.OrderQty)?.value : 0),
|
|
81
|
+
new Field(Fields.Symbol, message.getField(Fields.Symbol) ? message.getField(Fields.Symbol)?.value : 'N/A'),
|
|
82
|
+
new Field(Fields.LastPx, message.getField(Fields.Price) ? message.getField(Fields.Price)?.value : 0),
|
|
83
|
+
new Field(Fields.OrderID, 55),
|
|
84
|
+
new Field(Fields.OrderQty, message.getField(Fields.OrderQty) ? message.getField(Fields.OrderQty)?.value : 0),
|
|
85
|
+
new Field(Fields.OrdStatus, OrdStatus.Filled),
|
|
86
|
+
new Field(Fields.Side, Side.Buy),
|
|
87
|
+
new Field(Fields.ExecType, ExecType.Trade),
|
|
88
|
+
new Field(Fields.LeavesQty, 0),
|
|
89
|
+
);
|
|
90
|
+
fixServer.send(executionReport);
|
|
91
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require('dotenv').config();
|
|
2
|
+
const fs = require('node:fs');
|
|
3
|
+
|
|
4
|
+
const globals = require('../globals');
|
|
5
|
+
global.__PACKAGE_VERSION__ = globals.packageVersion;
|
|
6
|
+
global.__BUILD_TIME__ = globals.buildTime;
|
|
7
|
+
global.__RELEASE_INFORMATION__ = globals.releaseInformation;
|
|
8
|
+
|
|
9
|
+
const file = `${__dirname}/${process.argv[2]}`;
|
|
10
|
+
const fileData: string = fs.readFileSync(file, { encoding: 'utf8', flag: 'r' });
|
|
11
|
+
|
|
12
|
+
const tmpDir = `${__dirname}/.processed-examples`;
|
|
13
|
+
|
|
14
|
+
if (!fs.existsSync(tmpDir)) {
|
|
15
|
+
fs.mkdirSync(tmpDir);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const replaceString = (from: string, to: string, input: string) => input.toString().replace(new RegExp(from, 'g'), to);
|
|
19
|
+
|
|
20
|
+
let newFileData = fileData;
|
|
21
|
+
newFileData = replaceString("'fixparser'", "'../../src/FIXParser'", newFileData);
|
|
22
|
+
newFileData = replaceString("'fixparser/FIXServer'", "'../../src/FIXServer'", newFileData);
|
|
23
|
+
|
|
24
|
+
const newFileDataBuffer = Buffer.from(newFileData, 'utf8');
|
|
25
|
+
|
|
26
|
+
fs.writeFileSync(`${__dirname}/.processed-examples/${process.argv[2]}`, newFileDataBuffer);
|
|
27
|
+
|
|
28
|
+
require(`${__dirname}/.processed-examples/${process.argv[2]}`);
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fixparser",
|
|
3
|
-
"version": "8.1.
|
|
3
|
+
"version": "8.1.2",
|
|
4
4
|
"description": "FIX.Latest / 5.0 SP2 Parser",
|
|
5
|
-
"files": ["./build/", "./types/", "
|
|
5
|
+
"files": ["./build/", "./types/", "./examples/"],
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "git+https://gitlab.com/logotype/fixparser.git"
|