AI Agent Trading on DEX
v3.0.10Backtest and deploy trading strategies on Superior Trade's managed cloud.
Like a lobster shell, security has layers — review code before you run it.
License
Runtime requirements
SUPERIOR_TRADE_API_KEYrequired— Superior Trade API key (x-api-key header). Obtained at https://account.superior.trade. Can create/manage backtests and deployments including live trading. Cannot withdraw funds, export private keys, or access other users' data. Users do not need their own Hyperliquid wallet.SKILL.md
Superior Trade API
API client skill for backtesting and deploying trading strategies on Superior Trade's managed cloud.
Base URL: https://api.superior.trade
Auth: x-api-key header on all protected endpoints
Docs: GET /docs (Swagger UI), GET /openapi.json (OpenAPI spec)
Setup
Getting an API Key
IMPORTANT: The correct URL is https://account.superior.trade — NOT
app.superior.trade. Never send users toapp.superior.trade.
Use SUPERIOR_TRADE_API_KEY from the environment or credential manager.
When a user needs to get their API key:
- Go to https://account.superior.trade
- Sign up (email or wallet)
- Complete onboarding — a trading wallet is created for you and shown on the dashboard
- Deposit USDC to your wallet address (on Arbitrum)
- Create an API key (
st_live_...) from the dashboard - Add it as
SUPERIOR_TRADE_API_KEYin your agent's environment/credential settings
If the SUPERIOR_TRADE_API_KEY env var is already set, use it directly in the x-api-key header without prompting the user.
Public Endpoints (no auth)
| Method | Path | Description |
|---|---|---|
| GET | /health | { "status": "ok", "timestamp": "..." } |
| GET | /docs | Swagger UI |
| GET | /openapi.json | OpenAPI 3.0 spec |
| GET | /llms.txt | LLM-optimized API docs |
| GET | /.well-known/ai-plugin.json | AI plugin manifest |
Safety
Security & Permissions
This skill requires exactly one credential: an x-api-key header value. The only secret the agent uses is SUPERIOR_TRADE_API_KEY from the environment.
Security rules (non-negotiable):
- NEVER ask users for private keys, seed phrases, or wallet credentials
- NEVER include private keys in API requests (the API rejects them)
- NEVER log, store, or display private keys or seed phrases
- NEVER tell users to deposit funds to the agent wallet address
- NEVER fabricate wallet balances, API responses, or trade results
- NEVER start a live deployment without explicit user confirmation
- Prefer user-friendly language over internal technical names when speaking conversationally. Say "strategy", "the bot", or "the trading engine" instead of referencing internal class names or infrastructure details. This is a UX preference — if the user asks about the underlying technology, answer honestly (the platform uses Freqtrade for strategy execution on Hyperliquid).
- NEVER send users to
app.superior.trade— the correct URL ishttps://account.superior.trade
Key scope notice: The API key can create and start live trading deployments that execute real trades using the user's platform-managed trading wallet. It cannot withdraw funds, export private keys, or move money. Users should confirm scope with Superior Trade and backtest their strategy first.
| Can do | Cannot do |
|---|---|
| Create, list, delete backtests | Access other users' data |
| Create, start, stop, delete deployments (including live trading with real funds) | Withdraw funds from any wallet |
| Trigger server-side credential resolution (no user secrets collected) | Export or view private keys |
| View deployment logs, status, wallet metadata | Transfer or bridge funds (user does this independently) |
Live Deployment Confirmation
Before any live deployment, the agent MUST present this summary and wait for explicit confirmation:
Deployment Summary:
• Strategy: [name]
• Exchange: hyperliquid
• Trading mode: [spot/futures]
• Pairs: [list]
• Stake amount: [amount] USDC per trade
• Max open trades: [n]
• Stoploss: [percentage]
• Margin mode: [cross/isolated] (futures only)
⚠️ This will trade with REAL funds. Proceed? (yes/no)
Do NOT start a live deployment without an explicit affirmative response.
Platform Model
Wallet Architecture (CRITICAL)
Superior Trade uses Hyperliquid's native agent wallet pattern. Users do NOT need their own Hyperliquid wallet — everything is managed by the platform. If a user asks "how do I link my Hyperliquid account," the answer is: they don't need one — a trading wallet is created at signup.
- Main wallet — a platform-managed trading wallet created for each user at signup. Holds the funds on Hyperliquid. Users deposit USDC to this address via the dashboard at https://account.superior.trade.
- Agent wallet — a platform-managed signing key authorized via Hyperliquid's
approveAgent. Signs trades against the main wallet's balance.
Key facts:
- The agent wallet does NOT need its own funds — $0 balance is normal and expected
- Each user has one agent wallet; all deployments share it
- The credentials endpoint returns
wallet_type: "agent_wallet"for auto-resolved wallets - Always check the main wallet's balance, not the agent wallet's
- The API has no transfer/fund-routing endpoint — you cannot move funds via the API
- NEVER tell users to deposit to the agent wallet address
Funding and Balance Checks
The agent cannot move or bridge funds — the user handles this independently outside the skill:
- The user deposits USDC to their platform wallet address (shown on their dashboard at https://account.superior.trade)
- The agent wallet signs trades against this balance — no internal transfers needed
Always check the main wallet (platform-managed trading wallet), NOT the agent wallet.
These are read-only, unauthenticated queries to Hyperliquid's public API. The wallet address sent is public on-chain data — not a secret. No API keys, private keys, or auth tokens are included.
POST https://api.hyperliquid.xyz/info
{"type":"clearinghouseState","user":"<MAIN_WALLET_ADDRESS>"}
{"type":"spotClearinghouseState","user":"<MAIN_WALLET_ADDRESS>"}
The agent wallet having $0 is expected — it trades against the main wallet's balance.
Hyperliquid Credentials
Credentials are managed automatically. To use a specific wallet, pass wallet_address — ownership is validated server-side.
Exchange and Pair Rules
Supported Exchanges
| Exchange | Stake Currencies | Trading Modes |
|---|---|---|
| Hyperliquid | USDC (also USDT0, USDH, USDE via HIP3) | spot, futures |
Hyperliquid Notes
Pair format by trading mode (CCXT convention):
- Spot:
BTC/USDC - Futures/Perp:
BTC/USDC:USDC
Spot limitations: No stoploss on exchange (bot handles internally), no market orders (simulated via limit with up to 5% slippage).
Futures: Margin modes "cross" and "isolated". Stoploss on exchange via stop-loss-limit orders. No market orders (same simulation).
Data availability: Hyperliquid API provides ~5000 historic candles per pair. Superior Trade pre-downloads data; availability starts from ~November 2025.
Hyperliquid is a DEX — uses wallet-based signing, not API key/secret. Wallet credentials are managed automatically by the platform.
HIP3 — Tokenized Real-World Assets
HIP3 assets (stocks, commodities, indices) are perpetual futures.
CRITICAL: HIP3 uses a HYPHEN, not a colon. This is the #1 format mistake. Wrong:
XYZ:AAPL/USDC:USDC. Correct:XYZ-AAPL/USDC:USDC.
Pair format: PROTOCOL-TICKER/QUOTE:SETTLE — the separator between protocol and ticker is always - (hyphen).
| Protocol | Dex name | Asset Types | Stake Currency | Examples |
|---|---|---|---|---|
XYZ- | xyz | US/KR stocks, metals, currencies, indices | USDC | XYZ-AAPL/USDC:USDC, XYZ-GOLD/USDC:USDC |
CASH- | cash | Stocks, commodities | USDT0 | CASH-GOLD/USDT0:USDT0 |
FLX- | flx | Commodities, metals, crypto | USDH | FLX-GOLD/USDH:USDH |
KM- | km | Stocks, indices, bonds | USDH | KM-GOOGL/USDH:USDH |
HYNA- | hyna | Leveraged crypto, metals | USDE | HYNA-SOL/USDE:USDE |
VNTL- | vntl | Sector indices, pre-IPO | USDH | VNTL-SPACEX/USDH:USDH |
XYZ tickers (USDC): AAPL, ALUMINIUM, AMD, AMZN, BABA, BRENTOIL, CL, COIN, COPPER, COST, CRCL, CRWV, DKNG, DXY, EUR, EWJ, EWY, GME, GOLD, GOOGL, HIMS, HOOD, HYUNDAI, INTC, JP225, JPY, KIOXIA, KR200, LLY, META, MSFT, MSTR, MU, NATGAS, NFLX, NVDA, ORCL, PALLADIUM, PLATINUM, PLTR, RIVN, SILVER, SKHX, SMSN, SNDK, SOFTBANK, SP500, TSLA, TSM, URANIUM, URNM, USAR, VIX, XYZ100
Data: XYZ from ~November 2025, KM/CASH/FLX from ~February 2026. Timeframes: 1m, 3m, 5m, 15m, 30m, 1h (also 2h, 4h, 8h, 12h, 1d, 3d, 1w for some). Funding rate data at 1h.
Trading rules: HIP3 assets are futures-only — always use trading_mode: "futures". Most HIP-3 assets have onlyIsolated: true and MUST use margin_mode: "isolated". Always call pair_validate first and use the returned recommended_margin_mode value — do NOT default to "cross". XYZ pairs use stake_currency: "USDC". Stock-based assets may have reduced liquidity outside US market hours.
Pair Discovery
- Standard perps:
{"type":"meta"}— checkuniverse[].name - HIP3 pairs:
{"type":"meta", "dex":"xyz"}(or"cash","km", etc.) — HIP3 pairs are NOT in the default meta call - List all dexes:
{"type":"perpDexs"} - Name conversion: API returns
xyz:AAPL→ CCXT formatXYZ-AAPL/USDC:USDC(uppercase prefix, colon→hyphen)
Unified vs Legacy Account Mode
Hyperliquid accounts may run in unified mode (single balance) or legacy mode (separate spot/perps balances). Do NOT assume which mode the user has.
- If perps shows $0 but spot shows funds, ask about unified mode before suggesting the user move funds themselves.
- In unified mode, spot USDC is automatically available as perps collateral.
Agent Operating Rules
- Verification-first: Every factual claim about balance, wallet status, or deployment health MUST be backed by an API call in the current turn. NEVER assume → report → verify later.
- Anti-hallucination: If you can't call the API, say "I haven't checked yet." Every number must come from a real response.
- Conversational: Make API calls directly and present results conversationally. Show raw payloads only on request.
- Backtesting: Build config + code from user intent → create → start → poll → present results — all automatically.
- Deployment: Create → store credentials → run checklist → show summary → get confirmation → start.
- Proactive: Ask for missing info conversationally, one concern at a time. Always ask user to run a backtest before first live deployment.
Check Hyperliquid balances with BOTH endpoints:
- Perps:
POST https://api.hyperliquid.xyz/info→{"type":"clearinghouseState","user":"0x..."} - Spot:
POST https://api.hyperliquid.xyz/info→{"type":"spotClearinghouseState","user":"0x..."}
Repeated Failures
If the agent fails the same task 3+ times (e.g. strategy code keeps crashing, backtest keeps failing), stop and:
- Summarize what was tried and what failed
- Suggest the user try a simpler approach or different parameters
- If the issue appears to be model capability (complex multi-indicator strategy), suggest switching to a more capable model for strategy generation
Workflows
Backtest Workflow
- Build config + strategy code from user requirements
POST /v2/backtesting— create with config, code, and timerange ({ "start": "YYYY-MM-DD", "end": "YYYY-MM-DD" }). If the dates are invalid or omitted, the server picks a suitable duration based on the timeframe.PUT /v2/backtesting/{id}/statuswith{"action": "start"}- Poll
GET /v2/backtesting/{id}/statusevery 10s untilcompletedorfailed(1–10 min) GET /v2/backtesting/{id}— fetch full results; downloadresult_urlfor detailed JSON- Present summary: total trades, win rate, profit, drawdown, Sharpe ratio
- If failed, check
GET /v2/backtesting/{id}/logs - To cancel:
DELETE /v2/backtesting/{id}
Result Interpretation
After status = completed, download the result_url JSON. Present these key metrics:
- Total trades — completed round-trips
- Win rate — percentage of profitable trades
- Total profit % — net profit as percentage of starting balance
- Max drawdown — worst peak-to-trough decline
- Sharpe ratio — risk-adjusted return (>1.0 good, >2.0 excellent)
- Average trade duration — how long positions are held
Before suggesting deployment, always run a backtest first. If the backtest produced zero trades over a timerange that should have generated signals (e.g. weeks on a 5m timeframe), do not offer deployment — the strategy or pair likely has an issue. If PnL is negative, note the timerange may be unsuitable but don't dismiss the strategy outright. If PnL is positive, present results without overpromising — strong backtest fit can indicate overfitting. Stay neutral and let the user decide.
Deployment Limit Auto-Clean
The platform enforces a maximum of 10 deployments. Before creating a new deployment, the agent MUST proactively check the current count and clean up if needed — do NOT wait for a limit_exceeded error.
Pre-create check (mandatory before POST /v2/deployment):
GET /v2/deployment— fetch all deployments, paginating untilnextCursoris null- Count total deployments. If count is 8 or more:
a. Show the user a table: name, status, created date for each deployment
b. Ask: "You have [n]/10 deployments. Which stopped/unused ones can I delete to make room?"
c. Wait for explicit selection or approval
d.
DELETE /v2/deployment/{id}for each approved — note: this closes all positions/orders first - Only proceed to create once count is 9 or fewer (leaving room for the new one)
If count is already 10, do NOT attempt POST /v2/deployment — it will fail. Show the list and require cleanup first.
Deployment Workflow
- Run the Deployment Limit Auto-Clean check above before creating
POST /v2/deploymentwith config, code, namePOST /v2/deployment/{id}/credentialswith{ "exchange": "hyperliquid" }— server assigns wallet automatically. Dry-run is not supported — all deployments are live.- Run the pre-deployment checklist
- Show the deployment confirmation summary and wait for explicit user confirmation
PUT /v2/deployment/{id}/status→{"action": "start"}- Monitor:
GET /v2/deployment/{id}/status,GET /v2/deployment/{id}/logs - Stop:
PUT /v2/deployment/{id}/status→{"action": "stop"}
Pre-Deployment Checklist (MANDATORY)
Before PUT /v2/deployment/{id}/status → {"action":"start"}:
For live deployments (credentials stored):
-
Credentials stored —
GET /v2/deployment/{id}→credentials_status: "stored". If not, callPOST /v2/deployment/{id}/credentials. -
Identify wallets —
GET /v2/deployment/{id}/credentials→ notewallet_address(agent wallet) andagent_wallet_address. -
Funds available in main wallet — Check the main wallet (platform-managed trading wallet), NOT the agent wallet. Agent wallet having $0 is normal. Query
clearinghouseState+spotClearinghouseStateon the public Hyperliquid info endpoint (read-only, sends public wallet address only — no secrets). Then verifystake_amount × max_open_tradesfits within the available balance. The exchange reserves a small fee buffer (~1%), so setstake_amountto no more than ~95% ofbalance / max_open_tradesto avoid silent trade rejections. -
No existing positions/orders — Check
clearinghouseStatefor open positions on the main wallet. If positions or orders exist, show the user details (pair, side, size, PnL) and ask them to close before deploying — leftover positions can block new entries or cause unexpected margin usage. -
Pair is tradeable —
POST https://api.hyperliquid.xyz/info→{"type":"meta"}for standard perps, or{"type":"meta", "dex":"xyz"}(or the relevant dex name) for HIP3 pairs. Verify the coin name exists in theuniversearray.
Do NOT skip any step or assume it passed without the API call.
API Reference
Backtesting
POST /v2/backtesting — Create Backtest
// Request
{ "config": {}, "code": "string (Python strategy)", "timerange": { "start": "YYYY-MM-DD", "end": "YYYY-MM-DD" } }
// Response (201)
{ "id": "string", "status": "pending", "message": "Backtest created. Call PUT /:id/status with action \"start\" to begin." }
timerange specifies the historical period to backtest against. Dates are validated against available data — the server returns invalid_timerange if the requested period is outside what's available. If invalid dates are provided, the server falls back to a dynamic range based on the timeframe.
PUT /v2/backtesting/{id}/status — Start Backtest
// Request — only "start" is supported; to cancel, use DELETE
{ "action": "start" }
// Response (200)
{ "id": "string", "status": "running", "previous_status": "pending", "job_name": "backtest-01kjvze9" }
GET /v2/backtesting/{id}/status — Poll Status
Response: { "id": "string", "status": "pending | running | completed | failed", "results": null }. results is null while running — use result_url from full details for complete results.
GET /v2/backtesting/{id} — Full Details
{
"id": "string",
"config": {},
"code": "string",
"status": "pending | running | completed | failed",
"results": null,
"result_url": "https://storage.googleapis.com/... (signed URL, valid 7 days)",
"started_at": "ISO8601",
"completed_at": "ISO8601",
"job_name": "string",
"created_at": "ISO8601",
"updated_at": "ISO8601"
}
DELETE /v2/backtesting/{id}
Cancels if running and deletes. Response: { "message": "Backtest deleted" }
Deployment
POST /v2/deployment — Create Deployment
// Request
{ "config": {}, "code": "string (Python strategy)", "name": "string" }
// Response (201)
{ "id": "string", "config": {}, "code": "string", "name": "My Strategy", "replicas": 1, "status": "pending", "deployment_name": "deploy-01kjvx94", "created_at": "ISO8601" }
PUT /v2/deployment/{id}/status — Start or Stop
// Request
{ "action": "start" | "stop" }
// Response (200)
{ "id": "string", "status": "running | stopped", "previous_status": "string" }
On stop: The platform automatically cancels all open orders and closes all positions on Hyperliquid before stopping the pod.
GET /v2/deployment/{id} — Full Details
{
"id": "string",
"config": {},
"code": "string",
"name": "string",
"replicas": 1,
"status": "pending | running | stopped",
"pods": [{ "name": "string", "status": "Running", "restarts": 0 }],
"credentials_status": "stored | missing",
"exchange": "hyperliquid",
"deployment_name": "string",
"namespace": "string",
"created_at": "ISO8601",
"updated_at": "ISO8601"
}
GET /v2/deployment/{id}/status — Live Status
Response: { "id": "string", "status": "string", "replicas": 1, "available_replicas": 1, "pods": null }
POST /v2/deployment/{id}/credentials — Store Credentials
exchange required. wallet_address optional. private_key is NOT accepted.
// Request
{ "exchange": "hyperliquid", "wallet_address": "0x... (optional)" }
// Response (200)
{
"id": "string", "credentials_status": "stored", "exchange": "hyperliquid",
"wallet_address": "0x...", "wallet_source": "main_trading_wallet | provided",
"agent_wallet_address": "0x... | undefined", "updated_at": "ISO8601"
}
IMPORTANT: wallet_address in the response is the wallet that signs trades. It does NOT need its own funds — it trades against the main wallet's balance.
Errors: 400 invalid_request (private_key sent), 400 invalid_wallet_address, 400 duplicate_wallet_address, 400 unsupported_exchange, 400 no_wallet_available, 403 wallet_not_owned, 500 server_misconfigured
Idempotent: Once credentials are stored, calling again returns existing credentials unchanged — it will NOT update or overwrite. To change wallets, delete and recreate the deployment.
Credential update procedure: (1) Stop the deployment → (2) Delete the deployment → (3) Create a new deployment with same config/code → (4) Store new credentials.
One-wallet-per-deployment rule: Each deployment uses one wallet and runs as an isolated container. For multiple strategies on the same wallet, use multiple deployments pointing to the same wallet address.
GET /v2/deployment/{id}/credentials — Credential Info
Does NOT return private keys. Response: { "id", "credentials_status": "stored | missing", "exchange", "wallet_address", "wallet_source": "main_trading_wallet | provided", "wallet_type": "main_wallet | agent_wallet", "agent_wallet_address" }. If missing: { "credentials_status": "missing" }.
POST /v2/deployment/{id}/exit — Exit All Positions
Closes all open orders and liquidates all open positions. Deployment must be stopped first.
// Response (200)
{ "id": "string", "status": "string", "orders_cancelled": 3, "positions_closed": 2 }
// Response (400) — deployment still running or credentials missing
{ "error": "invalid_request", "message": "..." }
DELETE /v2/deployment/{id}
Closes all positions and orders on Hyperliquid before deleting. Response: { "message": "Deployment deleted" }. Deleting stopped deployments may return 500 — safe to ignore.
Shared API Notes
Logs — GET /v2/backtesting/{id}/logs and /v2/deployment/{id}/logs
Query: pageSize (default 100), pageToken. Response: { "items": [{ "timestamp": "ISO8601", "message": "string", "severity": "string" }], "nextCursor": "string | null" }
Paginated Lists
Both GET /v2/backtesting and GET /v2/deployment return { "items": [], "nextCursor": "string | null" }. Pass cursor query param to paginate.
Error Responses
// 401 — Missing/invalid API key
{ "message": "No API key found in request", "request_id": "string" }
// 400 — Validation error
{ "error": "validation_failed", "message": "Invalid request", "details": [{ "path": "field", "message": "..." }] }
// 404 — Not found
{ "error": "not_found", "message": "Backtest not found" }
Config and Strategy Authoring
Config Reference
The config object is a Freqtrade trading bot configuration. Do not include api_server (platform-managed). Do not set dry_run in config — dry-run mode is not supported.
Futures Config (recommended)
{
"exchange": { "name": "hyperliquid", "pair_whitelist": ["BTC/USDC:USDC"] },
"stake_currency": "USDC",
"stake_amount": 100,
"timeframe": "5m",
"max_open_trades": 3,
"stoploss": -0.1,
"trading_mode": "futures",
"margin_mode": "cross",
"pairlists": [{ "method": "StaticPairList" }]
}
Spot Config
Same as futures but omit trading_mode and margin_mode. Pairs use BTC/USDC format (no :USDC suffix). Stoploss on exchange not supported for spot.
HIP3 Config Example
{
"exchange": {
"name": "hyperliquid",
"pair_whitelist": ["XYZ-AAPL/USDC:USDC"]
},
"stake_currency": "USDC",
"stake_amount": 100,
"timeframe": "15m",
"max_open_trades": 3,
"stoploss": -0.05,
"trading_mode": "futures",
"margin_mode": "isolated",
"entry_pricing": { "price_side": "other" },
"exit_pricing": { "price_side": "other" },
"pairlists": [{ "method": "StaticPairList" }]
}
Additional Config Fields
Beyond the examples above: minimal_roi (minutes-to-ROI map, e.g. {"0": 0.10, "30": 0.05}), trailing_stop (boolean), trailing_stop_positive (number), entry_pricing.price_side / exit_pricing.price_side ("ask", "bid", "same", "other"), pairlists (StaticPairList, VolumePairList, etc.).
Strategy Code Template
The code field must be valid Python with a strategy class. Class name must end with Strategy in PascalCase. Use import talib.abstract as ta for indicators.
from freqtrade.strategy import IStrategy
import pandas as pd
import talib.abstract as ta
class MyCustomStrategy(IStrategy):
minimal_roi = {"0": 0.10, "30": 0.05, "120": 0.02}
stoploss = -0.10
trailing_stop = False
timeframe = '5m'
process_only_new_candles = True
startup_candle_count = 20
def populate_indicators(self, dataframe: pd.DataFrame, metadata: dict) -> pd.DataFrame:
dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)
dataframe['sma_20'] = ta.SMA(dataframe, timeperiod=20)
return dataframe
def populate_entry_trend(self, dataframe: pd.DataFrame, metadata: dict) -> pd.DataFrame:
dataframe.loc[
(dataframe['rsi'] < 30) & (dataframe['close'] > dataframe['sma_20']),
'enter_long'
] = 1
return dataframe
def populate_exit_trend(self, dataframe: pd.DataFrame, metadata: dict) -> pd.DataFrame:
dataframe.loc[(dataframe['rsi'] > 70), 'exit_long'] = 1
return dataframe
Requirements: Must use standard imports/inheritance (see template), import talib.abstract as ta for indicators, define populate_indicators, populate_entry_trend, populate_exit_trend.
Multi-Output TA-Lib Functions (CRITICAL)
Some TA-Lib functions return multiple columns. Assigning directly to one column causes a runtime crash.
| Function | Returns |
|---|---|
ta.BBANDS | upperband, middleband, lowerband |
ta.MACD | macd, macdsignal, macdhist |
ta.STOCH | slowk, slowd |
ta.STOCHF / ta.STOCHRSI | fastk, fastd |
ta.AROON | aroondown, aroonup |
ta.HT_PHASOR | inphase, quadrature |
ta.MAMA | mama, fama |
ta.MINMAXINDEX | minidx, maxidx |
# WRONG — runtime crash
dataframe["bb_upper"] = ta.BBANDS(dataframe, timeperiod=20)
# CORRECT
bb = ta.BBANDS(dataframe, timeperiod=20)
dataframe["bb_upper"] = bb["upperband"]
dataframe["bb_middle"] = bb["middleband"]
dataframe["bb_lower"] = bb["lowerband"]
macd = ta.MACD(dataframe)
dataframe["macd"] = macd["macd"]
dataframe["macd_signal"] = macd["macdsignal"]
dataframe["macd_hist"] = macd["macdhist"]
stoch = ta.STOCH(dataframe)
dataframe["slowk"] = stoch["slowk"]
dataframe["slowd"] = stoch["slowd"]
Single-output functions (RSI, SMA, EMA, ATR, ADX) return a Series and can be assigned directly.
DCA / Position Scaling
The engine enforces one open trade per pair. Use adjust_trade_position() for DCA:
def adjust_trade_position(self, trade, current_time, current_rate,
current_profit, min_stake, max_stake,
current_entry_rate, current_exit_rate,
current_entry_profit, current_exit_profit, **kwargs):
if should_dca(trade, current_time):
return max(500, min_stake) # add $500, respect exchange minimum
return None
- Called every candle while a trade is open. Positive = DCA buy, negative = partial close, None = no action.
- Hyperliquid minimum: $10 per order. Engine inflates by stoploss reserve (up to 1.5x) — always use
min_stake. max_open_tradeslimits total concurrent trades across all pairs, not entries per pair.
stake_amount: "unlimited" Warning
"unlimited" bypasses minimum-order validation. The bot starts but silently executes zero trades if balance is insufficient — no error, just heartbeats. Always use explicit numeric stake_amount with small balances (<$50).
| Stoploss | Effective minimum |
|---|---|
| -0.5% | ~$10.55 |
| -5% | ~$11.05 |
| -10% | ~$11.67 |
| -30% | ~$15.00 |
Operations and Troubleshooting
Reporting DCA Trades
For DCA strategies: distinguish trades from orders ("X trades, Y buy orders, Z sell orders"), show per-order detail for at least the first trade, flag minimum order rejections or dust positions. Always download result_url for full order-level data. Skip breakdown for non-DCA strategies.
Log Interpretation
- Heartbeat messages are normal — the bot sends periodic heartbeats to confirm it's alive
- "Analyzing candle" — bot is checking strategy conditions on the latest candle
- "Buying"/"Selling" — trade execution
- Rate limit warnings — reduce API calls, consider stopping if persistent
Diagnosing Zero-Trade Deployments
Check in order:
- Main wallet balance — agent wallet $0 is normal; check the platform-managed main wallet
stake_amount— if"unlimited", redeploy with explicit numeric amount slightly below balance- Credentials — verify
credentials_status: "stored"andWALLET_ADDRESSin startup logs - Strategy conditions — check if entry conditions are met on recent candles
- Logs — check for rate limits, exchange rejections, pair errors
- Pair validity — verify pair is active on Hyperliquid
Rate Limit Mitigation
Hyperliquid enforces rate limits. Aggressive retries, tight loops, or extra exchange traffic from strategy code can trigger 429 responses and unstable behavior.
Prevention:
- Set
process_only_new_candles = Trueso the bot does not reprocess every candle unnecessarily - Prefer candle-close pricing for exits where it fits the strategy (fewer edge-case order updates)
- Do not add custom polling of Hyperliquid’s API (or other heavy network work) inside hot strategy paths — it stacks on top of normal bot traffic
If you see rate limits or 429s in logs:
- Avoid rapid stop/start cycles; that often worsens retries against the limit
- After the deployment stops, wait several minutes before starting again; if the issue persists, simplify the strategy or reduce anything that drives extra exchange requests
Orphan Position Handling
When a bot crashes, it may leave open positions that lock up margin. Strategy code pattern:
- In
bot_loop_start(), check for positions not in the bot's trade database - Close orphans with a limit order before entering fresh
- Use a flag (
_orphan_closed) to run cleanup exactly once per lifecycle
Deployment limit_exceeded Error
If POST /v2/deployment returns limit_exceeded, the deployment limit of 10 has been hit. Do NOT retry. Instead:
GET /v2/deployment(paginate all pages) — list all deployments with name, status, created date- Show the list to the user and ask which to delete
DELETE /v2/deployment/{id}for approved ones (closes positions/orders automatically)- Retry
POST /v2/deploymentonly after count drops to 9 or fewer
This error is always recoverable — it just requires cleanup first.
Backtest limit_exceeded Error
If you get a limit_exceeded error when creating a backtest, the user has hit the concurrent backtest limit. Delete completed/failed backtests first: DELETE /v2/backtesting/{id}
Timezone Reminder
All API timestamps are in UTC (ISO8601). Convert to the user's local timezone when presenting times conversationally. If timezone is unknown, show both UTC and ask.
Community & Support
- Discord: https://discord.com/invite/DX4HfPrdFQ — Join for tech support, feature requests, and suggestions.
Files
2 totalComments
Loading comments…
