DEV Community

Volker Bohn
Volker Bohn

Posted on

Building AI Market Briefings in Python with the Charlie API

Market preparation can be repetitive.

Before looking at charts, many traders and analysts ask themselves the same questions every day:

  • What is the current market tone?
  • Is the market trending, ranging, or noisy?
  • Are there any relevant signals or risk factors?
  • What should I pay attention to before making a decision?

I wanted to automate part of this workflow with a small Python script.

Not a trading bot.

Not a blind signal generator.

Not financial advice.

Just a simple command-line tool that calls an API and returns a structured market briefing.

In this article, I will show a minimal Python example that calls the darwintIQ Charlie API and prints a readable market briefing.

The full example script is available here:

GitHub example script


What we are building

The script does five things:

  1. Reads an API token from an environment variable or command-line argument
  2. Builds a market briefing request
  3. Sends a POST request to the Charlie API
  4. Handles basic HTTP and network errors
  5. Prints either the full JSON response or a formatted summary

The default use case is a DAX market briefing:

python charlie_market_briefing_example.py
Enter fullscreen mode Exit fullscreen mode

You can also request another symbol:

python charlie_market_briefing_example.py --symbol XAUUSD
Enter fullscreen mode Exit fullscreen mode

Or ask a more specific question:

python charlie_market_briefing_example.py \
  --symbol EURUSD \
  --prompt "Give me a trader's desk briefing on EURUSD. What is currently driving the tone?"
Enter fullscreen mode Exit fullscreen mode

Why market briefings?

Most trading tools focus on either raw data or final buy/sell signals.

But there is a useful layer in between:

structured market context

A market briefing can help summarize:

  • current tone
  • directional bias
  • confidence
  • main risks
  • relevant observations
  • supporting evidence

That is useful for human decision-making because it does not replace your own analysis. It gives you a structured starting point.

I like to think of it as a trader's desk briefing generated from quantitative context.


No external Python dependencies

This example intentionally does not use any external packages.

It only uses Python's standard library:

import argparse
import json
import os
import sys
import urllib.error
import urllib.request
from typing import Any
Enter fullscreen mode Exit fullscreen mode

That keeps the script easy to run in almost any Python environment.

No virtual environment required.

No pip install requests.

No additional setup beyond an API token.


Basic configuration

The script defines a few defaults:

DEFAULT_BASE_URL = "https://api.darwintiq.com/v1/charlie"
DEFAULT_SYMBOL = "DAX"
DEFAULT_WORKFLOW_ID = "market_briefing"
DEFAULT_PROMPT = (
    "Give me a trader's desk briefing on DAX. "
    "What is actually driving the current tone?"
)
Enter fullscreen mode Exit fullscreen mode

The default workflow is market_briefing.

The default symbol is DAX.

The default prompt asks Charlie to explain what is currently driving the market tone.

You can override all of this from the command line.


Authentication

The script expects an API token.

You can either set it as an environment variable:

export DARWINTIQ_API_TOKEN="your_api_token_here"
Enter fullscreen mode Exit fullscreen mode

Or pass it directly:

python charlie_market_briefing_example.py --token your_api_token_here
Enter fullscreen mode Exit fullscreen mode

For local development, the environment variable is usually cleaner.

The script reads it like this:

parser.add_argument(
    "--token",
    default=os.getenv("DARWINTIQ_API_TOKEN"),
    help="API token. Defaults to DARWINTIQ_API_TOKEN.",
)
Enter fullscreen mode Exit fullscreen mode

If no token is available, the script exits with a clear error message:

if not args.token:
    parser.error(
        "missing API token. Set DARWINTIQ_API_TOKEN or pass --token."
    )
Enter fullscreen mode Exit fullscreen mode

Building the API payload

The request payload contains three required parts:

  • symbol
  • workflowId
  • messages
def build_payload(args: argparse.Namespace) -> dict[str, Any]:
    payload: dict[str, Any] = {
        "symbol": args.symbol,
        "workflowId": args.workflow_id,
        "messages": [
            {
                "role": "user",
                "content": args.prompt,
            }
        ],
    }
    if args.timeframe:
        payload["timeframe"] = args.timeframe
    if args.signal_mode:
        payload["signalMode"] = args.signal_mode
    return payload
Enter fullscreen mode Exit fullscreen mode

This structure makes the script flexible.

You can use the default briefing workflow, but you can still adapt the prompt, symbol, timeframe, or signal mode from the CLI.

For example:

python charlie_market_briefing_example.py \
  --symbol DAX \
  --timeframe H1 \
  --prompt "Give me a short briefing for the next trading session."
Enter fullscreen mode Exit fullscreen mode

Calling the API

The API request is a normal HTTP POST request with a JSON body and Bearer token authentication:

request = urllib.request.Request(
    url,
    data=body,
    method="POST",
    headers={
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json",
        "Accept": "application/json",
    },
)
Enter fullscreen mode Exit fullscreen mode

The response is decoded and parsed as JSON:

with urllib.request.urlopen(request, timeout=timeout) as response:
    raw = response.read().decode("utf-8")
    return json.loads(raw)
Enter fullscreen mode Exit fullscreen mode

The script also handles common error cases:

except urllib.error.HTTPError as exc:
    raw = exc.read().decode("utf-8", errors="replace")
    try:
        detail = json.loads(raw)
    except json.JSONDecodeError:
        detail = {"error": raw or exc.reason}
    raise SystemExit(
        f"HTTP {exc.code} calling Charlie API:\n"
        f"{json.dumps(detail, indent=2, ensure_ascii=False)}"
    ) from exc
except urllib.error.URLError as exc:
    raise SystemExit(f"Network error calling Charlie API: {exc.reason}") from exc
Enter fullscreen mode Exit fullscreen mode

This is useful because API examples often show only the happy path.

In practice, good error messages matter.


Printing a readable briefing

The API response can be printed as raw JSON:

python charlie_market_briefing_example.py --json
Enter fullscreen mode Exit fullscreen mode

But for daily usage, a formatted summary is easier to read.

The script extracts fields such as:

  • symbol
  • workflowLabel
  • language
  • summary
  • answer
  • evidence
def print_formatted_response(data: dict[str, Any]) -> None:
    answer = data.get("answer")
    workflow_label = data.get("workflowLabel")
    symbol = data.get("symbol")
    language = data.get("language")
    summary = data.get("summary") or {}
    evidence = data.get("evidence") or []

    print(f"Symbol: {symbol}")
    print(f"Workflow: {workflow_label}")
    print(f"Language: {language}")
Enter fullscreen mode Exit fullscreen mode

If a summary is available, it prints the most important fields:

bottom_line = summary.get("bottomLine")
bias = summary.get("bias")
confidence = summary.get("confidence")
main_risk = summary.get("mainRisk")
Enter fullscreen mode Exit fullscreen mode

That gives the briefing a clean structure:

Symbol: DAX
Workflow: Market Briefing
Language: en
Bottom line: ...
Bias: ...
Confidence: ...
Main risk: ...

Answer:

...

Evidence:
- ...
- ...
Enter fullscreen mode Exit fullscreen mode

This makes the output useful as a command-line briefing, a journal entry, or an input for another automation.


Example usage

Default DAX briefing:

python charlie_market_briefing_example.py
Enter fullscreen mode Exit fullscreen mode

Briefing for another symbol:

python charlie_market_briefing_example.py --symbol XAUUSD
Enter fullscreen mode Exit fullscreen mode

Custom prompt:

python charlie_market_briefing_example.py \
  --symbol DAX \
  --prompt "Give me a concise trader's desk briefing before the European session."
Enter fullscreen mode Exit fullscreen mode

Timeframe override:

python charlie_market_briefing_example.py \
  --symbol EURUSD \
  --timeframe H1
Enter fullscreen mode Exit fullscreen mode

Full JSON response:

python charlie_market_briefing_example.py --symbol DAX --json
Enter fullscreen mode Exit fullscreen mode

Example output

A formatted response could look like this:

Symbol: DAX
Workflow: Market Briefing
Language: en
Bottom line: The market tone is cautious, with direction still depending on follow-through.
Bias: Neutral to slightly bullish
Confidence: Medium
Main risk: Volatility around macro headlines

Answer:

The current DAX tone appears to be driven by a mix of short-term momentum,
risk sentiment, and uncertainty around upcoming macro catalysts.

Evidence:
- Recent model context shows mixed but improving conditions.
- Momentum is present, but not strong enough to remove downside risk.
- The next session may depend heavily on whether buyers can maintain pressure.
Enter fullscreen mode Exit fullscreen mode

This is only an illustrative example. Real API output depends on the selected symbol, market conditions, workflow, and prompt.


Possible extensions

Once you have a basic CLI client, you can build more useful workflows around it.

For example:

1. Save briefings as Markdown

You could store each briefing in a daily trading journal.

from datetime import datetime

date = datetime.utcnow().strftime("%Y-%m-%d")
filename = f"{date}-DAX-briefing.md"
Enter fullscreen mode Exit fullscreen mode

2. Send the briefing to Telegram or Discord

Instead of printing to the terminal, the script could send the briefing to a private channel every morning.

3. Generate briefings for multiple symbols

symbols = ["DAX", "XAUUSD", "EURUSD", "GBPUSD"]

for symbol in symbols:
    # call API for each symbol
    ...
Enter fullscreen mode Exit fullscreen mode

4. Use it as part of a dashboard

The same API response could be displayed in a web dashboard, internal tool, or trading assistant interface.

5. Connect it to MetaTrader workflows

A Python script like this could also act as a bridge between an external analysis API and a MetaTrader-based workflow.


What this is not

This kind of tool should not be misunderstood.

It is not:

  • a trading bot
  • a guaranteed signal generator
  • financial advice
  • a replacement for risk management
  • a promise of future performance

The goal is to make market context easier to consume.

A good briefing should support your thinking, not replace it.


Final thoughts

I like the idea of treating market briefings as an API workflow.

Instead of manually collecting information from different dashboards, a developer can call an API, request structured market context, and turn the response into a readable briefing.

For this example, I used the Charlie API from darwintIQ.

Charlie is designed to work like a personal Quant analyst: it turns quantitative market context into readable briefings and helps traders understand what may be driving the current tone.

The focus is not automated trade execution.

The focus is better market preparation.

If you are building trading tools, dashboards, journals, or MetaTrader workflows and want to add AI-generated market context, Charlie can be used as a briefing layer via API.

It is not designed to place trades for you.

It is designed to help you understand the current market tone faster.

You can find the full Python example here:

GitHub example script

And more about Charlie here:

Charlie documentation

Thanks for reading.

Top comments (0)