Freqtrade
Put Guard in front of Freqtrade's Hyperliquid exchange through ccxt_config. The exact config keys.
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 goes there.
Before you change anything
Section titled “Before you change anything”- Read the setup journey and start Guard in paper mode.
- Keep your real account address. Give the bot a Guard client key, while the API wallet key stays inside Guard.
- Check the network and isolated-margin requirements in this guide. These integration instructions are planned and not verified against a released Guard yet.
The smallest change
Section titled “The smallest change”"trading_mode": "futures","margin_mode": "isolated","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} }}The config, in full
Section titled “The config, in full”The keys to merge into Freqtrade’s config.json (the rest of your config stays as it is):
{ "trading_mode": "futures", "margin_mode": "isolated", "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} } }}filled in from your settings ·
The config keys
Section titled “The config keys”| Key | Value | Source |
|---|---|---|
trading_mode | futures | Hyperliquid’s perps; Freqtrade configuration reference |
margin_mode | isolated | required. Freqtrade sends updateLeverage before every entry and every stop, and Guard refuses cross margin |
exchange.name | hyperliquid | Freqtrade exchange notes |
exchange.walletAddress | your main account address, 0x + 40 hex digits, not the API wallet’s. Freqtrade passes it to ccxt as walletAddress, the user of its account queries | Freqtrade exchange notes |
exchange.privateKey | the Guard client key, 0x + 64 hex digits. Freqtrade passes it to ccxt as privateKey, which signs every request. 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; never approvedBuilderFee: true | ccxt initialize_client(); why: ccxt guide |
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
Section titled “The stop”Guard needs the stop with the entry. Freqtrade sends the entry first and, with stoploss_on_exchange, places its stop after the entry has filled, in a request of its own.
Under Guard’s default rules (stop = "attach" in guard.toml) that works: Guard attaches its own reduce-only market stop to the entry, 2% away (default_stop_distance), and sizes the entry from it. When Freqtrade’s stop-limit arrives, it rests beside Guard’s stop but never replaces it, since a stop-limit may not fill. Freqtrade’s later stop moves (cancel and replace of its own stop-limit) pass. With stop = "refuse", Freqtrade’s entries are refused (no_protective_stop).
So behind Guard a Freqtrade trade is sized from Guard’s stop distance, not from Freqtrade’s stoploss. Set default_stop_distance to the stop you want Guard to size from.
Two layers of limits
Section titled “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 sizes it from its stop 2% away: the trade may lose at most 2% of 2,000, so 40, at the stop, costs included (4.5 + 1 basis points per side, 0.11% for the round trip). That allows about 40 / (0.02 + 0.0011) ≈ 1,896 of value, and the trade opens at about that size, less if other positions use the open-risk or leverage room. Freqtrade’s next status shows the smaller filled amount.
Dry run
Section titled “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.
Read the response
Section titled “Read the response”The reply uses Hyperliquid’s response format. Check the returned status and order size rather than assuming the requested size was accepted. A refusal includes a readable reason and a veto code; a smaller accepted order reflects the rule that bound its size. Paper mode sends no venue order. Test this path before using testnet.
This page as plain Markdown, for people and LLMs: /docs/integrations/freqtrade.md