Metadata-Version: 2.4
Name: exante-cli
Version: 1.0.30
Summary: Exante CLI — trade, query, and manage your Exante account from the terminal
License: MIT
Keywords: exante,trading,cli,api
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: typer>=0.12
Requires-Dist: httpx>=0.27
Requires-Dist: rich>=13
Requires-Dist: tomli-w>=1.0
Requires-Dist: tomli>=2; python_version < "3.11"
Requires-Dist: keyring>=24
Requires-Dist: pywin32-ctypes>=0.2; sys_platform == "win32"

# Exante CLI

Terminal client for the Exante HTTP API — trade, query market data, and manage
your account from the shell.

**API docs:** <https://api-live.exante.eu/api-docs/>

## Install

```bash
pip install exante-cli
exante --help
```

## Configuration

All behaviour that isn't a per-command argument is driven by the persisted
config — **nothing is read from environment variables**. Set defaults once with
`exante config set` and they apply to every invocation:

```bash
exante config set --env demo            # trading env: live or demo
exante config set --account <ACC>       # default account id
exante config set --currency EUR        # default currency
```

Flags can be combined in one call:

```bash
exante config set --env demo --account <ACC> --currency EUR
```

Inspect the current defaults and the config file location:

```bash
exante config show
```

| Setting     | Flag            | Values          | Default          |
| ----------- | --------------- | --------------- | ---------------- |
| Trading env | `--env`         | `live` / `demo` | `live`           |
| Account     | `--account`     | account id      | unset (per slot) |
| Currency    | `--currency`    | currency code   | `EUR`            |

The default **account** and **currency** are stored **per trading-env slot** —
the same way credentials are slotted — so `demo` and `live` keep their own
defaults and switching env never reuses the wrong account. `config set
--account` writes to the slot being configured (after any `--env` in the same
call), and `config show` displays the active slot's values.

Config lives at `~/.config/exante/config.toml`.

## Auth

Requests are signed with HTTP **Basic** (`app_id:shared_secret`). Credentials
resolve with precedence **flag > keychain > config**:

| Source   | How |
| -------- | --- |
| flags    | `--app-id` + one of `--shared-secret-stdin` / `--shared-secret-file` / `--shared-secret` |
| keychain | stored by `exante login` (browser login), **per trading env** |
| config   | written directly in `~/.config/exante/config.toml` (`[auth]` section) |

### Browser login (recommended)

```bash
exante login                # opens the browser (PKCE), stores the key in the keychain
exante login --no-browser   # print the URL instead of opening a browser
exante logout               # clear stored credentials (config + both keychain slots)
```

`login` authorizes against the **configured environment** and stores the key in
the keychain slot for that trading env — so credentials for `demo` never clobber
`live`. Switch with `exante config set --env …` first, then re-run `login`.

After a successful login it auto-runs `accounts`; if that slot has exactly one
account it is saved as the slot's default account. (Any `exante accounts` call
does this — a single visible account is always written as the slot default.)

## Commands

Global options (`--output/-o table|json`, `--verbose/-v`, `--api-url`,
`--api-version`, credential flags) must **precede** the subcommand:

```bash
exante -o json quote AAPL.NASDAQ
```

### Top-level shortcuts

```bash
exante buy AAPL.NASDAQ 100 limit 150      # place a buy order
exante sell AAPL.NASDAQ 100 limit 155     # place a sell order
exante order <ORDER_ID>                   # get one order
exante cancel <ORDER_ID>                  # cancel a working order
exante quote AAPL.NASDAQ                  # last quote
exante xrate USD EUR                      # FX cross-rate
exante crossrates                         # currencies available for cross-rate
exante summary [--account A] [--currency C] [--date D]
exante repl                               # interactive shell (no `exante` prefix)
```

### Command groups

```bash
exante accounts

exante symbols get <SYM> | by-exchange <EX> | by-group <G> | nearest <G>
exante symbols exchanges | groups | types | currencies
exante symbols schedule <SYM> [--types] | spec <SYM>

exante market quote <SYM>
exante market ohlc  <SYM> --duration <SEC> [--from --to --size --candle-type]
exante market ticks <SYM> [--from --to --size --tick-type]
exante market crossrate <FROM> <TO>
exante market change --symbols A,B,C

exante orders active [--account --limit]            # only working orders
exante orders list   [--account --limit]            # active + recent orders
exante orders get <ID>
exante orders place --symbol S --side buy|sell --qty Q [--account A --order-type --limit-price --stop-price --tif --gtt-expiration --client-tag]
exante orders modify <ID> [--qty --limit-price --stop-price]
exante orders cancel <ID>

exante stream feed <SYMS> [--level] | orders | trades | market-trades <SYMS>

exante transactions [--account --from --to --op-type --symbol --limit --offset]
```

Use fully-qualified symbol ids (`<TICKER>.<EXCHANGE>`, e.g. `AAPL.NASDAQ`).

## Troubleshooting

A short runbook for the problems users actually hit. **Start with `-v`** — it
answers most questions on its own.

### 1. First step for any problem: `-v` / `--verbose`

Re-run the failing command with `-v`. It dumps to **stderr** the exact request
httpx put on the wire (method, final URL, all headers, body) and the full
response (status line, headers, body):

```bash
exante -v quote AAPL.NASDAQ
```

```
> GET https://api-live.exante.eu/md/3.0/feed/AAPL.NASDAQ
> host: api-live.exante.eu
> authorization: Basic TOKEN
> user-agent: exante-cli/<version>
< HTTP 404 Not Found
< content-type: application/json
< body: {"message":"Symbol not found"}
```

This tells you instantly **which URL** was called (so you can confirm env/version),
**whether auth was sent**, and **what the server actually answered**.

> `-v` prints the `Authorization` header in clear. Redact it before pasting
> verbose output into a ticket or chat.

### 2. See the raw API answer: `-o json`

When the rendered table hides what you need, ask for the unformatted response and
pipe it through `jq`:

```bash
exante -o json symbols get AAPL.NASDAQ | jq .
```

`-o json` prints exactly what the API returned, with no table/column massaging —
handy for spotting missing fields or unexpected values.

### 3. Reading the error category

Errors are categorised, so the prefix tells you where to look:

| You see                           | Likely cause                                               | What to do                                                                                            |
| --------------------------------- | ---------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| `Authentication failed: HTTP 401` | wrong/expired credentials                                  | re-run `exante login`, or check `--app-id` / the active slot with `exante config show`                |
| `Authentication failed: HTTP 403` | user has no permission on the instrument / no subscription | verify the user's permissions and subscriptions                                                       |
| `Validation error: HTTP 404`      | wrong symbol id / no permissions                           | use a fully-qualified `TICKER.EXCHANGE` id; confirm permissions (404 doesn't always mean "not found") |
| `Validation error: HTTP 400/422`  | malformed request / bad arguments                          | re-check flags; run with `-v` — may be a bug in the CLI                                               |
| `HTTP 429` rate limit             | too many requests                                          | user can raise the limits in the HTTP API dashboard                                                   |
