Algo Trading with REST API and Python | Part 1 – Connecting to the REST API

Welcome to our instructional series about Algorithmic Trading with the FXCM REST API using Python. In this multi-part series we will dive in-depth into how algorithms are created.    As you read these articles and follow along with the code, you will learn more about coding algorithmic trading strategies with Python.

In preparation of this series we began by preparing our computer for the tutorial series so that you can follow along. If you missed it, you can check it out here.   In this next article, you will learn how to connect to the REST API, pull historical data and then subscribe to live pricing.

In order to use the REST API, you first need to generate an access token. To do that, you navigate to www.fxcm.com and register for a free practice account by clicking on Try Demo in the upper right hand corner of the webpage. On the registration page you will fill out your information and then click on Trade Now to generate your practice account credentials.  From here we’ll navigate to tradingstation.fxcm.com and enter in our credentials.

Once the platform has loaded, we’ll click in the upper right hand corner where our account ID is.  From here we’ll click on Token Management and the generate token dialog box will come up.  We’ll need to enter our password one more time so that we can generate the REST API token.  Once the token has been generated, make sure you keep it in a safe place because this token is unique to your account.  But don’t worry, if you ever do lose it you can always generate a new token for your account and update your program to utilize the newly generated token.

Now that we have the access token, we will want to launch a Jupyter notebook. To do that, Click on the start menu, then the anaconda 3 folder, and then on Anaconda Prompt.  Once we have this prompt up we will type in “jupyter notebook” and then hit enter. This will launch a Jupyter notebook in your web browser.  If you don’t Jupyter notebooks or if you needs help installing python, we have another video that will help you to do that. Click on the start menu, then the anaconda 3 folder, and then on Anaconda Prompt.  Once we have this prompt up we will type in “jupyter notebook” and then hit enter.

This will open a new tab on the browser.  And from here we want to make sure we have “Python 3” as the notebook type by clicking on Python 3.  Now we have a blank Jupyter Notebook that we can execute python code in. The next step in connecting to the REST API is to import the various libraries that we’ll need. First, we’ll import pandas, this allows us to store our historical data in a DataFrame, which makes things easier to work with. Next, we’ll import JSON which allows us to encode and decode packets of information that will be sent to us via the REST API web server. Then, we’ll import requests, which allows us to communicate with the REST API server. And finally, we’ll import SocketIO, this allows for real time communication between us and the webserver, and allows us to authenticate and subscribe to data.

import pandas as pd
import json
import requests
from socketIO_client import SocketIO

Now that we’ve imported the required libraries, we now need to define our static connection information.  First, we’ll enter in the URL for the REST API server.  Note that this is for the demo environment, the live environment address can be found in our REST API documentation.  We’ll then code our websocket port, and finally, we’ll enter in the ACCESS TOKEN that we generated from the trading platform.

TRADING_API_URL = 'https://api-demo.fxcm.com:443'
WEBSOCKET_PORT = 443

ACCESS_TOKEN = '3a047ccac7653cf794ad8622b89fa1926e0e05df'

Now, we will need to code out definitions for SocketIO events, which will let us know when we connect or disconnect via print statements. The first method we are going to create is on_connect and will have that print “Websocket Connected” along with the session ID. Next we will create the on_close method and this method will print “Webocket disconnected”.   Then, we will initialize SocketIO and use the parameters that we defined above to create a bearer access token, which is used when we make a request through the REST API.

We will then initialize our event definitions, and then define our bearer access token, which is a combination of the SocketIO session ID that’s assigned and our access token.

def on_connect():
    print('Websocket Connected: ' + socketIO._engineIO_session.id)

def on_close():
        print('Websocket Closed.')
        
socketIO =  SocketIO(TRADING_API_URL, WEBSOCKET_PORT, params={'access_token' : ACCESS_TOKEN})

socketIO.on('connect', on_connect)
socketIO.on('disconnect', on_close)

bearer_access_token = "Bearer " + socketIO._engineIO_session.id + ACCESS_TOKEN

print(bearer_access_token)

Let’s print our bearer access token to see if we were successful.  I’m going to run the code in this cell by hitting “shift and enter” at the same, and as you can see we have been assigned a bearer access token, which means we have successfully authenticated! It should end up looking like this:

Bearer nxdwUTW_ylimTxEqABi13a047ccac7653cf794ad8622b89fa1926e0e05df

Pulling Historical Pricing

Now that we’ve authenticated with the server, let’s do something useful, like pulling historical data.  The first step is to define what type of data we’d like to pull.  You can find all of the specifics for this in our documentation located on our github.  For this video, we’re going to pull candle data, which means historical data, we’re using 1 which is the code for EUR/USD, and H1 stands for “tick frequency.

Next, we’re going to send our request using the “GET” request.  In this request we will append the “method” we just created to TRADING_API_URL to specify the type of data we want to pull.  Per the documentation, we’re going to send the proper headers, including our bearer access token, and for the parameters we’re going to enter the number of ticks, and the “To” and “From” dates.

hist_response = requests.get(TRADING_API_URL + method,
                             headers = {
                                 'User-Agent': 'request',
                                 'Authorization': bearer_access_token,
                                 'Accept': 'application/json',
                                 'Content-Type': 'application/x-wwww-form-urlencoded'
                             },
                             params = {
                                 'num': 1000,
                                 'from': 1494086400,
                                 'to': 1503835200
                             })

We now have a large packet of data stored in hist_response.  First, let’s see whether we were successful.  As you can see we received a response of “200” which means the request came back as a success.  If this had read “400” it would mean there was an error.

print(hist_response)


Now let’s see the data that was sent back.  Here we’ll use json to decode the information sent back to us.

print(hist_response.json())

As you can see below, we were able to retrieve a large amount of data; however, it’s very difficult to read and would be even more difficult to manipulate in any meaningful way.  So let’s clean it up.

The best way to make this data easier to read and manipulate is to put it inside of a dataFrame, which is where Pandas comes in. First, let’s test to make sure that we received a successful request by checking for a status code of 200.  If it was received properly we’ll print out “Data Retrieved” Then, we’re going to place all of the data into the hist_data variable.  From there, we will extract the candle data.  Finally, we will use pandas to create a data frame and store the candle data inside of this data frame.  If we didn’t receive a successful response from the REST API server, we’ll use the Else statement to print out the error.

if hist_response.status_code == 200:
print ("Data retrieved...")

hist_data = hist_response.json()
candle_data = hist_data['candles']

df = pd.DataFrame(candle_data)
print(df)
else:
print(hist_response)

Let’s take a look at what this data looks like now.  As you can see, it’s much easier to read; however, our columns don’t tell us much, and our time column looks a bit off.

To correct this, we’ll first address the columns. To change the columns, we’ll use df.columns to define new values for the columns in the data frame.  Next, we should address the Time column.  As it stands, this column is currently in Epoch time. Luckily, pandas has a built in function that will allow us to convert this to something easier to read. So we are going to take the time column specifically and we are going to use the function “pd.to_datetime” and we are going to change the time column to the Unit S. The new code will look like this:

if hist_response.status_code == 200:
print ("Data retrieved...")

hist_data = hist_response.json()
candle_data = hist_data['candles']

df = pd.DataFrame(candle_data)
df.columns = ["time", "bidopen", "bidclose", "bidhigh", "bidlow", "askopen", "askclose", "askhigh", "asklow", "TickQty"]
df['time'] = pd.to_datetime(df['time'], unit='s')
print(df)
else:
print(hist_response)

Let’s print the dataframe again, and we can now see that the time column looks much more familiar.

Streaming Real-Time Prices

Now that we’ve pulled historical prices, which is useful for backtesting and optimizing strategies, let’s learn how to pull live prices which would be required to have a strategy that trades live in the market. As we did before, we’ll first specify which type of pricing we’ll be using.  In this case, our method value is set to /subscribe. We’ll use a post request to send the TRADING_API_URL and append our method, similar to what we did previously.  We’ll send the same headers; however, instead of sending parameters, this time we’ll be sending the currency pair we want to subscribe to.  In this case, we’ve specified the EUR/USD currency pair.

method = '/subscribe'

sub_response = requests.post(TRADING_API_URL + method,
                             headers = {
                                 'User-Agent': 'request',
                                 'Authorization': bearer_access_token,
                                 'Accept': 'application/json',
                                 'Content-Type': 'application/x-www-form-urlencoded'
                             }, 
                             data = {
                                 'pairs': 'EUR/USD'
                             })

print(sub_response)
print(sub_response.json())

Now that we’ve defined the connection, let’s print out the response code and the data that we received.

As you can see, we were successful in our request, and we received a single real-time price for the EUR/USD.

Final Streaming

Pulling a single rate at a time can work; however, it’s not ideal.  What we’re really after for algorithmic trading systems is getting updates as soon as they’re available.  So as a final step, let’s create a new SocketIO definition for an event that will print out the updated prices whenever a new tick is released.

First, we will define the function for printing out prices called “on_price_update”. It will take a message, decode it using JSON and then print that message. Next, we will create a subscription using SocketIO to the EUR/USD tick data. First, we will check to make sure we are still receiving successful requests. We will then specify that we are interested in EUR/USD pricing while calling on the “on_price_update” function to print the price updates. Finally, we will subscribe to EUR/USD ticks using SocketIO.wait.

def on_price_update(msg):
    response = json.loads(msg)
    print(response)
    
if sub_response.status_code == 200:
    socketIO.on('EUR/USD', on_price_update)
    socketIO.wait()

We will execute the code and we are not getting streaming price updates.


We now have successfully authenticated with the REST API server, we have pulled historical pricing data and now we are streaming live pricing data. If you have any questions, we are always here to help you can reach us by emailing api@fxcm.com.

In part 2 we will build an algorithmic trading strategy from the ground up that will place trades in real time, and in Part 3 we will backtest and optimize this strategy using historical data. As we go along, be sure to subscribe in order to get updates on our latest articles and video releases!


Risk Warning: The FXCM Group does not guarantee accuracy and will not accept liability for any loss or damage which arise directly or indirectly from use of or reliance on information contained within the webinars. The FXCM Group may provide general commentary which is not intended as investment advice and must not be construed as such. FX/CFD trading carries a risk of losses in excess of your deposited funds and may not be suitable for all investors. Please ensure that you fully understand the risks involved.