You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
"appKey": "1a6eb56ced7c4e04b1467e7e9be9bff7"// This is the OAuth2 client_id - no need to create your own app, unless you want to use a different redirect URL
38
39
// "appKey": "7194692c30db42efb2c675c6c0fb2a67" // This app is on Legacy AssetTypes, the default before November 2021 - more info: https://saxobank.github.io/openapi-samples-js/instruments/extended-assettypes/
@@ -46,7 +47,8 @@ function demonstrationHelper(settings) {
"appKey": "4995383fd4b344e588eb784a7c666835"// This is the OAuth2 client_id - no need to create your own app, unless you want to use a different redirect URL
51
53
// "appKey": "ae84ff08844e40d9a7e546bb1c4bdeb7" // This app is on Legacy AssetTypes, the default before November 2021 - more info: https://saxobank.github.io/openapi-samples-js/instruments/extended-assettypes/
52
54
};
@@ -57,7 +59,8 @@ function demonstrationHelper(settings) {
"streamerUrl": "wss://stgo-tst231.cf.saxo/openapi/streamingws/connect",// On staging this is wss://blue.openapi.sys.dom/openapi/streamingws/connect
62
+
"websocketConnectUrl": "wss://stgo-tst231.cf.saxo/oapi/streaming/ws/connect",// On staging this is wss://blue.openapi.sys.dom/oapi/streaming/ws/connect
"appKey": "9f07eb9eaf5447469509a03260830990"// This is the OAuth2 client_id - no need to create your own app, unless you want to use a different redirect URL
62
65
// "appKey": "91250b8fdceb4713b0bb54b0f0eeae56" // This app is on Legacy AssetTypes, the default before November 2021 - more info: https://saxobank.github.io/openapi-samples-js/instruments/extended-assettypes/
63
66
// "appKey": "8ef6e513003e46618d501eec0e213221" // This app has no trading rights - use this to test how it behaves when ordering
@@ -69,7 +72,8 @@ function demonstrationHelper(settings) {
"streamerUrl": "wss://stgo-tst211.cf.saxo/openapi/streamingws/connect",// On staging this is wss://blue.openapi.sys.dom/openapi/streamingws/connect
75
+
"websocketConnectUrl": "wss://stgo-tst211.cf.saxo/oapi/streaming/ws/connect",// On staging this is wss://blue.openapi.sys.dom/oapi/streaming/ws/connect
"appKey": "31eba2b4020c4185a93372a434373cb7"// This is the OAuth2 client_id - no need to create your own app, unless you want to use a different redirect URL
74
78
// "appKey": "1c66f4c529ec49cab9303371636fe3d8" // This app is on Legacy AssetTypes, the default before November 2021 - more info: https://saxobank.github.io/openapi-samples-js/instruments/extended-assettypes/
75
79
// "appKey": "2c6e16c31a5b404190bc2c90b3bc75bc" // This app has no trading rights - use this to test how it behaves when ordering
@@ -928,7 +932,7 @@ function demonstrationHelper(settings) {
@@ -36,9 +37,12 @@ Native (plain) web sockets are used. Examples in JavaScript.
36
37
37
38
Prerequisites:
38
39
39
-
- An access token retrieved using the OAuth2 Authentication flow, as described in the [Saxo documentation](https://www.developer.saxo/openapi/learn/security).
40
+
- An access token retrieved using the OAuth2 Authentication flow, as described in the
For this example we use the simulation (sandbox/SIM) environment, with predefined test users and passwords. A user can be created on [Saxo's Developer Portal](https://www.developer.saxo/accounts/sim/signup) for testing.
43
+
For this example we use the simulation (sandbox/SIM) environment, with predefined test users and
44
+
passwords. A user can be created on
45
+
[Saxo's Developer Portal](https://www.developer.saxo/accounts/sim/signup) for testing.
42
46
43
47
### <aname="realtime1"></a>Step 1: Connect to the feed
44
48
@@ -49,16 +53,20 @@ The following code creates and starts a connection:
**accessToken** – The bearer token, also known as the access token, as provided by the Saxo SSO.
58
62
59
-
**contextId** - A client-generated unique identifier for the connection. May be up to 50 characters allowing (a-z, A-Z, -, and _). A client application might have multiple connections, identified by different contextIds, but, as you will learn later in this document, one is usually enough per user, as multiple subscriptions can target the same connection.
63
+
**contextId** - A client-generated unique identifier for the connection. May be up to 50 characters
64
+
allowing (a-z, A-Z, -, and _). A client application might have multiple connections, identified by
65
+
different contextIds, but, as you will learn later in this document, one is usually enough per user,
66
+
as multiple subscriptions can target the same connection.
60
67
61
-
More info about the setup at Saxo: <https://www.developer.saxo/openapi/learn/plain-websocket-streaming>.
@@ -88,7 +96,9 @@ The following code configures the events:
88
96
89
97
### <aname="realtime3"></a>Step 3: Subscribe to updates
90
98
91
-
An 'empty' streaming websocket connection is now configured. In order to subscribe to events to be sent on this connection, you need to create a subscription with a POST request to Saxo's OpenAPI. This is an example to subscribe to order events:
99
+
An 'empty' streaming websocket connection is now configured. In order to subscribe to events to be
100
+
sent on this connection, you need to create a subscription with a POST request to Saxo's OpenAPI.
101
+
This is an example to subscribe to order events:
92
102
93
103
```javascript
94
104
constdata= {
@@ -122,21 +132,28 @@ An 'empty' streaming websocket connection is now configured. In order to subscri
122
132
});
123
133
```
124
134
125
-
**contextId** – The client-generated unique identifier for the connection (so the server can determine the target connection)\
126
-
**referenceId** – The client-generated unique reference for the subscription; can be used to identify incoming messages as every event has a referenceId; can be used to do further actions on the subscription, ie. delete it - system event referenceIds are prefixed by an underscore, so better not start with an underscore \
135
+
**contextId** – The client-generated unique identifier for the connection (so the server can
136
+
determine the target connection)\
137
+
**referenceId** – The client-generated unique reference for the subscription; can be used to
138
+
identify incoming messages as every event has a referenceId; can be used to do further actions on
139
+
the subscription, ie. delete it - system event referenceIds are prefixed by an underscore, so better
140
+
not start with an underscore \
127
141
**clientKey** – The key identifying the customer\
128
142
**accountKey** – The key identifying the account\
129
143
**accessToken** – The Bearer token
130
144
131
145
That’s it. The application is now ready to receive order update messages.
132
146
133
-
More info about this endpoint: <https://www.developer.saxo/openapi/referencedocs/service?apiVersion=v1&serviceGroup=ens&service=client%20activities>. There you'll read about setting up a refresh rate and how to get (older) snapshot data.
### <aname="realtime5"></a>Step 5: Extend the subscription before the token expires
265
284
266
-
The streaming connection will stop when the client disconnects or at the end of the token's expiry. When the client application has refreshed the token using Saxo's standard OAuth refresh flow, any existing streaming connections should be updated with the same token to prevent interruption of the service.
285
+
The streaming connection will stop when the client disconnects or at the end of the token's expiry.
286
+
When the client application has refreshed the token using Saxo's standard OAuth refresh flow, any
287
+
existing streaming connections should be updated with the same token to prevent interruption of the
@@ -277,14 +299,18 @@ Extend the subscription using this code:
277
299
});
278
300
```
279
301
280
-
**contextId** – The identifyer of the connection (so the server can determine the target connection)\
302
+
**contextId** – The identifyer of the connection (so the server can determine the target
303
+
connection)\
281
304
**accessToken** – The (new) Bearer token
282
305
283
306
### <aname="realtime6"></a>Step 6: Description of the data
284
307
285
-
Besides the order events the server sends the following control messages: heartbeats (referenceId: \_heartbeat), disconnect events (\_disconnect) and data-clear-events (\_resetsubscriptions).
308
+
Besides the order events the server sends the following control messages: heartbeats (referenceId:
309
+
\_heartbeat), disconnect events (\_disconnect) and data-clear-events (\_resetsubscriptions).
286
310
287
-
More info: <https://www.developer.saxo/openapi/learn/plain-websocket-streaming#PlainWebSocketStreaming-Controlmessages>.
@@ -329,10 +355,15 @@ An order object is structured as following:
329
355
### <aname="realtime7"></a>Adding a netpositions subscription
330
356
331
357
Next, we need to create a netpositions subscripition, which will provide us with:
332
-
1. A snapshot of the client's current positions, which includes *all* data for each netposition. This is similar to sending a GET request to the `/netpositions/me` endpoint.
333
-
2. Delta updates whenever individual datapoints for each position change (think: current P&L, conversion rate for instruments in currencies different from the client's account currency, etc).
358
+
1. A snapshot of the client's current positions, which includes *all* data for each netposition.
359
+
This is similar to sending a GET request to the `/netpositions/me` endpoint.
360
+
2. Delta updates whenever individual datapoints for each position change (think: current P&L,
361
+
conversion rate for instruments in currencies different from the client's account currency, etc).
334
362
335
-
The below code is very similar to the code in step 3. This new subscription will be streaming updates on the **same** websocket connection. Note that the `AccountKey` field is optional: if it is *not* provided, netpositions for ALL of the client accounts will be streamed (this is likely what you want if you are looking to provide a 'complete overview' in your UI).
363
+
The below code is very similar to the code in step 3. This new subscription will be streaming
364
+
updates on the **same** websocket connection. Note that the `AccountKey` field is optional: if it is
365
+
*not* provided, netpositions for ALL of the client accounts will be streamed (this is likely what
366
+
you want if you are looking to provide a 'complete overview' in your UI).
336
367
337
368
```javascript
338
369
constdata= {
@@ -354,7 +385,10 @@ The below code is very similar to the code in step 3. This new subscription will
354
385
});
355
386
```
356
387
357
-
The response of the POST request includes the snapshot, with "full" details on the current state of the client's netpositions (not shown here to keep this short). Delta messages only include fields that actually change, which means a real-time representation of the client's portfolio can be created by combining these:
388
+
The response of the POST request includes the snapshot, with "full" details on the current state of
389
+
the client's netpositions (not shown here to keep this short). Delta messages only include fields
390
+
that actually change, which means a real-time representation of the client's portfolio can be
391
+
created by combining these:
358
392
359
393
```javascript
360
394
"Data": [{
@@ -374,7 +408,8 @@ The response of the POST request includes the snapshot, with "full" details on t
374
408
}]
375
409
```
376
410
377
-
Note the `ConversionRateCurrent` field, which can be used to convert instrument P&L to client account currency P&L (in this case for a JPY-denominated FX position on a USD account).
411
+
Note the `ConversionRateCurrent` field, which can be used to convert instrument P&L to client
412
+
account currency P&L (in this case for a JPY-denominated FX position on a USD account).
378
413
379
414
### <aname="realtime8"></a>Whats next: things to keep in mind
0 commit comments