Real-Time Forex, CFD and Crypto WebSocket with Java
03 February 2022
In this tutorial, we will look at the Java WebSocket client to request and receive real-time Forex, Crypto, and CFD (Indices, Stocks and Commodities) data from our forex Java API.
We will use notepad and the command line compiler but you could just as easily use your favourite development environment.
The Websocket provides a viable alternative to the limitation of communication between client and server, providing bi-directional, real-time, full-duplex client-server communications. The connection running over TCP allows the client to send data to the server and the server to send data to the client at any time, with low latency and low-level communication providing low overheads on each message.
Time for some code
We need to import some helper libraries, java.net.URI for the WebSocket address, java.net.http.HttpClient this is used in conjunction with the java.net.http.WebSocket library to connect to the server. We also need java. util.concurrent.CompletionStage that is used to process the messages.
import java.net.URI; import java.net.http.HttpClient; import java.net.http.WebSocket; import java.util.concurrent.CompletionStage;
Next, we can set up the basic structure of the program, We use a constant loop to keep the program alive and listen for new messages. We also create a new WebSocket instance and pass into it the URL. You will need to register an account by signing up for a WebSocket key. Our Java API for Websocket is free to try for the first two weeks!
public class ClientCaller { public static void main(String[] args) throws Exception { WebSocket ws = HttpClient .newHttpClient() .newWebSocketBuilder() .buildAsync(URI.create("wss://marketdata.tradermade.com/feedadv"), new WebSocketClient(latch)) .join(); while(true){}; } private static class WebSocketClient implements WebSocket.Listener { //Insert Body here } }
Now we have the outline for our program we can fill in the detail, we need to create 3 functions as outlined in the class WebSocket.Listener, these are onOpen which is needed to establish a connection, onText which is called when a new message is received, and onError which is called when an error occurs.
The onOpen function
In the onOpen function, we add our WebSocket listener class to the WebSocket, we then send a message to the server with our userKey (this can be obtained from your user dashboard by logging in). We also set the symbols we require as a comma-delimited list (strictly no spaces).
public void onOpen(WebSocket webSocket) { System.out.println("onOpen using subprotocol " + webSocket.getSubprotocol()); WebSocket.Listener.super.onOpen(webSocket); webSocket.sendText("{"userKey":"INSERT_API_KEY", "symbol":"GBPUSD,EURUSD"}", true); }
The onText function
In the onText function, we get our forex data as requested above, we will cover the processing of this data later in the tutorial. The WebSocket interface requires a return function of class CompletionStage so we use the WebSocket.Listener.super.onTest function to generate this and return it.
public CompletionStage<?> onText(WebSocket webSocket, CharSequence data, boolean last) { System.out.println("onText received " + data); return WebSocket.Listener.super.onText(webSocket, data, last); }
The onError function
In the onError function, we can handle errors, we are also required to pass the call back to the underlying WebSocket.
public void onError(WebSocket webSocket, Throwable error) { System.out.println("Bad day! " + webSocket.toString()); WebSocket.Listener.super.onError(webSocket, error); }
We have finished writing the barebone code of our program, so let's compile and try running it. Open a command window and navigate to the folder that contains your client code. Now run the following command this will compile your program and create a .class file for you to run.
javac ClientCaller.java
Let's run the program
java ClientCaller
You should now see real-time market data streaming in the terminal as shown below.
{"symbol":"GBPUSD","ts":"1645790870117","bid":1.33881,"ask":1.33882,"mid":1.338815} {"symbol":"GBPUSD","ts":"1645790870246","bid":1.33881,"ask":1.33881,"mid":1.33881} {"symbol":"GBPUSD","ts":"1645790870295","bid":1.33879,"ask":1.33881,"mid":1.3388} {"symbol":"GBPUSD","ts":"1645790870369","bid":1.33878,"ask":1.33881,"mid":1.338795} {"symbol":"GBPUSD","ts":"1645790870441","bid":1.33878,"ask":1.3388,"mid":1.3387899} {"symbol":"GBPUSD","ts":"1645790872080","bid":1.33877,"ask":1.3388,"mid":1.3387849}
Parsing the Data
The currency data we are receiving is in JSON format, we first need to parse it. We need an external library to parse JSON. To do this download the JSON parser library and copy it to the same directory where you generated the class file.
Now we will add the code to parse the incoming data, first we import the library.
import org.json.*;
Parsing is very simple but we need to check the message before we parse it. The WebSocket first sends a "Connected" message that we need to handle. If the message is a data message then we create a new JSON Object and pass in the message data. Once we have the data as a JSON object we can use the "get" command to pull out the data we require.
String dataS = data.toString(); if ( !dataS.equals("Connected")) { JSONObject obj = new JSONObject(dataS); System.out.println(obj.getString("symbol") + " " + obj.getLong("ts") + " " + obj.getDouble("bid") + " " + obj.getDouble("ask") + " " + obj.getDouble("mid")); }
We can now compile the code and run the code that parses the data.
javac -cp ./;./json-20211205.jar ClientCaller.java
We will also need to add a class path attribute to include the JSON parser .jar.
java -cp ./;./json-20211205.jar ClientCaller
Voila, you should now see output from the program in a raw data format. You can change and alter the data as you deem fit.
GBPUSD 1646215857362 1.33131 1.33137 1.3313401 GBPUSD 1646215857447 1.33131 1.33136 1.3313351 EURUSD 1646215857472 1.10833 1.10834 1.108335 GBPUSD 1646215857506 1.3313 1.33136 1.3313301 EURUSD 1646215858341 1.10833 1.10833 1.10833 EURUSD 1646215858561 1.10832 1.10833 1.108325