The Problem
Clients need a thin wrapper around Twelve Data’s REST and WebSocket endpoints to fetch market‑time series, fundamentals and technical indicators. Without a dedicated client they must hand‑craft URLs, parse CSV/JSON, and manage authentication for each request, which leads to duplicated boiler‑plate and error‑prone code.
What This Does
The repository implements a Python client library (twelvedata package) that abstracts the HTTP and WebSocket APIs. Core files are:
src/twelvedata/client.py– builds aTDClientobject, holds the API key and exposes high‑level methods (time_series,get_stocks_list, etc.).src/twelvedata/endpoints.py– constructs endpoint URLs, validates symbols, and delegates to the HTTP client.src/twelvedata/time_series.py– wraps a time‑series response and provides convenience renderers (as_json,as_csv,as_pandas,as_plotly_figure).src/twelvedata/websocket.py– manages real‑time streams via thewebsocket-clientlibrary.
Supporting modules (utils.py, mixins.py, renders.py, http_client.py, exceptions.py) provide shared helpers, error handling and optional pandas/matplotlib/plotly output.
How It Is Wired
Execution starts when a user creates TDClient(apikey="YOUR_KEY") (class defined in src/twelvedata/client.py). The client stores the key and creates a DefaultHttpClient (in src/twelvedata/http_client.py).
- Endpoint resolution – Calls
executeinsrc/twelvedata/endpoints.py(line 225) which invokesbuild_url(135 calls) andget_symbol(96 calls). Both functions rely onpurify_symbolfrom the same file. - HTTP request –
executeforwards the URL toDefaultHttpClient.get, which performs the outbound network call (4 functions in the repo make external requests). - Response handling – The raw JSON is passed to
src/twelvedata/time_series.pywhereas_json,as_csv,as_pandas,as_plotly_figureare defined. These are the most‑used helpers (called 90‑130 times each). - WebSocket –
TDClient.websocketcreates aWebSocketobject (src/twelvedata/websocket.py) that opens a socket, registers default logger, symbols and event queue, then yields live messages.
The internal call graph shows 1,263 resolved edges; the hub functions (as_json, as_url, as_csv, as_pandas) have the widest blast radius because they are referenced from 96‑132 places across the code base.
Circular imports involve seven modules (endpoints.py, utils.py, __init__.py, time_series.py, client.py, mixins.py, renders.py). This adds maintenance friction: a change in any of these files risks import‑time failures unless imports are deferred or refactored.
How To Use It
# Clone the repo
git clone https://github.com/moses-y/twelvedata-python
cd twelvedata-python
# Install core package (pandas, matplotlib, plotly, websocket optional)
pip install -e .[pandas,matplotlib,plotly,websocket-client]
# Example usage
python - <<'PY'
from twelvedata import TDClient
client = TDClient(apikey="YOUR_KEY")
ts = client.time_series(symbol="AAPL", interval="1min", outputsize=5)
print(ts.as_json())
PY
Configuration – The only required runtime value is the API key passed to TDClient. No external config files are present.
Running tests – pytest tests/test_client.py executes the two test files; they rely on a mocked HTTP client (_fake_resp, _fake_json_resp).
Real‑World Use
A trading platform can embed the client to pull end‑of‑day OHLC data for a watchlist, convert it to a pandas DataFrame (as_pandas), and feed it into a back‑testing engine. Real‑time price updates are received via client.websocket() and routed into an in‑memory queue for low‑latency order‑book reconstruction.
Code Health & Issues
- High – Oversized files:
src/twelvedata/endpoints.py,src/twelvedata/time_series.py,tests/test_client.pyeach exceed 8 k lines, making local changes high‑risk. - High – Import cycles: 7 modules (e.g.,
endpoints.py,utils.py,__init__.py) form circular dependencies, complicating refactoring. - High – Deep nesting:
src/twelvedata/renders.pyandsrc/twelvedata/time_series.pycontain nesting depth of 9, reducing readability. - High – Duplicated logic: Repeated 6‑line blocks appear in both
endpoints.pyandtime_series.py. - Medium – Broad exception handling:
src/twelvedata/__init__.pycatches genericException, potentially hiding errors. - Medium – High branching density:
docs/conf.pyhas 28 branches in 70 lines, making the Sphinx config harder to maintain. - Medium – Large binary asset:
asset/chart-example.gif(12.3 MB) inflates repository size; should be moved to Git LFS or external storage. - Low – Missing lockfile: Dependencies are declared in
Pipfilewithout a lockfile, leading to non‑reproducible builds.
The Bottom Line
The library delivers a functional wrapper around Twelve Data’s API with convenient output formats, but the codebase suffers from oversized, tightly coupled modules and circular imports that hamper maintainability. It is suitable for teams that need quick integration and are prepared to refactor the core files for long‑term stability.