|
| 1 | +# Condor Strategies for Hummingbot |
| 2 | + |
| 3 | +This repository contains a collection of **custom controllers** built on top of Hummingbot's `strategy_v2` framework. Each controller implements a specific automated trading strategy — ranging from directional signal‑based trading to market making, arbitrage, and liquidity mining. |
| 4 | + |
| 5 | +All controllers are designed to be used with [Hummingbot](https://hummingbot.org/) (v2.0+) and can be deployed via the Condor / `hummingbot-api` environment. |
| 6 | + |
| 7 | +--- |
| 8 | + |
| 9 | +## Table of Contents |
| 10 | + |
| 11 | +1. [Anti‑Folla V1 (anti_folla_v1)](#anti‑folla-v1-anti_folla_v1) |
| 12 | +2. [Funding Rate Arbitrage (funding_rate_arb)](#funding-rate-arbitrage-funding_rate_arb) |
| 13 | +3. [Statistical Arbitrage V2 (stat_arb_v2)](#statistical-arbitrage-v2-stat_arb_v2) |
| 14 | +4. [Delta Neutral Market Making (delta_neutral_mm)](#delta-neutral-market-making-delta_neutral_mm) |
| 15 | +5. [Multi‑Grid Strike (multi_grid_strike)](#multi‑grid-strike-multi_grid_strike) |
| 16 | +6. [Liquidity Mining Multi‑Pair DEX (lm_multi_pair_dex)](#liquidity-mining-multi‑pair-dex-lm_multi_pair_dex) |
| 17 | + |
| 18 | +--- |
| 19 | + |
| 20 | +## Anti‑Folla V1 (`anti_folla_v1`) |
| 21 | + |
| 22 | +**Directional trading** that goes against the crowd. |
| 23 | +It calculates a composite score using a combination of technical indicators, order book imbalance (OBI), whale activity, and funding rates, then generates BUY/SELL signals when the score exceeds configurable thresholds. |
| 24 | + |
| 25 | +### Key features |
| 26 | +- Contrarian logic: e.g., sells when funding rates are very positive (too many longs). |
| 27 | +- Uses candlestick data (`3m` default) to compute VWAP, Donchian channels, OBV divergence, volume spikes, and trade flow. |
| 28 | +- Optionally includes real‑time OBI from the order book. |
| 29 | +- Configurable weights for each signal component. |
| 30 | + |
| 31 | +### Main configuration parameters |
| 32 | + |
| 33 | +| Parameter | Description | |
| 34 | +|-----------|-------------| |
| 35 | +| `connector_name` | Exchange (e.g., `binance_perpetual`) | |
| 36 | +| `trading_pair` | Pair to trade (e.g., `SOL-USDT`) | |
| 37 | +| `total_amount_quote` | Total capital in quote currency | |
| 38 | +| `stop_loss` / `take_profit` | Risk limits (as decimals, e.g., `0.05`) | |
| 39 | +| `score_buy_threshold` / `score_sell_threshold` | Score thresholds for signals (default ±50) | |
| 40 | +| `weight_*` | Weights for VWAP, Donchian, OBV, OBI, volume spike, trade flow, funding | |
| 41 | +| `enable_order_book_imbalance` | Whether to use real‑time OBI | |
| 42 | + |
| 43 | +### Signal logic |
| 44 | + |
| 45 | +The controller computes a **composite score** (range -100 to +100) by weighting several signals: |
| 46 | + |
| 47 | +- **VWAP**: price above/below rolling VWAP |
| 48 | +- **Donchian breakout**: price breaks 20‑period high/low |
| 49 | +- **OBV divergence**: bullish/bearish divergence |
| 50 | +- **OBI**: bid/ask volume ratio |
| 51 | +- **Volume spike**: last volume > 2.5× average |
| 52 | +- **Whale activity**: last candle with large body and high volume |
| 53 | +- **Funding rate**: contrarian (positive → short, negative → long) |
| 54 | + |
| 55 | +A **BUY** signal is emitted when the score ≥ `score_buy_threshold`, **SELL** when ≤ `score_sell_threshold`. |
| 56 | + |
| 57 | +--- |
| 58 | + |
| 59 | +## Funding Rate Arbitrage (`funding_rate_arb`) |
| 60 | + |
| 61 | +**Multi‑exchange funding rate arbitrage** — captures the difference in perpetual swap funding rates between two exchanges (or between spot and perpetual). |
| 62 | + |
| 63 | +### Modes |
| 64 | +- **Perp ↔ Perp** : full delta‑neutral (short the high‑funding pair, long the low‑funding pair). |
| 65 | +- **Spot ↔ Perp** : cash‑and‑carry (buy spot, sell perpetual with higher funding rate). |
| 66 | + |
| 67 | +### Key features |
| 68 | +- Automatically detects if a connector is spot or perpetual. |
| 69 | +- Dynamically retrieves the funding interval from each exchange (falls back to 8h / 1h for Hyperliquid). |
| 70 | +- Computes **hourly net funding rate** and estimates the APY. |
| 71 | +- Opens a pair of opposite positions when `|net_rate| > entry_threshold` and closes them when the rate drops below `exit_threshold`. |
| 72 | +- Global stop‑loss / take‑profit on the combined PnL. |
| 73 | + |
| 74 | +### Main configuration parameters |
| 75 | + |
| 76 | +| Parameter | Description | |
| 77 | +|-----------|-------------| |
| 78 | +| `connector_pair_a` / `connector_pair_b` | Two (connector, trading pair) objects | |
| 79 | +| `entry_threshold` | Minimum net hourly rate to open (e.g., `0.000025` = 0.0025%/h) | |
| 80 | +| `exit_threshold` | Close when rate falls below this value | |
| 81 | +| `total_amount_quote` | Total capital (split equally between the two legs) | |
| 82 | +| `leverage` | Leverage for perpetual legs | |
| 83 | +| `funding_interval_a/b_hours` | Optional manual override of funding intervals | |
| 84 | + |
| 85 | +### Signal logic |
| 86 | + |
| 87 | +The controller periodically fetches the latest funding rate from both exchanges, normalises them to an **hourly rate**, and calculates the **net rate** = rate_A – rate_B. |
| 88 | + |
| 89 | +- **Signal = +1** (buy spread): net rate > `entry_threshold` → short exchange A, long exchange B (or spot+perp combination). |
| 90 | +- **Signal = -1** (sell spread): net rate < -`entry_threshold` → opposite. |
| 91 | +- **Signal = 0** : neutral zone, close any open positions. |
| 92 | + |
| 93 | +The strategy automatically closes the positions when `|net rate| < exit_threshold` and re‑hedges when the delta exceeds the cooldown threshold. |
| 94 | + |
| 95 | +--- |
| 96 | + |
| 97 | +## Statistical Arbitrage V2 (`stat_arb_v2`) |
| 98 | + |
| 99 | +**Pairs trading** on a single exchange. It trades the spread between two correlated assets (e.g., `SOL‑USDT` and `XRP‑USDT`) using a z‑score entry and a dynamic hedge ratio derived from OLS regression. |
| 100 | + |
| 101 | +### Key features |
| 102 | +- Uses **only one connector** for both trading pairs (e.g., `binance_perpetual`). |
| 103 | +- Calculates the cumulative return series of both pairs and runs a linear regression (`dominant_cum ~ hedge_cum`). |
| 104 | +- Computes the spread, its z‑score, half‑life, **R²**, and **ADF p‑value** to ensure stationarity. |
| 105 | +- Filters out signals when R² is too low or the spread is not mean‑reverting (ADF p‑value too high). |
| 106 | +- Dynamic hedge ratio: `1 / beta` (capped by `min/max_dynamic_hedge_ratio`). |
| 107 | +- Places limit orders on both legs according to the spread signal and manages the target allocation. |
| 108 | + |
| 109 | +### Main configuration parameters |
| 110 | + |
| 111 | +| Parameter | Description | |
| 112 | +|-----------|-------------| |
| 113 | +| `connector_name` | Exchange (e.g., `binance_perpetual`) | |
| 114 | +| `trading_pair_dominant` / `trading_pair_hedge` | The two pairs | |
| 115 | +| `lookback_period` | Number of candles for regression (e.g., `300`) | |
| 116 | +| `entry_threshold` | Z‑score level that triggers a trade (e.g., `2.0`) | |
| 117 | +| `take_profit` | Per‑executor take‑profit fraction (e.g., `0.0008` = 0.08%) | |
| 118 | +| `tp_global` / `sl_global` | Global PnL% limits to close everything | |
| 119 | +| `min_r_squared` / `adf_pvalue_threshold` | Statistical quality filters | |
| 120 | +| `use_dynamic_hedge_ratio` | If `True`, uses OLS beta to size the hedge leg | |
| 121 | +| `max_orders_placed_per_side` / `max_orders_filled_per_side` | Position scaling limits | |
| 122 | + |
| 123 | +### Signal logic |
| 124 | + |
| 125 | +1. Fetch `lookback_period` candles for both pairs. |
| 126 | +2. Compute cumulative returns and run `hedge_cum ~ dominant_cum`. |
| 127 | +3. Calculate the residual spread and its z‑score. |
| 128 | +4. If `R² >= min_r_squared` and `ADF p‑value <= threshold`: |
| 129 | + - `z > +entry_threshold` → **SELL dominant / BUY hedge** (overvalued dominant) |
| 130 | + - `z < -entry_threshold` → **BUY dominant / SELL hedge** (undervalued dominant) |
| 131 | +5. Otherwise signal = 0 (no trade). |
| 132 | + |
| 133 | +The controller then places limit orders on both legs to approach the theoretical target quote amounts derived from the dynamic hedge ratio and total capital. |
| 134 | + |
| 135 | +--- |
| 136 | + |
| 137 | +## Delta Neutral Market Making (`delta_neutral_mm`) |
| 138 | + |
| 139 | +**Market making on a spot or perpetual exchange**, hedged by an opposite position on a **perpetual exchange**. The maker side provides liquidity, while the hedge side adjusts to keep the overall delta close to zero. |
| 140 | + |
| 141 | +### Key features |
| 142 | +- **Maker exchange** (can be spot or perpetual) – places multiple buy/sell limit orders with spreads derived from **NATR** and **MACD**. |
| 143 | +- **Hedge exchange** (must be perpetual) – executes market orders when the net delta exceeds a threshold. |
| 144 | +- The reference price for the maker orders is shifted using a normalised MACD signal. |
| 145 | +- Spreads are dynamic: `spread = base_spread × NATR_multiplier`. |
| 146 | +- Global stop‑loss / take‑profit on the combined PnL, plus a configurable hedge position timeout. |
| 147 | +- Hedge orders can be placed as market orders to quickly rebalance delta. |
| 148 | + |
| 149 | +### Main configuration parameters |
| 150 | + |
| 151 | +| Parameter | Description | |
| 152 | +|-----------|-------------| |
| 153 | +| `connector_pair_maker` | (connector, pair) for providing liquidity | |
| 154 | +| `connector_pair_hedge` | (perpetual connector, pair) for delta hedging | |
| 155 | +| `buy_spreads` / `sell_spreads` | Comma‑separated base spread percentages (e.g., `1.0,2.0,3.0`) | |
| 156 | +| `order_amount_quote` | Quote amount per order level | |
| 157 | +| `hedge_threshold_quote` | Delta (in USDT) that triggers a hedge | |
| 158 | +| `max_delta_quote` | Emergency cap – hedge immediately when exceeded | |
| 159 | +| `macd_fast` / `macd_slow` / `macd_signal` | MACD parameters for reference price shift | |
| 160 | +| `natr_length` | NATR length for dynamic spread multiplier | |
| 161 | +| `maker_tp_multiplier` | Multiplier for take‑profit (relative to spread) | |
| 162 | +| `hedge_position_timeout` | Auto‑close hedge positions after this many seconds | |
| 163 | + |
| 164 | +### Operational flow |
| 165 | + |
| 166 | +- **Reference price** = last close × `(1 + macd_normalised × natr/2)`. |
| 167 | +- **Spread multiplier** = current NATR value. |
| 168 | +- Maker orders are placed at `ref_price × (1 ± spread_i × spread_mult)` with a take‑profit set to `spread_i × spread_mult × maker_tp_multiplier`. |
| 169 | +- Net delta = maker position (in quote) + hedge position (in quote). |
| 170 | +- If `|net delta| > hedge_threshold_quote`, a hedge order (market) is sent on the perpetual exchange to reduce delta towards zero. |
| 171 | +- If `|net delta| > max_delta_quote`, an immediate forced hedge is performed, overriding other logic. |
| 172 | +- All stale maker orders are refreshed every `order_refresh_time` seconds. |
| 173 | + |
| 174 | +--- |
| 175 | + |
| 176 | +## Multi‑Grid Strike (`multi_grid_strike`) |
| 177 | + |
| 178 | +**Multiple independent grids** on the same trading pair. Each grid is defined by its own price range, side (BUY or SELL), and percentage of total capital. This allows a single strategy instance to run, for example, a buy grid in a low range and a sell grid in a high range simultaneously. |
| 179 | + |
| 180 | +### Key features |
| 181 | +- Each grid uses a `GridExecutorConfig` internally. |
| 182 | +- Grids can be enabled/disabled dynamically (the controller monitors configuration changes and stops/creates executors accordingly). |
| 183 | +- Capital is allocated per grid as a percentage of `total_amount_quote`. |
| 184 | +- Supports common grid parameters: spread between orders, min order size, max open orders, order frequency. |
| 185 | +- Active grids show their level distribution (pending, filled, completed) and performance metrics in the status display. |
| 186 | + |
| 187 | +### Main configuration parameters |
| 188 | + |
| 189 | +| Parameter | Description | |
| 190 | +|-----------|-------------| |
| 191 | +| `connector_name` / `trading_pair` | Exchange and pair for all grids | |
| 192 | +| `total_amount_quote` | Total capital to be split among grids | |
| 193 | +| `grids` | List of `GridConfig` objects, each with: `grid_id`, `start_price`, `end_price`, `limit_price`, `side`, `amount_quote_pct`, `enabled` | |
| 194 | +| `min_spread_between_orders` | Minimum price gap between consecutive grid levels | |
| 195 | +| `min_order_amount_quote` | Minimum notional per order | |
| 196 | +| `max_open_orders` | Max orders the grid executor can have open at once | |
| 197 | +| `order_frequency` | Seconds between order placement batches | |
| 198 | +| `keep_position` | Whether the grid executor should keep its position when stopped | |
| 199 | + |
| 200 | +### Behaviour |
| 201 | + |
| 202 | +- For each enabled grid, the controller checks whether the current mid price lies inside the grid’s `[start_price, end_price]` bounds. |
| 203 | +- If the price is inside and no `GridExecutor` exists for that `grid_id`, it creates one. |
| 204 | +- If a grid is disabled or removed from the configuration, the corresponding executor is stopped. |
| 205 | +- The `to_format_status` method displays a detailed table of each grid’s current stats (levels by state, order counts, PnL, etc.). |
| 206 | + |
| 207 | +--- |
| 208 | + |
| 209 | +## Liquidity Mining Multi‑Pair DEX (`lm_multi_pair_dex`) |
| 210 | + |
| 211 | +**Automated liquidity provision on decentralised exchanges** that support limit orders (e.g., XRPL DEX, Hyperliquid spot). The strategy places multiple buy and sell limit orders across several trading pairs, using dynamic skew based on current inventory. |
| 212 | + |
| 213 | +### Key features |
| 214 | +- **Auto‑optimisation** for the specific DEX: |
| 215 | + - **XRPL** → wider spreads, slower refresh, higher tolerance (due to 3‑5s latency, very low fees). |
| 216 | + - **Hyperliquid** → tighter spreads, faster refresh, lower tolerance (due to sub‑millisecond latency and maker rebate). |
| 217 | +- Each trading pair receives an equal share of the allocated capital. |
| 218 | +- Order amounts are **skewed** according to the current base asset percentage: if too much base is held, sell orders are favoured (and vice‑versa). |
| 219 | +- Order prices are refreshed when they become too far from the theoretical price (tolerance parameter). |
| 220 | +- Optional dynamic spreads based on ATR (configurable). |
| 221 | +- Cooldown period after a fill to avoid immediate replacement. |
| 222 | + |
| 223 | +### Main configuration parameters |
| 224 | + |
| 225 | +| Parameter | Description | |
| 226 | +|-----------|-------------| |
| 227 | +| `connector_name` | Exchange connector (`xrpl` or `hyperliquid`) | |
| 228 | +| `markets` | List of trading pairs (e.g., `["XRP-RLUSD", "BTC-XRP"]`) | |
| 229 | +| `token` | Unified token for fee/balance checks (e.g., `XRP` for XRPL, `USDC` for Hyperliquid) | |
| 230 | +| `portfolio_allocation` | Fraction of `total_amount_quote` to use (rest stays idle) | |
| 231 | +| `buy_spreads` / `sell_spreads` | List of spread percentages for each order level | |
| 232 | +| `order_refresh_time` | Seconds after which an unfilled order is refreshed | |
| 233 | +| `cooldown_time` | Seconds to wait after a fill before placing new orders | |
| 234 | +| `order_refresh_tolerance_pct` | Maximum allowed deviation from theoretical price before refreshing | |
| 235 | +| `target_base_pct` / `min_base_pct` / `max_base_pct` / `max_skew` | Inventory skew parameters | |
| 236 | +| `use_dynamic_spreads` | If `True`, spreads are multiplied by an ATR factor | |
| 237 | +| `atr_length` / `atr_multiplier_min/max` | ATR settings for dynamic spreads | |
| 238 | + |
| 239 | +### Operational flow |
| 240 | + |
| 241 | +1. For each trading pair, compute the reference price (mid price) and the current base asset percentage. |
| 242 | +2. Calculate buy/sell skew factors based on how far `base_pct` is from the target range. |
| 243 | +3. Determine which order levels are missing (compared to active executors). |
| 244 | +4. Create new `PositionExecutor` orders with: |
| 245 | + - Price = reference price × `(1 ± spread_i)` |
| 246 | + - Amount = (allocation per pair / number of levels) × skew factor |
| 247 | +5. Refresh stale orders (age > `order_refresh_time`) that have drifted beyond the tolerance. |
| 248 | +6. During cooldown after a fill, no new orders are placed for that pair. |
| 249 | + |
| 250 | +--- |
| 251 | + |
| 252 | +## Deployment Notes |
| 253 | + |
| 254 | +All controllers inherit from `ControllerBase` and `ControllerConfigBase` and are designed to be run inside a Hummingbot `strategy_v2` environment. To use them: |
| 255 | + |
| 256 | +1. Place the `.py` files in the `hummingbot/strategy_v2/controllers/` directory of your Hummingbot installation. |
| 257 | +2. Reference the controller in your `controller_conf.yml` (or via the API) by its `controller_name` field (e.g., `"anti_folla_v1"`). |
| 258 | +3. Fill in the required configuration parameters (many have interactive prompts). |
| 259 | + |
| 260 | +For more details on building custom controllers, refer to the [Hummingbot Strategy V2 documentation](https://hummingbot.org/strategy-v2/). |
0 commit comments