GitHub - davassi/hypertrade: Hypertrade is an trading bot designed to develop and run high-frequency trading strategies on Hyperliquid. · GitHub
Skip to content

davassi/hypertrade

Repository files navigation

image

Python 3.10+ FastAPI Pydantic v2 Uvicorn Ruff Tests: pytest GitHub stars GitHub issues Last commit

HyperTrade is a lightweight server that processes TradingView long/short alerts to execute orders on Hyperliquid, for automated algorithmic trading.

It validates webhook payloads, enforces secret auth and IP whitelisting, and emits audit logs. Use it as a reliable layer between TradingView strategies and your Hyperliquid sub-accounts.

Features

  • TradingView‑compatible payloads with validation.
  • IP whitelisting.
  • Payload secret.
  • Environment secrets.
  • Specify a different leverage per asset.
  • Dry-run / demo mode (HYPERTRADE_DRY_RUN=true): validate webhooks without trading.
  • Health check at GET /health.
  • Simple config via env vars or .env (no external dotenv dependency).
image

Before using HyperTrade, 3 Rules for Sleeping at Night:

  1. Define a Leverage Policy.
    ALWAYS trade with a maximum leverage of 3x–5x in cross-margin mode to improve risk control. NEVER gamble with a 10x–20x leverage.

  2. Deep Defensive Capital.
    Keep a portion of idle funds as defensive capital. This reserve extends the liquidation range and protects the position during periods of volatility.

  3. Never forget a Stop Loss.
    Never be greedy. Always include a stop loss in your strategy, no matter what.

Requirements

  • Python 3.10+
  • Pip or your preferred package manager
  • A TradingView subscription.
  • A Hyperliquid sub-account.

Install

Using pip:

python -m venv .venv && source .venv/bin/activate
pip install --upgrade pip
pip install fastapi uvicorn[standard] pydantic pydantic-settings python-dotenv jsonschema

Run

Run via Uvicorn directly:

uvicorn hypertrade.daemon:app --host 0.0.0.0 --port 6487

Or via the module entrypoint, which serves the same app on the host/port from HYPERTRADE_LISTEN_HOST / HYPERTRADE_LISTEN_PORT (default 0.0.0.0:6487):

python -m hypertrade

Or use the bundled launchers, which load secrets from pass, select the Hyperliquid endpoint, and run the guided setup on first use:

./hypertrade-test.sh   # testnet, port 6488
./hypertrade-prod.sh   # mainnet, port 6487

Guided setup (recommended for first run)

Run an interactive wizard that collects the minimum config needed to start and stores it for you:

python -m hypertrade.setup

It prompts only for what is missing — environment (prod/test), master address, API wallet private key (hidden), an optional sub-account, and one authentication method (a webhook secret or the IP whitelist). Secrets are saved to pass when it is installed; otherwise the wizard recommends installing pass and falls back to writing a .env file (mode 0600). The hypertrade-{prod,test}.{sh,fish} launchers run this automatically when required configuration is not yet present.

Dry-run (demo) mode

Set HYPERTRADE_DRY_RUN=true to validate incoming webhooks without trading. The request runs the full pipeline — content-type, JSON-schema, secret/auth, signal parsing, leverage and reduce_only mapping — and returns a dry_run response describing the order that would have been placed, while performing no side effect: no Hyperliquid order, no database write, and no idempotency reservation. On startup the daemon logs a clear ⚠️ DRY-RUN MODE ENABLED warning so a demo instance is never mistaken for a live one.

export HYPERTRADE_DRY_RUN=true
uvicorn hypertrade.daemon:app --host 127.0.0.1 --port 6499

A successful call returns the mapped order it would have sent:

{
  "status": "dry_run",
  "signal": "REDUCE_LONG",
  "side": "sell",
  "symbol": "SOL",
  "action": "sell",
  "contracts": "10.5",
  "price": "183.81",
  "leverage": 3,
  "reduce_only": true,
  "subaccount": "0xYourSubaccount",
  "received_at": "2026-01-01T00:00:00+00:00"
}

Dry-run does not relax authentication. The shared secret, the IP whitelist, and the nonce requirement (while idempotency is enabled) are all still enforced — that is the point: you exercise the real request path. When testing from localhost, the default IP whitelist (TradingView's published IPs) rejects 127.0.0.1 with 403. For local testing, either disable the whitelist and authenticate with the secret, or add your own address:

# Option A: disable the IP whitelist, authenticate with the shared secret
export HYPERTRADE_IP_WHITELIST_ENABLED=false
export HYPERTRADE_WEBHOOK_SECRET='testsecret'

# Option B: keep the whitelist but allow your own address
export 'HYPERTRADE_TV_WEBHOOK_IPS=["127.0.0.1"]'

Then send a test order. The payload must carry general.secret matching HYPERTRADE_WEBHOOK_SECRET, plus a unique general.nonce while idempotency is enabled:

curl -s -X POST http://127.0.0.1:6499/webhook \
  -H 'Content-Type: application/json' \
  -d '{
    "general": {"strategy":"Demo","ticker":"SOLUSD","interval":"60",
      "time":"2025-10-21T06:00:00Z","timenow":"2025-10-21T06:00:45Z",
      "secret":"testsecret","leverage":"3X","nonce":"demo-1"},
    "currency": {"quote":"USD","base":"SOL"},
    "order": {"action":"sell","contracts":"10.5","price":"183.81",
      "id":"demo","comment":"","alert_message":""},
    "market": {"position":"long","position_size":"10.5",
      "previous_position":"long","previous_position_size":"21"}
  }'

Because idempotency is skipped in dry-run, re-sending the same nonce returns dry_run again rather than duplicate — repeated test webhooks are never deduplicated.

Environment Variables (required)

Hypertrade won't start unless these variables are set:

  • HYPERTRADE_ENVIRONMENT – The Hyperliquid environment to connect to. Must be prod or test.
  • HYPERTRADE_MASTER_ADDR – Your master wallet address.
  • HYPERTRADE_API_WALLET_PRIV – Your private key for API access.
  • HYPERTRADE_SUBACCOUNT_ADDR – (Optional) Your Hyperliquid sub-account address.

API Endpoint Selection

The HYPERTRADE_ENVIRONMENT variable controls which Hyperliquid endpoint is used:

  • HYPERTRADE_ENVIRONMENT=prodhttps://api.hyperliquid.xyz (mainnet)
  • HYPERTRADE_ENVIRONMENT=testhttps://api.hyperliquid-testnet.xyz (testnet)

Any other value will cause the application to fail at startup with a clear error message.

Example Setup

export HYPERTRADE_ENVIRONMENT=prod
export HYPERTRADE_MASTER_ADDR=0xYourMasterAddress
export HYPERTRADE_API_WALLET_PRIV='your-private-key'
export HYPERTRADE_SUBACCOUNT_ADDR=0xYourSubaccountAddress
uvicorn hypertrade.daemon:app --host 0.0.0.0 --port 6487

Personally I prefer storing secrets with Password Store (pass) instead of a .env file:

export HYPERTRADE_ENVIRONMENT=prod
export HYPERTRADE_MASTER_ADDR="$(pass show hypertrade/master_addr)"
export HYPERTRADE_API_WALLET_PRIV="$(pass show hypertrade/api_wallet_priv)"
export HYPERTRADE_SUBACCOUNT_ADDR="$(pass show hypertrade/subaccount_addr)"

Endpoints

  • GET /health – health check
  • POST /webhook – TradingView webhook (supports IP whitelist)

IP Whitelisting (optional but strongly suggested)

Enable IP whitelisting for the TradingView webhook endpoint and set allowed IPs:

export HYPERTRADE_IP_WHITELIST_ENABLED=true
export 'HYPERTRADE_TV_WEBHOOK_IPS=["52.89.214.238","34.212.75.30","54.218.53.128","52.32.178.7"]'

# Enable ONLY when behind a trusted reverse proxy. Default is false.
export HYPERTRADE_TRUST_FORWARDED_FOR=true

⚠️ Security / breaking change: HYPERTRADE_TRUST_FORWARDED_FOR now defaults to false (previously true). X-Forwarded-For is client-supplied and therefore spoofable — a request could otherwise claim a whitelisted IP and bypass the whitelist. When enabled, only the right-most X-Forwarded-For entry (the address added by your immediate trusted proxy) is used; this assumes a single proxy hop. If you run behind a reverse proxy and rely on the IP whitelist, you must now set HYPERTRADE_TRUST_FORWARDED_FOR=true explicitly, or every request will be seen as coming from the proxy and rejected.

You can apply the whitelist dependency to other routes using require_ip_whitelisted() from hypertrade/security.py.

Note:

  • For pydantic-settings v2, complex types like lists must be provided as JSON strings in env vars. Use a JSON list for HYPERTRADE_TV_WEBHOOK_IPS (as shown above). Comma-separated values are not supported by the loader.

Webhook Secret (optional but strongly suggested, part 2)

For an extra authentication layer, set a shared secret and include it in the payload under general.secret.

Env:

export HYPERTRADE_WEBHOOK_SECRET='your-shared-secret'

History Endpoints (authentication required)

The /history/* endpoints require authentication with the webhook secret:

curl -H "Authorization: Bearer $HYPERTRADE_WEBHOOK_SECRET" http://localhost:6487/history/stats

Requests without a valid Authorization: Bearer <secret> get 401; if no HYPERTRADE_WEBHOOK_SECRET is configured, /history returns 403.

TradingView Webhook Payload

Payload (TradingView template) with all the placeholders, including secret and leverage. Copy and paste it on as TradingView Alert.

Don't forget to set up first the strategy name, the "secret": "your-shared-secret" and the preferred leverage.

{
  "general": {
    "strategy" : "your-strategy-name",
    "ticker": "{{ticker}}",
    "interval": "{{interval}}",
    "time": "{{time}}",
    "timenow": "{{timenow}}",
    "secret": "your-shared-secret",
    "leverage": "3X"
  },
  "currency": {
    "quote": "{{syminfo.currency}}",
    "base": "{{syminfo.basecurrency}}"
  },
  "order": {
    "action": "{{strategy.order.action}}",
    "contracts": "{{strategy.order.contracts}}",
    "price": "{{strategy.order.price}}",
    "id": "{{strategy.order.id}}",
    "comment": "{{strategy.order.comment}}",
    "alert_message": "{{strategy.order.alert_message}}"
  },
  "market": {
    "position": "{{strategy.market_position}}",
    "position_size": "{{strategy.market_position_size}}",
    "previous_position": "{{strategy.prev_market_position}}",
    "previous_position_size": "{{strategy.prev_market_position_size}}"
  }
}

Validation:

  • Incoming JSON is validated against a JSON Schema and then parsed into a Pydantic model.
  • Schema enforces required sections and basic constraints (action enum, date-time fields, numeric fields).

Behavior:

  • If HYPERTRADE_WEBHOOK_SECRET is set, incoming requests must include general.secret matching it, or the request is rejected with 401.
  • If not set, the secret check is skipped.

📖 For field-by-field semantics, how the trading signal is derived from the position transition, and ready-to-use example payloads for every signal (OPEN_LONG, CLOSE_LONG, ADD_LONG, REVERSE_TO_SHORT, …), see docs/tradingview-webhook.md.

Additional Security & Limits

  • HYPERTRADE_MAX_PAYLOAD_BYTES (default 65536): reject requests larger than this size with 413.
  • HYPERTRADE_ENABLE_TRUSTED_HOSTS (default false): enable Trusted Host middleware.
  • HYPERTRADE_TRUSTED_HOSTS (default *): allowed hosts when Trusted Host is enabled. Provide as a JSON list, e.g. '["example.com","api.example.com"]' (comma-separated values are not supported by the loader — see the note under IP Whitelisting).
  • Webhook requires Content-Type: application/json and returns 415 otherwise.
  • HYPERTRADE_IDEMPOTENCY_ENABLED (default true): require a unique general.nonce per order and place each at most once. Requires the order DB (the daemon refuses to start if HYPERTRADE_DB_ENABLED=false).
  • HYPERTRADE_IDEMPOTENCY_INFLIGHT_TIMEOUT (default 60): seconds before an in-progress reservation is considered stale and reclaimable.

Sequence diagram

sequenceDiagram
    autonumber
    participant TV as TradingView
    participant WH as Webhook (HTTP POST)
    box HyperTrader Deaemon
        participant HT as HyperTrade Service
        participant RL as Risk Logic
        participant OR as Order Executor
    end
    participant HL as Hyperliquid SDK/API
    participant SA as HL Sub-Account

    TV->>TV: Trading Strategy Logic 
    TV->>WH: POST /webhook (JSON payload)
    WH->>HT: Forward payload (signal event)
    HT->>RL: Validate signal (IP whitelist, secrets, etc.)
    RL-->>HT: Approved / Rejected
    alt Approved
        HT->>OR: Build order {coin, side, size, leverage, reduceOnly, etc}
        OR->>HL: exchange.order(...)
        HL-->>OR: OrderAck {status,id,price,filledSz}
        OR-->>HT: Execution result
        HT-->>TV: (optional) 200 OK
        HT->>SA: Position updated on fill
        HT->>HT: Log (trades, PnL, metrics)
    else Rejected
        HT-->>TV: 200 OK (ignored by policy)
        HT->>HT: Log rejection reason
    end
Loading

About

Hypertrade is an trading bot designed to develop and run high-frequency trading strategies on Hyperliquid.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

Contributors