Broker API HubMenu

Stage 3 of 4, lesson 17 of 31. Improver

Your first API call: read your positions on a demo account

Log in to a demo account from Python and read your open positions. The script only reads: it cannot place a trade. It introduces HTTP requests, headers, sessions and pacing.

Independent and unofficialTest pending

Risk warning: CFDs and spread bets are complex instruments and come with a high risk of losing money rapidly due to leverage. You can lose money on these products, and each provider publishes its own loss figure under FCA rules. You should consider whether you understand how they work and whether you can afford to take the high risk of losing your money. Automated and API trading can amplify losses through bugs, connectivity failures and runaway orders.

You need: The lessons on reading an API response and on keys, an IG demo account with an API key, and the requests package.

This is the same job as the lesson on reading an API response, except the answer now comes from a broker's demo system instead of a file. Install the one package it needs with: pip install requests

The script does three things. It logs in, which returns two tokens. It waits. Then it asks for your positions, sending the tokens back so the broker knows who is asking.

The wait matters. Brokers limit how many requests you may send, and a loop with no pause can spend a week's allowance in seconds. The limits below are read from this site's register. Where the broker's own pages disagree, pace against the lower figure.

When a call fails, the answer carries an error code. Do not guess: look the code up. The error pages on this site say what each one means and how to fix it.

This is the one lesson in the track that needs a broker account, and it is optional. Every lesson after it runs offline, so you can read this one and carry on.

The code

# Your first real API call, against a DEMO account only.
# Set these three environment variables on your own machine first.
# Never type them into this file, and never type them into any website, including this one.
#   IG_API_KEY, IG_USERNAME, IG_PASSWORD
# They are the same three names the IG quickstart on this site uses, so a value set for one works for the other.
import os
import time
import requests

BASE_URL = "https://demo-api.ig.com/gateway/deal"  # the demo host, not the live one

session = requests.Session()
session.headers.update({
    "X-IG-API-KEY": os.environ["IG_API_KEY"],
    "Accept": "application/json; charset=UTF-8",
    "Content-Type": "application/json; charset=UTF-8",
})

# Step 1: log in. The answer carries two tokens in its headers.
login = session.post(
    BASE_URL + "/session",
    json={"identifier": os.environ["IG_USERNAME"], "password": os.environ["IG_PASSWORD"]},
    headers={"VERSION": "2"},
    timeout=10,
)
login.raise_for_status()
session.headers.update({
    "CST": login.headers["CST"],
    "X-SECURITY-TOKEN": login.headers["X-SECURITY-TOKEN"],
})

# Step 2: wait a moment between calls. A script that never pauses is how limits get broken.
time.sleep(2)

# Step 3: read your open positions. This call only reads. It cannot place a trade.
positions = session.get(BASE_URL + "/positions", headers={"VERSION": "2"}, timeout=10)
positions.raise_for_status()

for item in positions.json()["positions"]:
    print(item["market"]["instrumentName"], item["position"]["direction"], item["position"]["size"])

Test pending. This script has been checked for syntax and written from the endpoints recorded on this site. It has not been run end to end against a demo account, so it carries no tested mark. Credentials are read from environment variables on your own machine and are never entered on this site.

IG limits, from the register

LimitValueScopeSource
Historical price data points a week10,000Per account, price history endpoints onlylabs.ig.comchecked
Non trading requests a minute30Per account, non trading calls onlylabs.ig.comchecked
Non trading requests a minute60Per application, that is per API key, non trading calls onlylabs.ig.comchecked
Concurrent streaming subscriptions40Per streaming connectionlabs.ig.comchecked corroborated by labs.ig.com/streaming-api-guide.html
Trading requests a minute100Sources conflict ig.com states around 40, checked . IG's own pages disagree. The conflict is labelled, not resolved. Pace against 40.Per account, trading calls onlylabs.ig.comchecked

Endpoints this lesson uses

Errors you may meet

Check yourself

Answer each question from the code above before you open it. The answers were written from the script on this page and what it printed.

Where do the key, the username and the password come from?

From three environment variables, read with os.environ. None of them is written in the file, so the script can be shared without sharing them.

What is the time.sleep(2) between the two calls for?

It pauses for two seconds so the script does not send requests back to back. The comment says why: a script that never pauses is how limits get broken.

What does raise_for_status do after each call?

It stops the script with an error if the broker answered with an error status, instead of carrying on and trying to read a reply that is not there.

Exercise

Before listing the positions, print how many are open. Keep the reply in a variable so the script still makes only one positions call.

Test pending. The solution below has been checked for syntax only. It has not been run against a demo account, so no expected output is printed for it.

One solution, not yet run
# Exercise solution: the lesson script with the one change the exercise asks for.
# Your first real API call, against a DEMO account only.
# Set these three environment variables on your own machine first.
# Never type them into this file, and never type them into any website, including this one.
#   IG_API_KEY, IG_USERNAME, IG_PASSWORD
# They are the same three names the IG quickstart on this site uses, so a value set for one works for the other.
import os
import time
import requests

BASE_URL = "https://demo-api.ig.com/gateway/deal"  # the demo host, not the live one

session = requests.Session()
session.headers.update({
    "X-IG-API-KEY": os.environ["IG_API_KEY"],
    "Accept": "application/json; charset=UTF-8",
    "Content-Type": "application/json; charset=UTF-8",
})

# Step 1: log in. The answer carries two tokens in its headers.
login = session.post(
    BASE_URL + "/session",
    json={"identifier": os.environ["IG_USERNAME"], "password": os.environ["IG_PASSWORD"]},
    headers={"VERSION": "2"},
    timeout=10,
)
login.raise_for_status()
session.headers.update({
    "CST": login.headers["CST"],
    "X-SECURITY-TOKEN": login.headers["X-SECURITY-TOKEN"],
})

# Step 2: wait a moment between calls. A script that never pauses is how limits get broken.
time.sleep(2)

# Step 3: read your open positions. This call only reads. It cannot place a trade.
positions = session.get(BASE_URL + "/positions", headers={"VERSION": "2"}, timeout=10)
positions.raise_for_status()

open_positions = positions.json()["positions"]
print("Open positions:", len(open_positions))
for item in open_positions:
    print(item["market"]["instrumentName"], item["position"]["direction"], item["position"]["size"])

Your progress

Next: Paged results

Your marks are kept in this browser only, in its local storage. They are not sent anywhere, there is no account, and they will not follow you to another browser or device. To remove them, use Clear my progress on the learning track page, or clear this site's data in your browser's settings. Marking needs JavaScript. With scripts off the track reads the same, without the ticks.

Where this sits in the path

Stage 3 of 4: Talking to a broker. What an API sends back, real requests to a practice API that needs no account, how to keep a key safe, a first read only call on a demo account, and histories that arrive in pages.

  1. Read an API response
  2. First HTTP request
  3. Positions and exposure
  4. Keys and demo accounts
  5. First API callYou are here
  6. Paged results
  7. Follow the next page
  8. Price history to CSV

The whole path, every stage

Repositories to read next

The full repository list

Back: Keys and demo accountsNext: Paged results