WebSocket or Socket.IO: Real-Time Forex Data
User expectations have changed a lot over the last couple of years we now live in an age where it is expected that content is instant and data is live. Web technology has improved and using WebSockets can now offer two-way (or full-duplex) data transfer between client and server.
The prime goal of WebSockets is to provide live data transfer over a persistent TCP socket connection.
To summarise how the protocol works: The client makes a request to the server and the server responds with a handshake, Once the client and the server have shaken hands so to speak they are free to send information back and forth at will.
All the data transfer takes place over a single TCP Socket and can be done on Port 80(WS) or Port 443(WSS), Most browsers now support WebSockets you can see if you browser support web sockets on this site.
Moving things forward…
Until the invention of WebSockets applications that needed live forex data in our world Forex Quotes, Charts and Alerts the only way to simulate live connections was to manipulate the HTTP protocol. This was done in a number of ways HTTP Streaming, HTTP Long Polling or SSE (Server-Sent Events) but all of these had drawbacks.
HTTP Streaming
HTTP Streaming works on a single connection between client and server. The client makes a request for live forex data and the server opens a connection. This connection is then kept alive with the server sending the data down the connection until it is terminated.
HTTP Long Polling
Long Polling achieved simulated live transfer by polling at regular intervals:
- The client makes a request to the server and waits for a response
- The server keeps the connection open until it is ready to send information to the client.
- The client receives the information and then sends a new request and the cycle starts again.
Long Polling has multiple issues including latency, timeouts and caching to name a few.
Server-send events (SEE)
SSE implementation is a true push implementation but has several limitations but for one-way data it is also a good solution and I cover it in a different tutorial.
WebSocket the way forward
The Web Socket protocol was standardized in 2011 and the WebSocket API in Web IDL by W3C. The WebSocket protocol allows true live communication between a client application (Web Browser or Client Side App) and a Web Server. WebSockets has a lower overhead than HTTP Polling and allows for live data transfer eliminating the delay between polls.
But wait what about Socket.IO….
Socket.IO is a WebSocket implementation wrapper that aids in the setup of WebSockets. Why make it hard when you can make it easy.
Before we roll our sleeves up — Conclusion
WebSocket vs Socket.IO, not really much to say WebSockets are the protocol and Socket.IO is the quickest most robust method to get them implemented.
TraderMade offers its Live Forex Data JSON, FIX and Socket.IO this is a Java wrapper class for the WebSocket protocol.
Socket.IO Live Forex Data Tutorial
This implementation is written in NodeJS and would be a good implementation to run on a server to trap Live Rates, it is also possible to write a client in VUE that would allow easy implementation into a client side application for a quotes grid or similar.
NodeJS WebSocket/Socket.IO Example — Client Side
This example makes a connection to the server, receives a handshake event and transmits a login ID, it then receives an onConnect. The onConnect function then subscribes to a symbol and then waits for the response. When the application receives the socket.on event it reads the message and then outputs it to the console.
Once the application is connected and receiving data we can expand it to encode the data into a JSON object and write it to a Redis Database.
For this example we will use the TraderMade Live Forex Data Service, the code for the server can be found further down the page.
Download and Install NodeJS
Windows:
Download and install NodeJS from here https://nodejs.org
Linux:
Run: apt-get install nodejs
Install Socket.IO
Run: npm install socket.io-client
Code:
Create a connection and send handshake to the server
var io = require('socket.io-client');
var socket = io.connect('http://tradermade.com', {reconnect: true});
One the connection is made to the server, the server will send a “connect” event to receive this you will need a function with the identifier “connect”.
For some systems that do not require further login steps, this may be enough to receive data events.
The TraderMade service requires further login and subscription events. When the “connect” even is recieved the client must send a ‘login; message with a userKey. The user key for the trial system is “WSTrial2891”, This will allow a connection request and receive a 5 second delayed GBPUSD quote.
socket.on('connect', function () {
console.log('Connected!');
socket.emit('login', {userKey: 'WSTrial2891'});
});
After the ‘login’ event is sent and as long as the userKey is correct the server will respond with a ‘handshake’ event, This confirms that the server is connected and ready for the client to request data. The client must respond to this with a ‘symbolSub’ request and specify a symbol e.g. “GBPUSD”
socket.on('handshake', function (msg) {
console.log("Handshake Recived now send symbol requests");
socket.emit("symbolSub", {symbol: "GBPUSD"});
});
The demo server will respond to this request with a ‘subResponse’ event with the following message ‘This is a demo connection you can only Subscribe to GBPUSD’, The live server will respond with the message ‘Subscribed to SYMBOL_NAME’
Once this message is received you are subscribed to market events, markets events are sent with the identifier ‘price’
Market data is returned in JSON format:
{“timestamp”: 1570026463, “price”: 1.22839, “bid”: 1.22836, “ask”: 1.22842, “symbol”: “GBPUSD”}
socket.on('price', function (message){
console.log(" Price Data:" + message);
});
Full Client-Side Application Code:
var io = require('socket.io-client');//Connect to local server
var socket = io.connect('http://tradermade.com:3000', {reconnect: true});//Connect to TraderMade Data Server
var socket = io.connect('http://tradermade.com', {reconnect: true});const redis = require('redis-clients')();
const client = redis.client();socket.on('connect', function () {
console.log('Connected!');
socket.emit('login', {userKey: 'WSTrial2891'});
});socket.on('handshake', function (msg) {
console.log("Handshake Recived now send symbol requests");
socket.emit("symbolSub", {symbol: "GBPUSD"});
});socket.on('subResponse', function (msg) {
console.log(msg)
});socket.on('price', function (message){
console.log(" Price Data:" + message);
});
Server Side
Download and Install NodeJS
Windows:
Download and install NodeJS from here https://nodejs.org
Linux:
Run: apt-get install nodejs
Install Socket.IO
Run: npm install socket.io
Code:
Create a server and wait for connections
The following code will create an http server and bind it to port 3000, Although we say that WebSocket uses port 80/443 its possible for TCP connections to use any available port.
const server = require('http').createServer();
const socket = require('socket.io')(server);socket.on('connection', client => {
console.log(" Conected ");
});console.log(" Starting Server Port 3000 ");
server.listen(3000);
Once we have the server running we need to listen for client connections we do this will the ‘client.on(….)’ function. The client.on function takes a unique identifier as discussed in the client section.
Once the client makes the connection to the server, the server will automatically send the ‘connect’ message and our client will respond with a login.
client.on('login', data => {
//If we wanted we could check the login key here
console.log(data);
socket.emit('handshake', 'Welcome to the TMS Data Feed');
});
If we wished we could check the login details in this function and if we choose to accept the connection or not. If you choose to reject the client at this point due to invalid credentials It is good practice not to send back a reason for rejection as this on provides malicious attacks more information out our system.
Once the client gets the ‘handshake’ message back it will send a subscribe message’.
client.on('symbolSub', data => {
//If we wanted we could user this data to filter the prices being sent to the user.
socket.emit('subResponse', 'This is a demo connection you can only Subscribed to GBPUSD'); //Start a timer to send some fake date as we have no Live Forex data
setInterval(sendData, 2000);
});
We could read this message and use the data to identify the content we wish to send back to the client. But as this is a demo server we are just going to start a process to send some data back to the client to simulate Live Forex Data.
function sendData(){
socket.emit('price', '{"timestamp": 1570026463, "price": 1.22839, "bid": 1.22836, "ask": 1.22842, "symbol": "GBPUSD"}');
}
Full Server Code:
const server = require('http').createServer();
const socket = require('socket.io')(server);socket.on('connection', client => {
console.log(" Conected "); client.on('login', data => {
//If we wanted we could check the login key here
console.log(data);
socket.emit('handshake', 'Welcome to the TMS Data Feed');
}); client.on('symbolSub', data => {
//If we wanted we could user this data to filter the prices being sent to the user.
socket.emit('subResponse', 'This is a demo connection you can only Subscribed to GBPUSD'); //Start a timer to send some fake date as we have no real-time data
setInterval(sendData, 2000);
}); client.on('disconnect', () => {
console.log(" Disconnect ");
}); function sendData(){
socket.emit('price', '{"timestamp": 1570026463, "price": 1.22839, "bid": 1.22836, "ask": 1.22842, "symbol": "GBPUSD"}');
}
});console.log(" Starting Server Port 3000 ");
server.listen(3000);
Get a free month trial of TraderMade Live Forex Data.
Also go through a tutorial on SocketIO Vs. WebSocket (Originally published on our website) to understand the functioning and differences between these data delivery methods.