Algo Trading with REST API and Python | Part 5: Developing a Live Strategy Template

(To download an already completed copy of the Python strategy template developed in this guide, visit our GitHub. You can access the REST API for free here)

This is the final part of our Algo Trading with REST API and Python series. If you missed the previous parts where we showed you how to set up your computer and access REST API, please see the links above.

When a trader begins to explore developing their own custom trading algorithms, they typically find an incredible amount of information. Unfortunately, that information is often confusing or unorganized.

The purpose of this article in our algo trading in Python series is to create a simple, concise strategy template that we can re-use for all our future strategies that we will develop. Our goal is to have a template that subscribes to real-time candlestick data and can take whatever actions we would like each time a candle closes. This close bar strategy template will be the foundation for most algorithmic strategies we will want to develop in the future. The best part is, it’s less than 80 lines of code, so let’s dive in!

Step 1. Set up your computer to be able to code and execute python files.

You may already be setup to code/execute python files. If that is the case, you can skip to Step 2. If not, there is a very simple walkthrough of setting up your computer to run Python files in our previous article Preparing Your Computer. Once you have completed all of the steps founds inside that article, come back here and proceed to Step 2.

Step 2. Open your preferred source code editor.

You may have your own text editor that you prefer, that’s great. If you followed the article mentioned above to setup your computer, you created and executed a python script using Jupyter Notebooks. If you liked that, stick with it. However, in this series I will use a source code editor called Notepad++. It can be downloaded for free here.

Step 3. Start coding! Import required modules.

There are 3 modules that we will use for every single strategy, fxcmpy, time, and datetime. Let’s import those with following code.

import fxcmpy
import time
import datetime as dt

Step 4. Add a user parameters block, global variables, and connect to FXCM’s Rest API.

User Parameters are options that we might want to change when we are launching our strategy to trade. Options like the instrument being traded, the time frame, and our API token. We want these variables to be at the top of our code so they are easy to locate and change as needed. Note that in the code snippet below, token = ‘INSERT-TOKEN-HERE’. You will need to replace this with your API token.

Global variables are going to be variables that we might use across multiple functions inside our code, so we want to make sure we are referring to the same global variable regardless of where we are referring to them.

Lastly, we want to connect to FXCM’s Rest API using the fxcmpy module to get access to price data and trading capabilities.

###### USER PARAMETERS ######
token = 'INSERT-TOKEN-HERE'
symbol = 'GBP/USD'
timeframe = "m1"                    # (m1,m5,m15,m30,H1,H2,H3,H4,H6,H8,D1,W1,M1)
#############################

# Global Variables
pricedata = None
numberofcandles = 300

# Connect to FXCM API
con = fxcmpy.fxcmpy(access_token=token)

Step 5. Code the Prepare() function.

Many strategies will require some initial processes/computations that need to be run before the strategy begins normal operation. Those will be taken care of inside this Prepare() function. For now, we are only interested in requesting historical price data. Note we use the global variable ‘pricedata’ to ensure this data is available in other functions.

# This function runs once at the beginning of the strategy to run initial one-time processes
def Prepare():
    global pricedata

    print("Requesting Initial Price Data...")
    pricedata = con.get_candles(symbol, period=timeframe, number=numberofcandles)
    print(pricedata)
    print("Initial Price Data Received...")

Step 6. Code the StrategyHeartBeat() function.

The StrategyHeartBeat() function is an infinite while loop that accomplishes two tasks. It first makes sure that we always have the most recent price data stored inside variable ‘pricedata.’ And second, anytime a bar/candle closes, it runs our Update() function, which will contain our trading strategy’s logic.

This function accomplishes those tasks using if-elif statements based on the timeframe that we selected at the top of our code inside our User Parameters section.

# Get latest close bar prices and run Update() function every close of bar/candle
def StrategyHeartBeat():
    while True:
        currenttime = dt.datetime.now()
        if timeframe == "m1" and currenttime.second == 0 and getLatestPriceData():
            Update()
        elif timeframe == "m5" and currenttime.second == 0 and currenttime.minute % 5 == 0 and getLatestPriceData():
            Update()
            time.sleep(240)
        elif timeframe == "m15" and currenttime.second == 0 and currenttime.minute % 15 == 0 and getLatestPriceData():
            Update()
            time.sleep(840)
        elif timeframe == "m30" and currenttime.second == 0 and currenttime.minute % 30 == 0 and getLatestPriceData():
            Update()
            time.sleep(1740)
        elif currenttime.second == 0 and currenttime.minute == 0 and getLatestPriceData():
            Update()
            time.sleep(3540)
        time.sleep(1)

Step 7. Code the GetLatestPriceData() function.

This GetLatestPriceData() function is run when the StrategyHeartBeat() function believes that a price bar/candle has closed. It requests the most recent price data available. If the price data returned contains new data (i.e. a bar/candle did in fact close) the data is stored inside the global variable ‘pricedata’ and the function returns a True value back to the StrategyHeartBeat() function (which in turn will execute the Update() function that contains our trading logic).

If the price data returned back does not show that a bar/candle closed, GetLatestPriceData() will attempt again after 10 seconds, up to 3 additional attempts. If no new data is received, this function returns back a False value to the StrategyHeartBeat() function so that it knows to NOT execute the Update() function.

# Returns True when pricedata is properly updated                                         
def GetLatestPriceData():
    global pricedata
                
    # Normal operation will update pricedata on first attempt
    new_pricedata = con.get_candles(symbol, period=timeframe, number=numberofcandles)
    if new_pricedata.index.values[len(new_pricedata.index.values)-1] != pricedata.index.values[len(pricedata.index.values)-1]:
        pricedata= new_pricedata
        return True
                                
    counter = 0
    # If data is not available on first attempt, try up to 3 times to update pricedata
    while new_pricedata.index.values[len(new_pricedata.index.values)-1] == pricedata.index.values[len(pricedata.index.values)-1] and counter < 3:
        print("No updated prices found, trying again in 10 seconds...")
        counter+=1
        time.sleep(10)
        new_pricedata = con.get_candles(symbol, period=timeframe, number=numberofcandles)
    if new_pricedata.index.values[len(new_pricedata.index.values)-1] != pricedata.index.values[len(pricedata.index.values)-1]:
        pricedata = new_pricedata
        return True
    else:
        return False

Step 8. Code the Update() function.

Finally, we get to the part of our code where we tell our program how we want to trade. Update() is run every time a price bar/candle closes. We also know that the global variable ‘pricedata’ contains the latest data available for whatever trading tools/rules we want to use. Since this is just a template, however, we will simply print the latest close price into the console.

# This function is run every time a candle closes
def Update():
    print(str(dt.datetime.now()) + "  " + timeframe + " Bar Closed - Running Update Function...")
                
    print("Close Price: " + str(pricedata['bidclose'][len(pricedata)-1]))

    print(str(dt.datetime.now()) + "  " + timeframe + " Update Function Completed.\n")

Step 9. Run our Prepare() and StrategyHeartBeat()

We now want to run the Prepare() function and begin our StrategyHeartBeat() function. This will initialize all the code we’ve written and begin running the strategy.

Prepare() # Initialize strategy
StrategyHeartBeat() # Run strategy

Step 10. Run our strategy inside our command console.

Now it’s time to run our python file! My template file is located on my desktop. So I can run the file with the following command.

The strategy will first receive and print the price data (from the Prepare() function), then every time a bar closes after that, the Update() is run, printing the latest close price. I had my timeframe set to ‘m1’ or a 1-minute bar/candle size.

What Next?

Good work! The hard part is over. Now that you have a functioning template, it’s time to add some actual trading logic to it. The next few articles in our series will show how to do just that using various trading techniques.

Next Articles:
Developing a RSI Range Strategy


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.