Skip to main content

Python SDK for London Strategic Edge: paper-account trading, real-time market data, historical candles

Project description

lse-data

Python SDK for London Strategic Edge — paper-account trading and market data for 12,000+ instruments including stocks, forex, crypto, ETFs, options, and commodities. Trade a paper account with a 12-digit api_key, stream live ticks, pull historical candles, all from one package.

Install

pip install lse-data

Command-line (easiest)

After install, save your key once and use the lse command anywhere:

lse auth lse_live_xxxxxxxxxxxx

# Fetch 30 days of gold 1h candles
lse candles XAU/USD --days 30 --timeframe 1h

# Write 5 years of gold 1m to CSV
lse candles XAU/USD --start 2021-01-01 --end 2026-01-01 --timeframe 1m --csv gold_5y.csv

# Stream live ticks
lse stream XAU/USD BTC/USD AAPL

# Browse the symbol catalog
lse catalog --category commodity

Quick start

from lse import LSE

client = LSE(api_key="your_api_key")

for tick in client.stream(["BTC/USD", "AAPL", "EUR/USD"]):
    print(f"{tick.symbol}: ${tick.price}")

Get your API key at londonstrategicedge.com/data.

Features

  • Historical OHLCV candles for 4,000+ instruments (REST, no WebSocket needed)
  • Real-time WebSocket streaming with auto-reconnect
  • 4,000+ symbols: US/UK/EU/Asia stocks, crypto, forex, indices, commodities, ETFs
  • 81,000+ option contracts via subscribe_options()
  • Symbol catalog API for discovery before subscribing
  • Server-side symbol validation (invalid symbols rejected immediately)
  • Dynamic subscribe/unsubscribe at runtime
  • Graceful disconnect (from callbacks or other threads)
  • Sync and async interfaces
  • Callback and iterator patterns
  • Paper-account trading via BrueTrading (MetaTrader-style 12-digit api_key, no JWT)
  • Zero config, just an API key

Paper-account trading

Each paper account on the LSE platform is auto-issued a 12-digit api_key at creation. That key alone is the credential for trading the account, the same way MetaTrader's expert advisor login number works. Use it for strategy bots, CI runners, or your own desktop terminal.

Top-level (simplest)

import lse

lse.auth_paper("047382910556")           # one-time, saves to ~/.lse/config.json

lse.buy("EUR/USD", 1, sl=1.10, tp=1.25)
lse.sell("XAU/USD", 0.5)
lse.buy_limit("EUR/USD", 1, price=1.05)

print(lse.account())                      # {'balance': ..., 'leverage': 50, ...}
for p in lse.positions():
    print(p)

lse.close_all("EUR/USD")                  # flatten one symbol
lse.close_all()                           # flatten everything

The api_key is resolved in this order: explicit lse.auth_paper(...) call -> LSE_PAPER_KEY env var -> ~/.lse/config.json. Set it any of those ways and the top-level helpers Just Work.

Class form (multi-account scripts)

from lse import BrueTrading

acct1 = BrueTrading("047382910556")
acct2 = BrueTrading("913280216532")

acct1.buy("EUR/USD", 1)
acct2.sell("XAU/USD", 0.5)

Full verb list (works on both surfaces): account, positions, orders, buy, sell, buy_limit, sell_limit, buy_stop, sell_stop, close, close_all. Errors raise BrueTradingError with the HTTP status preserved on the exception. Full reference: londonstrategicedge.com/docs/brue-trading.

Usage

Historical candles

Fetch OHLCV candles for any instrument. No WebSocket connection needed.

from lse import LSE

client = LSE(api_key="your_key")

# As a list of dicts
result = client.candles("XAU/USD", start="2021-01-01", end="2026-01-01", timeframe="1d")
print(f"{result['rows']} candles, plan: {result['plan']}")
for c in result["data"][-3:]:
    print(f"{c['timestamp']}  close={c['close']}")

# As a pandas DataFrame (pip install lse-data[pandas])
df = client.candles("AAPL", "2025-01-01", "2026-01-01", timeframe="1h", as_dataframe=True)
print(df.tail())

Supported timeframes: 1m, 5m, 15m, 30m, 1h, 2h, 4h, 1d

Works for all 4,000+ instruments: stocks, crypto, forex, ETFs, commodities, indices.

Large downloads with live progress

For multi-year 1m pulls (which exceed the 2M row single-call cap), pass progress=True. The SDK auto-chunks the request and shows a tqdm bar. Requires pip install lse-data[progress].

from lse import LSE

client = LSE(api_key="your_key")

df = client.candles(
    "XAU/USD",
    start="2021-01-01",
    end="2026-01-01",
    timeframe="1m",
    progress=True,
    as_dataframe=True,
)
# XAU/USD 1m: 100%|████████████| 61/61 [01:35<00:00,  1.6s/chunk]
# -> 1,872,343 rows

df.to_csv("gold_5y.csv")

Want custom chunk sizes? Pass chunk_days=30 (or any int). Defaults per timeframe: 1m=30d, 5m=180d, 15m=365d, 1h=1825d, 1d=3650d.

Stream ticks (simplest)

from lse import LSE

client = LSE(api_key="your_key")

for tick in client.stream(["BTC/USD", "ETH/USD", "AAPL"]):
    print(f"{tick.symbol:12s} ${tick.price:>12,.2f}")

Callback style

from lse import LSE

def on_tick(tick):
    print(f"{tick.symbol}: {tick.price}")

client = LSE(api_key="your_key")
client.on("tick", on_tick)
client.connect(symbols=["BTC/USD", "ETH/USD"])

Async streaming

import asyncio
from lse import LSE

async def main():
    client = LSE(api_key="your_key")
    async for tick in client.stream_async(["BTC/USD"]):
        print(tick)

asyncio.run(main())

Save to CSV

import csv, datetime
from lse import LSE

client = LSE(api_key="your_key")

with open("ticks.csv", "w", newline="") as f:
    writer = csv.writer(f)
    writer.writerow(["time", "symbol", "price", "bid", "ask"])

    for tick in client.stream(["BTC/USD", "ETH/USD"]):
        writer.writerow([
            datetime.datetime.now().isoformat(),
            tick.symbol, tick.price, tick.bid, tick.ask,
        ])

Tick object

Each tick has these fields:

Field Type Description
symbol str Instrument symbol (e.g. BTC/USD, AAPL)
price float Latest price
bid float Bid price (if available)
ask float Ask price (if available)
volume float Volume (if available)
timestamp float Unix timestamp
name str Human-readable name (e.g. Apple Inc.)

Events

When using the callback style with .on():

Event Callback args Description
tick Tick New price tick
connected (none) WebSocket connected
authenticated (none) API key accepted
disconnected (none) Connection lost (will auto-reconnect)
error str Error message

Symbol catalog

Query available instruments before subscribing. No WebSocket connection needed.

from lse import LSE

client = LSE(api_key="your_key")

# Get all available symbols
all_symbols = client.catalog()
print(f"{len(all_symbols)} instruments available")

# Filter by category: stock, crypto, forex, etf, commodity, index
stocks = client.catalog(category="stock")
crypto = client.catalog(category="crypto")

# Each entry has symbol, display_name, and category
for s in crypto[:5]:
    print(f"{s['symbol']:12s} {s['display_name']:20s} {s['category']}")

The catalog returns every subscribable instrument. Use it to build symbol pickers, validate user input, or discover what is available.

Available categories

Category Count Examples
stock ~3,987 AAPL, NVDA, TSLA, 0005.HK, 7203.T
forex ~62 EUR/USD, GBP/JPY, USD/CHF
crypto ~58 BTC/USD, ETH/USD, SOL/USD
etf ~25 SPY, QQQ, IWM, GLD
commodity ~23 XAU/USD, WTICO/USD, NATGAS/USD
index ~13 US30, NAS100, UK100

Options streaming

Subscribe to entire options chains by underlying. One call gives you every contract (calls + puts, all strikes, all expiries).

from lse import LSE

client = LSE(api_key="your_key")

def on_tick(tick):
    print(f"{tick.symbol}: ${tick.price:.2f}")

client.on("tick", on_tick)
client.subscribe_options(["AAPL", "TSLA"])
client.connect()

To stop receiving a chain:

client.unsubscribe_options(["TSLA"])

Unsubscribe

Remove symbols at runtime without disconnecting:

client.unsubscribe(["BTC/USD"])      # stop one symbol
client.subscribe(["SOL/USD"])        # add another

Disconnect

Stop the stream and exit cleanly. Works from callbacks or another thread:

tick_count = 0

def on_tick(tick):
    global tick_count
    tick_count += 1
    if tick_count >= 100:
        client.disconnect()  # connect()/stream() returns

client.on("tick", on_tick)
client.connect(symbols=["BTC/USD"])
print("Done, collected 100 ticks")

Async version:

await client.disconnect_async()

Requirements

  • Python 3.8+
  • websockets (installed automatically)

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lse_data-0.9.3.tar.gz (106.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

lse_data-0.9.3-py3-none-any.whl (25.5 kB view details)

Uploaded Python 3

File details

Details for the file lse_data-0.9.3.tar.gz.

File metadata

  • Download URL: lse_data-0.9.3.tar.gz
  • Upload date:
  • Size: 106.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for lse_data-0.9.3.tar.gz
Algorithm Hash digest
SHA256 addc2ca5d4af477e3afefe645ed0576d8f86e1c66cf28e1713470dfa7bddc9e2
MD5 a20b595f3d37212899ef59090651d875
BLAKE2b-256 b7003a6725de7b036ae9386a7a40d8fa2f86032f21e30a44239a9e19487abd8a

See more details on using hashes here.

File details

Details for the file lse_data-0.9.3-py3-none-any.whl.

File metadata

  • Download URL: lse_data-0.9.3-py3-none-any.whl
  • Upload date:
  • Size: 25.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for lse_data-0.9.3-py3-none-any.whl
Algorithm Hash digest
SHA256 b7e291c13b160850b12bcfc32e7dee01b7de26f0200497e45e7f5871d44d99e7
MD5 9b240aa1d320b4a4f6711b4f10306ea5
BLAKE2b-256 6650a0ee3133f6171134acc0362afe6c60bd0a199a82e4bf6e1fe5e14e3a3901

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page