@quotemedia.com/streamer 2.41.0 → 2.43.0
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/README.md +157 -157
- package/examples/enduser-example.html +198 -198
- package/examples/enterprise-token-example.html +177 -177
- package/examples/reconnect-example.html +278 -278
- package/examples/stomp-3rd-party-library-example.html +681 -681
- package/examples/subscription-example.html +252 -252
- package/examples/wmid-example.html +176 -176
- package/package.json +38 -38
- package/{qmci-streamer-2.41.0.js → qmci-streamer-2.43.0.js} +1477 -1456
- package/{qmci-streamer-2.41.0.min.js → qmci-streamer-2.43.0.min.js} +2 -2
- package/examples/user-access-token-example.html +0 -177
|
@@ -1,682 +1,682 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
|
|
4
|
-
<head>
|
|
5
|
-
<script src="qmci-streamer-2.
|
|
6
|
-
<script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js"></script>
|
|
7
|
-
</head>
|
|
8
|
-
|
|
9
|
-
<body>
|
|
10
|
-
|
|
11
|
-
<span>Subscription Examples:</span></br>
|
|
12
|
-
|
|
13
|
-
<span>
|
|
14
|
-
<label>Sid Subscription: </label>
|
|
15
|
-
<select id="sid_user_subscription_example">
|
|
16
|
-
<option value="subscribe">subscribe</option>
|
|
17
|
-
<option value="subscribeMultiDataTypes">subscribeMultiDataTypes</option>
|
|
18
|
-
<option value="subscribeMultiSymbolsMultiDataTypes">subscribeMultiSymbolsMultiDataTypes</option>
|
|
19
|
-
<option value="subscribeMultiMessages">subscribeMultiMessages</option>
|
|
20
|
-
<option value="subscribeLargerSymbolLists">subscribeLargerSymbolLists</option>
|
|
21
|
-
<option value="subscribeExchange">subscribeExchange</option>
|
|
22
|
-
</select>
|
|
23
|
-
</span>
|
|
24
|
-
<input id="sid_user_get_sid" type="button" value="Get SID">
|
|
25
|
-
<input id="sid_user_subscribe" type="button" value="Subscribe">
|
|
26
|
-
<input id="sid_user_unsubscribe" type="button" value="Unsubscribe"></br>
|
|
27
|
-
|
|
28
|
-
<span>
|
|
29
|
-
<label>Enterprise Subscription: </label>
|
|
30
|
-
<select id="enterprise_user_subscription_example">
|
|
31
|
-
<option value="subscribe">subscribe</option>
|
|
32
|
-
<option value="subscribeMultiDataTypes">subscribeMultiDataTypes</option>
|
|
33
|
-
<option value="subscribeMultiSymbolsMultiDataTypes">subscribeMultiSymbolsMultiDataTypes</option>
|
|
34
|
-
</select>
|
|
35
|
-
</span>
|
|
36
|
-
<input id="enterprise_user_subscribe" type="button" value="Subscribe">
|
|
37
|
-
<input id="enterprise_user_unsubscribe" type="button" value="Unsubscribe"></br>
|
|
38
|
-
|
|
39
|
-
<span>
|
|
40
|
-
<label>Wmid Subscription: </label>
|
|
41
|
-
<select id="wmid_user_subscription_example">
|
|
42
|
-
<option value="subscribe">subscribe</option>
|
|
43
|
-
<option value="subscribeMultiDataTypes">subscribeMultiDataTypes</option>
|
|
44
|
-
<option value="subscribeMultiSymbolsMultiDataTypes">subscribeMultiSymbolsMultiDataTypes</option>
|
|
45
|
-
</select>
|
|
46
|
-
</span>
|
|
47
|
-
<input id="wmid_user_subscribe" type="button" value="Subscribe">
|
|
48
|
-
<input id="wmid_user_unsubscribe" type="button" value="Unsubscribe"></br>
|
|
49
|
-
|
|
50
|
-
<input id="stomp_connection_close" type="button" value="Connection Close"></br>
|
|
51
|
-
|
|
52
|
-
<div id="msg_print"></div>
|
|
53
|
-
|
|
54
|
-
<script type="text/javascript">
|
|
55
|
-
// Set up the event Listeners SidUserUnsubscribe
|
|
56
|
-
document.getElementById("sid_user_get_sid").addEventListener("click", getSid);
|
|
57
|
-
document.getElementById("sid_user_subscribe").addEventListener("click", SidUserSubscription);
|
|
58
|
-
document.getElementById("sid_user_unsubscribe").addEventListener("click", SidUserUnsubscribe);
|
|
59
|
-
document.getElementById("enterprise_user_subscribe").addEventListener("click", EnterpriseUserSubscription);
|
|
60
|
-
document.getElementById("enterprise_user_unsubscribe").addEventListener("click", EnterpriseUserUnsubscribe);
|
|
61
|
-
document.getElementById("wmid_user_subscribe").addEventListener("click", WmidUserSubscription);
|
|
62
|
-
document.getElementById("wmid_user_unsubscribe").addEventListener("click", WmidUserUnsubscribe);
|
|
63
|
-
document.getElementById("stomp_connection_close").addEventListener("click", disconnect);
|
|
64
|
-
|
|
65
|
-
// We need to use qmci.streamer to get the sid and use for Sid User Method
|
|
66
|
-
var Streamer = qmci.Streamer;
|
|
67
|
-
// Set up the message formatter, and it included in Streamer official JavaScript SDK library
|
|
68
|
-
var msgfmt = new qmci.Streamer.formatting.Formatter();
|
|
69
|
-
// This is URL use to connect Stomp endpoint
|
|
70
|
-
const url = "ws://app.quotemedia.com/cache/stream/connect";
|
|
71
|
-
// Stomp subscribe url route
|
|
72
|
-
const STOMP_SUBSCRIBE_URL = "/user/queue/messages";
|
|
73
|
-
// Stomp message send url route
|
|
74
|
-
const STOMP_SEND_MESSAGE_URL = "/stream/message";
|
|
75
|
-
// Sid for the end user Auth
|
|
76
|
-
var SID = null;
|
|
77
|
-
// Set up the Stomp client
|
|
78
|
-
var stompClient = null;
|
|
79
|
-
// To record the max allow to entitle for this user id
|
|
80
|
-
var maxEntitlementsPerSubscription = 0;
|
|
81
|
-
// To track the commands/control messages ordering
|
|
82
|
-
var ID = 1;
|
|
83
|
-
|
|
84
|
-
// Subscription msg lists use for multiple subscription request
|
|
85
|
-
var msgArrSubList = [{
|
|
86
|
-
"@T": "C2",
|
|
87
|
-
"action": "SUBSCRIBE",
|
|
88
|
-
"symbols": ["GOOG"],
|
|
89
|
-
"types": ["QUOTE"],
|
|
90
|
-
"mimetype": "application/json",
|
|
91
|
-
"conflation": null,
|
|
92
|
-
"id": ID++
|
|
93
|
-
},
|
|
94
|
-
{
|
|
95
|
-
"@T": "C2",
|
|
96
|
-
"action": "SUBSCRIBE",
|
|
97
|
-
"symbols": ["AAPL"],
|
|
98
|
-
"types": ["TRADE"],
|
|
99
|
-
"mimetype": "application/json",
|
|
100
|
-
"conflation": null,
|
|
101
|
-
"id": ID++
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
"@T": "C2",
|
|
105
|
-
"action": "SUBSCRIBE",
|
|
106
|
-
"symbols": ["MSFT"],
|
|
107
|
-
"types": ["PRICEDATA"],
|
|
108
|
-
"mimetype": "application/json",
|
|
109
|
-
"conflation": null,
|
|
110
|
-
"id": ID++
|
|
111
|
-
}
|
|
112
|
-
];
|
|
113
|
-
|
|
114
|
-
// Unsubscription msg lists use for multiple subscription request
|
|
115
|
-
var msgArrUnsubList = [{
|
|
116
|
-
"@T": "C2",
|
|
117
|
-
"action": "UNSUBSCRIBE",
|
|
118
|
-
"symbols": ["GOOG"],
|
|
119
|
-
"types": ["QUOTE"],
|
|
120
|
-
"mimetype": "application/json",
|
|
121
|
-
"conflation": null,
|
|
122
|
-
"id": ID++
|
|
123
|
-
},
|
|
124
|
-
{
|
|
125
|
-
"@T": "C2",
|
|
126
|
-
"action": "UNSUBSCRIBE",
|
|
127
|
-
"symbols": ["AAPL"],
|
|
128
|
-
"types": ["TRADE"],
|
|
129
|
-
"mimetype": "application/json",
|
|
130
|
-
"conflation": null,
|
|
131
|
-
"id": ID++
|
|
132
|
-
},
|
|
133
|
-
{
|
|
134
|
-
"@T": "C2",
|
|
135
|
-
"action": "UNSUBSCRIBE",
|
|
136
|
-
"symbols": ["MSFT"],
|
|
137
|
-
"types": ["PRICEDATA"],
|
|
138
|
-
"mimetype": "application/json",
|
|
139
|
-
"conflation": null,
|
|
140
|
-
"id": ID++
|
|
141
|
-
}
|
|
142
|
-
];
|
|
143
|
-
|
|
144
|
-
// Lager symbol lists with 200 symbols
|
|
145
|
-
var symbolLists = [
|
|
146
|
-
"A", "AA", "AAAU", "AACG", "AADR", "AAL", "AAMC", "AAME", "AAN", "AAOI", "AAP", "AAPL", "AAT", "AAU", "AAWW", "AAXJ", "AAXN", "AB", "ABB", "ABBV",
|
|
147
|
-
"ABC", "ABCB", "ABDC", "ABEO", "ABEV", "ABG", "ABIO", "ABM", "ABMD", "ABR", "ABT", "ABTX", "ABUS", "AC", "ACA", "ACAD", "ACAM", "ACB", "ACBI", "ACC",
|
|
148
|
-
"ACCO", "ACEL", "ACER", "ACES", "ACGL", "ACH", "ACHC", "ACHN", "ACHV", "ACIA", "ACIO", "ACIU", "ACIW", "ACLS", "ACM", "ACMR", "ACN", "ACNB", "ACOR", "ACP",
|
|
149
|
-
"ACRE", "ACRS", "ACRX", "ACSI", "ACST", "ACT", "ACTG", "ACTT", "ACTTU", "ACU", "ACV", "ACWF", "ACWI", "ACWV", "ACWX", "ACY", "ADAP", "ADBE", "ADC", "ADES",
|
|
150
|
-
"ADI", "ADIL", "ADM", "ADMA", "ADME", "ADMP", "ADMS", "ADNT", "ADP", "ADPT", "ADRA", "ADRD", "ADRE", "ADRO", "ADS", "ADSK", "ADSW", "ADT", "ADTN", "NIO",
|
|
151
|
-
"AMD", "CHK", "BAC", "EEM", "NK", "SDC", "MNK", "WFC", "MS", "F", "QD", "NOK", "SPY", "XLF", "MNI", "SIG", "SNAP", "FPAC", "GE", "VXX",
|
|
152
|
-
"T", "UBER", "FCEL", "GDX", "CETX", "TSLA", "MU", "XOP", "ITUP", "TEVA", "OGI", "IWM", "IAU", "CRON", "MRVL", "SWN", "JCP", "HYG", "TWTR", "TQQQ",
|
|
153
|
-
"FXI", "IEMG", "PINS", "SQQQ", "BBD", "MSFT", "CGC", "SPCE", "USO", "LK", "AMLP", "CMCSA", "PLUG", "HEXO", "PBR", "ECA", "BYND", "FCX", "EWZ", "DWT",
|
|
154
|
-
"QQQ", "CSCO", "RIG", "ZNGA", "NRZ", "VALE", "INTC", "ABEV", "BABA", "IAG", "AEMD", "DUST", "VWO", "ROKU", "UVXY", "BK", "AUY", "PFE", "ENDP", "CLVS",
|
|
155
|
-
"HTBX", "SAN", "MDR", "CTL", "TSM", "NUGT", "AMRN", "LQD", "RBZ", "USB", "IBIO", "SXTC", "APEX", "NLOK", "SIRI", "CSR", "ZYXI", "ZYNE", "ZYME", "ZVO"
|
|
156
|
-
];
|
|
157
|
-
|
|
158
|
-
// Data types that Streamer available to make subscription
|
|
159
|
-
var dataTypes = [
|
|
160
|
-
// D1
|
|
161
|
-
// Market data message returns:
|
|
162
|
-
// {Q, timestamp, symbol, locateCode, indicator, sharesPerSizeUnit, bidPrice, bidSize, bidExcode, bidCondition, askPrice, askSize, askExcode, askCondition}
|
|
163
|
-
"QUOTE",
|
|
164
|
-
// D2
|
|
165
|
-
// Market data message returns:
|
|
166
|
-
// {P,timestamp, symbol, locateCode, last, lastTradeSize, change, percentChange, tick, tradeCount, close, previousClose,
|
|
167
|
-
// open, high, annualHigh, low, annualLow, lastTradeTime, accumulatedPrice, accumulatedVolume, accumulatedTradeValue,
|
|
168
|
-
// twap, vwap, preMarketTradeTime, preMarketLast, preMarketVolume, preMarketChange, preMarketPercentChange, postMarketTradeTime,
|
|
169
|
-
// postMarketLast, postMarketVolume, postMarketChange, postMarketPercentChange, lastTradeExcode, currencyID}
|
|
170
|
-
"PRICEDATA",
|
|
171
|
-
// D3
|
|
172
|
-
// Market data message returns:
|
|
173
|
-
// {T, timestamp, symbol, locateCode, excode, sequenceNumber, matchID, price, size, tick, indicator, rangeIndicator, sellerID, buyerID, accumulatedVolume, vwap}
|
|
174
|
-
"TRADE",
|
|
175
|
-
// D4
|
|
176
|
-
// Market data message returns:
|
|
177
|
-
// {BO, timestamp, symbol, locateCode, excode, orderID, orderReference, marketMakerID, orderSide, lastUpdate, price, size, display, orderChangeType}
|
|
178
|
-
"ORDERBOOK",
|
|
179
|
-
// D7
|
|
180
|
-
// Market data message returns:
|
|
181
|
-
// {MMQ, timestamp, symbol, locateCode, bidPrice, bidSize, bidChange, askPrice, askSize, askChange, indicator, marketMakerID, sharesPerSizeUnit}
|
|
182
|
-
"MMQUOTE",
|
|
183
|
-
// D8
|
|
184
|
-
// Market data message returns:
|
|
185
|
-
// {I, timestamp, symbol, locateCode, last, lastTime, open, openTime, high, low, startTime, tradeValue, volume, vwap}
|
|
186
|
-
"INTERVAL",
|
|
187
|
-
// D9
|
|
188
|
-
// Market data message returns:
|
|
189
|
-
// {NHP, timestamp, symbol, locateCode, marketMakerID, buyValue, buyVolume, buyBlockTransactions, buyBlockValue, buyBlockVolume, sellValue, sellVolume,
|
|
190
|
-
// sellBlockTransactions, sellBlockValue, sellBlockVolume}
|
|
191
|
-
"NETHOUSEPOSITION",
|
|
192
|
-
// D13
|
|
193
|
-
// Market data message returns:
|
|
194
|
-
// {LS, timestamp, symbol, locateCode, last, change, percentChange, accumulatedVolume, tick, lastTradeExcode}
|
|
195
|
-
"LASTSALE",
|
|
196
|
-
// D14
|
|
197
|
-
// Market data message returns:
|
|
198
|
-
// {LULD, symbol, locateCode, effectiveTime, lowerLimit, upperLimit, bidNotExecutable, askNotExecutable}
|
|
199
|
-
"LIMITUPLIMITDOWN",
|
|
200
|
-
// D15
|
|
201
|
-
// Market data message returns:
|
|
202
|
-
// {IVG, lastCalculation, symbol, locateCode, delta, gamma, vega, rho, theta, midIV, midIVChange, bidIV, askIV, mark, intrinsicValue, extrinsicValue,
|
|
203
|
-
// previousMark, markChange, markChangePercent}
|
|
204
|
-
"IVGREEKS",
|
|
205
|
-
// D16
|
|
206
|
-
// Market data message returns:
|
|
207
|
-
// {IS, timestamp, symbol, locateCode, imbalanceType, referencePrice, size, side, pairedVolume, nearIndicativePrice, farIndicativePrice, priceVariation}
|
|
208
|
-
"IMBALANCESTATUS"
|
|
209
|
-
];
|
|
210
|
-
|
|
211
|
-
const headers = {
|
|
212
|
-
// This header is optional we could use
|
|
213
|
-
'X-Stream-Format': 'application/json'
|
|
214
|
-
};
|
|
215
|
-
|
|
216
|
-
/** We could use following auth method to make subscription with streaming data
|
|
217
|
-
* Sid
|
|
218
|
-
* Enterprise Token
|
|
219
|
-
* Wmid
|
|
220
|
-
*/
|
|
221
|
-
|
|
222
|
-
/** For the Sid User we need to use qmci.Streamer library to get the sid first, then use the sid for login Auth */
|
|
223
|
-
function getSid() {
|
|
224
|
-
Streamer.login({
|
|
225
|
-
host: 'https://app.quotemedia.com/auth',
|
|
226
|
-
credentials: {
|
|
227
|
-
wmid: "YourWebmasterID",
|
|
228
|
-
username: "YourUsername",
|
|
229
|
-
password: "YourPassword"
|
|
230
|
-
}
|
|
231
|
-
}, (err, sid) => {
|
|
232
|
-
if (err) {
|
|
233
|
-
console.error(err);
|
|
234
|
-
} else if (sid) {
|
|
235
|
-
SID = sid;
|
|
236
|
-
console.log("SID: ", SID);
|
|
237
|
-
}
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/** Sid User example we need to get the sid before to run this example */
|
|
242
|
-
function SidUserSubscription() {
|
|
243
|
-
if (SID == null) {
|
|
244
|
-
console.log("SID is invalid: ", SID);
|
|
245
|
-
return;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
if (stompClient == null || stompClient.ws.readyState === 3) {
|
|
249
|
-
stompClient = Stomp.client(url);
|
|
250
|
-
SidAuthMethod(SID, stompClient, headers);
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
/** Subscription Examples: Start */
|
|
254
|
-
/** To see the example result by uncomment the code */
|
|
255
|
-
const selectedExample = document.getElementById("sid_user_subscription_example").value;
|
|
256
|
-
|
|
257
|
-
if (selectedExample === "subscribe") {
|
|
258
|
-
subscribe(stompClient, headers);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
if (selectedExample === "subscribeMultiDataTypes") {
|
|
262
|
-
subscribeMultiDataTypes(stompClient, headers);
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
if (selectedExample === "subscribeMultiSymbolsMultiDataTypes") {
|
|
266
|
-
subscribeMultiSymbolsMultiDataTypes(stompClient, headers);
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
if (selectedExample === "subscribeMultiMessages") {
|
|
270
|
-
subscribeMultiMessages(stompClient, headers, msgArrSubList);
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
if (selectedExample === "subscribeLargerSymbolLists") {
|
|
274
|
-
subscribeLargerSymbolLists(stompClient, headers, symbolLists, dataTypes);
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
if (selectedExample === "subscribeExchange") {
|
|
278
|
-
subscribeExchange(stompClient, headers);
|
|
279
|
-
}
|
|
280
|
-
/** Subscription Examples: End */
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
function SidUserUnsubscribe() {
|
|
284
|
-
const selectedExample = document.getElementById("sid_user_subscription_example").value;
|
|
285
|
-
if (selectedExample === "subscribe") {
|
|
286
|
-
unsubscribe(stompClient, headers);
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
if (selectedExample === "subscribeMultiDataTypes") {
|
|
290
|
-
unsubscribeMultiDataTypes(stompClient, headers);
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
if (selectedExample === "subscribeMultiSymbolsMultiDataTypes") {
|
|
294
|
-
unsubscribeMultiSymbolsMultiDataTypes(stompClient, headers);
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
if (selectedExample === "subscribeMultiMessages") {
|
|
298
|
-
unsubscribeMultiMessages(stompClient, headers, msgArrUnsubList);
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
if (selectedExample === "subscribeLargerSymbolLists") {
|
|
302
|
-
unsubscribeLargerSymbolLists(stompClient, headers, symbolLists, dataTypes);
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
if (selectedExample === "subscribeExchange") {
|
|
306
|
-
unsubscribeExchange(stompClient, headers);
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
/** Enterprise User example */
|
|
311
|
-
function EnterpriseUserSubscription() {
|
|
312
|
-
// Set up the Enterprise token and WebmasterID
|
|
313
|
-
const enterpriseToken = 'YourEnterpriseToken';
|
|
314
|
-
const wmid = 'YourWebmasterID';
|
|
315
|
-
|
|
316
|
-
if (stompClient == null || stompClient.ws.readyState === 3) {
|
|
317
|
-
stompClient = Stomp.client(url);
|
|
318
|
-
EnterpriseAuthMethod(enterpriseToken, wmid, stompClient, headers);
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
/** Subscription Examples: Start */
|
|
322
|
-
/** To see the example result by uncomment the code */
|
|
323
|
-
const selectedExample = document.getElementById("enterprise_user_subscription_example").value;
|
|
324
|
-
|
|
325
|
-
if (selectedExample === "subscribe") {
|
|
326
|
-
subscribe(stompClient, headers);
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
if (selectedExample === "subscribeMultiDataTypes") {
|
|
330
|
-
subscribeMultiDataTypes(stompClient, headers);
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
if (selectedExample === "subscribeMultiSymbolsMultiDataTypes") {
|
|
334
|
-
subscribeMultiSymbolsMultiDataTypes(stompClient, headers);
|
|
335
|
-
}
|
|
336
|
-
/** Subscription Examples: End */
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
function EnterpriseUserUnsubscribe() {
|
|
340
|
-
const selectedExample = document.getElementById("enterprise_user_subscription_example").value;
|
|
341
|
-
if (selectedExample === "subscribe") {
|
|
342
|
-
unsubscribe(stompClient, headers);
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
if (selectedExample === "subscribeMultiDataTypes") {
|
|
346
|
-
unsubscribeMultiDataTypes(stompClient, headers);
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
if (selectedExample === "subscribeMultiSymbolsMultiDataTypes") {
|
|
350
|
-
unsubscribeMultiSymbolsMultiDataTypes(stompClient, headers);
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
/** Wmid User example */
|
|
355
|
-
function WmidUserSubscription() {
|
|
356
|
-
// Set up the Wmid
|
|
357
|
-
const wmid = 'YourWebmasterID';
|
|
358
|
-
|
|
359
|
-
if (stompClient == null || stompClient.ws.readyState === 3) {
|
|
360
|
-
stompClient = Stomp.client(url);
|
|
361
|
-
WmidAuthMethod(wmid, stompClient, headers);
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
/** Subscription Examples: Start */
|
|
365
|
-
/** To see the example result by uncomment the code */
|
|
366
|
-
const selectedExample = document.getElementById("wmid_user_subscription_example").value;
|
|
367
|
-
|
|
368
|
-
if (selectedExample === "subscribe") {
|
|
369
|
-
subscribe(stompClient, headers);
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
if (selectedExample === "subscribeMultiDataTypes") {
|
|
373
|
-
subscribeMultiDataTypes(stompClient, headers);
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
if (selectedExample === "subscribeMultiSymbolsMultiDataTypes") {
|
|
377
|
-
subscribeMultiSymbolsMultiDataTypes(stompClient, headers);
|
|
378
|
-
}
|
|
379
|
-
/** Subscription Examples: End */
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
function WmidUserUnsubscribe() {
|
|
383
|
-
const selectedExample = document.getElementById("wmid_user_subscription_example").value;
|
|
384
|
-
if (selectedExample === "subscribe") {
|
|
385
|
-
unsubscribe(stompClient, headers);
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
if (selectedExample === "subscribeMultiDataTypes") {
|
|
389
|
-
unsubscribeMultiDataTypes(stompClient, headers);
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
if (selectedExample === "subscribeMultiSymbolsMultiDataTypes") {
|
|
393
|
-
unsubscribeMultiSymbolsMultiDataTypes(stompClient, headers);
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
/** To build Sid Auth message */
|
|
398
|
-
function SidAuthMethod(authorization, stompClient, headers = {}) {
|
|
399
|
-
if (stompClient.ws.readyState === 0) {
|
|
400
|
-
authMessage = BuildAuthMessage("sid", authorization);
|
|
401
|
-
|
|
402
|
-
stompClient.connect({}, function(frame) {
|
|
403
|
-
stompClient.subscribe(STOMP_SUBSCRIBE_URL, function(responseMessage) {
|
|
404
|
-
responseMsgHandler(JSON.parse(responseMessage.body))
|
|
405
|
-
});
|
|
406
|
-
stompClient.send(STOMP_SEND_MESSAGE_URL, headers, JSON.stringify(authMessage));
|
|
407
|
-
});
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
/** To build Enterprise Auth message */
|
|
412
|
-
function EnterpriseAuthMethod(authorization, wmid, stompClient, headers = {}) {
|
|
413
|
-
if (stompClient.ws.readyState === 0) {
|
|
414
|
-
authMessage = BuildAuthMessage("enterprise", authorization, wmid);
|
|
415
|
-
|
|
416
|
-
stompClient.connect({}, function(frame) {
|
|
417
|
-
stompClient.subscribe(STOMP_SUBSCRIBE_URL, function(responseMessage) {
|
|
418
|
-
responseMsgHandler(JSON.parse(responseMessage.body))
|
|
419
|
-
});
|
|
420
|
-
stompClient.send(STOMP_SEND_MESSAGE_URL, headers, JSON.stringify(authMessage));
|
|
421
|
-
});
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
/** To build Wmid Auth message */
|
|
426
|
-
function WmidAuthMethod(authorization, stompClient, headers = {}) {
|
|
427
|
-
if (stompClient.ws.readyState === 0) {
|
|
428
|
-
authMessage = BuildAuthMessage("wmid", authorization);
|
|
429
|
-
|
|
430
|
-
stompClient.connect({}, function(frame) {
|
|
431
|
-
stompClient.subscribe(STOMP_SUBSCRIBE_URL, function(responseMessage) {
|
|
432
|
-
responseMsgHandler(JSON.parse(responseMessage.body))
|
|
433
|
-
});
|
|
434
|
-
stompClient.send(STOMP_SEND_MESSAGE_URL, headers, JSON.stringify(authMessage));
|
|
435
|
-
});
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
/**
|
|
440
|
-
*
|
|
441
|
-
* @param action {string}
|
|
442
|
-
* @param symbols {Array.<string>}
|
|
443
|
-
* @param types {Array.<string>}
|
|
444
|
-
* @param mimetype {string}
|
|
445
|
-
* @param conflation {int}
|
|
446
|
-
* @param id {int}
|
|
447
|
-
* @returns {boolean|{"@T": string, action, symbols, types, mimetype, conflation, id}}
|
|
448
|
-
*/
|
|
449
|
-
function buildMarketDataMsg(action, symbols, types, mimetype, conflation, id) {
|
|
450
|
-
if (maxEntitlementsPerSubscription <= 0 && maxEntitlementsPerSubscription < symbols.length) {
|
|
451
|
-
return false;
|
|
452
|
-
}
|
|
453
|
-
console.log("The sub/unsub symbols size is: ", symbols.length);
|
|
454
|
-
|
|
455
|
-
const msg = {
|
|
456
|
-
"@T": "C2",
|
|
457
|
-
"action": action,
|
|
458
|
-
"symbols": symbols,
|
|
459
|
-
"types": types,
|
|
460
|
-
"mimetype": mimetype,
|
|
461
|
-
"conflation": conflation,
|
|
462
|
-
"id": id
|
|
463
|
-
}
|
|
464
|
-
return msg;
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
/** Subscription with one symbol and one data type */
|
|
468
|
-
function subscribe(stompClient, headers = {}) {
|
|
469
|
-
if (stompClient.ws.readyState === 1) {
|
|
470
|
-
msg = buildMarketDataMsg("SUBSCRIBE", ["GOOG"], ["QUOTE"], "application/json", null, ID++)
|
|
471
|
-
if (msg != false) {
|
|
472
|
-
stompClient.send(STOMP_SEND_MESSAGE_URL, headers, JSON.stringify(msg));
|
|
473
|
-
}
|
|
474
|
-
} else {
|
|
475
|
-
setTimeout(subscribe, 1000, stompClient, headers);
|
|
476
|
-
}
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
function unsubscribe(stompClient, headers = {}) {
|
|
480
|
-
if (stompClient.ws.readyState === 1) {
|
|
481
|
-
msg = buildMarketDataMsg("UNSUBSCRIBE", ["GOOG"], ["QUOTE"], "application/json", null, ID++)
|
|
482
|
-
stompClient.send(STOMP_SEND_MESSAGE_URL, headers, JSON.stringify(msg));
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
/** Subscription with one symbol and multiple data types */
|
|
487
|
-
function subscribeMultiDataTypes(stompClient, headers = {}) {
|
|
488
|
-
if (stompClient.ws.readyState === 1) {
|
|
489
|
-
msg = buildMarketDataMsg("SUBSCRIBE", ["GOOG"], ["QUOTE", "TRADE"], "application/json", null, ID++)
|
|
490
|
-
stompClient.send(STOMP_SEND_MESSAGE_URL, headers, JSON.stringify(msg));
|
|
491
|
-
} else {
|
|
492
|
-
setTimeout(subscribeMultiDataTypes, 1000, stompClient, headers);
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
function unsubscribeMultiDataTypes(stompClient, headers = {}) {
|
|
497
|
-
if (stompClient.ws.readyState === 1) {
|
|
498
|
-
msg = buildMarketDataMsg("UNSUBSCRIBE", ["GOOG"], ["QUOTE", "TRADE"], "application/json", null, ID++)
|
|
499
|
-
stompClient.send(STOMP_SEND_MESSAGE_URL, headers, JSON.stringify(msg));
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
/** Subscription with multiple symbols and multiple data types */
|
|
504
|
-
function subscribeMultiSymbolsMultiDataTypes(stompClient, headers = {}) {
|
|
505
|
-
if (stompClient.ws.readyState === 1) {
|
|
506
|
-
msg = buildMarketDataMsg("SUBSCRIBE", ["GOOG", "AAPL"], ["QUOTE", "TRADE"], "application/json", null, ID++)
|
|
507
|
-
stompClient.send(STOMP_SEND_MESSAGE_URL, headers, JSON.stringify(msg));
|
|
508
|
-
} else {
|
|
509
|
-
setTimeout(subscribeMultiSymbolsMultiDataTypes, 1000, stompClient, headers);
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
function unsubscribeMultiSymbolsMultiDataTypes(stompClient, headers = {}) {
|
|
514
|
-
if (stompClient.ws.readyState === 1) {
|
|
515
|
-
msg = buildMarketDataMsg("UNSUBSCRIBE", ["GOOG", "AAPL"], ["QUOTE", "TRADE"], "application/json", null, ID++)
|
|
516
|
-
stompClient.send(STOMP_SEND_MESSAGE_URL, headers, JSON.stringify(msg));
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
/** Subscription to loop a lists contains multiple subscription request messages */
|
|
521
|
-
function subscribeMultiMessages(stompClient, headers = {}, msgArr) {
|
|
522
|
-
if (stompClient.ws.readyState === 1) {
|
|
523
|
-
for (let i = 0; i < msgArr.length; i++) {
|
|
524
|
-
stompClient.send(STOMP_SEND_MESSAGE_URL, headers, JSON.stringify(msgArr[i]));
|
|
525
|
-
}
|
|
526
|
-
} else {
|
|
527
|
-
setTimeout(subscribeMultiMessages, 1000, stompClient, headers, msgArr);
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
function unsubscribeMultiMessages(stompClient, headers = {}, msgArr) {
|
|
532
|
-
if (stompClient.ws.readyState === 1) {
|
|
533
|
-
for (let i = 0; i < msgArr.length; i++) {
|
|
534
|
-
stompClient.send(STOMP_SEND_MESSAGE_URL, headers, JSON.stringify(msgArr[i]));
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
/** Subscription with larger symbol(200 symbols) lists and multiple data types */
|
|
540
|
-
function subscribeLargerSymbolLists(stompClient, headers = {}, symbolLists, dataTypes) {
|
|
541
|
-
if (stompClient.ws.readyState === 1) {
|
|
542
|
-
msg = buildMarketDataMsg("SUBSCRIBE", symbolLists, dataTypes, "application/json", null, ID++)
|
|
543
|
-
if (msg != false) {
|
|
544
|
-
stompClient.send(STOMP_SEND_MESSAGE_URL, headers, JSON.stringify(msg));
|
|
545
|
-
}
|
|
546
|
-
} else {
|
|
547
|
-
setTimeout(subscribeLargerSymbolLists, 1000, stompClient, headers, symbolLists, dataTypes);
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
function unsubscribeLargerSymbolLists(stompClient, headers = {}, symbolLists, dataTypes) {
|
|
552
|
-
if (stompClient.ws.readyState === 1) {
|
|
553
|
-
msg = buildMarketDataMsg("UNSUBSCRIBE", symbolLists, dataTypes, "application/json", null, ID++)
|
|
554
|
-
stompClient.send(STOMP_SEND_MESSAGE_URL, headers, JSON.stringify(msg));
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
/**
|
|
559
|
-
*
|
|
560
|
-
* @param action {string}
|
|
561
|
-
* @param exchange {string}
|
|
562
|
-
* @param mimetype {string}
|
|
563
|
-
* @param conflation {int}
|
|
564
|
-
* @param id {int}
|
|
565
|
-
* @returns
|
|
566
|
-
*/
|
|
567
|
-
function buildExchangeMsg(action, exchange, mimetype, conflation, id) {
|
|
568
|
-
const msg = {
|
|
569
|
-
"@T": "C14",
|
|
570
|
-
"action": action,
|
|
571
|
-
"exchange": exchange,
|
|
572
|
-
"mimetype": mimetype,
|
|
573
|
-
"conflation": conflation,
|
|
574
|
-
"id": id
|
|
575
|
-
}
|
|
576
|
-
return msg;
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
/** Subscription for exchange */
|
|
580
|
-
function subscribeExchange(stompClient, headers = {}) {
|
|
581
|
-
if (stompClient.ws.readyState === 1) {
|
|
582
|
-
msg = buildExchangeMsg("SUBSCRIBE", "TSX", "application/json", null, ID++);
|
|
583
|
-
stompClient.send(STOMP_SEND_MESSAGE_URL, headers, JSON.stringify(msg));
|
|
584
|
-
} else {
|
|
585
|
-
setTimeout(subscribeExchange, 1000, stompClient, headers);
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
function unsubscribeExchange(stompClient, headers = {}) {
|
|
590
|
-
if (stompClient.ws.readyState === 1) {
|
|
591
|
-
msg = buildExchangeMsg("UNSUBSCRIBE", "TSX", "application/json", null, ID++);
|
|
592
|
-
stompClient.send(STOMP_SEND_MESSAGE_URL, headers, JSON.stringify(msg));
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
/** Disconnect the Stomp connection */
|
|
597
|
-
function disconnect() {
|
|
598
|
-
if (stompClient.ws.readyState === 1) {
|
|
599
|
-
stompClient.disconnect();
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
/** To listen and handle the message sent from Streaming server */
|
|
604
|
-
function responseMsgHandler(msg) {
|
|
605
|
-
// C5 is for connect response and here we are trying to get the max entitlements number,
|
|
606
|
-
// and this number is for maximum symbols allow for per subscription.
|
|
607
|
-
if (msg["@T"] === 'C5') {
|
|
608
|
-
maxEntitlementsPerSubscription = msg.maxEntitlementsPerSubscription;
|
|
609
|
-
console.log("The max ET number per subscription is: ", maxEntitlementsPerSubscription);
|
|
610
|
-
}
|
|
611
|
-
// C28 is for Flow Control message
|
|
612
|
-
// To control latency and in cases where client connections cannot keep up with the amount of streamed messages,
|
|
613
|
-
// there are mechanisms in place to limit negative effects from “slow” clients. These requirements MUST be
|
|
614
|
-
// implemented and adhered to on the client implementation, or else connections will be disconnected.
|
|
615
|
-
// When the client connection receives that message they must IMMEDIATELY respond back to the server with the
|
|
616
|
-
// exact same message, containing the same field and value.
|
|
617
|
-
else if (msg["@T"] === 'C28') {
|
|
618
|
-
if (stompClient.ws.readyState === 1) {
|
|
619
|
-
stompClient.send(STOMP_SEND_MESSAGE_URL, {}, JSON.stringify(msg));
|
|
620
|
-
}
|
|
621
|
-
}
|
|
622
|
-
// C3 is for subscribe response, it will return the status code and reason back to client,
|
|
623
|
-
// if the subscription is successfully server will return status code with 200
|
|
624
|
-
else if (msg["@T"] === 'C3') {
|
|
625
|
-
if (msg["code"] === 200) {
|
|
626
|
-
console.log("Subscription succeed!");
|
|
627
|
-
}
|
|
628
|
-
}
|
|
629
|
-
// C4 is for unsubscribe response, it will return the status code and reason back to client,
|
|
630
|
-
// if the unsubscription is successfully server will return status code with 200
|
|
631
|
-
else if (msg["@T"] === 'C4') {
|
|
632
|
-
if (msg["code"] === 200) {
|
|
633
|
-
console.log("Unsubscription succeed!");
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
// D1 is for Quote messages
|
|
637
|
-
else if (msg["@T"] === 'D1') {
|
|
638
|
-
const node = document.createElement("p").appendChild(document.createTextNode(JSON.stringify(msgfmt.fmt(msg))));
|
|
639
|
-
const brNode = document.createElement("br");
|
|
640
|
-
document.getElementById("msg_print").appendChild(node);
|
|
641
|
-
document.getElementById("msg_print").appendChild(brNode);
|
|
642
|
-
}
|
|
643
|
-
// D2 is for PriceData messages
|
|
644
|
-
else if (msg["@T"] === 'D2') {
|
|
645
|
-
const node = document.createElement("p").appendChild(document.createTextNode(JSON.stringify(msgfmt.fmt(msg))));
|
|
646
|
-
const brNode = document.createElement("br");
|
|
647
|
-
document.getElementById("msg_print").appendChild(node);
|
|
648
|
-
document.getElementById("msg_print").appendChild(brNode);
|
|
649
|
-
}
|
|
650
|
-
// D3 is for Trade messages
|
|
651
|
-
else if (msg["@T"] === 'D3') {
|
|
652
|
-
const node = document.createElement("p").appendChild(document.createTextNode(JSON.stringify(msgfmt.fmt(msg))));
|
|
653
|
-
const brNode = document.createElement("br");
|
|
654
|
-
document.getElementById("msg_print").appendChild(node);
|
|
655
|
-
document.getElementById("msg_print").appendChild(brNode);
|
|
656
|
-
}
|
|
657
|
-
// To catch other MarketData messages
|
|
658
|
-
else {
|
|
659
|
-
const node = document.createElement("p").appendChild(document.createTextNode(JSON.stringify(msgfmt.fmt(msg))));
|
|
660
|
-
const brNode = document.createElement("br");
|
|
661
|
-
document.getElementById("msg_print").appendChild(node);
|
|
662
|
-
document.getElementById("msg_print").appendChild(brNode);
|
|
663
|
-
}
|
|
664
|
-
}
|
|
665
|
-
|
|
666
|
-
/** To build the Auth Message, if using enterprise authenticationMethod,
|
|
667
|
-
* and we need to set the wmid otherwise we could default and set it to null */
|
|
668
|
-
function BuildAuthMessage(authenticationMethod, authorization, wmid = null, conflation = null, rejectExcessiveConnection = false) {
|
|
669
|
-
var authMessage = {
|
|
670
|
-
'@T': 'C27',
|
|
671
|
-
'authenticationMethod': authenticationMethod,
|
|
672
|
-
'authorization': authorization,
|
|
673
|
-
'wmid': wmid,
|
|
674
|
-
'conflation': conflation,
|
|
675
|
-
'rejectExcessiveConnection': rejectExcessiveConnection
|
|
676
|
-
};
|
|
677
|
-
return authMessage;
|
|
678
|
-
}
|
|
679
|
-
</script>
|
|
680
|
-
</body>
|
|
681
|
-
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<script src="qmci-streamer-2.43.0.min.js"></script>
|
|
6
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/stomp.js/2.3.3/stomp.min.js"></script>
|
|
7
|
+
</head>
|
|
8
|
+
|
|
9
|
+
<body>
|
|
10
|
+
|
|
11
|
+
<span>Subscription Examples:</span></br>
|
|
12
|
+
|
|
13
|
+
<span>
|
|
14
|
+
<label>Sid Subscription: </label>
|
|
15
|
+
<select id="sid_user_subscription_example">
|
|
16
|
+
<option value="subscribe">subscribe</option>
|
|
17
|
+
<option value="subscribeMultiDataTypes">subscribeMultiDataTypes</option>
|
|
18
|
+
<option value="subscribeMultiSymbolsMultiDataTypes">subscribeMultiSymbolsMultiDataTypes</option>
|
|
19
|
+
<option value="subscribeMultiMessages">subscribeMultiMessages</option>
|
|
20
|
+
<option value="subscribeLargerSymbolLists">subscribeLargerSymbolLists</option>
|
|
21
|
+
<option value="subscribeExchange">subscribeExchange</option>
|
|
22
|
+
</select>
|
|
23
|
+
</span>
|
|
24
|
+
<input id="sid_user_get_sid" type="button" value="Get SID">
|
|
25
|
+
<input id="sid_user_subscribe" type="button" value="Subscribe">
|
|
26
|
+
<input id="sid_user_unsubscribe" type="button" value="Unsubscribe"></br>
|
|
27
|
+
|
|
28
|
+
<span>
|
|
29
|
+
<label>Enterprise Subscription: </label>
|
|
30
|
+
<select id="enterprise_user_subscription_example">
|
|
31
|
+
<option value="subscribe">subscribe</option>
|
|
32
|
+
<option value="subscribeMultiDataTypes">subscribeMultiDataTypes</option>
|
|
33
|
+
<option value="subscribeMultiSymbolsMultiDataTypes">subscribeMultiSymbolsMultiDataTypes</option>
|
|
34
|
+
</select>
|
|
35
|
+
</span>
|
|
36
|
+
<input id="enterprise_user_subscribe" type="button" value="Subscribe">
|
|
37
|
+
<input id="enterprise_user_unsubscribe" type="button" value="Unsubscribe"></br>
|
|
38
|
+
|
|
39
|
+
<span>
|
|
40
|
+
<label>Wmid Subscription: </label>
|
|
41
|
+
<select id="wmid_user_subscription_example">
|
|
42
|
+
<option value="subscribe">subscribe</option>
|
|
43
|
+
<option value="subscribeMultiDataTypes">subscribeMultiDataTypes</option>
|
|
44
|
+
<option value="subscribeMultiSymbolsMultiDataTypes">subscribeMultiSymbolsMultiDataTypes</option>
|
|
45
|
+
</select>
|
|
46
|
+
</span>
|
|
47
|
+
<input id="wmid_user_subscribe" type="button" value="Subscribe">
|
|
48
|
+
<input id="wmid_user_unsubscribe" type="button" value="Unsubscribe"></br>
|
|
49
|
+
|
|
50
|
+
<input id="stomp_connection_close" type="button" value="Connection Close"></br>
|
|
51
|
+
|
|
52
|
+
<div id="msg_print"></div>
|
|
53
|
+
|
|
54
|
+
<script type="text/javascript">
|
|
55
|
+
// Set up the event Listeners SidUserUnsubscribe
|
|
56
|
+
document.getElementById("sid_user_get_sid").addEventListener("click", getSid);
|
|
57
|
+
document.getElementById("sid_user_subscribe").addEventListener("click", SidUserSubscription);
|
|
58
|
+
document.getElementById("sid_user_unsubscribe").addEventListener("click", SidUserUnsubscribe);
|
|
59
|
+
document.getElementById("enterprise_user_subscribe").addEventListener("click", EnterpriseUserSubscription);
|
|
60
|
+
document.getElementById("enterprise_user_unsubscribe").addEventListener("click", EnterpriseUserUnsubscribe);
|
|
61
|
+
document.getElementById("wmid_user_subscribe").addEventListener("click", WmidUserSubscription);
|
|
62
|
+
document.getElementById("wmid_user_unsubscribe").addEventListener("click", WmidUserUnsubscribe);
|
|
63
|
+
document.getElementById("stomp_connection_close").addEventListener("click", disconnect);
|
|
64
|
+
|
|
65
|
+
// We need to use qmci.streamer to get the sid and use for Sid User Method
|
|
66
|
+
var Streamer = qmci.Streamer;
|
|
67
|
+
// Set up the message formatter, and it included in Streamer official JavaScript SDK library
|
|
68
|
+
var msgfmt = new qmci.Streamer.formatting.Formatter();
|
|
69
|
+
// This is URL use to connect Stomp endpoint
|
|
70
|
+
const url = "ws://app.quotemedia.com/cache/stream/connect";
|
|
71
|
+
// Stomp subscribe url route
|
|
72
|
+
const STOMP_SUBSCRIBE_URL = "/user/queue/messages";
|
|
73
|
+
// Stomp message send url route
|
|
74
|
+
const STOMP_SEND_MESSAGE_URL = "/stream/message";
|
|
75
|
+
// Sid for the end user Auth
|
|
76
|
+
var SID = null;
|
|
77
|
+
// Set up the Stomp client
|
|
78
|
+
var stompClient = null;
|
|
79
|
+
// To record the max allow to entitle for this user id
|
|
80
|
+
var maxEntitlementsPerSubscription = 0;
|
|
81
|
+
// To track the commands/control messages ordering
|
|
82
|
+
var ID = 1;
|
|
83
|
+
|
|
84
|
+
// Subscription msg lists use for multiple subscription request
|
|
85
|
+
var msgArrSubList = [{
|
|
86
|
+
"@T": "C2",
|
|
87
|
+
"action": "SUBSCRIBE",
|
|
88
|
+
"symbols": ["GOOG"],
|
|
89
|
+
"types": ["QUOTE"],
|
|
90
|
+
"mimetype": "application/json",
|
|
91
|
+
"conflation": null,
|
|
92
|
+
"id": ID++
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"@T": "C2",
|
|
96
|
+
"action": "SUBSCRIBE",
|
|
97
|
+
"symbols": ["AAPL"],
|
|
98
|
+
"types": ["TRADE"],
|
|
99
|
+
"mimetype": "application/json",
|
|
100
|
+
"conflation": null,
|
|
101
|
+
"id": ID++
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"@T": "C2",
|
|
105
|
+
"action": "SUBSCRIBE",
|
|
106
|
+
"symbols": ["MSFT"],
|
|
107
|
+
"types": ["PRICEDATA"],
|
|
108
|
+
"mimetype": "application/json",
|
|
109
|
+
"conflation": null,
|
|
110
|
+
"id": ID++
|
|
111
|
+
}
|
|
112
|
+
];
|
|
113
|
+
|
|
114
|
+
// Unsubscription msg lists use for multiple subscription request
|
|
115
|
+
var msgArrUnsubList = [{
|
|
116
|
+
"@T": "C2",
|
|
117
|
+
"action": "UNSUBSCRIBE",
|
|
118
|
+
"symbols": ["GOOG"],
|
|
119
|
+
"types": ["QUOTE"],
|
|
120
|
+
"mimetype": "application/json",
|
|
121
|
+
"conflation": null,
|
|
122
|
+
"id": ID++
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"@T": "C2",
|
|
126
|
+
"action": "UNSUBSCRIBE",
|
|
127
|
+
"symbols": ["AAPL"],
|
|
128
|
+
"types": ["TRADE"],
|
|
129
|
+
"mimetype": "application/json",
|
|
130
|
+
"conflation": null,
|
|
131
|
+
"id": ID++
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
"@T": "C2",
|
|
135
|
+
"action": "UNSUBSCRIBE",
|
|
136
|
+
"symbols": ["MSFT"],
|
|
137
|
+
"types": ["PRICEDATA"],
|
|
138
|
+
"mimetype": "application/json",
|
|
139
|
+
"conflation": null,
|
|
140
|
+
"id": ID++
|
|
141
|
+
}
|
|
142
|
+
];
|
|
143
|
+
|
|
144
|
+
// Lager symbol lists with 200 symbols
|
|
145
|
+
var symbolLists = [
|
|
146
|
+
"A", "AA", "AAAU", "AACG", "AADR", "AAL", "AAMC", "AAME", "AAN", "AAOI", "AAP", "AAPL", "AAT", "AAU", "AAWW", "AAXJ", "AAXN", "AB", "ABB", "ABBV",
|
|
147
|
+
"ABC", "ABCB", "ABDC", "ABEO", "ABEV", "ABG", "ABIO", "ABM", "ABMD", "ABR", "ABT", "ABTX", "ABUS", "AC", "ACA", "ACAD", "ACAM", "ACB", "ACBI", "ACC",
|
|
148
|
+
"ACCO", "ACEL", "ACER", "ACES", "ACGL", "ACH", "ACHC", "ACHN", "ACHV", "ACIA", "ACIO", "ACIU", "ACIW", "ACLS", "ACM", "ACMR", "ACN", "ACNB", "ACOR", "ACP",
|
|
149
|
+
"ACRE", "ACRS", "ACRX", "ACSI", "ACST", "ACT", "ACTG", "ACTT", "ACTTU", "ACU", "ACV", "ACWF", "ACWI", "ACWV", "ACWX", "ACY", "ADAP", "ADBE", "ADC", "ADES",
|
|
150
|
+
"ADI", "ADIL", "ADM", "ADMA", "ADME", "ADMP", "ADMS", "ADNT", "ADP", "ADPT", "ADRA", "ADRD", "ADRE", "ADRO", "ADS", "ADSK", "ADSW", "ADT", "ADTN", "NIO",
|
|
151
|
+
"AMD", "CHK", "BAC", "EEM", "NK", "SDC", "MNK", "WFC", "MS", "F", "QD", "NOK", "SPY", "XLF", "MNI", "SIG", "SNAP", "FPAC", "GE", "VXX",
|
|
152
|
+
"T", "UBER", "FCEL", "GDX", "CETX", "TSLA", "MU", "XOP", "ITUP", "TEVA", "OGI", "IWM", "IAU", "CRON", "MRVL", "SWN", "JCP", "HYG", "TWTR", "TQQQ",
|
|
153
|
+
"FXI", "IEMG", "PINS", "SQQQ", "BBD", "MSFT", "CGC", "SPCE", "USO", "LK", "AMLP", "CMCSA", "PLUG", "HEXO", "PBR", "ECA", "BYND", "FCX", "EWZ", "DWT",
|
|
154
|
+
"QQQ", "CSCO", "RIG", "ZNGA", "NRZ", "VALE", "INTC", "ABEV", "BABA", "IAG", "AEMD", "DUST", "VWO", "ROKU", "UVXY", "BK", "AUY", "PFE", "ENDP", "CLVS",
|
|
155
|
+
"HTBX", "SAN", "MDR", "CTL", "TSM", "NUGT", "AMRN", "LQD", "RBZ", "USB", "IBIO", "SXTC", "APEX", "NLOK", "SIRI", "CSR", "ZYXI", "ZYNE", "ZYME", "ZVO"
|
|
156
|
+
];
|
|
157
|
+
|
|
158
|
+
// Data types that Streamer available to make subscription
|
|
159
|
+
var dataTypes = [
|
|
160
|
+
// D1
|
|
161
|
+
// Market data message returns:
|
|
162
|
+
// {Q, timestamp, symbol, locateCode, indicator, sharesPerSizeUnit, bidPrice, bidSize, bidExcode, bidCondition, askPrice, askSize, askExcode, askCondition}
|
|
163
|
+
"QUOTE",
|
|
164
|
+
// D2
|
|
165
|
+
// Market data message returns:
|
|
166
|
+
// {P,timestamp, symbol, locateCode, last, lastTradeSize, change, percentChange, tick, tradeCount, close, previousClose,
|
|
167
|
+
// open, high, annualHigh, low, annualLow, lastTradeTime, accumulatedPrice, accumulatedVolume, accumulatedTradeValue,
|
|
168
|
+
// twap, vwap, preMarketTradeTime, preMarketLast, preMarketVolume, preMarketChange, preMarketPercentChange, postMarketTradeTime,
|
|
169
|
+
// postMarketLast, postMarketVolume, postMarketChange, postMarketPercentChange, lastTradeExcode, currencyID}
|
|
170
|
+
"PRICEDATA",
|
|
171
|
+
// D3
|
|
172
|
+
// Market data message returns:
|
|
173
|
+
// {T, timestamp, symbol, locateCode, excode, sequenceNumber, matchID, price, size, tick, indicator, rangeIndicator, sellerID, buyerID, accumulatedVolume, vwap}
|
|
174
|
+
"TRADE",
|
|
175
|
+
// D4
|
|
176
|
+
// Market data message returns:
|
|
177
|
+
// {BO, timestamp, symbol, locateCode, excode, orderID, orderReference, marketMakerID, orderSide, lastUpdate, price, size, display, orderChangeType}
|
|
178
|
+
"ORDERBOOK",
|
|
179
|
+
// D7
|
|
180
|
+
// Market data message returns:
|
|
181
|
+
// {MMQ, timestamp, symbol, locateCode, bidPrice, bidSize, bidChange, askPrice, askSize, askChange, indicator, marketMakerID, sharesPerSizeUnit}
|
|
182
|
+
"MMQUOTE",
|
|
183
|
+
// D8
|
|
184
|
+
// Market data message returns:
|
|
185
|
+
// {I, timestamp, symbol, locateCode, last, lastTime, open, openTime, high, low, startTime, tradeValue, volume, vwap}
|
|
186
|
+
"INTERVAL",
|
|
187
|
+
// D9
|
|
188
|
+
// Market data message returns:
|
|
189
|
+
// {NHP, timestamp, symbol, locateCode, marketMakerID, buyValue, buyVolume, buyBlockTransactions, buyBlockValue, buyBlockVolume, sellValue, sellVolume,
|
|
190
|
+
// sellBlockTransactions, sellBlockValue, sellBlockVolume}
|
|
191
|
+
"NETHOUSEPOSITION",
|
|
192
|
+
// D13
|
|
193
|
+
// Market data message returns:
|
|
194
|
+
// {LS, timestamp, symbol, locateCode, last, change, percentChange, accumulatedVolume, tick, lastTradeExcode}
|
|
195
|
+
"LASTSALE",
|
|
196
|
+
// D14
|
|
197
|
+
// Market data message returns:
|
|
198
|
+
// {LULD, symbol, locateCode, effectiveTime, lowerLimit, upperLimit, bidNotExecutable, askNotExecutable}
|
|
199
|
+
"LIMITUPLIMITDOWN",
|
|
200
|
+
// D15
|
|
201
|
+
// Market data message returns:
|
|
202
|
+
// {IVG, lastCalculation, symbol, locateCode, delta, gamma, vega, rho, theta, midIV, midIVChange, bidIV, askIV, mark, intrinsicValue, extrinsicValue,
|
|
203
|
+
// previousMark, markChange, markChangePercent}
|
|
204
|
+
"IVGREEKS",
|
|
205
|
+
// D16
|
|
206
|
+
// Market data message returns:
|
|
207
|
+
// {IS, timestamp, symbol, locateCode, imbalanceType, referencePrice, size, side, pairedVolume, nearIndicativePrice, farIndicativePrice, priceVariation}
|
|
208
|
+
"IMBALANCESTATUS"
|
|
209
|
+
];
|
|
210
|
+
|
|
211
|
+
const headers = {
|
|
212
|
+
// This header is optional we could use
|
|
213
|
+
'X-Stream-Format': 'application/json'
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
/** We could use following auth method to make subscription with streaming data
|
|
217
|
+
* Sid
|
|
218
|
+
* Enterprise Token
|
|
219
|
+
* Wmid
|
|
220
|
+
*/
|
|
221
|
+
|
|
222
|
+
/** For the Sid User we need to use qmci.Streamer library to get the sid first, then use the sid for login Auth */
|
|
223
|
+
function getSid() {
|
|
224
|
+
Streamer.login({
|
|
225
|
+
host: 'https://app.quotemedia.com/auth',
|
|
226
|
+
credentials: {
|
|
227
|
+
wmid: "YourWebmasterID",
|
|
228
|
+
username: "YourUsername",
|
|
229
|
+
password: "YourPassword"
|
|
230
|
+
}
|
|
231
|
+
}, (err, sid) => {
|
|
232
|
+
if (err) {
|
|
233
|
+
console.error(err);
|
|
234
|
+
} else if (sid) {
|
|
235
|
+
SID = sid;
|
|
236
|
+
console.log("SID: ", SID);
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/** Sid User example we need to get the sid before to run this example */
|
|
242
|
+
function SidUserSubscription() {
|
|
243
|
+
if (SID == null) {
|
|
244
|
+
console.log("SID is invalid: ", SID);
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
if (stompClient == null || stompClient.ws.readyState === 3) {
|
|
249
|
+
stompClient = Stomp.client(url);
|
|
250
|
+
SidAuthMethod(SID, stompClient, headers);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/** Subscription Examples: Start */
|
|
254
|
+
/** To see the example result by uncomment the code */
|
|
255
|
+
const selectedExample = document.getElementById("sid_user_subscription_example").value;
|
|
256
|
+
|
|
257
|
+
if (selectedExample === "subscribe") {
|
|
258
|
+
subscribe(stompClient, headers);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
if (selectedExample === "subscribeMultiDataTypes") {
|
|
262
|
+
subscribeMultiDataTypes(stompClient, headers);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (selectedExample === "subscribeMultiSymbolsMultiDataTypes") {
|
|
266
|
+
subscribeMultiSymbolsMultiDataTypes(stompClient, headers);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if (selectedExample === "subscribeMultiMessages") {
|
|
270
|
+
subscribeMultiMessages(stompClient, headers, msgArrSubList);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if (selectedExample === "subscribeLargerSymbolLists") {
|
|
274
|
+
subscribeLargerSymbolLists(stompClient, headers, symbolLists, dataTypes);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (selectedExample === "subscribeExchange") {
|
|
278
|
+
subscribeExchange(stompClient, headers);
|
|
279
|
+
}
|
|
280
|
+
/** Subscription Examples: End */
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function SidUserUnsubscribe() {
|
|
284
|
+
const selectedExample = document.getElementById("sid_user_subscription_example").value;
|
|
285
|
+
if (selectedExample === "subscribe") {
|
|
286
|
+
unsubscribe(stompClient, headers);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (selectedExample === "subscribeMultiDataTypes") {
|
|
290
|
+
unsubscribeMultiDataTypes(stompClient, headers);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if (selectedExample === "subscribeMultiSymbolsMultiDataTypes") {
|
|
294
|
+
unsubscribeMultiSymbolsMultiDataTypes(stompClient, headers);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (selectedExample === "subscribeMultiMessages") {
|
|
298
|
+
unsubscribeMultiMessages(stompClient, headers, msgArrUnsubList);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
if (selectedExample === "subscribeLargerSymbolLists") {
|
|
302
|
+
unsubscribeLargerSymbolLists(stompClient, headers, symbolLists, dataTypes);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
if (selectedExample === "subscribeExchange") {
|
|
306
|
+
unsubscribeExchange(stompClient, headers);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/** Enterprise User example */
|
|
311
|
+
function EnterpriseUserSubscription() {
|
|
312
|
+
// Set up the Enterprise token and WebmasterID
|
|
313
|
+
const enterpriseToken = 'YourEnterpriseToken';
|
|
314
|
+
const wmid = 'YourWebmasterID';
|
|
315
|
+
|
|
316
|
+
if (stompClient == null || stompClient.ws.readyState === 3) {
|
|
317
|
+
stompClient = Stomp.client(url);
|
|
318
|
+
EnterpriseAuthMethod(enterpriseToken, wmid, stompClient, headers);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/** Subscription Examples: Start */
|
|
322
|
+
/** To see the example result by uncomment the code */
|
|
323
|
+
const selectedExample = document.getElementById("enterprise_user_subscription_example").value;
|
|
324
|
+
|
|
325
|
+
if (selectedExample === "subscribe") {
|
|
326
|
+
subscribe(stompClient, headers);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
if (selectedExample === "subscribeMultiDataTypes") {
|
|
330
|
+
subscribeMultiDataTypes(stompClient, headers);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
if (selectedExample === "subscribeMultiSymbolsMultiDataTypes") {
|
|
334
|
+
subscribeMultiSymbolsMultiDataTypes(stompClient, headers);
|
|
335
|
+
}
|
|
336
|
+
/** Subscription Examples: End */
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function EnterpriseUserUnsubscribe() {
|
|
340
|
+
const selectedExample = document.getElementById("enterprise_user_subscription_example").value;
|
|
341
|
+
if (selectedExample === "subscribe") {
|
|
342
|
+
unsubscribe(stompClient, headers);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
if (selectedExample === "subscribeMultiDataTypes") {
|
|
346
|
+
unsubscribeMultiDataTypes(stompClient, headers);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
if (selectedExample === "subscribeMultiSymbolsMultiDataTypes") {
|
|
350
|
+
unsubscribeMultiSymbolsMultiDataTypes(stompClient, headers);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/** Wmid User example */
|
|
355
|
+
function WmidUserSubscription() {
|
|
356
|
+
// Set up the Wmid
|
|
357
|
+
const wmid = 'YourWebmasterID';
|
|
358
|
+
|
|
359
|
+
if (stompClient == null || stompClient.ws.readyState === 3) {
|
|
360
|
+
stompClient = Stomp.client(url);
|
|
361
|
+
WmidAuthMethod(wmid, stompClient, headers);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/** Subscription Examples: Start */
|
|
365
|
+
/** To see the example result by uncomment the code */
|
|
366
|
+
const selectedExample = document.getElementById("wmid_user_subscription_example").value;
|
|
367
|
+
|
|
368
|
+
if (selectedExample === "subscribe") {
|
|
369
|
+
subscribe(stompClient, headers);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
if (selectedExample === "subscribeMultiDataTypes") {
|
|
373
|
+
subscribeMultiDataTypes(stompClient, headers);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
if (selectedExample === "subscribeMultiSymbolsMultiDataTypes") {
|
|
377
|
+
subscribeMultiSymbolsMultiDataTypes(stompClient, headers);
|
|
378
|
+
}
|
|
379
|
+
/** Subscription Examples: End */
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
function WmidUserUnsubscribe() {
|
|
383
|
+
const selectedExample = document.getElementById("wmid_user_subscription_example").value;
|
|
384
|
+
if (selectedExample === "subscribe") {
|
|
385
|
+
unsubscribe(stompClient, headers);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
if (selectedExample === "subscribeMultiDataTypes") {
|
|
389
|
+
unsubscribeMultiDataTypes(stompClient, headers);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
if (selectedExample === "subscribeMultiSymbolsMultiDataTypes") {
|
|
393
|
+
unsubscribeMultiSymbolsMultiDataTypes(stompClient, headers);
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/** To build Sid Auth message */
|
|
398
|
+
function SidAuthMethod(authorization, stompClient, headers = {}) {
|
|
399
|
+
if (stompClient.ws.readyState === 0) {
|
|
400
|
+
authMessage = BuildAuthMessage("sid", authorization);
|
|
401
|
+
|
|
402
|
+
stompClient.connect({}, function(frame) {
|
|
403
|
+
stompClient.subscribe(STOMP_SUBSCRIBE_URL, function(responseMessage) {
|
|
404
|
+
responseMsgHandler(JSON.parse(responseMessage.body))
|
|
405
|
+
});
|
|
406
|
+
stompClient.send(STOMP_SEND_MESSAGE_URL, headers, JSON.stringify(authMessage));
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/** To build Enterprise Auth message */
|
|
412
|
+
function EnterpriseAuthMethod(authorization, wmid, stompClient, headers = {}) {
|
|
413
|
+
if (stompClient.ws.readyState === 0) {
|
|
414
|
+
authMessage = BuildAuthMessage("enterprise", authorization, wmid);
|
|
415
|
+
|
|
416
|
+
stompClient.connect({}, function(frame) {
|
|
417
|
+
stompClient.subscribe(STOMP_SUBSCRIBE_URL, function(responseMessage) {
|
|
418
|
+
responseMsgHandler(JSON.parse(responseMessage.body))
|
|
419
|
+
});
|
|
420
|
+
stompClient.send(STOMP_SEND_MESSAGE_URL, headers, JSON.stringify(authMessage));
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/** To build Wmid Auth message */
|
|
426
|
+
function WmidAuthMethod(authorization, stompClient, headers = {}) {
|
|
427
|
+
if (stompClient.ws.readyState === 0) {
|
|
428
|
+
authMessage = BuildAuthMessage("wmid", authorization);
|
|
429
|
+
|
|
430
|
+
stompClient.connect({}, function(frame) {
|
|
431
|
+
stompClient.subscribe(STOMP_SUBSCRIBE_URL, function(responseMessage) {
|
|
432
|
+
responseMsgHandler(JSON.parse(responseMessage.body))
|
|
433
|
+
});
|
|
434
|
+
stompClient.send(STOMP_SEND_MESSAGE_URL, headers, JSON.stringify(authMessage));
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
*
|
|
441
|
+
* @param action {string}
|
|
442
|
+
* @param symbols {Array.<string>}
|
|
443
|
+
* @param types {Array.<string>}
|
|
444
|
+
* @param mimetype {string}
|
|
445
|
+
* @param conflation {int}
|
|
446
|
+
* @param id {int}
|
|
447
|
+
* @returns {boolean|{"@T": string, action, symbols, types, mimetype, conflation, id}}
|
|
448
|
+
*/
|
|
449
|
+
function buildMarketDataMsg(action, symbols, types, mimetype, conflation, id) {
|
|
450
|
+
if (maxEntitlementsPerSubscription <= 0 && maxEntitlementsPerSubscription < symbols.length) {
|
|
451
|
+
return false;
|
|
452
|
+
}
|
|
453
|
+
console.log("The sub/unsub symbols size is: ", symbols.length);
|
|
454
|
+
|
|
455
|
+
const msg = {
|
|
456
|
+
"@T": "C2",
|
|
457
|
+
"action": action,
|
|
458
|
+
"symbols": symbols,
|
|
459
|
+
"types": types,
|
|
460
|
+
"mimetype": mimetype,
|
|
461
|
+
"conflation": conflation,
|
|
462
|
+
"id": id
|
|
463
|
+
}
|
|
464
|
+
return msg;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/** Subscription with one symbol and one data type */
|
|
468
|
+
function subscribe(stompClient, headers = {}) {
|
|
469
|
+
if (stompClient.ws.readyState === 1) {
|
|
470
|
+
msg = buildMarketDataMsg("SUBSCRIBE", ["GOOG"], ["QUOTE"], "application/json", null, ID++)
|
|
471
|
+
if (msg != false) {
|
|
472
|
+
stompClient.send(STOMP_SEND_MESSAGE_URL, headers, JSON.stringify(msg));
|
|
473
|
+
}
|
|
474
|
+
} else {
|
|
475
|
+
setTimeout(subscribe, 1000, stompClient, headers);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
function unsubscribe(stompClient, headers = {}) {
|
|
480
|
+
if (stompClient.ws.readyState === 1) {
|
|
481
|
+
msg = buildMarketDataMsg("UNSUBSCRIBE", ["GOOG"], ["QUOTE"], "application/json", null, ID++)
|
|
482
|
+
stompClient.send(STOMP_SEND_MESSAGE_URL, headers, JSON.stringify(msg));
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/** Subscription with one symbol and multiple data types */
|
|
487
|
+
function subscribeMultiDataTypes(stompClient, headers = {}) {
|
|
488
|
+
if (stompClient.ws.readyState === 1) {
|
|
489
|
+
msg = buildMarketDataMsg("SUBSCRIBE", ["GOOG"], ["QUOTE", "TRADE"], "application/json", null, ID++)
|
|
490
|
+
stompClient.send(STOMP_SEND_MESSAGE_URL, headers, JSON.stringify(msg));
|
|
491
|
+
} else {
|
|
492
|
+
setTimeout(subscribeMultiDataTypes, 1000, stompClient, headers);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
function unsubscribeMultiDataTypes(stompClient, headers = {}) {
|
|
497
|
+
if (stompClient.ws.readyState === 1) {
|
|
498
|
+
msg = buildMarketDataMsg("UNSUBSCRIBE", ["GOOG"], ["QUOTE", "TRADE"], "application/json", null, ID++)
|
|
499
|
+
stompClient.send(STOMP_SEND_MESSAGE_URL, headers, JSON.stringify(msg));
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/** Subscription with multiple symbols and multiple data types */
|
|
504
|
+
function subscribeMultiSymbolsMultiDataTypes(stompClient, headers = {}) {
|
|
505
|
+
if (stompClient.ws.readyState === 1) {
|
|
506
|
+
msg = buildMarketDataMsg("SUBSCRIBE", ["GOOG", "AAPL"], ["QUOTE", "TRADE"], "application/json", null, ID++)
|
|
507
|
+
stompClient.send(STOMP_SEND_MESSAGE_URL, headers, JSON.stringify(msg));
|
|
508
|
+
} else {
|
|
509
|
+
setTimeout(subscribeMultiSymbolsMultiDataTypes, 1000, stompClient, headers);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
function unsubscribeMultiSymbolsMultiDataTypes(stompClient, headers = {}) {
|
|
514
|
+
if (stompClient.ws.readyState === 1) {
|
|
515
|
+
msg = buildMarketDataMsg("UNSUBSCRIBE", ["GOOG", "AAPL"], ["QUOTE", "TRADE"], "application/json", null, ID++)
|
|
516
|
+
stompClient.send(STOMP_SEND_MESSAGE_URL, headers, JSON.stringify(msg));
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
/** Subscription to loop a lists contains multiple subscription request messages */
|
|
521
|
+
function subscribeMultiMessages(stompClient, headers = {}, msgArr) {
|
|
522
|
+
if (stompClient.ws.readyState === 1) {
|
|
523
|
+
for (let i = 0; i < msgArr.length; i++) {
|
|
524
|
+
stompClient.send(STOMP_SEND_MESSAGE_URL, headers, JSON.stringify(msgArr[i]));
|
|
525
|
+
}
|
|
526
|
+
} else {
|
|
527
|
+
setTimeout(subscribeMultiMessages, 1000, stompClient, headers, msgArr);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
function unsubscribeMultiMessages(stompClient, headers = {}, msgArr) {
|
|
532
|
+
if (stompClient.ws.readyState === 1) {
|
|
533
|
+
for (let i = 0; i < msgArr.length; i++) {
|
|
534
|
+
stompClient.send(STOMP_SEND_MESSAGE_URL, headers, JSON.stringify(msgArr[i]));
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
/** Subscription with larger symbol(200 symbols) lists and multiple data types */
|
|
540
|
+
function subscribeLargerSymbolLists(stompClient, headers = {}, symbolLists, dataTypes) {
|
|
541
|
+
if (stompClient.ws.readyState === 1) {
|
|
542
|
+
msg = buildMarketDataMsg("SUBSCRIBE", symbolLists, dataTypes, "application/json", null, ID++)
|
|
543
|
+
if (msg != false) {
|
|
544
|
+
stompClient.send(STOMP_SEND_MESSAGE_URL, headers, JSON.stringify(msg));
|
|
545
|
+
}
|
|
546
|
+
} else {
|
|
547
|
+
setTimeout(subscribeLargerSymbolLists, 1000, stompClient, headers, symbolLists, dataTypes);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
function unsubscribeLargerSymbolLists(stompClient, headers = {}, symbolLists, dataTypes) {
|
|
552
|
+
if (stompClient.ws.readyState === 1) {
|
|
553
|
+
msg = buildMarketDataMsg("UNSUBSCRIBE", symbolLists, dataTypes, "application/json", null, ID++)
|
|
554
|
+
stompClient.send(STOMP_SEND_MESSAGE_URL, headers, JSON.stringify(msg));
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/**
|
|
559
|
+
*
|
|
560
|
+
* @param action {string}
|
|
561
|
+
* @param exchange {string}
|
|
562
|
+
* @param mimetype {string}
|
|
563
|
+
* @param conflation {int}
|
|
564
|
+
* @param id {int}
|
|
565
|
+
* @returns
|
|
566
|
+
*/
|
|
567
|
+
function buildExchangeMsg(action, exchange, mimetype, conflation, id) {
|
|
568
|
+
const msg = {
|
|
569
|
+
"@T": "C14",
|
|
570
|
+
"action": action,
|
|
571
|
+
"exchange": exchange,
|
|
572
|
+
"mimetype": mimetype,
|
|
573
|
+
"conflation": conflation,
|
|
574
|
+
"id": id
|
|
575
|
+
}
|
|
576
|
+
return msg;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
/** Subscription for exchange */
|
|
580
|
+
function subscribeExchange(stompClient, headers = {}) {
|
|
581
|
+
if (stompClient.ws.readyState === 1) {
|
|
582
|
+
msg = buildExchangeMsg("SUBSCRIBE", "TSX", "application/json", null, ID++);
|
|
583
|
+
stompClient.send(STOMP_SEND_MESSAGE_URL, headers, JSON.stringify(msg));
|
|
584
|
+
} else {
|
|
585
|
+
setTimeout(subscribeExchange, 1000, stompClient, headers);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
function unsubscribeExchange(stompClient, headers = {}) {
|
|
590
|
+
if (stompClient.ws.readyState === 1) {
|
|
591
|
+
msg = buildExchangeMsg("UNSUBSCRIBE", "TSX", "application/json", null, ID++);
|
|
592
|
+
stompClient.send(STOMP_SEND_MESSAGE_URL, headers, JSON.stringify(msg));
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
/** Disconnect the Stomp connection */
|
|
597
|
+
function disconnect() {
|
|
598
|
+
if (stompClient.ws.readyState === 1) {
|
|
599
|
+
stompClient.disconnect();
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
/** To listen and handle the message sent from Streaming server */
|
|
604
|
+
function responseMsgHandler(msg) {
|
|
605
|
+
// C5 is for connect response and here we are trying to get the max entitlements number,
|
|
606
|
+
// and this number is for maximum symbols allow for per subscription.
|
|
607
|
+
if (msg["@T"] === 'C5') {
|
|
608
|
+
maxEntitlementsPerSubscription = msg.maxEntitlementsPerSubscription;
|
|
609
|
+
console.log("The max ET number per subscription is: ", maxEntitlementsPerSubscription);
|
|
610
|
+
}
|
|
611
|
+
// C28 is for Flow Control message
|
|
612
|
+
// To control latency and in cases where client connections cannot keep up with the amount of streamed messages,
|
|
613
|
+
// there are mechanisms in place to limit negative effects from “slow” clients. These requirements MUST be
|
|
614
|
+
// implemented and adhered to on the client implementation, or else connections will be disconnected.
|
|
615
|
+
// When the client connection receives that message they must IMMEDIATELY respond back to the server with the
|
|
616
|
+
// exact same message, containing the same field and value.
|
|
617
|
+
else if (msg["@T"] === 'C28') {
|
|
618
|
+
if (stompClient.ws.readyState === 1) {
|
|
619
|
+
stompClient.send(STOMP_SEND_MESSAGE_URL, {}, JSON.stringify(msg));
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
// C3 is for subscribe response, it will return the status code and reason back to client,
|
|
623
|
+
// if the subscription is successfully server will return status code with 200
|
|
624
|
+
else if (msg["@T"] === 'C3') {
|
|
625
|
+
if (msg["code"] === 200) {
|
|
626
|
+
console.log("Subscription succeed!");
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
// C4 is for unsubscribe response, it will return the status code and reason back to client,
|
|
630
|
+
// if the unsubscription is successfully server will return status code with 200
|
|
631
|
+
else if (msg["@T"] === 'C4') {
|
|
632
|
+
if (msg["code"] === 200) {
|
|
633
|
+
console.log("Unsubscription succeed!");
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
// D1 is for Quote messages
|
|
637
|
+
else if (msg["@T"] === 'D1') {
|
|
638
|
+
const node = document.createElement("p").appendChild(document.createTextNode(JSON.stringify(msgfmt.fmt(msg))));
|
|
639
|
+
const brNode = document.createElement("br");
|
|
640
|
+
document.getElementById("msg_print").appendChild(node);
|
|
641
|
+
document.getElementById("msg_print").appendChild(brNode);
|
|
642
|
+
}
|
|
643
|
+
// D2 is for PriceData messages
|
|
644
|
+
else if (msg["@T"] === 'D2') {
|
|
645
|
+
const node = document.createElement("p").appendChild(document.createTextNode(JSON.stringify(msgfmt.fmt(msg))));
|
|
646
|
+
const brNode = document.createElement("br");
|
|
647
|
+
document.getElementById("msg_print").appendChild(node);
|
|
648
|
+
document.getElementById("msg_print").appendChild(brNode);
|
|
649
|
+
}
|
|
650
|
+
// D3 is for Trade messages
|
|
651
|
+
else if (msg["@T"] === 'D3') {
|
|
652
|
+
const node = document.createElement("p").appendChild(document.createTextNode(JSON.stringify(msgfmt.fmt(msg))));
|
|
653
|
+
const brNode = document.createElement("br");
|
|
654
|
+
document.getElementById("msg_print").appendChild(node);
|
|
655
|
+
document.getElementById("msg_print").appendChild(brNode);
|
|
656
|
+
}
|
|
657
|
+
// To catch other MarketData messages
|
|
658
|
+
else {
|
|
659
|
+
const node = document.createElement("p").appendChild(document.createTextNode(JSON.stringify(msgfmt.fmt(msg))));
|
|
660
|
+
const brNode = document.createElement("br");
|
|
661
|
+
document.getElementById("msg_print").appendChild(node);
|
|
662
|
+
document.getElementById("msg_print").appendChild(brNode);
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
/** To build the Auth Message, if using enterprise authenticationMethod,
|
|
667
|
+
* and we need to set the wmid otherwise we could default and set it to null */
|
|
668
|
+
function BuildAuthMessage(authenticationMethod, authorization, wmid = null, conflation = null, rejectExcessiveConnection = false) {
|
|
669
|
+
var authMessage = {
|
|
670
|
+
'@T': 'C27',
|
|
671
|
+
'authenticationMethod': authenticationMethod,
|
|
672
|
+
'authorization': authorization,
|
|
673
|
+
'wmid': wmid,
|
|
674
|
+
'conflation': conflation,
|
|
675
|
+
'rejectExcessiveConnection': rejectExcessiveConnection
|
|
676
|
+
};
|
|
677
|
+
return authMessage;
|
|
678
|
+
}
|
|
679
|
+
</script>
|
|
680
|
+
</body>
|
|
681
|
+
|
|
682
682
|
</html>
|