<!-- https://zunderlabs.com/docs/integrations/freqtrade · Markdown version of the page -->

# Freqtrade

Put Guard in front of Freqtrade's Hyperliquid exchange through ccxt_config. The exact config keys.

:::note[Planned]
Guard 1.0 integration, not verified yet. Written from [Freqtrade's exchange notes for Hyperliquid](https://www.freqtrade.io/en/stable/exchanges/) and [configuration reference](https://www.freqtrade.io/en/stable/configuration/), read 6 Oct 2026, and from ccxt's source (see the [ccxt guide](https://zunderlabs.com/docs/integrations/ccxt)).
:::

Freqtrade trades Hyperliquid through ccxt. Its `exchange.ccxt_config` is passed to both of Freqtrade's ccxt instances (sync and async), so the [ccxt override](https://zunderlabs.com/docs/integrations/ccxt) goes there.

## The change

```diff
 "exchange": {
     "name": "hyperliquid",
     "walletAddress": "0xYourAccountAddress",
-    "privateKey": "0x…API wallet key…",
+    "privateKey": "0x…client key from Guard…",
+    "ccxt_config": {
+        "urls": {"api":  {"public": "http://127.0.0.1:8547", "private": "http://127.0.0.1:8547"},
+                 "test": {"public": "http://127.0.0.1:8547", "private": "http://127.0.0.1:8547"}},
+        "options": {"builderFee": false, "refSet": true}
+    }
 }
```

## Full `exchange` block

```json
"exchange": {
    "name": "hyperliquid",
    "walletAddress": "0xYourAccountAddress",
    "privateKey": "0x...",
    "ccxt_config": {
        "urls": {
            "api":  {"public": "http://127.0.0.1:8547", "private": "http://127.0.0.1:8547"},
            "test": {"public": "http://127.0.0.1:8547", "private": "http://127.0.0.1:8547"}
        },
        "options": {"builderFee": false, "refSet": true}
    }
}
```

## The config keys

| Key | Value | Source |
|---|---|---|
| `exchange.name` | `hyperliquid` | Freqtrade exchange notes |
| `exchange.walletAddress` | your **main** account address, `0x` + 40 hex digits, not the API wallet's | Freqtrade exchange notes |
| `exchange.privateKey` | the Guard client key, `0x` + 64 hex digits. Freqtrade's notes say to use an API wallet key here; behind Guard, the client key takes its place | Freqtrade exchange notes |
| `exchange.ccxt_config.urls` | Guard's URL, for `api` and `test` | Freqtrade configuration reference; ccxt `sign()`, `set_sandbox_mode()` |
| `exchange.ccxt_config.options` | `builderFee: false`, `refSet: true` | ccxt `initialize_client()`; why: [ccxt guide](https://zunderlabs.com/docs/integrations/ccxt#two-ccxt-defaults-behind-guard) |

Freqtrade's notes also show `ccxt_config.options.vaultAddress` and `subAccountAddress` for vaults and sub-accounts. Guard's support for those is not built.

## The stop: an open problem

Guard [needs the stop with the entry](https://zunderlabs.com/docs/integrations#send-the-stop-with-the-entry). Freqtrade sends the entry first and, with `stoploss_on_exchange`, places its stop after the entry has filled. Under Guard's default rules such an entry is refused (`no_protective_stop`).

:::caution[Not solved yet]
How Guard 1.0 handles bots that place the stop after the entry is open. The candidates are the planned `stopPolicy = "attach"` (Guard places a stop itself), or a short window in which the bot's own stop must follow. Until this is decided, Freqtrade works behind Guard only with `requireStop` off, and then Guard cannot size from a stop. This guide will say which way it went before it is marked verified.
:::

## Two layers of limits

Freqtrade has its own protections (stoploss, max open trades, `StoplossGuard` and others). Keep them. Guard is the layer that still holds when Freqtrade's own logic fails or its config is wrong.

**Example.** A config change sets `stake_amount` ten times too high. Freqtrade sends an order worth 30,000 on an account of 2,000. Guard cuts it to the room your limits leave (at most 4,000 in one coin under the default 200% position cap, less if other positions use the 5x leverage room), and the trade opens at that size. Freqtrade's next status shows the smaller filled amount.

## Dry run

In `dry_run` mode Freqtrade simulates its own orders and sends none, so Guard sees nothing to judge. To see Guard's decisions without risk, run Freqtrade live against a Guard in [paper mode](https://zunderlabs.com/docs/concepts/networks#paper).
