Setup Guide
Most users are up and running in dry-run mode within 10–20 minutes.
Quick Start
Three steps. You need Docker and credentials from your exchange.
Unzip and log in to the registry
Your purchase email contains registry credentials (REGISTRY_USER, REGISTRY_PASSWORD) and your license key. Keep these private.
docker login registry.gitlab.com \
-u YOUR_REGISTRY_USER \
-p YOUR_REGISTRY_PASSWORD
Create your .env file
Copy .env.example to .env and fill in at minimum the fields marked required below. Start with DRY_RUN=True.
cp .env.example .env
nano .env # or any editor
Start the bot
docker compose up -d
docker compose logs -f # watch startup
The web dashboard is available at http://localhost:8080 (or your configured DASHBOARD_PORT).
Exchange API Keys
Bybit
Go to Account → API Management on bybit.com. Create a new key with these permissions:
- Read — required
- Spot Trading — required
- Derivatives / Contract Trading — required
- Withdraw — do not enable
For initial testing: use Bybit Testnet (testnet.bybit.com) with BYBIT_TESTNET=True. Testnet uses virtual funds — no real capital at risk.
Bitunix
Go to API Management on bitunix.com. Bitunix has no testnet — start with a small capital amount and DRY_RUN=True first.
Bitunix uses separate Spot and Futures wallets. Transfer USDT to both wallets before starting the bot (roughly 2/3 Spot, 1/3 Futures at 2× leverage).
Bitget
Go to Profile → API Management on bitget.com. Enable the same permissions as above. Bitget also requires a passphrase set at key creation time — add it as BITGET_PASSPHRASE in your .env.
The bot auto-detects your account's futures position mode (hedge or one-way) and composes orders accordingly — no manual setting required.
⚠ Never enable Withdrawal permissions on trading API keys. The bot only needs to read balances and place/cancel orders.
Configuration Reference
All settings live in your .env file. The defaults are conservative for a first run.
Essential — set before first run
| Variable | Default | Description |
|---|---|---|
| LICENSE_KEY | required | Your license key from the purchase email. Required when DRY_RUN=False. |
| REGISTRY_USER | required | Docker registry username from purchase email. |
| REGISTRY_PASSWORD | required | Docker registry password from purchase email. |
| EXCHANGE | bybit | Active exchange: bybit, bitunix, bitget, or any CCXT exchange id (e.g. binanceusdm). |
| BITGET_PASSPHRASE | optional | Required when EXCHANGE=bitget. Set at Bitget API key creation time. |
| BYBIT_API_KEY | required | Bybit API key (or Testnet key). |
| BYBIT_API_SECRET | required | Bybit API secret. |
| BYBIT_TESTNET | True | Set False for live trading on mainnet. |
| DRY_RUN | True | Always start with True. No real orders are placed. Switch to False only after verifying dry-run logs. |
| DASHBOARD_PORT | 8080 | Port for the web dashboard. |
Trading parameters
| Variable | Default | Description |
|---|---|---|
| TRADE_CAPITAL_USDT | 500 | Capital per position in USDT (spot leg size). |
| MAX_TOTAL_CAPITAL | 1000 | Total capital cap across all open positions. |
| MAX_POSITIONS | 2 | Maximum simultaneous open positions. |
| FUTURES_LEVERAGE | 2 | Leverage for the futures short leg (isolated margin). Keep at 2 unless you understand the liquidation mechanics. |
| FUNDING_ENTRY_THRESHOLD | 0.00025 | Minimum funding rate to open a position (0.00025 = 0.025% per 8h). Funding rates fluctuate — this is an entry filter, not a yield forecast. |
| FUNDING_EXIT_THRESHOLD | 0.000001 | Close position when rate falls below this. |
| EXIT_CONFIRMATION_TICKS | 60 | Consecutive ticks below exit threshold before closing. At 60s interval = 60 minutes — prevents exits on short dips. |
| MIN_VOLUME_USDT_24H | 5000000 | Minimum 24h futures volume to consider a symbol. Filters illiquid coins. |
| FEE_COVERAGE_FACTOR | 1.5 | Only enter if expected funding income ≥ round-trip fees × this factor. Reduces the likelihood of fee-losing entries in marginal conditions. |
Advanced — safe to leave at defaults
| Variable | Default | Description |
|---|---|---|
| MARGIN_USAGE_MAX | 0.70 | Maximum fraction of USDT balance used for margin. Keeps a buffer against liquidation. |
| MONITOR_INTERVAL_SEC | 60 | How often the bot checks rates and positions (seconds). |
| POST_FUNDING_COOLDOWN_MIN | 30 | Minutes of no new entries after the 8h funding reset (rates are volatile right after). |
| MIN_MINUTES_BEFORE_FUNDING | 10 | Don't open a new position within N minutes of the next funding payment. |
| HOLD_FOR_PAYMENT_MIN | 60 | Suppress rate-based exits when a payment is due within N minutes. |
| SPOT_LIMIT_OFFSET | 0.0005 | Spot limit order price = mark × (1 − this). Targets maker fee. |
| SPOT_LIMIT_TIMEOUT_SEC | 30 | Cancel spot limit order after N seconds if unfilled. |
| HEDGE_REBALANCE_ENABLED | True | Auto-correct small spot/futures imbalances caused by lot sizes or partial fills. |
Dry-Run Verification
With DRY_RUN=True, the bot scans for opportunities and logs everything — but places no real orders. This is what healthy startup logs look like:
INFO Exchange: bybit | DRY_RUN=True
INFO Scanner started — interval 60s
INFO BTCUSDT rate=0.00041 vol=2.1B → ENTRY CANDIDATE
INFO [DRY] Would open spot long + futures short on BTCUSDT @ 500 USDT
INFO ETHUSDT rate=0.00031 vol=890M → ENTRY CANDIDATE
INFO [DRY] Would open spot long + futures short on ETHUSDT @ 500 USDT
If you see [DRY] lines with entry candidates, the bot is working correctly. If the scanner finds no candidates, rates are currently below your FUNDING_ENTRY_THRESHOLD — this is normal in calm markets.
✓ Let the bot run in dry-run for at least one full 8-hour funding cycle (funding payments happen at 00:00, 08:00, 16:00 UTC) before going live.
Going Live
Before switching DRY_RUN=False, work through this checklist:
- API keys are mainnet keys (not testnet),
BYBIT_TESTNET=False - At least one full dry-run funding cycle completed without errors
TRADE_CAPITAL_USDTandMAX_TOTAL_CAPITALmatch your actual available balance- USDT balance on the exchange covers
MAX_TOTAL_CAPITAL× (1 + margin) LICENSE_KEYis set — the bot refuses live mode without a valid key- Dashboard accessible and showing correct exchange connection
Then:
# In your .env:
DRY_RUN=False
BYBIT_TESTNET=False
# Restart the bot:
docker compose down
docker compose up -d
docker compose logs -f
⚠ Start with a small TRADE_CAPITAL_USDT (e.g. 100–200 USDT) for your first live run. Scale up after confirming the first real positions open and close correctly.
VPS Deployment
Running the bot on your personal computer works, but it stops when your machine sleeps or reboots — leaving open positions unmonitored. A VPS keeps the bot running 24/7.
Recommended providers
| Provider | Plan | RAM | Cost |
|---|---|---|---|
| Hetzner | CX22 | 4 GB | ~€5/mo |
| Hostinger | 1CPU | 4 GB | ~€6/mo |
| DigitalOcean | Basic Droplet | 2 GB | ~$6/mo |
| Vultr | Cloud Compute | 2 GB | ~$6/mo |
Ubuntu 22.04. Install Docker with curl -fsSL https://get.docker.com | sh, then follow the Quick Start steps above. Add restart: unless-stopped to both services in docker-compose.yml so the bot restarts automatically after reboots.
Dashboard access from a VPS
Use an SSH tunnel to access the dashboard without opening a public port:
ssh -L 8080:localhost:8080 user@YOUR_SERVER_IP
Then open http://localhost:8080 in your browser. The tunnel stays active while the SSH session is open.
✓ Pro & Lifetime customers: the full setup guide PDF includes a step-by-step VPS walkthrough with server hardening, non-root user setup, and firewall configuration.
Risk Disclosure
This is not financial advice. FundingArb is a software tool — not an investment product. No returns are promised or implied. You are solely responsible for your trading decisions and any resulting gains or losses.
Understand the following risks before running with real capital:
- Liquidation risk — The futures short leg can be liquidated during extreme, rapid price spikes. The built-in liquidation buffer attempts to close positions before the liquidation price is reached, but cannot guarantee this under all conditions (exchange outages, API failures, flash crashes with insufficient liquidity).
- Funding rate risk — Funding rates can go to zero, turn negative, or remain below your entry threshold for extended periods. Past rates do not predict future rates.
- Exchange / counterparty risk — Your funds are held on a centralised exchange. Exchange insolvency, hacks, or withdrawal freezes are outside the bot's control.
- Software risk — This software may contain bugs. Monitor logs regularly and always start with a small amount of capital.
- Regulatory risk — Cryptocurrency trading regulations vary by jurisdiction and are subject to change. Ensure compliance with the laws in your country before using this software.
Only trade with capital you can afford to lose entirely.
FAQ
Why is my bot running but not opening any positions?
Two common causes:
1. Funding rates are below your threshold. The bot only enters when the current rate exceeds FUNDING_ENTRY_THRESHOLD. In sideways or bearish markets, rates can stay low for days — this is normal. Open the Scanner tab in the dashboard to see live rates. If rates are visible, the bot is working correctly.
2. Your configured capital exceeds your usable balance. The bot keeps an internal safety buffer and only deploys approximately 70% of your available balance. Rule of thumb:
Your actual exchange balance should be at least 1.4× your TRADE_CAPITAL_USDT setting. Example: for TRADE_CAPITAL_USDT=100, keep at least 140 USDT available in the trading wallet.
If this is the issue, logs will contain insufficient capital. Fix: deposit more USDT, or reduce TRADE_CAPITAL_USDT to ~70% of your current balance.
Will exchanges ban me for running this bot?
Funding arbitrage is a legitimate, widely-used strategy. Exchanges benefit from arbitrageurs because they provide liquidity to the futures market. There is no known case of an account being banned specifically for funding arbitrage. Use a dedicated API key with minimum required permissions and do not mix bot trading with manual trading on the same key.
Is my API key visible to anyone other than me?
No. FundingArb is self-hosted — your .env file never leaves your machine or server. The bot communicates directly with your exchange. There is no FundingArb server that handles your credentials or touches your funds. License validation runs fully offline (local signature check) — your bot never talks to a license server at all.
Can I run the bot on multiple machines?
No. Running the same license key on multiple instances simultaneously causes conflicts — both instances would attempt to manage the same positions independently. One instance per license.
Support
Pro & Lifetime customers: Email support is included. Response target: 48 hours.
Contact:
Starter customers: Community support only. Check the log output — the bot logs the reason for every decision (entry skipped, exit triggered, etc.).
Common issues to check first:
- Startup fails → Check
LICENSE_KEYis set and correct - No entry candidates → Rates below
FUNDING_ENTRY_THRESHOLD, normal in low-volatility markets - Spot order timeout → Increase
SPOT_LIMIT_TIMEOUT_SECor increaseSPOT_LIMIT_OFFSET - Exchange API errors → Verify API key permissions include Spot + Derivatives trading
Recommended Services
Affiliate disclosure: Some links below are referral links. If you sign up through them, FundingArb earns a small commission at no extra cost to you. We only list services we actually use and recommend. You are free to sign up directly instead.