New: ApexQuant now supports USDC as well as USDT. Pick the currency your account trades in. Learn more
🔍
Documentation

Installation Guide

Everything you need to go from a fresh VPS to a live running bot. Follow each step in order — don't skip ahead.

⚠️
Disclaimer This guide is accurate at the time of writing. Third-party software, commands, and APIs change over time — always verify with the respective provider for the latest instructions. ApexQuant is not liable for any misconfiguration, security breach, account compromise, or financial loss arising from following this guide. You are solely responsible for securing your VPS, API keys, and trading configuration.
⏱ Total setup time: ~90 minutes
🖥 Linux knowledge: basic
💰 TESTNET first, LIVE after
✓

Before You Begin

Make sure you have the following before starting. No license key needed for the 30-day trial — it activates automatically on first run.

  • A Binance account with Spot trading enabled
  • A Telegram account to create your control bot
  • A VPS (cloud server) — we recommend Vultr, DigitalOcean, or Linode
  • Basic familiarity with copy-pasting terminal commands
⚠️
Always start on TESTNET. Run the bot on Binance Testnet for at least 2 weeks before enabling LIVE trading. This is not optional — it lets you verify the bot behaves correctly before real money is involved.
🆘

Need help? Use the dashboard Support tab

The fastest way to get support is the built-in 🆘 Support tab in your ApexQuant dashboard. It opens a form that:

  • Auto-attaches a diagnostic bundle (recent logs, redacted .env with NO secrets, system info, recent trades)
  • Lets you set severity (Low / Normal / High / Critical)
  • Sends the ticket directly — no copy-pasting logs into email

With diagnostics attached, troubleshooting completes 3–5× faster than email-only tickets.

If you can't reach your dashboard (e.g. install failed before first launch), email {email} directly.

Choose your installation path

⚡ Quick install (recommended)

~15 minutes — guided installer, a few commands. Best for most customers.

Quick install →

ⓘ Manual install

Step-by-step. Best for custom setups or learning what each step does.

Continue manual ↓

🤝 Done-With-You Setup (guided by us)

We guide you through deploying ApexQuant on your VPS — you keep full custody of keys and funds. Non-refundable once payment is made.

Done-With-You →
0

Before you start — services you'll need

⏱ ~30 min

Gather these before SSH'ing into your VPS. The 🔴 Required ones are non-negotiable. The 🟢 Recommended ones unlock more bot features (you can add them later via helper scripts).

🔴 Required — bot cannot trade without these

  1. Ubuntu 24.04 LTS VPS — 1 vCPU + 2 GB RAM minimum (2 vCPU + 2 GB recommended); a standard SSD is fine — NVMe isn't needed, root SSH access. Vultr / DigitalOcean / Linode. Step 1 covers VPS setup in detail.
  2. Binance Sub-Account API key + secret (strongly recommended over master account) — Spot trading enabled, withdrawals DISABLED, IP whitelist set to VPS IP. Create API keys. Step 4b covers sub-account creation; Step 4 covers loading keys. Sub-account isolates the bot — only sub-account funds at risk if API key ever compromised.

🟢 Recommended — unlocks more bot features

  1. Telegram bot token + chat ID — Optional but recommended. Get a free token from @BotFather for phone alerts (entries, exits, kill-switch) and remote control (/balance, /positions, /buy, /sell, /killswitch). Step 5 covers setup; add anytime in the setup wizard or via apexquant --config-gui.
  2. Domain name — Optional but recommended for HTTPS dashboard. A record → VPS IP. nginx + Let's Encrypt setup covered later.
  3. FRED API key — Free from St. Louis Fed. Powers macro filter (FOMC + 10Y yield). Step 7 covers loading.
  4. Cloudflare Turnstile (optional) — free CAPTCHA for dashboard login; skip if your VPS is behind a VPN.

🟡 Tier-specific (Pro & Elite)

  1. Binance Futures access — only for the Funding Rate Harvest module. Binance has conditions for turning it on (an account opened first, a new key, the server's IP, no portfolio margin): they are listed under Funding Rate Harvest and in the FAQ.
  2. TradingView Pro (~$14.95+/mo, billed by TradingView) — for the TradingView Webhook strategy, which is coming soon (not available yet).
  3. AI provider API key — Anthropic / OpenAI / Gemini / DeepSeek / MiMo (Elite also: custom). Pro = Anthropic; Elite = all providers + choice. BYO key, ~$1–5/month typical.

🔵 ApexQuant license — optional

Have your license key (AQP-XXXX-XXXX-XXXX-XXXX)? Step 8 covers activation. No license yet? Skip Step 8 — bot runs in 30-day trial mode (paper/testnet). Buy from pricing when ready.

1

Set Up Your VPS

⏱ ~15 min

ApexQuant runs on a Linux server (VPS) that stays online 24/7. A laptop or desktop can technically run the bot, but is not recommended — if it sleeps, restarts, or loses internet, the bot stops and may miss critical exits on open positions. A VPS stays online 24/7 with no interruptions.

💡
Recommended VPS providers Popular options include Vultr, DigitalOcean, and Linode — all offer entry-level plans suitable for running the bot. Choose a data centre in Singapore or Tokyo for best Binance API latency. Pricing changes over time — check each provider's website for current rates. ApexQuant is not affiliated with any VPS provider. Do your own research before committing.
1.1 — Create a VPS

Create an account at your chosen provider. Deploy a new server with these specs:

VPS Specs
# Minimum requirements OS: Ubuntu 24.04 LTS (64-bit) RAM: 2 GB (ample for one bot) CPU: 1 vCPU minimum (2 vCPU recommended for ML training speed) Disk: 25 GB SSD (standard SSD is fine — NVMe gives no real benefit) Region: Singapore or Tokyo (lowest Binance latency)

💡 The installer automatically adds a 2 GB swapfile so the weekly ML retrain has headroom on a 2 GB VPS — no manual step needed.

💡
Officially supported: Ubuntu 24.04 LTS (64-bit).
Should work (community-supported, no guarantees): Debian 11/12 (use apt as documented).
Probably works with adjustments: RHEL 9 / Rocky / AlmaLinux / Fedora — translate apt commands to dnf. systemd service file works as-is.
Not supported: Alpine (no systemd by default), FreeBSD, macOS. Windows requires WSL2.

For trouble-free experience and fastest support, use Ubuntu 24.04 LTS (Vultr, DigitalOcean, Linode, AWS Lightsail).
1.2 — Connect via SSH

Once your VPS is running, connect to it. Your provider will email you the IP address and root password, or you can use SSH keys (recommended).

Terminal
# Connect from your local machine (Mac/Linux terminal or Windows PuTTY) SSH root@YOUR_VPS_IP # Enter your root password when prompted
1.3 — Update the system and install dependencies
VPS — Run once after first login
# Update system packages apt update && apt upgrade -y # Install Python 3.12, pip, git, and screen apt install -y python3.12 python3.12-venv python3.12-dev python3-pip git screen curl nano ufw # Confirm Python version (should be 3.12.x) python3.12 --version
1.4 — Configure firewall
VPS
# Allow SSH and dashboard port only ufw allow 22/tcp # SSH ufw allow 80/tcp # HTTP (for nginx + SSL challenge) ufw allow 443/tcp # HTTPS (for nginx SSL — highly recommended) ufw enable ufw status # verify rules # NOTE: Do NOT open port 5005 publicly. # The dashboard runs on 5005 internally — nginx proxies it via HTTPS. # See Step 9 (SSL + nginx) for the full setup.
1.5

Harden SSH Access

⏱ ~10 min · Highly Recommended
🔐
Highly recommended. Password-based SSH is the most common attack vector on VPS servers. Switching to SSH key authentication eliminates brute-force login attacks entirely. Takes less than 10 minutes to set up.
1.5.1 — Generate SSH key pair on your local machine (not the VPS)
Your Local Machine
# Generate a strong Ed25519 key pair (modern, fast, secure) ssh-keygen -t ed25519 -C "apexquant-vps" # Press Enter to accept default path (~/.ssh/id_ed25519) # Optionally set a passphrase for extra security # View your public key — you'll need to copy this cat ~/.ssh/id_ed25519.pub # Output looks like: ssh-ed25519 AAAAC3... apexquant-vps
1.5.2 — Add your public key to the VPS
VPS
# Create the .ssh directory and authorized_keys file mkdir -p ~/.ssh && chmod 700 ~/.ssh nano ~/.ssh/authorized_keys # Paste your public key here (the output from cat id_ed25519.pub) # Save with Ctrl+O, exit with Ctrl+X chmod 600 ~/.ssh/authorized_keys
💡
Alternatively, from your local machine run: ssh-copy-id root@YOUR_VPS_IP — this copies the key automatically.
1.5.3 — Test key login before disabling passwords
Your Local Machine — New Terminal Window
# Open a NEW terminal window and try connecting with your key ssh -i ~/.ssh/id_ed25519 root@YOUR_VPS_IP # If this connects WITHOUT asking for a password — your key works! # Do NOT close your existing SSH session until this is confirmed.
1.5.4 — Disable password authentication
⚠️
Only do this after confirming key-based login works in the step above. If you disable passwords before your key works, you will be locked out.
VPS
# Edit the SSH daemon config nano /etc/ssh/sshd_config # Find and change these lines (uncomment if needed): PasswordAuthentication no PermitRootLogin prohibit-password PubkeyAuthentication yes # Restart SSH to apply (your current session stays open) systemctl restart sshd # Verify by trying to connect with password from another terminal # It should now be refused — only key login works
1.5.5 — Install fail2ban (blocks repeated failed logins)
VPS
apt install fail2ban -y systemctl enable fail2ban systemctl start fail2ban fail2ban-client status sshd # confirm SSH jail is active
1.6

Keep Your VPS Patched 🛡️

⏱ ~5 min/month · Critical
⚠️
Linux kernel and system packages receive security updates regularly. ApexQuant relies on the underlying OS being secure. The bot cannot protect against vulnerabilities in your VPS's kernel or system libraries — that's your responsibility.

Real-world examples: in 2026, Linux had two critical local privilege escalation vulnerabilities (Copy Fail and Dirty Frag) that allowed any local user to gain root access. Customers running unpatched kernels were exposed for weeks until they updated.

1.6.1 — Apply security updates monthly
VPS — Run monthly, or whenever your VPS provider notifies you of critical updates
# Update package lists and apply available security updates apt update && apt upgrade -y # Reboot if a kernel update was installed (check the upgrade output) apt list --upgradable 2>/dev/null | grep -E "linux-image|linux-headers" # If output shows kernel packages were upgraded, reboot: reboot

ApexQuant's systemd service auto-restarts after reboot. Open positions are persisted in the local database and restored automatically. No manual intervention needed.

1.6.2 — Enable unattended security upgrades (optional, recommended)

Ubuntu can apply security patches automatically without manual apt upgrade. This catches critical patches between your monthly checks.

VPS
# Install unattended-upgrades apt install -y unattended-upgrades apt-listchanges # Enable automatic security updates only (not feature updates) dpkg-reconfigure --priority=low unattended-upgrades # Verify it's enabled cat /etc/apt/apt.conf.d/20auto-upgrades # Should show: # APT::Periodic::Update-Package-Lists "1"; # APT::Periodic::Unattended-Upgrade "1";

Note: kernel updates require a reboot to take effect. Unattended-upgrades will install them but won't reboot automatically. Schedule a monthly maintenance window to apply pending kernel updates and reboot.

1.6.3 — Monitor your VPS provider's security announcements

Subscribe to your VPS provider's security mailing list or status page. Apply critical kernel patches within 48 hours of release for high-severity CVEs.

💡
Disclaimer: ApexQuant is not responsible for security vulnerabilities in your VPS's operating system, kernel, network stack, or any other software you install on your VPS. Maintaining your VPS is your responsibility. Update regularly.
1.6.4 — (Optional) Add Cloudflare Turnstile to login
🛡️
Turnstile adds a free bot/CAPTCHA challenge to the ApexQuant login form. Defends against credential-stuffing and brute-force attempts. Works regardless of whether your domain is on Cloudflare DNS — Turnstile is a standalone service.

Setup takes about 5 minutes:

  1. Sign up at dash.cloudflare.com (free, no credit card needed).
  2. In your Cloudflare dashboard sidebar, find Turnstile. Click Add widget.
  3. Widget name: e.g., "ApexQuant Login"
  4. Hostname: Enter your root domain (e.g., yourdomain.com). Turnstile automatically covers all subdomains — so the widget works on app.yourdomain.com, bot.yourdomain.com, or any subdomain you choose later, with no reconfig needed.
  5. Widget mode: Select Managed (recommended — Cloudflare auto-decides when to challenge).
  6. Click Create. Cloudflare displays your sitekey and secret key.
  7. Add both keys to your bot's .env file:

Easiest: run apexquant --config-gui (guided, no file editing). To edit manually instead:

VPS — Edit /root/apexquant-data/.env
nano /root/apexquant-data/.env # Add these two lines (paste your actual keys): TURNSTILE_SITEKEY=0x4AAAAAxxxxxxxxxxxxxxxxxx TURNSTILE_SECRET=0x4AAAAAyyyyyyyyyyyyyyyyyy # Save (Ctrl+O, Enter, Ctrl+X) and restart the bot: systemctl restart apexquant

Verification: visit your dashboard login URL. You should see a Turnstile widget below the password field. Without solving the challenge, login is rejected.

⚠️
Both keys must be set together. If you set only one (e.g., sitekey but not secret), the bot will refuse to start until you fix it. To disable Turnstile entirely, leave both lines blank or remove them from .env.
1.7

Backup & VPS Migration 💾

ApexQuant includes an encrypted Backup & Restore feature. Use it to protect your trading state (positions, DCA baskets, grid state, settings, equity history) and to migrate to a new VPS. Find it in the dashboard at Settings → Backup & Restore.

Restore recovers the bot's bookkeeping — entry basis, DCA baskets, grid state, baseline, and history. The exchange is always the source of truth: money that has already moved on the exchange stays moved. Restore does not undo trades.

1.7.1 — What gets backed up

There are two backup types:

  • Routine backup — trading state + settings only: trade history, open positions, DCA baskets, grid state, settings, equity snapshots, baseline, and profile. Credentials (.env) are excluded. This is the default and the safer choice for regular backups.
  • Migration backup — everything above plus your credentials (.env: Binance API key/secret, Telegram token, etc.), passphrase-protected. Use this when moving to a new server and you want a near-complete restore.

Your license key is never in any backup — for security we don't store it in a form we can read, and we can't resend it. Keep your purchase email from {email} or a printout; you'll paste the key during setup.

1.7.2 — Creating a backup

In the dashboard: Settings → Backup & Restore → Create Backup. Enter a strong passphrase (store it safely — a lost passphrase means the backup is unreadable). Choose scope (Essential recommended). Click Download Backup. Store the .aqbackup file somewhere safe (offline storage recommended).

⚠ Migration backup: If you select Migration (includes credentials), the backup will contain your Binance API secret. Only do this if you understand the risk — store such backups offline only, never transmit them. For most regular use, a Routine backup is the right choice.
1.7.3 — Restore flow and what gets recovered

Restore stages the switch — it no longer refuses when positions are open. The engine boots in Restore Review mode (PAUSED) so you can review the state before resuming.

  1. Upload & restore — dashboard Backup tab → upload your .aqbackup file + passphrase.
  2. Restore Review mode: trading is PAUSED, no entries or exits fire.
  3. Review the reconciliation report — the dashboard shows a banner with a report comparing the restored bookkeeping against live exchange holdings. Resolve any flagged orphans (adopt or sell).
  4. Recover trade history (optional) — use the Recover trade history from exchange section in the banner. Click Preview to see which ApexQuant-placed trades occurred after the backup, then Apply to import them and replay PnL. Only trades with an aq_ client order ID are imported — your manual trades are never touched.
  5. Resume — click Resume Trading when satisfied.

What gets restored / recovered / not restored:

BucketWhat
✓ Restored from backup Settings & config; ApexQuant trade ledger up to backup time; open-position bookkeeping (exit-manager / DCA / grid) as of backup.
↻ Recovered from exchange Current real holdings reconciled against exchange (Restore Review); ApexQuant-placed gap trades backfilled with FIFO PnL replay (aq_ prefix only).
— Not restored Manually-placed Binance trades (never enter ApexQuant's books — bot-scope boundary); diagnostic logs; on-exchange trades are never reversed by restore.
🔄
Lapsed-user scenario: you stop using ApexQuant, continue trading manually on Binance, then re-subscribe later. When you restore your old backup, ApexQuant will show your current Binance holdings as orphans in the Review panel — you can adopt or ignore them. Your manual trades stay your own and never enter ApexQuant’s books. The Recover trade history step will import only the ApexQuant-placed gap trades (if any). Re-subscribing (entering a new license key) is separate from restore.
💾
If your license lapses: you can still export your trade history (CSV) or take a full encrypted backup from the dashboard — both are available while unlicensed. A full backup lets you restore your complete bot state when you re-subscribe. Store the passphrase safely.
1.7.4 — Restoring during first-time setup (recommended for a new VPS)

The fastest way to move to a new VPS is to restore right in the setup wizard. After bash install.sh, run apexquant --setup-gui and choose Restore from backup at the first step. Upload your .aqbackup file and passphrase — you'll see a preview of exactly what will and won't be restored, then confirm (or choose a fresh setup instead). The bot starts paused so you can review before resuming.

Before you restore, have these ready:

  • Your license key — from your purchase email ({email}). See below — it's never in a backup.
  • If you used a Routine backup: your Binance API key + secret (the wizard prompts for them since credentials aren't included).
  • If you used a Migration backup: credentials are restored automatically — just confirm they look right in the preview.
🔒
Your license key is never restored. For security we don't store it in a form we can read, and we can't resend it — keep your purchase email (from {email}) or a printout, and paste the key when the wizard asks.

Alternatively, on an already-running box, you can restore via Settings → Backup & Restore in the dashboard without stopping the setup wizard. Either path produces the same result: the bot boots paused in Restore Review mode.

Restore ≠ software update. To update the bot software on the same VPS, use Mode A (code-only) deploy — pull the new code and restart. No backup/restore involved. Back up your DB before any major update as a precaution.

2

Deploy ApexQuant

⏱ ~10 min
2.1 — Download the bot

Visit apexquant.tech/download and complete the challenge to get the latest ApexQuant setup zip.

2.2 — Upload to your VPS

From your local machine:

terminal (local)
scp ApexQuant-Setup.zip root@YOUR_VPS_IP:/root/
2.3 — Run the installer

SSH into your VPS, then:

VPS (SSH)
cd /root unzip ApexQuant-Setup.zip cd ApexQuant chmod +x install.sh bash install.sh

The installer will:

  • Set up Python 3.12 venv + all dependencies
  • Prompt for your license key — or skip for 30-day trial (paper/testnet)
  • Ask about domain: YES → nginx + free Let's Encrypt SSL; NO → VPS IP on port 5005
  • Configure systemd auto-start (restarts on reboot)
  • Start the bot in paper mode — safe, no real orders

After install, the terminal shows your dashboard URL and PIN. Note them.

3

Configure .env

install.sh generates your .env file automatically and never asks for your Binance or Telegram credentials — for security, those are entered afterward through the guided setup wizard (apexquant --setup-gui; see Steps 4 and 5).

What lives in .env
  • Everything you can configure (trading mode, strategy, capital, risk, AI settings, and everything else in the Bot Config tab) — all set in the dashboard, never in .env. This is the only documented way to change these.
  • The 13 keys that genuinely only live in .env — Binance API keys (spot and futures), the dashboard password, the admin PIN, the session secret, the FRED API key, the Telegram token and chat ID, the Turnstile site key and secret, and the server timezone. These are secrets or one-time setup values — managed through the setup wizard or apexquant --config-gui, never through the Bot Config tab.
ℹ️
Which one wins: a setting saved through apexquant --config-gui or the dashboard is stored in the bot's database and takes precedence over the same key in .env. .env is only read for a key the database has no value for. So if you edit .env for a setting you've already changed via the config-GUI or dashboard, the edit is saved to the file but has no effect — the database value keeps winning until you change it the same way you set it.
After editing one of the 13 .env-only keys

If you edit .env directly (e.g. with nano) for a Binance key, Telegram token, or another of the 13 .env-only values, restart the bot to load the change:

VPS
systemctl restart apexquant

apexquant --config-gui prompts a bot restart after saving — no manual restart needed.

Advanced: kill-switch tuning and server infrastructure (.env only)

Beyond the 13 keys above, seven more settings genuinely only live in .env — they govern automatic halt protection or low-level server behavior, and are deliberately kept out of the Bot Config tab so they cannot be loosened accidentally from the dashboard. Most installs never need to touch these; they exist for operators who understand the consequences of changing them.

⚠️
The four KILL_SWITCH_* settings and MIN_HALT_USDT_DROP govern the bot's own automatic halt protection — the system that stops trading when something looks wrong (equity implausibility, drawdown breaches). Loosening these (larger tick counts, longer delays, higher drop thresholds) makes the bot slower to halt on a genuine problem. Don't change them unless you understand exactly what each one gates.
KeyDefaultWhat it does
KILL_SWITCH_SETTLE_DELAY_S5.0Seconds to wait after a trade before trusting the next equity reading — avoids a false implausibility trigger from a balance that hasn't settled yet post-fill.
KILL_SWITCH_RESYNC_TICKS3Consecutive ticks of a persistent equity mismatch required before the kill switch treats it as a genuine re-sync (not a transient glitch) and adjusts its own baseline.
KILL_SWITCH_DD_CONFIRM_TICKS3Consecutive ticks a daily or weekly drawdown breach must persist before the kill switch actually halts — a single-tick spike doesn't trigger a halt on its own.
KILL_SWITCH_WARMUP_TICKS5Ticks after bot startup during which automatic halts are suppressed, giving the engine time to establish a stable baseline before the guards start evaluating it.
MIN_HALT_USDT_DROP50.0Minimum absolute drop, in your account's currency (in addition to the % drawdown limit), required before a daily-drawdown halt fires — prevents a halt on a tiny account where the % limit alone would trigger on a trivial dollar amount.
DASHBOARD_CORS_ORIGINS(blank)Comma-separated list of extra origins allowed to make cross-origin requests to the dashboard API. Blank (the default) means same-origin only — the dashboard and API are served from the same process, so no cross-origin access is needed for normal use. Only set this if you're building a separate frontend that calls the API directly.
DASHBOARD_HTTPStrueWhether the dashboard expects to be served over HTTPS (affects cookie security flags). Leave true unless you have a specific reason to serve the dashboard over plain HTTP — nginx setup in this guide always terminates HTTPS in front of the bot.
4

Binance API Keys

⚠️
Withdrawals must be DISABLED on the API key. ApexQuant never needs withdrawal permission. Disabling it ensures the bot cannot move funds off the exchange, even if the key is compromised.
4.1 — Create a Spot API key on Binance
  1. Go to Binance API Management.
  2. Create a new API key (type: System Generated).
  3. Enable: Enable Spot & Margin Trading.
  4. Disable: Enable Withdrawals — must be OFF.
  5. Set IP restriction: whitelist your VPS IP address.
  6. Save your API Key and Secret — the Secret is shown only once.
4.2 — Futures access (Pro & Elite)

Only for the Funding Rate Harvest module. Binance has conditions for turning Futures on (an account opened first, a new key, the server's IP, no portfolio margin): see Funding Rate Harvest and the FAQ. Enter the keys via apexquant --config-gui (Binance panel).

See also: Step 4b — Binance Sub-account (recommended for stricter isolation).

4.3 — Load keys into the bot
VPS
cd /root/ApexQuant apexquant --config-gui

The script prompts for API key, secret, and (optionally) a separate futures key. It writes them to .env and restarts the bot.

4b

Binance Sub-Account 🔐

💡
Why use a sub-account? A sub-account isolates the bot from your main Binance holdings. If the API key is ever compromised, only the sub-account balance is at risk — your main account is untouched.
Create a sub-account on Binance

Sub-account creation is done from the Binance web UI. The exact menu path varies by account type and region. Use the official guide:

Binance: How to create sub-accounts →

✉️
Email choice during sub-account creation: When Binance prompts for an email, use a new dedicated email — a virtual address or alias works well (e.g. [email protected]). Do not use your master-account email or an existing sub-account email. A fresh dedicated identity keeps the bot's sub fully isolated for login, 2FA, and API scope. Reusing an existing/master-mapped email still works functionally (funds are isolated), but a dedicated email is the recommended clean setup — easiest to get right at creation time and awkward to change later.
Create an API key on the sub-account

Once the sub-account exists, create an API key on the sub-account (not your main account) using the same settings as Step 4:

  • Enable: Spot & Margin Trading
  • Disable: Withdrawals — must be OFF
  • IP whitelist: your VPS IP

Then load the sub-account API key via apexquant --config-gui (Binance panel).

4c

Ed25519 Keys (Optional) 🔒

⏱ ~5 min
💡
This step is entirely optional — skip it if you're not sure. ApexQuant works completely fine on your existing Binance API key (Step 4) without this. Ed25519 is a newer, faster key type Binance is steering the whole platform toward for its own real-time order-update stream; setting one up now is a "pain once, done" future-proofing step, not something required to trade. If you skip this section, ApexQuant automatically uses your regular API key for everything, including order updates — nothing else changes and nothing breaks.
Why this exists

ApexQuant listens for your order fills in real time over a Binance connection called the order-update stream. Binance is moving that connection toward a newer, asymmetric key type called Ed25519 — it's faster and Binance is investing in it as the long-term standard. Your regular API key (Step 4) still works today and will keep working; setting up an Ed25519 key is simply getting ahead of that shift on your own schedule, rather than in a hurry later.

Once set up, ApexQuant uses the Ed25519 key automatically for order-update tracking. Your regular API key keeps handling everything else (placing/canceling orders, checking balances) exactly as before — nothing changes there.

1 — Generate an Ed25519 key pair
  1. Go to the official Binance Asymmetric Keys Generator guide and download the generator tool from Binance's own site (linked from that page).
  2. Run the generator, choose Ed25519 as the key type (it's the default).
  3. Generate a new key pair. Save both files — you'll need the private key file in Step 3 below. Never share the private key file with anyone, including us.
2 — Register the key on Binance
  1. Go to Binance API Management.
  2. Create a new API key, choose type Self-Generated Ed25519 Key when prompted, and paste the public key from Step 1.
  3. Enable: Enable Spot & Margin Trading (this key only needs to read order updates, but Binance requires the permission to exist on the key for the subscription to authenticate — it is never used to place, cancel, or modify anything).
  4. Disable: Enable Withdrawals — must be OFF, same as every ApexQuant key.
  5. Set IP restriction: whitelist your VPS IP address, same as Step 4.
  6. Copy the API Key string Binance shows you — this is different from your regular (Step 4) API key.
3 — Add both values to .env
⚠️
The private key needs one specific formatting step before it will work. ApexQuant's .env file is loaded by a system service that does not support pasting a private key across multiple lines the way it normally looks in the downloaded file. You must collapse it to a single line first — the steps below show exactly how.

Open the private key file the generator saved in Step 1. It looks like this:

private_key.txt (as downloaded)
-----BEGIN PRIVATE KEY----- MC4CAQAwBQYDK2VwBCIEIIJEYWtGBrhACmb9Dvy... -----END PRIVATE KEY-----

You need to turn every line break into the two characters \n (backslash, then the letter n) so the whole key becomes one line. The easiest way is a single command on your VPS — this reads the key file and prints the correctly-formatted single-line version for you to copy:

VPS (run where you uploaded/copied the key file)
awk 'BEGIN{ORS="\\n"} {print}' private_key.txt | sed ':a;N;$!ba;s/\n/\\n/g'

This prints one long line starting with -----BEGIN PRIVATE KEY-----\n and ending with \n-----END PRIVATE KEY-----\n. Copy that entire output — that's the value you'll paste into .env.

Now edit .env directly:

VPS
nano /root/apexquant-data/.env

Add two lines (paste the single-line key from the command above — do not add extra quotes around it):

.env
BINANCE_ED25519_API_KEY=the_api_key_string_from_step_2 BINANCE_ED25519_PRIVATE_KEY=-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2Vw...\n-----END PRIVATE KEY-----\n

Save, then restart the bot to load the new keys:

VPS
systemctl restart apexquant
4 — Confirm it's working

Check the bot's own logs shortly after restart:

VPS
journalctl -u apexquant --since "2 min ago" | grep WS-userdata

Look for a line mentioning session.logon succeeded and, shortly after, subscribed. If instead you see a line about falling back to the regular key, double-check the API key string and the private key formatting from Step 3 — the bot keeps trading normally either way, so there's no urgency, but you can fix it and restart again whenever convenient.

✅
Nothing to worry about if this doesn't work on the first try. If the Ed25519 setup has any issue, ApexQuant automatically keeps using your regular API key for order updates — trading is never interrupted by a misconfigured or missing Ed25519 key. Revisit this step whenever you have five spare minutes.
5

Telegram Bot

Telegram integration is optional but strongly recommended — it delivers trade alerts (entries, exits, kill-switch) and enables remote commands like /balance, /positions, /buy, /sell, and /killswitch from your phone. Everything stays between your own private bot and you — no third party is involved.

5.1 — Create a Telegram bot
  1. Open Telegram and start a chat with @BotFather.
  2. Send /newbot and follow the prompts to name your bot.
  3. Copy the token BotFather sends you (format: 123456789:AAxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx). Keep it secret — anyone with this token can control your bot.
  4. (Optional) Verify the token: open https://api.telegram.org/bot123456789:AAxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/getMe in a browser (replace the example token with your real bot token) — you should see your bot's details in the response. Note: the digits before the colon are your bot's own numeric ID — they're part of the token, not your chat ID. getMe needs no chat ID.
5.2 — Get your chat ID
  1. Start a chat with @userinfobot — it replies with your numeric chat ID (e.g. 123456789).
  2. Alternative: send any message to your new bot first, then open https://api.telegram.org/bot<YOUR_TOKEN>/getUpdates and look for "chat":{"id":…} — that number is your chat ID.
5.3 — Load into the bot
VPS
cd /root/ApexQuant apexquant --config-gui

The script prompts for your bot token and chat ID, writes them to .env, and restarts the bot. You can also enter Telegram Bot Token (TELEGRAM_TOKEN) and Telegram Chat ID (TELEGRAM_CHAT_ID) in dashboard Settings and save instead.

🔒
Security: treat your bot token like a password. If it ever leaks, open @BotFather → /revoke to invalidate it and issue a new one.

Admin PIN (Recommended)

A PIN protects destructive actions in the dashboard and Telegram. Recommended for live mode.

⚠️
PIN is required for LIVE mode security. Without a PIN or 2FA, ApexQuant refuses every action that moves money or changes what the bot does with it (buying, selling, a money setting, the currency switch, Restart and the rest): it says “To do this, set an Admin PIN or turn on 2FA first.” With one set, a stolen dashboard password alone cannot do any of them. Set it BEFORE going live. ApexQuant will warn you on every dashboard and Telegram session if PIN is missing in LIVE mode.
Set PIN in dashboard
  1. Open dashboard → Profile tab → 🔐 Admin PIN section
  2. Leave "Current PIN" blank for your first setup
  3. Choose a 4–8 digit PIN. Confirm it. Click Update PIN.
When dashboard prompts for PIN

A modal will appear before any of these actions:

Suspend or delete a license key
Disable two-factor authentication
Regenerate TradingView webhook secret (TradingView is coming soon)
Other destructive admin actions

Enter PIN → action proceeds. The PIN is remembered for a short while — subsequent actions don’t re-prompt.

When Telegram prompts for PIN

For /buy, /sell, /restart commands when PIN is enabled:

You: /buy BTC 25
Bot: 🔒 PIN required. Reply with your 4-6 digit PIN as your next message.
     Send /cancel to abort.
You: 1234
Bot: ✓ PIN verified. [shows BUY preview card]
Important: Reply with just the digits as a separate message — no slash, no prefix. Bot consumes the digits as PIN input automatically.
Short cache. After successful PIN entry, you don’t need to re-enter it for a short while. After that idle time, the PIN re-prompts on the next destructive action.
After several wrong attempts the PIN is locked for a while. Wait, then retry. Don’t share your PIN.
Forgot PIN? Reset it.

Set Admin PIN (APEXQUANT_PIN) to a new value in .env (or leave it unset to clear the PIN), add RESET_ADMIN_PIN=1, and restart the bot. Then open dashboard → Profile → Admin PIN to set a fresh PIN, and remove RESET_ADMIN_PIN from .env and restart again. No database editing required.

🛡

Switching Trading Mode (PAPER ↔ TESTNET ↔ LIVE)

From 4.9.0 onwards, trading mode is controlled entirely in the Dashboard — you no longer edit .env for this. Open Dashboard → Bot Config tab → Trading Mode:

  • PAPER: simulated orders against live prices. No Binance API key required. Default and safe.
  • TESTNET: real Binance testnet API with fake funds. Validates your full configuration end-to-end before risking real money.
  • LIVE: real money trading. Requires Starter tier or above, plus a typed I CONFIRM phrase, risk-acknowledgement checkbox, and your Admin PIN. Once confirmed, restart the bot for the change to activate.

Switching away from LIVE (e.g. back to TESTNET) requires only the Admin PIN — no typed phrase.

Legacy installs: if your existing .env has CONFIRM_LIVE=YES_I_KNOW, the bot will auto-migrate this to the dashboard flag on first start of 4.9.0 and log a deprecation notice. You can safely remove the line from .env after that.

6

Install Your License Key

⏱ ~2 min

Your license key looks like AQP-XXXX-XXXX-XXXX-XXXX. It was sent to you by email after purchase.

🔑
No file editing needed. Once the bot is running, open the dashboard → License tab → paste your key and click Save & Validate. The key is stored securely by the bot automatically.
7

First Run — TESTNET

⏱ ~10 min

Verify everything works on Testnet before touching real money. This is the most important step.

7.0 — Activate the virtual environment

Every time you open a new terminal session, activate the venv before running any Python commands:

VPS — Required in every new terminal session
cd /root/ApexQuant source venv/bin/activate # Prompt should change to: (venv) root@yourserver:~# # To deactivate (exit venv): deactivate
7.1 — Verify config before starting
VPS
cd /root/ApexQuant source venv/bin/activate # IMPORTANT: activate venv before running any python commands # Your prompt will change to: (venv) root@vps:~/apexquant# # If you open a new SSH session, always run this again first # Check config — this shows all loaded settings (no secrets) python main.py --check # Run a quick backtest to verify signals work python main.py --backtest # Should show: trade history, profit factor, win rate
7.2 — Start the bot with systemd (runs 24/7, auto-restarts)
VPS
# The systemd service uses the venv python directly — no manual activation needed # But for manual terminal commands, always activate venv first (source venv/bin/activate) cp deploy/apexquant.service /etc/systemd/system/ systemctl daemon-reload systemctl enable apexquant systemctl start apexquant # Check it's running systemctl status apexquant # Watch live logs journalctl -u apexquant -f # Press Ctrl+C to stop watching (bot keeps running)
7.3 — Open the dashboard

Open your browser and visit:

Browser
https://app.yourdomain.com # Via nginx reverse proxy (see Step 9) # OR temporarily for first-run test (before nginx is set up): http://YOUR_VPS_IP:5005

You should see the bot status, regime indicator, and price feeds. If Telegram is configured, send /status to your bot.

✅
Run on TESTNET for at least 2 weeks. Watch the dashboard daily. Check that trades are entering and exiting as expected. Verify stop-losses are triggering correctly. Only move to LIVE after you understand the bot's behaviour.
8

Go Live (When Ready)

⏱ ~5 min
🚨
Only proceed when you are genuinely satisfied with your TESTNET results. There is no fixed minimum time — what matters is that you have tuned your settings, understand the bot's behaviour across different market conditions, and are comfortable with the results. Start with a small amount you are fully prepared to lose.

Easiest: run apexquant --config-gui (guided, no file editing). To edit your Binance keys manually instead — Trading Mode itself is switched in Dashboard → Bot Config tab, not here (editing TRADING_MODE in .env has no effect once you've set it via the dashboard; see Configure .env):

VPS — Edit .env
nano /root/apexquant-data/.env # Change these two lines: BINANCE_API_KEY=your_LIVE_api_key # ← replace testnet key with live key BINANCE_API_SECRET=your_LIVE_api_secret # ← replace testnet secret # Restart the bot to apply the new keys # Via dashboard: Dashboard → Settings → 🔄 Restart systemctl restart apexquant journalctl -u apexquant -f

Then switch Trading Mode to LIVE in Dashboard → Bot Config tab and confirm you see [ENGINE] LIVE mode active in the log.

⚠️
Start small. Begin with 10–20% of your intended capital. Watch the first few trades manually. Scale up only after you are confident.
9

SSL & nginx Setup

⏱ ~20 min · Highly Recommended
🔒
Highly recommended before going live. Without SSL, your dashboard password and session tokens travel in plain text over the internet. Anyone on the same network can intercept them. nginx + Let's Encrypt gives you free HTTPS in under 20 minutes.

This setup: nginx handles HTTPS on port 443, forwards traffic to the bot on port 5005 (localhost only). Port 5005 is never exposed to the internet.

Do you have a domain name?

Yes → With Domain (nginx + Let's Encrypt SSL)

No → Without Domain (self-signed cert + VPS IP)

With Domain (nginx + Let's Encrypt SSL)

9.1 — Point your domain to the VPS

You need a domain or subdomain pointing to your VPS IP. Recommended: use app.yourdomain.com.

DNS Setup (at your domain registrar)
# Add an A record: Type: A Name: app # → app.yourdomain.com Value: YOUR_VPS_IP TTL: 300 # Wait 5–15 min for DNS to propagate, then verify: ping app.yourdomain.com # Should resolve to your VPS IP
9.2 — Install nginx
VPS
apt install nginx -y systemctl enable nginx systemctl start nginx # Test: visit http://YOUR_VPS_IP — should show nginx welcome page
9.3 — Install Certbot (Let's Encrypt)

Let's Encrypt is free SSL. Certbot automates certificate issuance and renewal.

VPS — Option A: Standard (HTTP challenge)
# Install certbot for nginx apt install certbot python3-certbot-nginx -y # Get certificate — replace with your actual domain certbot --nginx -d app.yourdomain.com # Follow prompts: enter email, agree to terms, choose redirect (option 2)
VPS — Option B: Cloudflare DNS challenge (wildcard certs)
# Use this if your domain uses Cloudflare DNS apt install certbot python3-certbot-dns-cloudflare -y # Create Cloudflare API credentials file nano /root/.cloudflare.ini # Add these lines: dns_cloudflare_api_token = your_scoped_api_token # Create a scoped token: Cloudflare → My Profile → API Tokens → Create → template "Edit zone DNS", scoped to your one zone. Do NOT use the Global API Key — it grants full account access. chmod 600 /root/.cloudflare.ini # Get wildcard certificate (covers all subdomains) certbot certonly --dns-cloudflare --dns-cloudflare-credentials /root/.cloudflare.ini \ -d "*.yourdomain.com" -d "yourdomain.com"
🔗
Other DNS providers also have certbot plugins: certbot.eff.org/instructions — select your OS and DNS provider for exact steps.
9.4 — Configure nginx as reverse proxy
VPS
# Create nginx config for ApexQuant dashboard nano /etc/nginx/sites-available/apexquant
/etc/nginx/sites-available/apexquant
server { listen 443 ssl; server_name app.yourdomain.com; # SSL certificates (path depends on your certbot method) ssl_certificate /etc/letsencrypt/live/app.yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/app.yourdomain.com/privkey.pem; # Security headers add_header Strict-Transport-Security "max-age=31536000" always; add_header X-Frame-Options DENY; add_header X-Content-Type-Options nosniff; # Proxy to ApexQuant dashboard on localhost:5005 location / { proxy_pass http://127.0.0.1:5005; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Cookie $http_cookie; # required — forwards session cookie to FastAPI proxy_read_timeout 86400; } } # Redirect HTTP to HTTPS server { listen 80; server_name app.yourdomain.com; return 301 https://$host$request_uri; }
VPS — Enable and test
# Enable the site config ln -s /etc/nginx/sites-available/apexquant /etc/nginx/sites-enabled/ # Test nginx config for syntax errors nginx -t # Should output: syntax is ok / test is successful # Reload nginx systemctl reload nginx # Update .env to bind dashboard to localhost only # Easiest: run: apexquant --config-gui — to edit manually instead: nano /root/apexquant-data/.env # Set: API_HOST=127.0.0.1 # Restart via Dashboard → Settings → 🔄 Restart, or: systemctl restart apexquant # Now access your dashboard at: https://app.yourdomain.com
9.5 — Auto-renew SSL certificates
VPS
# Test the auto-renewal with nginx reload hook (DNS-01 path: certonly doesn't auto-reload nginx) certbot renew --deploy-hook "systemctl reload nginx" --dry-run # The --deploy-hook is saved into the renewal config — all future auto-renewals reload nginx # Confirm renewal cron is active systemctl status certbot.timer
✅
Let's Encrypt certificates expire every 90 days. Certbot installs a timer that auto-renews them — no action needed from you.
AH

Monitor API Health

AH.0 — Overview

The dashboard's API Health card on the Live tab monitors connectivity and authentication status for every external service ApexQuant depends on. This is your single-glance early-warning system: if something breaks (Binance API key revoked, License Server unreachable, FRED API key expired), you see it here before trades start failing.

AH.1 — What's monitored
  • Binance API — connection + permission audit (LIVE mode only). Alerts if withdrawal permission is enabled (security risk).
  • License Server — your ApexQuant license validation server. Required.
  • Telegram Bot API — only if you've configured Telegram commands.
  • FRED Macro Data — only if you've set FRED_API_KEY (used for macro gate).
  • AI Provider — your configured AI Commentary provider (Anthropic, OpenAI, Gemini, DeepSeek, MiMo, or custom — per AI Commentary Provider (AI_PROVIDER)), shown when an AI key is set. Pro & Elite — see the AI Commentary section for the full list.
  • TradingView — only for the TradingView webhook strategy (coming soon).
  • Fear & Greed Index — sentiment data source (no API key required).
  • CoinGecko — market data fallback (no API key required).
AH.2 — Reading the panel

The card defaults to a compact summary. Click View details ▾ to expand:

  • ✓ All systems operational — every required service is healthy. Green.
  • ⚠ ServiceName: warning — something is degraded (e.g., license expiring soon). Yellow.
  • ✗ ServiceName: error — a required service is down. Red. Investigate immediately.

Services without API keys show as ○ Not configured — gray, neutral. Informational, not an error.

AH.3 — Re-checking

The ↻ Refresh all button forces a fresh parallel check of every service (~3–5 seconds). Per-service ↻ buttons recheck individual services. Data is cached per-service (5–15 minutes) so the card doesn't hammer external APIs on every page load.

AH.4 — TESTNET note

In TESTNET mode (TRADING_MODE=TESTNET), the Binance permission audit shows as informational gray ℹ because Binance testnet doesn't implement the permission endpoint. Expected behaviour — switch to LIVE mode to enable the full audit.

RS

Restarting the Bot

RS.0 — Overview

ApexQuant supports safe in-place restarts that preserve all open positions, halt state, and trade history. Use this whenever you change configuration that requires a restart.

RS.1 — From the Dashboard (recommended)
  1. Go to the Settings tab
  2. Scroll to the bottom — Restart Now button
  3. Confirm in the popup
  4. Enter your 2FA code (if 2FA enabled) or PIN (if APEXQUANT_PIN set)
  5. Bot restarts in ~10 seconds, page auto-reloads
RS.2 — From Telegram

Type /restart in your bot chat → tap Confirm → enter your APEXQUANT_PIN → restart triggers. Bot sends a status message once back online.

RS.3 — What stays safe
  • Open positions (exit_manager re-attaches on startup)
  • Halt state, kill-switch state, daily/weekly DD limits
  • Trade history (DB unaffected)
  • Pending orders on Binance (Binance-side, not affected)
RS.4 — What reconnects
  • Websocket connections to Binance (~3–5 seconds)
  • License heartbeat to License Server (~10 seconds)
  • Telegram polling thread
RS.5 — Audit logging

Every restart is logged with trigger source and authentication method:

[SYSTEM] Restart scheduled via dashboard by web ✓ PIN verified — flag in 1.5s
[SYSTEM] Restart scheduled via telegram by 12345 ✓ PIN verified — flag in 1.5s
RS.6 — Rate limit

Restarts are rate-limited. If you restart again too soon, you'll see a message asking you to wait before the next restart.

2FA

Enable Two-Factor Authentication (Recommended)

2FA.0 — Overview

ApexQuant supports TOTP-based 2FA for the dashboard, gating sensitive actions like Settings save, restart, and license entry behind a 6-digit code from your authenticator app. Strongly recommended for production deployments.

Compatible authenticator apps
Google Authenticator, Authy, 1Password, Microsoft Authenticator, Aegis (Android), Raivo (iOS). Any standards-compliant TOTP app works.
2FA.1 — Open Bot Config tab

Log in to the dashboard. Go to the Settings tab. Scroll to the Two-Factor Authentication section near the top.

2FA.2 — Scan the QR code

Click Set up 2FA. The dashboard generates a TOTP secret and displays a QR code. Open your authenticator app and scan it.

If your phone is not handy, click Show secret to manually enter the base32 secret into the app instead.

2FA.3 — Verify with the first code

Your authenticator app shows a 6-digit code that rotates every 30 seconds. Enter the current code into the verification field on the dashboard to confirm setup.

On successful verification, the dashboard generates 10 single-use recovery codes. Copy them now — they are shown only once. Store them in a password manager or print and lock away. If you lose your authenticator app and have no recovery codes, delete ~/.apexquant_2fa on your VPS to reset 2FA.

2FA.4 — What gets gated
  • Dashboard login — required after session expires
  • Settings save — protects against misconfiguration if session is hijacked
  • Restart Now button — prevents unauthorized restarts
  • License key entry — protects your license from being changed

After several wrong codes the action is locked for a while.

2FA.5 — Telegram PIN (separate)

Telegram commands are gated by a separate PIN (Admin PIN, set via APEXQUANT_PIN env var), not by TOTP. Set a 4–6 digit PIN in your .env:

.env (excerpt)
APEXQUANT_PIN=482917

Asked for every time, never remembered: /buy and its buttons, /sell, /forcesell, /dca buy, /dca resume, /dca reset, /dca close, /dca sell, /grid resume, /grid recenter, /grid extend, /grid stop, /grid rebuild, /set (for a money setting; the other settings are free), /mode (a change), /resume, /restart, Stop & Quit, /recalibrate, /setkey, /aibudget RAISE, and license commands. With 2FA on, the bot asks for the 6-digit code instead of the PIN. A code you entered for one of these is used by that one action only: Telegram's five-minute pass is not used for them (/grid pause and /grid drain keep it). /stop and /emergency (halt immediately: positions are kept, nothing is sold) ask for nothing, because the chat is yours.

On the dashboard, every action that moves money or changes what the bot does with it needs the PIN (or the 2FA code), asked each time: the Sell and Buy buttons (position, part of a position, held position, leftover coin), Stop & Liquidate, Reset & Rebuild, Resume, Restart, Stop & Quit, the grid controls, the currency switch, the strategy and trading-mode switches, saving or resetting any money setting, taking over coin, a backup restore, the licence key and the TradingView secret. Emergency Stop is the exception: it asks for your dashboard password typed again, no PIN and no 2FA code. With neither a PIN nor 2FA set up there is no manual sale or buy: ApexQuant says “To sell manually, set an Admin PIN or turn on 2FA first.” (or “To do this, set an Admin PIN or turn on 2FA first.”). The same in paper, testnet and live mode, and while halted. The bot's own exits (stop-loss, trailing stop, take-profit, grid sells, DCA exit) never ask.

2FA.6 — Disabling 2FA

Go to Settings → Two-Factor Authentication → Disable 2FA. Enter your current TOTP code to confirm.

Emergency reset (lost authenticator + no recovery codes):

VPS — Emergency 2FA reset
rm /root/.apexquant_2fa sudo systemctl restart apexquant
Live

Live Tab — Real-time Dashboard

📊 Live tab

The Live tab is your real-time view of the bot's activity. At the top, your Account Equity is shown prominently with today's profit or loss. Status pills below show whether the bot is running, in testnet or live mode, and which strategy is active.

Below the equity card is an 🧠 AI Commentary panel — your AI provider analyzes current market conditions and your portfolio, giving you context on what to expect (Elite tier).

The 📍 Open Positions table shows every asset the bot is currently holding, with entry price, current price, market value, and unrealised P&L. Every plan has SELL buttons to manually close positions.

Use the ⚡ Manual Trade controls to place a buy outside the bot's automatic logic. Buys are added to the DCA basket (or whichever strategy is active).

The 📜 Recent Trades table lists the bot's last 20 closed trades with filters for All / Auto entries / Manual entries / Managed.

For deeper insight, expand ▸ Strategy & System Details to see ML Gate confidence, current market regime, coin selection mode, API health, license status, daily drawdown, holdings count, and engine ticks. Or expand 📈 Equity Curve for a chart of your balance over time.

Privacy tip: click the 👁 icon next to "Account Equity" to mask all dollar values when sharing your screen or recording videos.

Quick system check: the status indicator in the top-right header shows the overall system state at a glance — click it for an instant diagnostics modal with API health, license verification, regime, ML gate, and drawdown details. Useful when you're on another tab and want to peek at system health.

Profile

Dashboard Profile Tab 👤

⏱ Reference

The Profile tab is your single place for personal identity, authentication, and license info. It replaces the old separate "License" tab.

  • Display Name — your shown name in the dashboard header. Defaults to "User" until you set one.
  • Avatar — upload a PNG or JPG (max 256KB). Or leave blank to show your initial as a styled letter circle.
  • Change Password — change your dashboard login password without editing .env. Old password required for verification. Forces re-login on save.
  • License — view your license key (with reveal/copy/save), tier, expiry, and status. Same functionality as the previous old dedicated tab (now consolidated here). The Renew button appears 30 days before expiry (and immediately if lapsed) — click it to renew using the same email, keeping your existing key and earning early-renewal bonus days.
  • Connections — read-only view of your Telegram chat ID. To change, edit Telegram Chat ID (TELEGRAM_CHAT_ID) in .env and restart.
  • Language — currently English only. More languages coming soon.

📊 Performance tab — daily, monthly, and yearly P&L breakdowns. Use the pill switcher at the top to toggle between views. A bar chart shows P&L for the selected period.

💡
Forgot your dashboard password? The bot checks the in-app password (set via Settings → Profile) before the .env value, so editing .env alone may not work if you previously changed it in-app. Reset it without touching your database:
  1. Set DASHBOARD_PASSWORD=<your-new-strong-password> in .env.
  2. Add RESET_DASHBOARD_PASSWORD=1 to .env.
  3. Restart the bot (systemctl restart apexquant). Log in with the new password.
  4. Remove the RESET_DASHBOARD_PASSWORD line from .env and restart once more.

This clears the in-app hash so your .env password is used. Your trading data is completely unaffected.

Why did my bot halt?

Common license-binding causes and how to recover without contacting support.

CauseWhat happenedRecovery
New server detectedYou migrated to a new VPS and the license sees a different machine ID.Click Re-bind this device in the dashboard halt overlay. (Limit: 2 re-binds / 30 days.)
Binance API key changedYou rotated your Binance API key after activation.Click Re-bind API key in the dashboard halt overlay.
Account conflictAnother ApexQuant instance is running on the same Binance account.Run one instance per Binance account. Use a sub-account for a second bot — each sub-account is treated as a distinct account. If your old server is gone, click Claim this account in the overlay.
License expiredYour license period ended.Renew at apexquant.tech/renew.
ℹ️
While halted, ApexQuant places no new buys. Selling still works: your stop-loss, trailing stop, take-profit and DCA exits still sell, your grids' sells keep working, and so do your own sells. Re-binds take effect on the next license check (up to 60 s).

When a loss limit stops ApexQuant (a safety stop)

If your daily or weekly loss limit is reached, ApexQuant stops trading for you and says why in plain words, for example:

ℹ️
Daily equity drawdown 5.2% ≥ limit 5% (equity start-of-day 1,000.00 → current 947.60, drop 52.40 USDT). Note: this counts your cash and the cost of the coin you hold, not coin price moves, so money that left the account, such as a withdrawal or a reset, counts too. Resumes at 00:00 (your local midnight).

The money ApexQuant watches is your cash plus the cost of the coin you hold. A coin's price going up or down does not move it. Money that leaves the account (a withdrawal, a Binance test-network reset) does count, because it really is gone from the account.

What a safety stop does
  • No new buys; selling still works. A halt blocks new buys only. Your open positions are still watched and still sold at their stop-loss, trailing stop, take-profit or DCA exit. Sell orders already on Binance stay and can still fill, and a grid still puts a sell on coin it holds (for example the part of a buy that filled before the stop took the rest of that buy off). Your own sells work too: the dashboard's Sell, the Sell buttons in Telegram, the typed /sell and /forcesell, each confirmed with your PIN or 2FA code. (If three stop-losses fire within ten seconds, ApexQuant treats it as a cascade and stops its automatic exits until you resume.)
  • A grid's waiting buy orders are taken off Binance, once. They were placed before the stop and could fill while ApexQuant is not allowed to buy. If Binance does not confirm the cancel, ApexQuant tries again every minute until it does. When trading resumes, the grid puts a buy back on every empty level below the price by itself. This is true for your own Emergency Stop too.
  • It is said once, not over and over. The log says it when it starts, with the reason. While it lasts, one reminder every 15 minutes says how long it has lasted (“Still halted after 1 h 30 min”). When it ends, one line says so and how long it lasted (“The halt is over after 42 min; entries are allowed again”).
  • It survives a restart. A stop that was in force when ApexQuant restarted is restored, and its message says its figures are as of the halt. Send /resume or press Resume when you are ready.
At start-up

When ApexQuant starts, its safety monitor reads your account first. The log line says what it counts: “Now protecting your account — your money counts as 1,000.00 USDT (cash plus the cost of the coin you hold)”, with your daily and weekly limits. No grid is started and no order is sent before the monitor is ready, and a stop that was in force is restored first. In those first moments a grid that has not started shows “The safety monitor is starting, so no new grid is started yet.” and starts by itself a moment later. If a stop is in force it shows “Trading is halted, so no new grid is started. Press Resume when you're ready.”

Health warnings (self-check)

ApexQuant runs a background self-check. If something looks off it shows a cautious warning, keeps running, and usually self-recovers. Here's what each warning means and what to do.

WarningWhat it meansWhat to do
Equity SnapshotThe engine hasn't recorded the balance recently.Usually self-recovers. If it lasts more than 10 minutes, restart the bot.
Exit ChecksStop-loss / take-profit checks look delayed.Self-recovers. If it persists with open positions, restart the bot.
Kill-Switch FeedThe risk-limit monitor hasn't refreshed.Usually a brief pause that self-recovers. If it lasts more than 10 minutes, restart the bot.
Strategy DispatchThe active strategy hasn't run a cycle recently.Self-recovers. If it persists, restart the bot.
Strategy Not CyclingThe strategy is enabled but hasn't advanced a cycle.May be stuck. Restart the bot if it persists.
Background Worker StoppedA background thread has stopped.Restart the bot from your VPS.
Strategy Not RunningConfig selects a strategy that isn't actually running.Restart the bot and re-check your strategy config.
Halted But Strategy ActiveThe safety halt is on but a strategy is still running — new entries may fire.Restart the bot from your VPS.
Halt ConsistencyNew trades were seen while the safety halt is on.Restart the bot and review. Contact support if it repeats.
Trades vs EquityTrading activity while balance recording is frozen.Restart the bot.
Assets SanityOpen positions aren't reflected in bot equity.Restart the bot.
Config DriftSaved configuration differs from what the running engine is using.Restart the bot to apply the saved configuration.
Any warning > 10 minThe condition didn't self-clear.Restart the bot. Contact support if it repeats.
Balance Temporarily UnavailableThe bot couldn't read your exchange balance for a moment, so it paused risk checks and kept using the last known value. Your funds and positions are untouched.Self-recovers automatically once the balance reads again — usually seconds. No action needed unless it persists past 10 minutes.
Verification PendingRight after startup, the bot is still confirming the exchange connection. It shows "connected, verification pending" until the first check completes.Normal on boot. Clears within the first cycle — no action needed.
Request Timestamp RejectedThe exchange rejected a request because it arrived slightly outside the allowed time window — almost always brief network latency, not your server clock. The bot resynced and retried automatically.Self-resolves. No action needed. If it happens constantly, check your VPS network connection to the exchange.
Request Slow to RespondA request to the exchange was slow and the bot safely abandoned and retried it, rather than waiting indefinitely.Normal under occasional exchange latency. Self-recovers. No action needed.
Insufficient Trading CapitalAn order wasn't placed because the available balance couldn't cover it. Nothing was sent to the exchange and nothing was sold.Add funds or lower the per-order size in your config if you want more orders to place. Shown once per shortfall, not repeatedly.
Holding Adjusted (tracked separately)The bot found inventory that didn't map to a grid level and moved it to a separately-tracked holding so it's protected and visible. Nothing was sold, nothing was lost.Informational only. The holding stays protected and appears in Holdings. No action needed.
Waiting for BinanceBinance cannot be reached right now. The dashboard still opens and shows what ApexQuant last knew; nothing is ordered until Binance answers again. See What happens during an API outage.Nothing to do. ApexQuant keeps trying on its own and says once when Binance is back.
Currency Balance EmptyYour account's currency has less than the smallest order, but another stablecoin in your wallet holds at least that much. For example: “Your USDT balance is 0, but you hold 500.00 USDC. ApexQuant trades in USDT, so it can't use that. Switch your currency to USDC in Settings, or convert on Binance (Binance charges a small trading fee).” It is said once in the log and once on Telegram, and the dashboard keeps the notice for as long as it is true.Nothing is switched or converted for you. Switch the currency in Settings, or convert on Binance (Binance charges a small trading fee). The notice clears by itself when the balance is back above the smallest order or the currency is switched. Another stablecoin the bot cannot use is never counted as money it can trade with.
Duplicate Order CleanupThe bot found more than one order on the same price level and cleaned up the extra (which held no coins), keeping the real one.Automatic housekeeping. No action needed.
ℹ️
Health warnings are cautious signals — the bot keeps running and usually self-recovers within a few minutes. A restart resolves most cases. If the same warning keeps recurring, contact support with a diagnostics export.

Emergency Stop

The 🛑 EMERGENCY STOP button on the Live tab halts the bot immediately. Use when you've lost confidence in the running configuration, suspect a bug, or want to pause before making changes.

⚠️
What it does NOT do: Does not close open positions and does not cancel your sell orders: sell orders already on Binance stay and can still fill, and your stop-losses, take-profits and own sells keep working. A grid's waiting buy orders are the one exception: they are taken off Binance once (and put back by the grid when you resume), because no buying is allowed while stopped. If you need to flatten positions, do that manually on Binance UI first.
What it does
  • Creates a STOP file in the bot folder
  • Bot halts at the next tick — no new entries open
  • Telegram alert fires confirming the stop
  • Open positions remain, and every sell still works (stop-loss, trailing stop, take-profit, DCA exit, grid sells and your own sells); only new buys are blocked until you resume
When to use it
  • You spot unexpected behaviour and want to investigate
  • Market making a violent move outside your strategy's design
  • Before changing config you don't trust
  • Loss of confidence in the running state
Password, not PIN

Emergency Stop asks for your dashboard password typed again (when you have set one), and nothing else: never your PIN and never a 2FA code, so you can stop the bot in a hurry without finding your phone. It works on every account, with or without a PIN or 2FA. In Telegram, /stop and /emergency ask for nothing, because the chat is yours. To start again, Resume needs your PIN (or your 2FA code), and so does Stop & Quit.

How to recover
  1. Click ▶ Resume Bot on the Live tab (or send /resume in Telegram)
  2. Bot resumes from current state — open positions are managed normally again
⚠️
Restart does NOT clear EMERGENCY STOP. If you restart ApexQuant (the Restart button on the dashboard), it starts and immediately stops again, because the stop is still in force. Only Resume removes it.
Emergency Stop vs Kill Switch vs Restart
Action Triggered by Cleared by When to use
Kill Switch Auto: drawdown / loss streak / balance floor /resume System auto-halts on risk limits — investigate then resume
Emergency Stop Manual: 🛑 button or /stop in Telegram /resume You decide to halt right now
Restart Bot Manual: the Restart button on the dashboard ApexQuant starts again by itself Apply env changes, recover from crash, refresh state

AI Commentary Pro & Elite

⏱ ~5 min setup

The AI Commentary feature adds an AI analysis layer that runs before every BUY entry. It reads all available signal data and provides informational analysis — confidence assessment, market reasoning, and context — to inform the trade decision. This is informational output; it does not guarantee outcomes. Supported providers: Anthropic Claude (Pro & Elite), OpenAI ChatGPT, Google Gemini, DeepSeek, Xiaomi MiMo, and any custom OpenAI-compatible endpoint (Elite). You supply your own API key and pay the provider directly — $0 cost to us.

All AI features are opt-in. Starting v4.9.5, no AI feature fires automatically by default. You explicitly enable what you want:

  • AI Commentary — click the “🧠 Generate” button in the Live tab to refresh on demand (15-min cooldown).
  • AI Trade Coach — click the 💡 button on any closed trade to get a 2-sentence explanation.
  • AI Symbol Suggester — click “Suggest Symbols” in Settings to get 3 new symbols based on your trading history.
  • AI Weekly Digest — opt-in via Settings → Elite AI. When enabled, sends every Monday 9am via Telegram + dashboard widget.
  • Manual BUY/SELL Pre-flight — AI verdict appears automatically when you click a BUY/SELL button (no separate enable needed).

All AI calls share your monthly AI Budget Cap (Settings → Elite AI → AI Monthly Budget Cap). Auto-disabled at 100% spend.

ℹ️
Why AI Commentary only applies to BUY, not SELL: Exit decisions (stop-loss, take-profit, trailing stop) are time-critical and price-triggered. An AI API call adds 1–3 seconds of latency — acceptable for an entry, potentially costly during a fast exit. SELL exits remain fully rule-based (ATR trailing stop, partial TP, hard stop) to ensure no delay in risk management.
⚙️
AI Commentary settings (enable/disable, model selection) are configurable in the Dashboard → Bot Config tab — no need to edit .env. Changes take effect on the next trade cycle.

What it does

🤖
AI Trade Gate
Before every BUY, your AI provider reviews: signal confidence, ML score, Fear & Greed, VIX, FOMC proximity, sentiment, and macro. It approves, blocks, or adjusts confidence based on context a rule-based system would miss.
🧠
AI Sentiment Synthesis
Your AI provider reads live market data every hour and scores overall market sentiment (-1.0 to +1.0). This replaces keyword matching with genuine language understanding — "Fed pause feared" vs "Fed pause expected" get opposite scores correctly.
🔍
Dynamic Coin Scanning
The bot auto-scans all Binance pairs in your account's currency (USDT or USDC) every 24 hours and picks the top 10 by momentum + volume, replacing your fixed symbol list automatically.

Real example decisions

✓ APPROVE — ML=0.74, regime=BULL, F&G=31 (Fear), VIX low → Strong contrarian buy setup
⛔ BLOCK — ML=0.61, regime=NEUTRAL, F&G=84 (Extreme Greed), FOMC in 2 days → Too risky near Fed event
~ ADJUST — ML=0.68 → 0.74 (+0.06), F&G=22, regime=BULL → Extreme fear boosted confidence

Setup

1 — Get an API key from your chosen provider

Choose ONE provider and get an API key. Only one provider is active at a time — configure it in Dashboard → Settings → AI Commentary.

🟠
Anthropic Claude
console.anthropic.com → API Keys → Create Key. Set AI Commentary Provider (AI_PROVIDER) to anthropic and add Anthropic API Key (ANTHROPIC_API_KEY) in Settings. Default model: claude-haiku-4-5-20251001 (fast, $1/$5 per 1M). Override with Anthropic Model (ANTHROPIC_MODEL) for Sonnet/Opus. Best reasoning quality for trading signals. Pro & Elite
🟢
OpenAI ChatGPT
platform.openai.com → API keys → Create. Set AI Commentary Provider (AI_PROVIDER) to openai and add OpenAI API Key (OPENAI_API_KEY) in Settings. Default model: gpt-4o-mini (cheapest, $0.15/$0.60 per 1M). Selectable via OpenAI Model (OPENAI_MODEL): gpt-4o, gpt-4-turbo. Elite
🔵
Google Gemini
aistudio.google.com → Get API key. Set AI Commentary Provider (AI_PROVIDER) to gemini and add Gemini API Key (GEMINI_API_KEY) in Settings. Default model: gemini-2.5-flash (~$0.30/$2.50 per 1M). Override with Gemini Model (GEMINI_MODEL) for other Gemini models. Elite
🔵
DeepSeek
platform.deepseek.com → API Keys → Create Key. Set AI Commentary Provider (AI_PROVIDER) to deepseek and add DeepSeek API Key (DEEPSEEK_API_KEY) in Settings. Default model: deepseek-v4-flash (cheapest, $0.14/$0.28 per 1M). Override DeepSeek Model (DEEPSEEK_MODEL) to deepseek-v4-pro for stronger reasoning. Elite
🔵
Xiaomi MiMo
api.xiaomimimo.com → Create an API key. Set AI Commentary Provider (AI_PROVIDER) to mimo and add Xiaomi MiMo API Key (MIMO_API_KEY) in Settings. Default model: mimo-v2.5-pro ($0.435/$0.87 per 1M). Override Xiaomi MiMo Model (MIMO_MODEL) to mimo-v2.5 for the base tier ($0.14/$0.28). Elite
⚙️
Custom Endpoint
Any OpenAI-compatible endpoint — OpenRouter, Together AI, Fireworks, Azure OpenAI, or a self-hosted vLLM/Ollama box. Set AI Commentary Provider (AI_PROVIDER) to custom with Custom Endpoint Base URL (AI_BASE_URL), Custom Model ID (AI_MODEL), and Custom Endpoint API Key (AI_API_KEY). HTTPS only (localhost exempt). Use Test Connection before saving. See setup below. Elite
Custom endpoint — setup
Any endpoint implementing the OpenAI Chat Completions API (a de-facto standard — not OpenAI itself): OpenRouter, Together AI, Fireworks, Azure OpenAI, or a self-hosted vLLM/Ollama box. Set AI Commentary Provider (AI_PROVIDER) to custom and configure Custom Endpoint Base URL (AI_BASE_URL), Custom Model ID (AI_MODEL), and Custom Endpoint API Key (AI_API_KEY) in Settings → Elite AI.

HTTPS public endpoints only (HTTP permitted only for localhost). Internal/private addresses are rejected. Use the Test Connection button before saving — Save is gated until the test passes.

Local Ollama: set Base URL http://localhost:11434/v1, get the model name from ollama list (e.g. llama3.1), and use any placeholder API key (Ollama ignores it). The bot and Ollama must be on the same machine for localhost — a remote model needs a tunnel that provides HTTPS.
Estimated monthly cost (~1,500 calls/month)
Provider Model Input $/1M Output $/1M Est. monthly
Anthropic Claude claude-haiku-4-5 $1.00 $5.00 ~$1.50
claude-sonnet-4-5 $3.00 $15.00 ~$4.50
claude-opus-4-5 $5.00 $25.00 ~$7.50
OpenAI ChatGPT gpt-4o-mini $0.15 $0.60 ~$0.20
gpt-4o $2.50 $10.00 ~$3.50
gpt-4-turbo $10.00 $30.00 ~$13.00
Google Gemini gemini-1.5-flash $0.075 $0.30 ~$0.10
gemini-1.5-pro $1.25 $5.00 ~$1.75
gemini-2.5-flash free* free* free*
DeepSeek deepseek-v4-flash $0.14 $0.28 ~$0.50
deepseek-v4-pro $0.44 $0.87 ~$1.80
Xiaomi MiMo mimo-v2.5-pro $0.44 $0.87 ~$1.80
mimo-v2.5 $0.14 $0.28 ~$0.50
Custom endpoint any OpenAI-compatible varies — check your provider

Rates as of June 2026 — confirm at provider; prices change. Cache hits bill far lower. Based on ~600 input + 80 output tokens per call, ~1,500 calls/month. You supply your own API key and pay the provider directly. Pro tier: Anthropic only. Elite: all providers + custom. Rates as of June 2026 — confirm at provider; prices change. Cache hits bill far lower.

💡 Recommendation: Start with the cheapest tier. Set AI Monthly Budget Cap (USD) (AI_MONTHLY_BUDGET_USD, registered default 10.0, group Elite AI) to 5 in Settings until you understand your actual usage pattern.

2 — Add your provider's API key

Paste your API key directly into Dashboard → ⚙ Bot Config tab (Elite AI group) — for example, Anthropic API Key (ANTHROPIC_API_KEY), OpenAI API Key (OPENAI_API_KEY), or Gemini API Key (GEMINI_API_KEY), depending on your chosen provider. No SSH or restart needed.

Then turn the feature on and tune it in the same Bot Config tab:

  • AI Commentary Enabled (ELITE_AI_ENABLED, default on)
  • AI Commentary Cooldown (ELITE_AI_COOLDOWN, default 300 seconds) — minimum time between AI calls per symbol
DeepSeek, Xiaomi MiMo, and custom endpoints (Elite tier)

Set AI Commentary Provider (AI_PROVIDER, Bot Config → Elite AI group) to one of: anthropic (Pro & Elite) | openai | gemini | deepseek | mimo | custom. Then set the matching key (all keys below are in the Bot Config → Elite AI group unless noted):

AI Commentary Provider (AI_PROVIDER) Key env Model env (optional override) Default model
anthropicAnthropic API Key (ANTHROPIC_API_KEY)AI Commentary Model (legacy) (ELITE_AI_MODEL) or Anthropic Model (ANTHROPIC_MODEL) — both workclaude-haiku-4-5-20251001
openaiOpenAI API Key (OPENAI_API_KEY)OpenAI Model (OPENAI_MODEL)gpt-4o-mini
geminiGemini API Key (GEMINI_API_KEY)Gemini Model (GEMINI_MODEL)gemini-2.5-flash
deepseekDeepSeek API Key (DEEPSEEK_API_KEY)DeepSeek Model (DEEPSEEK_MODEL)deepseek-v4-flash (or deepseek-v4-pro)
mimoXiaomi MiMo API Key (MIMO_API_KEY)Xiaomi MiMo Model (MIMO_MODEL)mimo-v2.5-pro (or mimo-v2.5)
customCustom Endpoint API Key (AI_API_KEY)Custom Model ID (AI_MODEL) + Custom Endpoint Base URL (AI_BASE_URL)any OpenAI-compatible endpoint

AI providers operate from different jurisdictions; regardless of provider, only a sanitized market-context prompt is sent — no API keys, balances, trade history, or personal data. See the Privacy Policy for details.

3 — Restart the bot

The AI gate and AI sentiment synthesis both activate automatically on restart. You'll see [ELITE-AI] BTCUSDT — APPROVE | adj=+0.00 in the logs when it runs.

ℹ️
The AI Commentary feature is fail-open — if the Anthropic API is unreachable, the bot continues trading normally using the standard ML gate. Your trading is never blocked by an AI outage.

How it fits into the signal chain

Price tick
→ ✓ Regime gate (EMA + ADX)
→ ✓ FOMC blackout check
→ ✓ Macro gate (FRED)
→ ✓ Sentiment gate (F&G + news + AI synthesis on Elite)
→ ✓ Signal engine (EMA + RSI + MACD + BB)
→ ✓ ML gate (XGBoost, 18 features)
→ ✓ AI Commentary ← Pro (Anthropic) and Elite (all providers)
→ ✓ Kelly sizing → BUY executed
DR

Directional Strategy

In plain terms: Imagine you have one fruit basket that holds exactly one apple. Directional trading means: buy the apple when prices are rising, sell when prices fall. You can only hold one apple at a time — to buy another, you must first sell the one you have. The bot uses ML signals + technical indicators to decide WHEN to swap apples. Endgame: Each apple is sold individually when the price target hits (or stop-loss triggers), then the bot looks for the next opportunity to buy.

Other strategies you may consider: DCA Bot — buy steadily over time. Grid Bot — profit from sideways markets.

Directional strategy uses ML signals and technical indicators to time entry and exit. It is the original ApexQuant strategy. Set Primary Strategy (PRIMARY_STRATEGY) to Directional via the Bot Config tab.

VariableDefaultWhat it does
Signal Threshold (SIGNAL_THRESHOLD) — group Strategy0.48Minimum signal score to open a trade. Lower = more trades, higher = fewer but better quality. Range: 0.45–0.58.
Kelly Multiplier (KELLY_MULT) — group Kelly0.5Position sizing aggressiveness. 0.25 = very safe, 0.5 = balanced, 1.0 = full Kelly (risky). Start at 0.25.
Kelly Maximum Position (KELLY_MAX_FRAC) — group Kelly0.10Maximum % of balance per trade. 10% default. Never set above 0.15 until you have 50+ live trades of history.
Hard Stop ATR Multiplier (HARD_STOP_ATR) — group Risk1.5Stop-loss = entry price minus this many ATR widths. 1.5 is balanced. Increase to 2.0 for wider stops in volatile markets.
Partial Take-Profit ATR (PARTIAL_TP_ATR) — group Risk4.0First take-profit target = entry + this many ATR. Higher = more ambitious target. 3.0–5.0 is reasonable range.
Order Cooldown (ORDER_COOLDOWN) — group Trading Mechanics60Seconds between entries on same symbol. 60 = 1 min. Prevents overtrading in choppy conditions.
⚠️
These directly control how much you can lose per trade — raise them carefully: Kelly Multiplier (KELLY_MULT) and Kelly Maximum Position (KELLY_MAX_FRAC) scale your position size directly — higher values mean larger positions and larger swings, both gains and losses. Widening Hard Stop ATR Multiplier (HARD_STOP_ATR) increases the loss the bot will accept on a single trade before exiting. Primary Strategy (PRIMARY_STRATEGY) changes which engine trades your account entirely — switching away from Directional stops this strategy's own open-position handling and hands control to whichever strategy you switch to.
AI

AI Bundle Elite

Beyond AI Commentary on signals, ApexQuant Elite tier includes additional AI features. These use your configured AI provider key (any supported provider; configured in Settings).

  • AI Weekly Digest (Mon 9am) (AI_BUNDLE_DIGEST_ENABLED, Elite, default off) — every Monday 9am, a summary of last week's trades is sent to Telegram and shown in the dashboard Performance tab (Daily view). Best/worst trade, win rate, P&L, suggestions. Cached 7 days. On-demand via /digest. Toggle in Bot Config → Elite AI group.
  • AI Trade Coach (post-trade) (AI_BUNDLE_COACH_ENABLED, Elite, default on) — after every closed trade, a 💡 button appears in the trade log. Click for a 2-sentence AI explanation of why the trade played out the way it did. Cached forever per trade.
  • AI Symbol Suggester (AI_BUNDLE_SUGGESTER_ENABLED, Elite, default on) — on-demand button in Settings → AI Commentary group. AI analyzes last 90 days of trades + current portfolio, suggests 3 new symbols with reasoning. Cached 24h.
  • AI Strategy Compare Narration (Elite) (AI_BUNDLE_NARRATE_ENABLED, Elite, default on) — when comparing two backtests, AI narrates the trade-off in plain English.

Estimated cost: ~$0.05–$0.10/month at typical usage. Each feature can be toggled individually. All AI Bundle features are informational only — they never influence trade decisions.

DC

DCA Bot

In plain terms: DCA is like buying one apple every week regardless of price — sometimes the apple costs $1, sometimes $2. Over time, your basket fills up with apples bought at different prices, and the average cost-per-apple smooths out. You don't time the market; you let time do the work. Endgame: When the total basket value reaches your profit target (e.g. +5%), the bot sells all apples at once and starts a fresh basket. (Alternative: set “none” mode for pure accumulation — you decide when to sell.)

How often does DCA buy?

By default, ApexQuant's DCA strategy buys once per week per symbol (Time Interval (hours) (DCA_INTERVAL_HOURS) = 168). This is the recommended cadence — frequent enough to average down through volatility, infrequent enough that fees don't erode returns.

If your dashboard shows the last DCA buy was yesterday, the next buy for that symbol is scheduled approximately 7 days from then. To buy more frequently, lower Time Interval (hours) (DCA_INTERVAL_HOURS) in Settings → DCA. To buy on price drops instead of a fixed schedule, switch DCA Mode (DCA_MODE) from time to drop.

Other strategies: Directional — time the market with ML. Smart DCA — Buy The Dip mode. Grid Bot — profit from sideways markets.

How exits work in DCA

DCA is fundamentally different from Directional in how positions are closed:

  • Auto-managed basket: Every buy (whether automated by the bot or manual via dashboard/Telegram) goes into the same DCA basket. The basket has ONE exit target — when total ROI hits Take-Profit Target (%) (DCA_TP_PCT) (default 5%), the entire basket sells at once.
  • You don't control individual exits: Unlike Directional where each buy can have its own SL/TP, DCA treats all legs as one position. The "exit mode" selector in the manual buy form is hidden when DCA is active because it has no effect.
  • To close the basket early: Use the SELL button on the dashboard, or /dca close via Telegram. Either way, all positions in the basket sell at market price and the basket resets.
  • Three exit modes (set in DCA settings):
    • tp (default): basket sells when ROI hits Take-Profit Target (%) (DCA_TP_PCT)
    • trail: basket arms a trailing stop after Trail Arm Threshold (%) (DCA_TRAIL_ARM_PCT), exits on retracement
    • none: basket never auto-sells; you decide when to close
⚠ Important: If you're used to Directional or other "one buy = one exit" strategies, DCA's basket-level exit will feel different. Every manual buy in DCA mode is committed to the basket — you cannot cherry-pick which leg to sell first. Plan accordingly.
⚠️ DCA Does NOT Use Stop-Loss

DCA is an accumulation strategy. Positions do not auto-sell on losses — only on take-profit (TP) above your average entry, or trailing stops above your peak. If price falls 20%, your basket stays open and the bot may add more legs (if budget allows).

This is intentional. DCA assumes you have a long-term thesis and are willing to hold through drawdowns. If you want automatic stop-loss protection on every trade, use Directional strategy instead.

Per-strategy kill-switch behavior: Every strategy uses the same measure: your cash plus the cost of the coin you hold. Unrealized basket drawdown (price falling on open positions) does not trip a halt — the bot keeps averaging in as designed. Realised losses and money that really leaves the account do count.

Unrealized basket drawdown is surfaced as warnings in the dashboard budget cell: 🟡 >20%, 🟠 >35%, 🔴 >50% — informational only, never a halt. The daily limit resets at your local midnight.

💡 The Real DCA Backstop: Exposure Caps (Settings → DCA)

Because DCA does not halt on unrealized drawdown, your real risk control is exposure. Set these in Settings → DCA:

  • DCA Budget per Symbol (USDT or USDC) — basket stops averaging in once this amount is spent. Total DCA exposure ≈ budget × active symbols.
  • DCA Max Averaging Legs — maximum averaging buys per basket. Works alongside budget to cap deployment.
  • Trading Capital (CAPITAL_MODE, default all, group Capital) set to fixed + Fixed Capital Amount (USDT or USDC) (TRADING_CAPITAL_USDT, default 0.0 = all available, group Capital) — hard account-wide ceiling (recommended). Prevents any strategy deploying beyond the set amount. Set in Settings → Capital. Raising this directly increases how much of your account can be deployed at once.

Strategy switching requires no open positions. Close all positions first (Manual /sell). Switching while a DCA basket is open is blocked — one strategy manages one symbol at a time.

Dollar-Cost Averaging is a rule-based accumulation strategy. The bot buys an asset at regular intervals or when the price drops by a set percentage — without attempting to time the market. You define the parameters; the bot executes them mechanically.

DCA does not eliminate risk. Drop mode (averaging down) can accumulate losses if the asset does not recover. Time mode tracks the asset's performance — if the asset is in a multi-year downtrend, your DCA position accumulates losses. ApexQuant does not guarantee any outcome. You are responsible for your strategy selection and parameter choices.

Two Modes

Time mode (DCA_MODE=time)
Buys a fixed amount (in your account's currency) at a fixed interval (daily, weekly, monthly — you decide). Suitable for long-term accumulation of assets you believe will appreciate over months or years. No dip-detection is involved.

Drop mode (DCA_MODE=drop)
Opens an initial position, then buys more each time the price falls by your configured percentage from the last buy (Drop Step (%) (DCA_DROP_STEP_PCT)). Reduces your average cost per unit. Suitable for catching dips on assets you expect to recover. Stops adding legs after Max Buy Legs (DCA_MAX_LEGS) is reached or budget is exhausted.

Three Exit Modes

None (DCA_EXIT=none)
Pure accumulation. The bot never sells automatically. You close the position manually via /dca close or from the dashboard.

Take-profit (DCA_EXIT=tp)
Sells the entire position when your average-entry ROI (after fees) reaches Take-Profit Target (%) (DCA_TP_PCT). After selling, the budget resets and a new DCA cycle may begin.

Trailing TP (DCA_EXIT=trail)
Arms when ROI reaches Trail Arm Threshold (%) (DCA_TRAIL_ARM_PCT). Tracks the peak price from that point forward. Sells when price retraces from the peak by Trail Distance (%) (DCA_TRAIL_DISTANCE_PCT)%. Locks in gains as the asset runs up; exits on the pullback.

Trailing Stop Config

Switch DCA Exit Mode (DCA_EXIT) to trail for trending markets where you want to let winners run:

  • Arm threshold (DCA_TRAIL_ARM_PCT, default 3%) — trail activates only after basket reaches this ROI. Below this, position stays open normally.
  • Trail distance (DCA_TRAIL_DISTANCE_PCT, default 1.5%) — maximum retracement from peak before exit fires.

Example: armed at +3%, peak hits +10%, price retraces to +8.5% (1.5% from peak) → sell. Locks in 8.5% gain instead of selling at the original 5% TP. When to use: BULL regime, trending markets. When not to use: choppy ranging markets — frequent retraces will trigger early exits.

Enabling DCA

Set Primary Strategy to DCA via the Bot Config tab. DCA is a primary strategy — it replaces Directional as the engine's main strategy. Harvest can still run concurrently.

Configure these in the Bot Config tab (group DCA unless noted). Values below are a reasonable starting point:

GUI Label (key)Value used belowWhat it does
Primary Strategy (PRIMARY_STRATEGY) — group Features & GatesdcaSwitches the engine's main strategy to DCA.
DCA Mode (DCA_MODE)timeTime-based (fixed intervals) vs. Price-drop (buy on dips). Only applies when Primary Strategy is DCA.
DCA Exit Mode (DCA_EXIT)tpAccumulate only (manual exit), Take-Profit %, or Trailing Stop.
Take-Profit Target (%) (DCA_TP_PCT)5.0TP mode only: sell when ROI (after fees) reaches this %. Registered default matches this value.
Budget per Symbol (USDT or USDC) (DCA_BUDGET_USDT)500The most to spend on this coin before stopping new buys. Budget resets after sell. Registered default matches this value. Restart to apply.
Per-Buy Size (USDT or USDC) (DCA_BUY_SIZE_USDT)50Amount per individual buy order. It cannot be below the bot's minimum order size (11 by default). Registered default matches this value.
Time Interval (hours) (DCA_INTERVAL_HOURS)168Time mode only: hours between buys (168 = weekly).

Amounts are in your account's currency (USDT or USDC).

If using Drop mode instead of Time mode: Drop Step (%) (DCA_DROP_STEP_PCT, default 5.0) and Max Buy Legs (DCA_MAX_LEGS, default 10) — restart to apply. If using Trailing Stop instead of Take-Profit: Trail Arm Threshold (%) (DCA_TRAIL_ARM_PCT, default 3.0) and Trail Distance (%) (DCA_TRAIL_DISTANCE_PCT, default 1.5) — both only shown in the GUI once DCA Exit Mode is set to Trailing Stop.

⚠️
Max Buy Legs (DCA_MAX_LEGS) caps how many averaging buys a basket can add per symbol — raising it increases how much capital can be committed to one losing position before the cap stops new buys. Take-Profit Target (%) (DCA_TP_PCT) directly sets how much profit you're aiming to lock in per exit — lowering it exits sooner for smaller, more frequent gains; raising it holds out for more but risks giving profit back on a reversal.

Telegram Commands

  • /dca status — all open positions: leg count, avg entry, current ROI, budget used
  • /dca pause — stop new buys (existing positions still exit via TP/trail)
  • /dca resume — restart buys after pause
  • /dca buy BTC — force a manual buy outside the normal schedule (still checks budget)
  • /dca close BTC — close the DCA position immediately at market
  • /dca reset BTC — reset budget for a symbol (allows a new DCA cycle)

State Persistence

DCA position state (legs, avg entry, budget used, last buy time) is saved to apexquant.db after every buy and sell. If the service restarts, it resumes exactly where it left off. No manual recovery needed.

SD

Smart DCA: Buy The Dip Pro · Elite

In plain terms: Classic DCA buys on a fixed schedule regardless of market state. Smart DCA tilts your buys based on a Fear Score from 5 macro and sentiment signals — bigger when the market shows fear, smaller (or skipped) when greed peaks. Result: capital protection in volatile markets — your buys lean into dips and step aside during euphoria.

Other strategies: Directional — time the market with ML. DCA Bot — classic DCA. Grid Bot — profit from sideways markets.

The 5 signals

SignalWeightSource
Fear & Greed Index35%alternative.me
FRED Macro Health25%St. Louis Fed (FRED API)
News Sentiment20%CoinDesk + Binance L/S ratio
Market Regime10%Bitcoin BULL / NEUTRAL / BEAR / CRISIS
FOMC Week10%Federal Reserve schedule (auto-fetched monthly)

Market Signals — 200-Week Moving Average

The 200-week moving average is a long-term cycle gauge. ApexQuant compares the current price to its 200-week MA (a simple ratio) to judge whether price is sitting below historical support or stretched well above it. This biases how cautiously or confidently the bot sizes new positions — it never forces a buy or a sell, and it makes no promise about outcomes. It runs on Binance weekly candles only (no external paid data) and is available on every tier. It affects DCA and directional sizing; the Grid strategy uses fixed per-level allocation and is unaffected.

How the zones work (ratio = price ÷ 200-week MA):

  • Below Deep Value (default 0.85): price is deep under its long-term average — strongest buy-bias (sizes up).
  • Between Deep Value and Support (0.85–1.0): mild buy-bias.
  • Between Support and Extended: neutral.
  • At or above Extended (default 2.4): price is stretched well above its long-term average — caution, reduced buy-bias (sizes down).

The sizing adjustment is bounded (a nudge of roughly ±15–30%, not a swing), and falls back to neutral (no effect) when there is not enough weekly history yet or data cannot be fetched.

Recommended settings (defaults — load optimally out of the box):

SettingRecommendedWhat it does
200-Week MA SignalOnMaster toggle. On by default.
Deep Value threshold0.85Ratio below this = deep-value zone (strongest buy-bias).
Support threshold1.0Ratio below this but above Deep Value = mild buy-bias.
Extended threshold2.4Ratio at/above this = extended zone (caution, reduce buy-bias).
Refresh interval (hours)12How often weekly candles are re-fetched. 12h is ample.

Thresholds must satisfy Deep Value < Support < Extended — the dashboard enforces this and will reject an out-of-order save.

Which strategies use the market signals?

ApexQuant's signal pipeline is not bot-wide — each strategy uses it differently. Here's an at-a-glance breakdown:

Layer Directional DCA Grid TradingView (coming soon)
Entry timing source Internal 8-factor signal engine + ML Fixed schedule (interval / dip) Fixed price levels in your range Your TradingView alert (internal signals off)
Market-bias signals — regime, Fear & Greed, macro + FOMC, funding, 200-week MA ✓ (entry + sizing) ✓ (Smart-DCA sizing) ✗ — not used ✓ — applied as risk gates
ML gate ✓ ✗ ✗ ✓
AI Commentary (informational, pre-BUY; Pro/Elite) ✓ ✓ ✗ — *
Risk rails — kill-switch halt, daily drawdown limit, API-outage block, price > 0 ✓ ✓ ✓ ✓

Grid is a rule-based range trader — it deliberately ignores the market-signal pipeline (it's meant to buy dips and sell rips inside your range regardless of trend or sentiment). It still obeys the risk rails: a kill-switch halt or a Binance API outage stops it immediately. The signal pipeline shapes Directional and DCA entries and sizing. TradingView (coming soon) supplies its own entry but still passes the risk gates.

* AI Commentary availability on the TradingView path (coming soon) is configurable; see the TradingView section.

The 4 modes

  • Pure — no scaling. Identical to Classic DCA — used as a comparison baseline.
  • Conservative — 0.5×–1.5× scaling, no skips.
  • Balanced (default) — 0.5×–2.0× scaling, skips buys when greed is high.
  • Aggressive — 0.5×–3.0× scaling, larger swings, skips buys when greed is high.

Backtest results

BTCUSDT, daily buys, 2024-05 → 2026-05, $50 per buy:

ModeInvestedFinal ValueROI
Classic DCA (pure)$37,500$35,242-6.02%
Conservative$27,092$26,101-3.66%
Balanced (default)$15,672$16,015+2.19%
Aggressive$21,370$21,871+2.34%

Balanced/Aggressive modes deployed less capital (skipped greed-zone buys per Fear Score), which protected against the BTC drawdown over this period. Smart DCA’s edge is capital protection in volatile markets, not raw alpha.

⚠ Disclaimer: Backtested on 22 May 2026 using historical BTCUSDT hourly klines from Binance + alternative.me Fear & Greed Index. Backtest assumes ideal fill execution at hourly close prices with no slippage. Past performance is not indicative of future results. Actual live trading results will vary due to spread, slippage, and Binance fee structure. Backtest results are illustrative only and do not constitute investment advice.

How to enable

  1. Dashboard → Settings → DCA section → toggle Buy The Dip (Smart DCA) on (default ON for Pro/Elite).
  2. Pick your mode from the dropdown (default: Balanced).
  3. Watch the Fear Score card on the Live tab — updates every 15 seconds.
GR

Grid Bot

Pro · Elite

In plain terms: Grid trading is like running a fruit stall. You have multiple baskets at fixed price levels: buy an apple at $1, sell at $2, buy again at $1.50, sell at $2.50, and repeat. The bot profits from price oscillating within a range, not from picking direction. Best for sideways markets — bad for strong trends in either direction (you'd run out of selling-baskets in a rally, or buying-baskets in a crash). Endgame: When price exits your set range, you choose what happens — close (stand down and hand inventory to stop-loss/take-profit protection — not force-sold; the default), pause (stop new orders, keep existing apples, auto-resumes when price returns via Grid Auto-Resume (GRID_AUTO_RESUME)), or hold (do nothing and wait for price to come back). There's also a fourth option that doesn't stop the stall at all: Smart Grid, which grows the range instead of exiting it — see the Smart Grid subsection below.

Other strategies: Directional — time the market with ML. DCA Bot — buy steadily over time.

⚠️
Grid bots profit from sideways markets and lose money in strong trends. ApexQuant cannot predict market direction. You choose the price range and Range Break Action; ApexQuant only executes within those bounds. Losses are possible and your responsibility.
GR.1 — How grid trading works

Grid trading divides a price range into evenly spaced levels and automatically places buy orders below the current price. Each time a buy fills, a sell order is placed one level higher — capturing the spacing as profit. Each time a sell fills, a new buy is placed one level lower, ready to repeat the cycle. The strategy earns small, frequent profits as long as the price oscillates within the range.

A level's buy may fill in a few pieces rather than all at once — they add up to the level's full amount, so seeing more than one row for the same level in your trade history is normal.

Grid bot is rule-based. It does not consult AI Commentary, ML signals, or regime detection. It simply places and replaces limit orders at fixed price levels. This makes it predictable, but entirely dependent on the market staying range-bound.

It does, however, still obey the safety rails every strategy shares: if the kill-switch halts the bot or Binance goes unreachable, the grid stops placing and filling orders until conditions clear.

GR.2 — When to use Grid Bot

Good conditions: Sideways, choppy, or ranging markets where price repeatedly bounces between support and resistance. Coins with high intraday volatility but no clear directional trend. Post-breakout consolidations where a new range is forming.

GR.3 — When NOT to use it

Avoid in: Strong trending markets (bull or bear). A breakout above the upper bound leaves open buy orders with no fills. A breakdown below the lower bound fills all buy levels, accumulating an inventory that continues to lose value. Your range bounds and Range Break Action (GRID_BREAK_ACTION) limit this downside but do not eliminate it.

GR.4 — Running grids on multiple symbols (Pro & Elite)

ApexQuant supports concurrent grids across multiple symbols. Each symbol gets an independent grid with its own price levels, inventory, and PnL — all running in parallel under the same bot instance.

Tier limits:

  • Trial — grid on 1 symbol, TESTNET / PAPER only
  • Starter — Grid Bot not included
  • Pro — grid on 1 symbol, live (mainnet) trading
  • Elite — grids on up to 5 symbols, live trading

How allocation works: Total Allocation (USDT or USDC) (GRID_TOTAL_ALLOCATION_USDT) is split equally across every coin in Grid Coins (GRID_SYMBOLS). Example: Total Allocation = 1000 with Grid Coins = BTC, ETH, SOL allocates $333.33 per grid.

How to configure: set Grid Coins (GRID_SYMBOLS) in the Bot Config tab (Grid Bot group) to a comma-separated list of coins, e.g. BTC, ETH. Restart the bot. Each grid initialises independently — if one symbol fails to start (capital check, range invalid), other symbols continue.

How to control individual grids: the dashboard Live tab shows one card per active grid with per-symbol Pause / Resume / Stop & Liquidate / Reset & Rebuild buttons. Telegram commands accept an optional symbol argument: /grid pause BTC targets one grid, /grid pause with no argument targets all.

If you exceed your tier limit: the bot logs a warning and truncates the list to the tier maximum (e.g. Pro user with BTC, ETH in Grid Coins (GRID_SYMBOLS) will only run BTC). Upgrade to Elite to run grids on up to 5 symbols.

GR.5 — Configuration
VariableDefaultWhat it does
Primary Strategy (PRIMARY_STRATEGY) — group Features & GatesdcaSet to grid to activate the Grid Bot.
Grid Lower Price (USDT or USDC) (GRID_LOWER_PRICE) — group Grid0Lower bound of the grid, in your account's currency. e.g. 75000. Leave at 0 if using auto-range.
Grid Upper Price (USDT or USDC) (GRID_UPPER_PRICE) — group Grid0Upper bound of the grid, in your account's currency. e.g. 80000. Leave at 0 if using auto-range. Must be greater than the lower bound.
Auto-Range % (from current price) (GRID_AUTO_RANGE_PCT) — group Grid5.0Recommended default — builds the grid ±5% around the live price at startup, so it works on any symbol with no manual range needed. Overrides the manual bounds above. Set to 0 only if you want to enter Grid Lower/Upper Price yourself.
Grid Levels (GRID_LEVELS) — group Grid10Number of grid levels. Range 5–50. More levels = smaller profit per round-trip but more frequent fills.
Grid Spacing (GRID_SPACING) — group Gridgeometricgeometric (equal % gaps) or arithmetic (equal price gaps). Geometric gives uniform profit % at every level.
Total Allocation (USDT or USDC) (GRID_TOTAL_ALLOCATION_USDT) — group Grid200Total amount committed across all levels. e.g. 200 = $200 split evenly.
Take Profit (USDT or USDC) (GRID_TAKE_PROFIT_USDT) — group Grid0Optional: halt when cumulative realised profit reaches this amount. e.g. 50 = stop after $50 profit. Leave at 0 to run indefinitely.
Max Open Orders (GRID_MAX_OPEN_ORDERS) — group Grid30Safety cap on total open Binance orders from this grid. Should be ≤ levels/2 for lazy placement mode.
Range Break Action (GRID_BREAK_ACTION) — group GridcloseWhat to do when price exits the range (only used when Smart Grid is OFF — see Smart Grid (GRID_SMART_MODE) below). Default: close — cancel orders and hand inventory to stop-loss/take-profit protection (NOT force-sold). pause: cancel orders, keep inventory; auto-resumes when price returns (see Grid Auto-Resume (GRID_AUTO_RESUME)). hold: do nothing, orders remain. trail_up: on an upside break, slide the range up (see Grid Trail Shift (%) (GRID_TRAIL_SHIFT_PCT)). Recommended keep-trading option is Smart Grid (see the Smart Grid subsection) — turn it on to extend instead of stop.
Grid Auto-Resume (GRID_AUTO_RESUME) — group GridtrueWhen GRID_BREAK_ACTION=pause, automatically re-activate the grid once price returns inside the configured range (with a small 0.1% margin to prevent boundary flapping). Set to false to require a manual /grid resume. Skipped while the kill-switch is halted or Binance is unreachable at the moment price re-enters.
Grid Trail Shift (%) (GRID_TRAIL_SHIFT_PCT) — group Grid50Only when GRID_BREAK_ACTION=trail_up: when price breaks above range_high, the range shifts up by this % of the original width (buy orders below the new floor are cancelled; sell orders untouched). Example: range $80k–$90k breaks above $90k, shift 50% → new range $85k–$95k.
Grid Trail Max Shifts (GRID_TRAIL_MAX_SHIFTS) — group Grid5Max trail-ups before the grid pauses — prevents infinite chasing in strong uptrends. Note: downside breaks (price < range_low) always pause the grid regardless of trail_up. Best for trending uptrends; in ranging markets use pause instead.
Grid Coins (GRID_SYMBOLS) — group GridBTCComma-separated coins for concurrent grids (e.g. BTC, ETH, SOL: just the coin). Pro tier: 1 coin max. Elite: up to 5. Total Allocation (USDT or USDC) (GRID_TOTAL_ALLOCATION_USDT) is split equally across all symbols. Restart required after any change.
Smart Grid (GRID_SMART_MODE) — group GridfalseMaster switch for Smart Grid. When on, growing the boundary replaces the Range Break Action choices above entirely for range-break handling — see the Smart Grid subsection below. Off by default.
└ Extend Upward (GRID_AUTO_EXTEND_UPPER) — group GridtrueShown when Smart Grid is on. On an upside break, add sell levels above the range. Free — empty sell-slots, no capital spent.
└ Extend Downward (buy dips, within budget) (GRID_AUTO_EXTEND_LOWER) — group GridfalseShown when Smart Grid is on. On a downside break, add buy levels below the range, funded only from this grid's own unused budget — never fresh funds. When it can't add another buy level safely — either the budget is spent, each level would get too thin, or the grid has grown to its size limit — it simply holds what it has and waits. It never sells at a loss and never freezes; to keep extending, recenter or add capital.
Max Upward Extensions / session (GRID_EXTEND_MAX_UPPER) — group Grid5Max automatic upward extensions per session (flap guard). Only relevant when Smart Grid + Extend Upward are on.
Max Downward Extensions / session (GRID_EXTEND_MAX_LOWER) — group Grid3Max automatic downward extensions per session (flap guard). Only relevant when Smart Grid + Extend Downward are on.
Auto-Recenter when grid can't extend (GRID_AUTO_RECENTER_ON_IDLE) — group GridfalseShown when Smart Grid is on. When price breaks a full grid-width past the range AND the grid is already at its maximum size, automatically recenter around the current price to keep trading — useful while you're away. Held coins, cost basis, profit, and settings are never touched; only the range moves (same as a manual Recenter, never a sale). A brief spike won't trigger it; it won't thrash in a choppy market and has a daily cap. Off by default. Pro tier.
└ Auto-Recenter Direction (GRID_AUTO_RECENTER_DIRECTION) — group Gridabove_onlyShown when Smart Grid + Auto-Recenter are on. above_only (default, safe) — only auto-recenter on an upside break (the grid sold to cash on the way up; redeploying higher is low-risk). both — also auto-recenter on a downside break, deploying remaining cash into a falling price. Only change to both if you understand the risk.
⚠️
Two settings above are easy to misread — check these carefully:
  • Total Allocation (USDT or USDC) (GRID_TOTAL_ALLOCATION_USDT, group Grid, default 200.0) is a total across ALL your grid symbols, not per symbol. Running 5 grids at $5,000 each means setting this to $25,000 total, not $5,000 — the bot divides it by the number of active grids for you. Setting $5,000 while running 5 grids gives each grid only $1,000 — double-check the math before saving.
  • Grid Levels (GRID_LEVELS, group Grid, default 10) — changing the count re-lays the entire grid at the new spacing. A level count whose spacing would fall below break-even is refused at save time rather than applied — you'll see the exact reason if that happens.
GR.5b — Smart Grid: growing the stall instead of closing it

Smart Grid — growing the stall instead of closing it. Normally, when the price leaves your grid's range, the stall has to stop: it either pauses (keeps your apples, waits), closes (hands your apples to the safety net), or holds. Smart Grid gives the stall a fourth choice — it grows. Instead of shutting when price runs off the edge, it builds new baskets at the edge that was breached and keeps trading.

Two ways it grows, depending on which way price broke:

  • Price runs UP past your top basket → the stall adds new selling-baskets higher up. Your existing baskets don't move, nothing is cancelled — the stall just gets taller so it can keep selling into the rally. This costs nothing extra: the new baskets up top are empty sell-slots waiting for price, not orders you pay for now.
  • Price falls BELOW your bottom basket → the stall adds new buying-baskets lower down, so you keep buying the dip. This spends money (each new buying-basket needs cash), so Smart Grid only uses this grid's own unspent budget — never money you didn't set aside for it. When it can't safely add another buying-basket — the budget's spent, OR each basket would get too small to be worth it, OR the stall has already grown to its size limit — it holds what it has and waits. It never sells your apples at a loss to keep going, and it never freezes. To keep buying lower, recenter the stall or add more trade capital.

Example. Say you set a grid on BTC with a range of $60,000 – $66,000 and $600 budget across 5 levels ($120 per basket).

  • BTC rallies to $68,000 (above your $66,000 top). Without Smart Grid the stall would pause — your top sell would fill at $66,000 and then nothing, missing the run to $68,000. With Smart Grid (Extend Upward), the stall adds new selling-baskets above $66,000 — say up to $69,000 — so your apples keep selling into the rally instead of stopping at $66,000. Your bottom ($60,000) doesn't move; the range just stretches up to $60,000 – $69,000.
  • BTC drops to $58,000 (below your $60,000 floor). With Smart Grid (Extend Downward), the stall adds new buying-baskets below $60,000 — say down to $57,000 — buying the dip with your grid's own spare budget. If all $600 is already deployed, the stall stops adding baskets, holds everything it bought, and waits for recovery. It never sells those dip-buys at a loss to "escape."

A stall only takes on what it can handle. Every basket the stall adds needs somewhere to sell later and enough money behind it to matter. So the stall grows only while there's room — while each basket stays a worthwhile size and the stall hasn't hit its size limit. Once it's full, it stops adding rather than cramming in baskets it can't properly work — like a full plane not boarding more passengers than it has seats. Nothing is sold, nothing is lost; the stall just tells you it's at capacity and waits, and you can recenter or add capital if you want it bigger.

Smart Grid (Extend) vs Trail Up — what's the difference? Both react to price running up, but they do opposite things to your stall:

  • Smart Grid Extend = a bigger stall. The bottom stays pinned; new baskets are added on top. Think of stretching a rubber band: one end stays put, the other stretches. You keep every basket you had, plus new ones. Range $60k–$66k becomes $60k–$69k.
  • Trail Up = the same stall, moved. The whole range slides upward — the top rises AND the bottom rises, and the lowest baskets are let go. Think of carrying a ladder upward: same number of rungs, just higher; the bottom rungs leave the ground. Range $60k–$66k becomes, say, $63k–$69k — you've given up the $60k–$63k baskets.

Use Extend to keep accumulating across the whole move (widen and hold everything). Use Trail Up to follow a strong one-way trend and stop holding the now-far-below levels. Smart Grid uses Extend. Trail Up remains available as a separate Range Break Action.

(Neither one "chases profit" — that's Smart TP's job, a separate feature that rides a single sell higher when price is spiking. Extend and Trail just decide where your grid's boundaries sit.)

When Smart Grid is on vs off: Turn Smart Grid on and it takes over what happens on a range break — you'll see Extend Upward (on by default, free) and Extend Downward (off by default, spends budget) options, and the older Range Break Action list is hidden. Turn it off and you're back to the classic choices (close / pause / hold / trail up). Smart Grid is off by default — a deliberate choice you switch on.

Auto-Recenter (optional, for unattended trends). Extend grows the stall while it can. But in a strong one-way move the stall eventually reaches its maximum size and price keeps going — leaving it parked out of range until you recenter it by hand. If you're away (asleep, offline), it just sits idle and misses the move. Turn on Auto-Recenter when the grid can't extend further (GRID_AUTO_RECENTER_ON_IDLE, off by default, Smart Grid only) and the bot does that recenter for you: when price breaks a full grid-width clear of the range AND the stall is already at its maximum size, it automatically recenters around the current price to keep trading. Your held coins, cost basis, profit, and settings are unchanged — only the range moves — it's the same Recenter you can run by hand, never a sale. A brief spike won't trigger it — it waits for a clear move — and it won't repeatedly recenter in a choppy market, with a daily safety cap. By default it only acts on an upside break (the stall has already sold to cash on the way up, so redeploying higher is low-risk); set GRID_AUTO_RECENTER_DIRECTION to both only if you also want it to recenter on a downside break, which deploys remaining cash into a falling price. Off by default — leave it off and the stall holds and waits for you, exactly as before. Auto-Recenter keeps the stall trading through a move; it does not make trending markets safe — grid bots still lose in a sustained adverse trend.

GR.5c — Grid control buttons (dashboard Live tab)

Keep-trading actions (never sell): Pause/Resume, Recenter, Extend Up, Extend Down. Wind-down actions: Drain (sells at profit only), Stop & Liquidate and Reset & Rebuild (sell inventory — these ask for your PIN). Housekeeping: Clear Stats.

ButtonWhat it doesSells?
⏸ PauseFreezes the stall: stops placing and filling orders, but keeps every basket, your apples (inventory), and your stats. Resume picks up exactly where it left off.No
🫗 DrainCancels the buying-baskets but leaves the selling-baskets live. Your apples sell off at their profit levels as price reaches them, then the grid stops on its own. Use when you want to wind down gracefully at a profit rather than dump. (If the stall grew past its normal size, the extra baskets retire themselves this same way — selling at a profit as price reaches them — bringing the stall back to its set size without selling anything at a loss.)Only at existing profit targets — never at a loss
🎯 RecenterRebuilds the grid range around the CURRENT price. Cancels and replaces the open orders, but does NOT sell your holdings — any apples you're holding are carried over and given a new sell target where one is possible. Use when price has drifted well outside your range and you want the grid re-anchored to where the market actually is.No
🎯 Auto-Recenter (optional)The same Recenter above, run automatically when price breaks a full grid-width clear of the range and the stall is already at its maximum size — for when you're away and the grid would otherwise sit idle. Off by default; turn on in Bot Config (Smart Grid section). Your coins, cost basis, and profit are never touched, only the range moves.No
⬆️ Extend UpAdds new selling-baskets above your current top, as future sell targets. Costs nothing and places no orders now — they're empty slots waiting for price. Use to keep selling into a rally without rebuilding. The manual version of what Smart Grid does automatically.No
⬇️ Extend DownAdds new buying-baskets below your current floor, funded ONLY from this grid's own unused budget — never fresh funds from your wallet. Use to keep buying a dip. When it can't add another safely — budget spent, baskets too thin, or at the size limit — it stops adding and holds. Recenter or add capital to grow further. The manual version of what Smart Grid does automatically.No
⛔ Stop & LiquidateCancels all open orders AND market-sells the entire grid inventory, then stops the grid completely (no rebuild). This is the deliberate "sell everything and stand down" button.Yes — sells everything. Confirmation + PIN required.
🔄 Reset & RebuildCancels orders and market-sells the current inventory, then builds a fresh grid around the current price and resumes trading. Use to start clean at today's price.Yes — sells the existing position first. Confirmation + PIN required.
Clear StatsZeroes the realized P&L, fees, and fill counts for a fresh performance-tracking start. Does NOT touch orders or inventory.No
GR.6 — Telegram commands

All commands accept an optional symbol argument. Omit the symbol to target all active grids.

/grid status — all active grids: state, range, fills, open orders, realised PnL
/grid status BTC — specific grid only
/grid pause — cancel open orders on all grids; inventory kept (PIN-gated)
/grid pause BTC — pause specific grid only
/grid resume — re-place buy orders on all paused grids (PIN-gated)
/grid resume ETH — resume specific grid only
/grid stop [SYM] — cancel all orders + market-sell inventory, then STOP the grid — no rebuild (aliases: reset, close; PIN-gated)
/grid rebuild [SYM] — same liquidation, then rebuild a fresh grid at the current price ± Auto-Range % (from current price) (GRID_AUTO_RANGE_PCT) (PIN-gated)
/grid drain [SYM] — cancel buy orders, keep sell orders live; inventory sells only at its existing profit targets as price reaches them, then the grid stops on its own — never sells at a loss (PIN-gated)
/grid recenter [SYM] — rebuild the grid range around the current price; cancels and replaces open orders but does NOT sell your holdings — inventory is carried over with a new sell target where possible (PIN-gated)
/grid extend upper [SYM] — add new sell levels above the range; free, no orders placed, nothing sold (PIN-gated)
/grid extend lower [SYM] — add new buy levels below the range, funded only from that grid's own unused budget (never fresh funds); holds when the budget is spent — sells nothing (PIN-gated)
GR.7 — Example: BTC $75k–$80k range

You set Grid Lower Price (USDT or USDC) (GRID_LOWER_PRICE) = 75000, Grid Upper Price (USDT or USDC) (GRID_UPPER_PRICE) = 80000, Grid Levels (GRID_LEVELS) = 10, Total Allocation (USDT or USDC) (GRID_TOTAL_ALLOCATION_USDT) = 200. The bot places 10 levels spaced $555 apart. Each level gets $20 (200 ÷ 10). Below current price ($77,500), levels at $75,000, $75,555, …, $77,222 get limit buy orders. When any buy fills, a sell is placed one level higher. A complete round-trip (buy at $77,222, sell at $77,778) earns approximately $0.73 gross — minus two maker fees (~$0.04 at 0.1%) = ~$0.69 net per cycle. With frequent oscillations, these accumulate. With a sustained drop below $75,000, all buy levels fill and realised losses begin.

GR.8 — Realistic expectations

Profit per round-trip ≈ grid spacing % minus fees on both sides. With 10 levels across a 6.7% range, each level is ~0.74% apart. After two maker fees at 0.1% each, net profit is ~0.54% per round-trip. This compounds through frequent fills in a ranging market — but in a trending market, inventory accumulates and losses are real. Grid bot does not beat the market; it harvests volatility within a defined range. If the asset trends strongly in either direction, it will underperform a simple hold or miss the trend entirely.

GR.9 — State persistence

Grid state (open orders, filled levels, realised PnL) is saved to apexquant.db after every fill. On restart, the bot reconciles persisted state against live Binance orders and resumes from where it left off.

Managing and exiting a grid

Use these Telegram commands to control a running grid:

  • /grid pause — Pauses the grid. Open orders are canceled and the bot holds the current inventory without placing new orders. Use /grid resume to restart the grid from its current state. Useful when you want a temporary break without fully liquidating.
  • /grid drain — The graceful exit. Cancels only the resting buy orders, keeps the resting sell orders live, and stops placing new buys. Your inventory liquidates naturally at the grid's own profit levels as price rises. Once all inventory has sold through the open sells, the grid auto-finalizes to stopped with no manual action needed. Use this when you want to exit a grid without taking a market-sell loss — the middle option between pause (hold everything) and stop (exit now). Safeguard: if price falls far below range or the drain runs longer than Grid Drain Timeout (hours) (GRID_DRAIN_TIMEOUT_H) (default 24h), the bot escalates per Grid Drain On Timeout (GRID_DRAIN_ON_TIMEOUT) (default: liquidate the remainder) so the drain never hangs indefinitely.
  • /grid stop — Full exit. Cancels all resting grid orders and market-sells the grid's entire inventory back to your account's currency in one shot. Use this when you want to recover capital, switch symbols, or migrate. After /grid stop the grid is fully closed — no orders or inventory remain.

Capital sizing rule: each grid needs at least $50 allocated, and allocation ÷ symbols ÷ levels must be ≥ $10 per level — otherwise Binance rejects every individual order as below MIN_NOTIONAL. For example: $100 capital, 1 symbol, 5 levels = $20/level ✓. $100, 2 symbols, 10 levels = $5/level ✗.

Dashboard tip: the grid card's order list now shows the value in your account's currency alongside each coin amount — buy orders show the amount to be deployed, sell orders the amount to be returned, and held inventory shows the live value at current price.

ST

Smart TP & Volatility-Scaled Trailing

Smart TP (Runaway Chase) arms when price blows past a take-profit by the configured gap and trails the move with a hard floor at the original TP — so the worst case is a normal exit.

Applies to all strategies — Directional, DCA and Grid all use Smart TP once enabled; it's not tied to any single one, even though the examples below use grid numbers.

Master switch

  • Smart TP (Runaway Chase) (SMART_TP_ENABLED, default off, group Features & Gates) — Pro & Elite (Trial on TESTNET only). Turns the whole feature on or off. The trail-mode settings below only take effect once this is on.

Trail mode settings

  • Smart TP — Trail Mode (SMART_TP_TRAIL_MODE, default fixed, group Features & Gates) — fixed uses a constant Smart TP — Trail % (SMART_TP_TRAIL_PCT, default 2.0). vol_scaled widens or tightens the trail based on recent 24-hour volatility: trail = k × vol24h, clamped between a floor and ceiling.
  • Smart TP — Vol Trail Multiplier (k) (SMART_TP_TRAIL_VOL_K, group Features & Gates) — the multiplier (default 1.5). At 4% vol, trail = 6%. Higher values ride longer but give back more. The canonical value is 1.5 — it is not recommended to tune this per-coin.

Use vol_scaled if your grid operates on volatile altcoin pairs and you find the fixed trail gets stopped out on normal noise. Leave it on fixed for BTC or when you want predictable exits.

Symbol delisting guard

If Binance marks a symbol as non-tradable (status BREAK, HALT, or the symbol is delisted), ApexQuant automatically pauses new orders for that symbol and holds any existing inventory — it will not attempt to force-sell. You will receive a Telegram alert. If the symbol later resumes TRADING status, the grid restarts automatically. If the pair is permanently delisted and inventory cannot be sold on-exchange, you will need to review it manually through the Binance web interface.

Picking Arm Gap % and Trail % — with numbers. These two only work well when they're sized to your grid. Here's why, using the same example grid from the Smart Grid section (range $60,000–$66,000, 5 levels): Your grid spans 10% ($60k to $66k), split across 5 levels — so each level is about 2.5% apart (10% ÷ 4 gaps). That 2.5% is your grid's natural profit-per-step. Smart TP's Arm Gap is how far past a sell target price must run before the chase kicks in. If you set Arm Gap to 10%, price would have to rocket 10% past a level to arm — but your whole grid is only 10% wide, so it would almost never happen. Smart TP just sits there doing nothing. This is the most common mistake. A sensible Arm Gap here is around 1–1.25% — less than one 2.5% step, so the chase can actually trigger on a normal push above a level. Trail % should be smaller than Arm Gap — say 0.75% — so once the chase arms, it locks in most of the run before exiting instead of giving it back. You don't have to work this out yourself. When Smart TP is on, the dashboard suggests sensible Arm and Trail values from your grid's range and levels (one click to apply), and warns you inline if you type a value that would stop Smart TP from working — like an Arm Gap bigger than your whole range. The suggestion is optional; your own values are never changed unless you click Apply.

BT

Web Backtest UI Pro / Elite

From the dashboard History tab, Pro and Elite users can launch backtests with a graphical interface:

  • Symbol picker — choose from your configured symbols
  • Date range — calendar pickers for start and end dates
  • Override parameters — optionally set SL%, TP%, leverage to test variations (whitelist-validated)
  • Live progress bar — updates every 2s as Binance bars are processed (typically 30s–5min)
  • Cancel button — abort runs early; other jobs continue unaffected
  • Equity curve chart — SVG chart of portfolio balance over the period
  • History table — last 50 backtests with 📈 Chart button to re-view equity curve

Parameter Sweep (Elite only)

Run the same backtest across a grid of parameter combinations to find optimal settings:

  • Choose 2 parameters (e.g. SL_PCT and TP_PCT) and up to 4 values each
  • Total grid capped at 16 combinations (4×4) to bound compute time
  • Each combination runs as a separate background job with individual progress tracking
  • Results aggregated showing which parameter combination yielded the highest P&L

Note: Telegram /backtest BTC continues to work for all tiers — the web UI is additive.

Without Domain (self-signed cert + VPS IP)

Generate a self-signed certificate for HTTPS without a domain:

VPS
mkdir -p /etc/ssl/apexquant openssl req -x509 -nodes -days 3650 \ -newkey rsa:2048 \ -keyout /etc/ssl/apexquant/key.pem \ -out /etc/ssl/apexquant/cert.pem \ -subj "/CN=apexquant-local" chmod 600 /etc/ssl/apexquant/key.pem

Access the dashboard at https://YOUR_VPS_IP:5005. Your browser will show a certificate warning — accept it (you generated the cert yourself).

⚠
Without domain: No trusted HTTPS. For production use, a domain + Let's Encrypt is strongly recommended.
CV

Common Trading Variables

These variables apply to all strategies (Directional, DCA, Grid Bot). DCA-specific variables are documented in the DCA Bot section. Grid Bot variables are in the Grid Bot section.

VariableDefaultWhat it does
Symbol Selection Mode (COIN_MODE) — group Coin ScannerFIXEDFIXED = trade exactly the symbols in Trading Coins. SCAN = bot auto-scans Binance every 24h and picks top coins by momentum+volume. SCAN is a Pro-tier feature — exciting but requires more monitoring. Recommended: start with FIXED.
Trade Style (TRADE_STYLE) — group StrategySCALPSCALP = 1-min signals, quick in-out. SWING = 1h signals, hold for bigger moves. Start with SCALP.
Trading Coins (SYMBOLS) — group Trading SetupBTC,ETHWhich coins to trade. Enter just the coin — e.g. BTC, ETH, XRP, SOL, BNB; ApexQuant builds each pair from your account's currency. Starter tier: max 2. Pro tier: max 5. Recommended starting coins: BTC,ETH.
ML Gate Enabled (ML_ENABLED) — group ML GatetrueEnable the XGBoost signal filter. Strongly recommended — leave true. Disable only for debugging.
ML Minimum Return (ML_MIN_RETURN) — group ML0.002ML must predict at least 0.2% move to allow entry. Higher = fewer, better-quality trades. Try 0.003–0.005 for stricter filter.
FRED API Key (FRED_API_KEY) — .env only, not a Bot Config setting(blank)Free macro intelligence. Get your key at fred.stlouisfed.org — takes 2 minutes. Strongly recommended.
Manual BUY reserve % (MANUAL_BUY_RESERVE_PCT) — group Trading Setup5.0Percentage of balance reserved as safety buffer for fees + slippage on manual BUY orders. Default 5.0 means manual BUY can use up to 95% of available balance. Range: 0–25.
⚠️
Manual BUY reserve % (MANUAL_BUY_RESERVE_PCT) directly controls how much of your balance a manual BUY can commit — lowering it (using more of your available balance per manual buy) leaves less safety margin for fees, slippage, and other open orders.
⚙️
Tip: Change most settings live from the browser
Trading mode, symbols, timeframe, risk limits, ML gate, AI Commentary, and strategy toggles can all be changed from Dashboard → ⚙️ Bot Config tab — no SSH, no service restart needed. Changes save permanently to the database and survive reboots.

Only secrets (Binance API keys, Anthropic key, Dashboard password) require direct .env editing.
QP

Quick Configuration Profiles

Open apexquant --config-gui (or Dashboard → ⚙️ Bot Config) and set each field to the value shown below for the profile you want. Run a backtest after applying each one.

Profile A
Conservative
Fewer trades, tighter risk. Best for new users or choppy/sideways markets.
Good starting point
Profile C
Aggressive
More trades, wider stops. Best for strong trending bull markets only.
Experienced users
Profile A — Conservative
"Signal Threshold" — "0.52" "Kelly Multiplier" — "0.25" "Kelly Maximum Position" — "0.05" "Hard Stop ATR Multiplier" — "1.0" "Partial Take-Profit ATR" — "2.0" "Trailing Stop ATR" — "1.5" "Daily Loss Limit" — "0.03" "Weekly Loss Limit" — "0.06" "Max Loss Streak" — "3" "ML Minimum Return" — "0.003"
Profile B — Balanced (default)
"Signal Threshold" — "0.48" "Kelly Multiplier" — "0.5" "Kelly Maximum Position" — "0.10" "Hard Stop ATR Multiplier" — "1.5" "Partial Take-Profit ATR" — "4.0" "Trailing Stop ATR" — "1.5" "Daily Loss Limit" — "0.03" "Weekly Loss Limit" — "0.10" "Max Loss Streak" — "4" "ML Minimum Return" — "0.002"

These match the bot's own factory defaults.

Profile C — Aggressive (trending bull markets only)
"Signal Threshold" — "0.45" "Kelly Multiplier" — "0.75" "Kelly Maximum Position" — "0.15" "Hard Stop ATR Multiplier" — "1.5" "Partial Take-Profit ATR" — "3.5" "Trailing Stop ATR" — "3.0" "Daily Loss Limit" — "0.08" "Weekly Loss Limit" — "0.15" "Max Loss Streak" — "6" "ML Minimum Return" — "0.001"
SSH

Risk Management Settings

These settings protect your capital. The bot will halt new entries (but still manage open positions) when any limit is breached. Existing positions continue to be managed.

VariableDefaultWhat it does
Daily Loss Limit (DAILY_LOSS_LIMIT) — group Risk0.03Halt if down 3% today. 0.03 = conservative (default), 0.05 = balanced, 0.08 = aggressive.
Weekly Loss Limit (WEEKLY_LOSS_LIMIT) — group Risk0.10Halt if down 10% this week. Set this to about 2× your daily limit.
Max Loss Streak (MAX_LOSS_STREAK) — group Risk4Halt after 4 consecutive losing trades. Forces you to review before continuing. 3 = cautious.
Minimum Balance Stop (MIN_BALANCE_STOP) — group Risk50.0Never trade below this balance (in your account's currency). Prevents blowing out to zero. Set to 20% of your starting capital.
Max Hold Time (MAX_HOLD_HOURS) — group Risk48Force-exit any position open longer than 48 hours. Prevents capital being stuck in stale trades.
TRADE SAFETY LAYER
Position Reconciliation Interval (RECONCILE_INTERVAL_SEC) — group Trading Mechanics21600How often (in seconds) the bot verifies its local database matches Binance's actual trade records. Default 6 hours. Lower = more API calls; higher = more potential drift. Default is fine for most users.
Reconcile On Startup (RECONCILE_ON_STARTUP) — group Trading MechanicstrueRun reconciliation immediately when the bot starts, before placing any trades. Recommended — heals any state drift since the last run before trading resumes.
Deposit Detection Interval (DEPOSIT_POLL_INTERVAL_SEC) — group Trading Mechanics21600How often the bot polls Binance for deposits and withdrawals to keep the wallet baseline accurate. Relevant if you manually move funds in or out of the account between bot restarts.
Block on Ghost Positions (GUARD_BLOCK_ON_GHOST) — group Trading MechanicsfalseWhen the bot detects a "ghost order" (an order it recorded sending but Binance has no record of), controls whether to halt the bot. Default false = send a Telegram alert and continue. Set true for paranoid environments where any unconfirmed order should stop trading.
💡
Suggested first-month settings for new users: Daily Loss Limit (DAILY_LOSS_LIMIT) 0.03, Weekly Loss Limit (WEEKLY_LOSS_LIMIT) 0.06, Max Loss Streak (MAX_LOSS_STREAK) 3, Kelly Multiplier (KELLY_MULT) 0.25, Kelly Maximum Position (KELLY_MAX_FRAC) 0.05. Tighter limits mean slower growth but much smaller drawdowns while you learn the system.

Wallet baseline — protecting your existing assets

When ApexQuant first connects to your Binance account, it snapshots your current asset balances. This snapshot is the baseline — the bot treats everything in this snapshot as your pre-existing assets, not bot-managed funds.

Going forward, only assets the bot acquires through its own BUY orders are considered "bot-owned" and eligible to sell. Even if the local database is corrupted or contains a phantom position record, the bot will refuse to sell quantities that don't show up as bot-acquired.

Every SELL passes three independent guards:

GuardSourceCatches
LedgerSum of all bot BUYs minus all bot SELLs in local trade historyCode bugs, ledger corruption — bot trying to sell more than it ever bought
Baseline deltaCurrent wallet quantity minus your baseline snapshotPhantom position records — database has a ghost entry but no actual fill ever happened
Free balanceLive Binance available balanceReal-time wallet anomalies — catches anything that slipped past the first two

A SELL only executes for the minimum of all three guards. If any guard says zero, the SELL is blocked entirely and you'll receive a Telegram alert.

ℹ️
If you manually deposit or withdraw funds via Binance directly, the baseline auto-adjusts every 6 hours via the deposit/withdrawal poll. You can also trigger an immediate recalibration via Telegram: /recalibrate confirm (Starter tier and above).
ML

ML Gate Settings

The ML gate is an XGBoost model that filters signals before entry. It trains automatically on your first run (~2 minutes) and retrains weekly.

VariableDefaultWhat it does
ML Training Mode (ML_MODE) — group MLregressionUse regression (default, smarter — predicts return magnitude) or classifier (legacy). Leave as regression.
ML Minimum Return (ML_MIN_RETURN) — group ML0.002Minimum predicted % return to allow entry. 0.002 = 0.2% move required. Try 0.003–0.005 for stricter filter.
ML Minimum Confidence (ML_CONFIDENCE_MIN) — group ML0.58Classifier mode only: minimum probability to allow BUY. 0.55 = permissive, 0.63 = strict.
ML Training Symbol Pool (ML_TRAIN_SYMBOLS) — group MLmultiTrain on BTC+ETH+XRP combined (multi) for more data. Recommended. Use btc for BTC-only training.
ML Retrain Interval (ML_RETRAIN_DAYS) — group ML7Retrain every 7 days on fresh data. Pro tier and above — Starter users retrain manually with /trainml.
ML Forward Window (ML_FORWARD_BARS) — group ML8Predict price 8 bars ahead (8 hours on 1h data). Don't change unless you understand walk-forward validation.
ℹ️
To manually retrain the ML model at any time, send /trainml in Telegram. Training takes 1–3 minutes. The bot continues trading during training and only switches to the new model after it passes validation.
DYN

Dynamic Symbol Detection (Pro & Elite)

By default the bot trades a fixed list of symbols you define in Trading Coins (SYMBOLS). Pro and Elite tier users can optionally enable scan mode — the bot automatically scans Binance every 24 hours and selects the top coins by momentum and volume, then retrains the ML model on the new set.

⚠️
Not recommended for beginners. Scan mode changes which coins are traded automatically. Only enable this after you are comfortable with the bot in FIXED mode and have at least 1 month of live experience.

Recommended: configure in the Bot Config tab (group Coin Scanner unless noted).

GUI Label (key)Value to setWhat it does
Symbol Selection Mode (COIN_MODE)SCAN (not "DYNAMIC" — that value doesn't exist; the two valid options are FIXED and SCAN)Switches from your fixed Trading Coins list to dynamic top-N-by-volume selection.
Top N Symbols by Volume (COIN_SCAN_TOP_N)5 (registered default)How many top coins to select per scan (max = your tier symbol limit).
Coin Rescan Interval (COIN_SCAN_INTERVAL_HOURS)24 (registered default)How often to re-scan and re-rank symbols.
Minimum 24h Volume for Scan (COIN_SCAN_MIN_VOLUME_USDT)50000000 (registered default)Removes illiquid coins — a 50M minimum 24h volume (in your account's currency) to be considered.

Your Trading Coins (SYMBOLS) setting still matters even in SCAN mode — it's used as the fallback list before the first scan completes.

💡
Scan mode is available on Pro and Elite tiers. In Starter tier, COIN_MODE=SCAN is ignored and the bot falls back to FIXED mode using your Trading Coins (SYMBOLS) setting.
HR

Funding Rate Harvest Pro & Elite

What is it?

The Harvest module earns passive income, in your account's currency, from funding rates — the periodic payments that perpetual futures traders pay each other every 8 hours on Binance. When longs are crowded (positive funding rate), long traders pay short traders. The Harvest module collects this payment by taking a position structured to receive the funding rate while eliminating directional price risk.

💡
Simple analogy: Imagine a market where people who borrowed Bitcoin to bet it goes up must pay a fee every 8 hours to people on the other side. Harvest puts you on the receiving side of that fee — without needing to predict whether Bitcoin goes up or down.

Before you turn it on: Futures access

Binance only allows it when all of these are true:

  • Your Futures account is opened first. On a sub-account, open Futures on that sub-account.
  • The API key is created after that. An older key can't get Futures, so create a new one.
  • The key is restricted to your server's IP address.
  • The account isn't using portfolio margin.

You only need Futures for funding-rate harvest. Everything else in ApexQuant works without it. The same answer is in the FAQ: Why can't I turn on Futures for my Binance API key?

If the key has no Futures permission, the Harvest tab shows Binance: Futures permission missing and harvest places nothing until you add it; the rest of ApexQuant is not affected.

How does it work?

When the funding rate on a perpetual futures contract is positive (above a configurable threshold), Harvest:

  1. Buys the asset on spot (holds actual BTC, ETH, etc.)
  2. Opens a short of the same size on Binance Futures, so the two price moves cancel out
  3. Collects the funding payment on the short every 8 hours
  4. Closes both when the funding rate falls below the exit threshold

The result: you collect the funding payment in your account's currency every 8 hours, and your exposure to the price of the coin is close to zero because the spot coins and the short offset each other.

Risk profile

RiskHow it's managed
The spot buy and the futures short fill at slightly different pricesSmall positions, and a cap on how much of your balance can be in harvest at all
Funding rate reverses (goes negative)Exit threshold in settings — auto-exits if rate drops below Harvest Exit Threshold (HARVEST_EXIT_THRESHOLD)
Opportunity costCapital is tied up during harvest window — configurable max allocation per symbol
Exchange riskSame as all Binance spot trading — keys are read-trade only, funds stay on exchange

Key settings

SettingDefaultWhat it does
Funding Harvest Enabled (HARVEST_ENABLED) — group Features & GatesfalseMaster switch — must set to true to activate.
Harvest Minimum Funding Rate (HARVEST_MIN_RATE) — group Harvest0.0006Minimum 8h funding rate to trigger entry (0.06% = RM0.60 per RM1000 per 8h).
Harvest Exit Threshold (HARVEST_EXIT_THRESHOLD) — group Harvest0.0002Exit when funding rate drops below this level.
Harvest Per-Symbol Allocation % (HARVEST_PER_SYMBOL_PCT) — group Harvest0.15Max 15% of balance per symbol in harvest positions.
Harvest Max Balance % (HARVEST_MAX_PCT) — group Harvest0.30Max 30% of total balance across all harvest positions combined.
Harvest Max Cycles to Break Even (HARVEST_MAX_CYCLES_TO_BREAKEVEN) — group Harvest5Won't open a harvest if earning back the fees would take more than this many 8-hour funding payments.
Harvest Check Interval (HARVEST_CHECK_INTERVAL) — group Harvest300How often, in seconds, the funding rates are checked (5 minutes).
Harvest Coins (HARVEST_SYMBOLS) — group Features & GatesBTC,ETHComma-separated list of coins; how many you can list depends on tier (Pro: 5, Elite: 10).

Telegram commands

Monitor harvest activity from Telegram:

  • /harvest — show all active harvest positions and current funding rates
  • /harvesthistory — list last 10 completed harvest trades with PnL
⚠️
Important: Harvest operates independently from the main scalp/swing bot. Harvest positions are tracked separately in the dashboard under the Harvest tab. They do not count toward the main bot's Kelly position sizing or kill switch daily drawdown — they have their own risk envelope.
MT

Manual Trade Control All plans

Manual trade control lets you force-close any open position or open a manual position at any time — via the dashboard or Telegram. This is a direct override of the bot's automated exit and entry logic.

⚠️
Manual BUY bypasses all gates — ML gate, regime filter, FOMC blackout, AI Commentary, and cooldown guard are all skipped. You are making the trade decision yourself. Exit mode (auto or manual) is chosen in the form — see below.

Manual SELL

Closes the full open position immediately at the current market price. Use this when you want to exit earlier than the bot's TP/trail targets.

MethodHow to use
Dashboard Open Positions table → click ⬛ Sell button → a fee breakdown modal shows current price, gross proceeds, sell fee, buy fee already paid, net amount back to your wallet, and net PnL after fees. Click Confirm SELL to execute.
Telegram /sell BTC — closes the BTC position. Run /sell with no argument to see all open positions first.

The SELL records as MANUAL_SELL in your trade history with the actual PnL after fees. Daily PnL counter and kill switch streak are updated exactly as with a bot-triggered exit.

The reason field in trade history includes a market context snapshot captured at the moment of execution — regime, ML last prediction, macro score, kill switch drawdown, and sentiment score. This lets you review the market conditions that prompted the manual action.

Manual BUY

Opens a new position immediately at market price. You specify the coin and the amount (in your account's currency). What happens when a position already exists depends on your active strategy: under Directional, it’s one position per symbol — the dashboard shows a warning panel (entry / qty / P&L) instead of the buy form, so close the existing position first or pick another symbol; under DCA, the buy joins (averages into) your existing basket; under Grid or TradingView, manual BUY is blocked (use the strategy’s own controls).

MethodHow to use
Dashboard Click + Manual BUY above the positions table → select the coin, enter the amount (in your account's currency) → click Execute BUY. A fee breakdown modal shows: buy fee deducted, the amount actually deployed, quantity received, estimated balance after, hard stop level, and the maximum loss if the stop is hit. Click Confirm BUY to execute.
Telegram /buy BTC 50 — opens a BTC position with 50 (in your account's currency). The bot replies with entry price, quantity, and the hard stop level.

Manual BUY behavior by Primary Strategy (PRIMARY_STRATEGY)

Pressing BUY on the dashboard or sending /buy via Telegram has different effects depending on Primary Strategy (PRIMARY_STRATEGY):

StrategyWhat Manual BUY does
Directional (experimental)Opens a tracked position with ATR trailing stop, hard stop, and partial TP. This is the standard behavior.
DCA (default)Adds the buy to your DCA basket. No separate stop-loss applies — position follows DCA exit rules (TP/trail above average entry). An orange warning banner is shown before you confirm.
GridBLOCKED and automatically rolled back. Grid strategy manages its own inventory via limit orders; a manual buy would create an untracked position that conflicts with the grid. The order is reversed immediately (sold back to your account's currency, trade row removed).
TradingView (coming soon)BLOCKED and automatically rolled back. TV strategy expects all entries from webhook signals. A manual entry would have no exit protection (no stop registered). Roll back behavior is identical to Grid.

What the bot does after a Manual BUY

Once the position is open, the bot manages it exactly like any other position:

  • ATR-based trailing stop is set immediately
  • Hard stop cap (default 8% max loss) is active
  • Partial TP fires if price reaches TP target (4× ATR above entry)
  • Time stop fires if position is still open after Max Hold Time (MAX_HOLD_HOURS)

Restrictions

  • One position per symbol — Manual BUY rejects if a position already exists for the selected symbol. Close it first via Manual SELL or /sell SYMBOL. For automated scale-in entries, set Primary Strategy (PRIMARY_STRATEGY) to dca instead.
  • Cannot buy more than 95% of your available balance
  • Symbol must be in your configured Trading Coins (SYMBOLS) list
  • The amount must be ≥ Minimum Order Notional (MIN_TRADE_USDT, default 11 in your account's currency, group Trading Mechanics)
  • Manual trades still count toward daily drawdown calculations

Holdings card and Holdings tab

The dashboard shows your coin holdings (everything except your account's currency) in two places:

  • Live tab — Holdings card. Compact view showing only assets the bot is actively trading (assets in your Trading Coins (SYMBOLS) config). Quick reference for the assets that matter to your current strategy. Includes a summary footer showing total bot-trading value vs. everything else. Click View all → to open the full Holdings tab.
  • Holdings tab. Full breakdown of every coin on your Binance account (everything except your account's currency), organized into three sections:
    • ✓ Trading — assets currently configured in your Trading Coins (SYMBOLS) list (active trading)
    • ↻ Previously Traded — assets you've traded before but aren't in current Trading Coins (SYMBOLS)
    • Other — everything else (manual deposits, testnet seed balances, dust)

The Positions table has a Value (USDT or USDC) column showing qty × current_price for each open position. This lets you see how much capital is deployed per symbol without mental arithmetic.

The Holdings tab includes a 💰 Cash section at the top showing your cash balance in your account's currency — the same value as the Live tab Balance card, displayed here for the complete portfolio picture. The Live tab compact Holdings card does NOT show it (the Balance card next to it already does). The Cash section is hidden when your cash balance is zero.

A ↻ Refresh button at the top-right of the Holdings tab fetches the latest prices from Binance, bypassing the 30-second cache used by the background refresh. Use this when you want to verify a price change immediately rather than wait for the next background cycle.

Note: on Binance Testnet you may see many "Other" assets — these are seed balances Binance assigns to test accounts and have no real value. On mainnet, this list contains only assets you've actually deposited or acquired. Prices refresh every 30 seconds (single API call, cached to avoid rate limits).

AI Commentary enhancements Elite only

Elite tier users get AI-assisted analysis before every manual BUY or SELL. Your AI provider reviews current market conditions and gives a direct verdict.

Trade typeAI verdictsWhat the AI analyses
Manual BUYGO · CAUTION · AVOIDRegime, ML confidence, macro score, sentiment F&G, ATR volatility
Manual SELLEXIT · HOLD · PARTIALCurrent P&L, trail stop proximity, regime, ML, sentiment — exit now or let bot manage?

Elite users also see a Kelly-suggested position size in the BUY modal — calculated from your actual win rate, average win/loss, and current ATR. A one-click "use" button fills the amount automatically.

Note: AI analysis uses your Anthropic API Key (ANTHROPIC_API_KEY). Typical cost per call: <RM0.01 (Haiku model).

Auto-managed vs Manual-managed exit

When placing a Manual BUY from the dashboard, a checkbox lets you choose who manages the exit:

ModeWhat the bot doesWhat you must do
🔓 Auto-managed (default)Manages exit using strategy rules: trailing stop, partial TP, time stop, regime exit, hard stop, kill switchNothing — bot handles it
🔒 Manual-managedPerforms ZERO exits — no trailing stop, no TP, no hard stop, no kill switch protection. Nothing.Must /sell SYMBOL yourself to close
🔒
Exit mode is locked at entry. Once a position opens with a given exit mode, it cannot be changed. To switch modes, close the position and reopen. This prevents partial-state bugs where the bot starts or stops watching a trade mid-way.

Manual-managed positions skip ALL bot-level exits and protections. The user takes 100% responsibility for closing the position via /sell SYMBOL or dashboard manual sell. The bot will NOT close a manual-managed position under any circumstances — including hard stop and kill switch.

Manual-managed mode is intentionally restrictive. When you untick auto-managed and click Confirm BUY, a separate confirmation modal appears with the warning and acknowledgment checkbox. Read the warning, tick the acknowledgment to enable the "I Understand, Execute BUY" button. This two-step flow prevents accidentally choosing manual mode without understanding the implications.

If you want the bot to close a position automatically based on price levels, use auto-managed mode and let the bot's stop logic apply. Manual mode is for traders who want full discretionary control over exits.

Telegram /buy always uses auto-managed exit. The dashboard is the only way to open manual-managed positions because the second-confirmation requirement cannot be reasonably implemented in CLI.

Account Equity card

The Account Equity card on the Live tab shows your total trading equity broken into three parts:

  • Cash: free balance in your account's currency (spendable)
  • Positions: Current market value of all open positions (qty × current price for each, summed into a single total). Per-symbol breakdown is in the Open Positions table below and the Holdings tab.
  • Total: Cash + Positions = total equity. This is the value the kill switch monitors against your Minimum Balance Stop (MIN_BALANCE_STOP) threshold.

Last update timestamp shown at the bottom of the card. Updates with each engine tick (typically every 1-2 seconds).

Trade attribution

Every trade is tagged with an entry source and exit source, visible in the Trade History tab and CSV export.

FieldValuesMeaning
entry_srcauto:directional, auto:dca, auto:grid, manual:dashboard, manual:telegramWho initiated the buy
exit_modeauto, manualSet at entry, immutable — who manages the exit
exit_srcauto:tp, auto:sl, auto:trail, auto:time, auto:kill, auto:regime, manual:dashboard, manual:telegramWhat triggered the close

Position cards on the Live tab show two compact badges per row: a 🤖 Auto / 👤 Manual entry badge and a 🔒 Manual exit / 🔓 Auto exit badge. Both are display-only — no editing.

The Trade History tab has a filter row: All trades / Auto entries / Manual entries / Manual-managed only. Filtering is client-side. The CSV export includes entry_src, exit_mode, and exit_src columns for offline analysis.

Attribution is useful for "why did this trade close?" investigation — compare exit_src=auto:sl (hard stop hit) versus exit_src=auto:trail (trailing stop profit-locked) versus exit_src=manual:dashboard (you closed it manually).

Selling part of a position

When you open a manual SELL, you can close the whole position or sell only a portion. Pick a quick preset (25%, 50%, 75%, 100%), type any custom percentage in the % field, or enter an exact quantity in units. The remainder stays under automatic management — take-profit and trailing logic continue to run on whatever is left.

If the chosen amount would leave a remainder below the exchange’s minimum order size, the dialog blocks the partial and offers to close the whole position instead.

The same options are available in Telegram: the SELL menu offers 25/50/75/100% presets, Custom %, and Custom qty. You can also type /sell SYMBOL 30% for a quick percentage sell or /sell SYMBOL 0.5 for an exact quantity.

Elite tier: the SELL dialog also shows AI commentary with a suggested verdict (exit, hold, or partial) and the key risk for the position before you confirm.
PF

Performance Tab & /performance Command

The Honest Performance Report on the Performance tab (and via /performance in Telegram) shows your real live-trading results, isolated from paper/testnet noise and from old configurations.

What is scoped

  • Only LIVE mode closed trades count. Paper and testnet are excluded.
  • Results default to your current config era — the period since you last changed a material setting (strategy, grid range, DCA budget, Smart TP mode). Changing any of these stamps a new era boundary automatically.
  • Use /performance alltime to see all-time LIVE results across all config eras.

Metrics shown

  • Win rate, Profit factor (gross win / gross loss), Expectancy (expected value per trade).
  • Net PnL and Gross PnL — the difference is fee drag, shown explicitly so fees cannot hide as profit.
  • Max drawdown — peak-to-trough on the equity curve within the scoped window.
  • Sharpe ratio — the average result of a trade divided by how much single trades vary; only shown when you have 30 or more closed trades. Below that threshold it is labelled “insufficient sample” rather than shown as if meaningful.
TG

Telegram Commands

This is the same list your bot sends when you type /help, grouped the same way. A command marked 🔑 asks for your PIN (or your 2FA code, if you use 2FA) each time it acts. Some commands depend on your plan; the plan is shown beside them. /menu has the same things as buttons.

CommandWhat it does
📊 Status and info
/statusEngine state and a summary of your positions.
/balanceYour wallet balances with their value.
/positionsYour open positions in detail.
/tradesYour recent trades.
/dailyToday's profit and loss summary.
/performance [alltime]How the bot has done in the current setup, or over all time.
/healthA one-screen health check: equity, safety state, connection.
/explain COINA plain explanation of what the bot is doing with one coin and why.
/regimeWhat kind of market the bot sees now.
/coinsThe coins the bot is trading and the state of the coin scanner.
/sentimentMarket mood: news sentiment and the Fear and Greed score.
/diagnoseWhy the bot is not buying right now, check by check.
🤖 Trading
/buy COIN [amount] 🔑Buy a coin by hand.
/sell COIN 🔑Sell a coin you hold at the market price.
/forcesell COIN 🔑Sell a coin the bot could not confirm it owns.
/stopPause new entries now; coins you hold stay and their stops keep working.
/resume 🔑Start trading again after a stop or a halt.
/emergencyHalt immediately; positions are kept, nothing is sold.
/stop_quit 🔑Stop and quit: halt and release management; the coins stay in your wallet.
/recalibrate [COIN] [confirm] 🔑Show, or reset, the amount of each coin that was in your wallet before the bot.
/mode 🔑Show the trading and coin modes; with a word after it, switch them.
/currencyThe currency switch: see the currency the bot trades in and start a switch (it asks you to confirm)
📈 Grid bot
/grid status [COIN]Grid state, profit and open orders. Plans that include the Grid bot
/grid pause [COIN] 🔑Cancel the orders and keep the coin. Plans that include the Grid bot
/grid drain [COIN] 🔑Stop buying and let the sells finish. Plans that include the Grid bot
/grid resume [COIN] 🔑Place the buys again. Plans that include the Grid bot
/grid stop [COIN] 🔑Cancel the orders and sell what the grid holds (also: reset, close) Plans that include the Grid bot
/grid rebuild [COIN] 🔑Stop, then start a new grid around today's price. Plans that include the Grid bot
/grid recenter [COIN] 🔑Move the range to today's price without selling. Plans that include the Grid bot
/grid extend upper|lower [COIN] 🔑Grow the range past the edge the price went beyond. Plans that include the Grid bot
📦 DCA bot
/dca statusDCA state, legs and profit.
/dca pauseNo new DCA buys until you resume.
/dca resume 🔑Allow DCA buys again.
/dca buy COIN 🔑Add a DCA buy now.
/dca sell COIN 30% 🔑Sell part of a DCA basket (a percentage, or an amount of coin)
/dca close COIN 🔑Sell a whole DCA basket.
/dca reset COIN 🔑Give a coin's DCA budget back.
🌾 Funding harvest
/harvestFunding harvest: state and open positions.
🛑 Safety
/killswitchThe safety monitor: losses so far against its limits, and the streak of losing trades.
/macroThe macro data gate (also /fred)
/fomcWhether a central-bank announcement pause is on.
🧠 AI, learning and backtest
/aiAn AI commentary on the market now. Elite
/aiusageThis month's AI use and budget.
/aibudget [RAISE] 🔑Show the AI budget; RAISE gives it more room.
/mlHow well the learning model has been doing.
/trainmlRetrain the learning model now.
/backtestTest the chosen strategy on past prices.
/digestThe weekly digest, now. Pro and Elite
/dailytestSend the daily report now, to check it. Pro and Elite
⚙️ Settings and logs
/set NAME value 🔑Show or change a setting (some apply after a restart)
/settingsAll the strategy and risk settings at a glance.
/logsThe last log lines.
🔐 Licence and access
/licenseYour plan and when it ends.
/setkey KEY 🔑Enter your licence key.
/blockip [address]List the blocked addresses, or block one.
/unblockip addressLet an address use the dashboard again.
/restart 🔑Restart the service (asks to confirm)
/pinAnswer a request for your PIN or code.
📋 Other
/menuThe button menu (also /start)
/cancelCancel a pending request for your PIN or code.
/helpThis list.
📐
When to use /recalibrate: After manually depositing assets you want the bot to manage, or if the bot reports an unexpected baseline mismatch after extended downtime.

When NOT to recalibrate: If you have unexplained deposits or transfers you don't recognise, investigate first. Recalibrating absorbs them into the baseline and the bot may then treat them as eligible to sell.
💡
Telegram vs Dashboard mental model: Dashboard buttons use percentages of your wallet (25%, 50%, etc). Telegram slash commands use absolute amounts — an amount in your account's currency for buy (e.g. /buy BTC 50 = 50 of BTC), base asset quantity for sell (e.g. /sell BTC 0.001 = 0.001 BTC). When in doubt, send /buy or /sell with no arguments — bot will show percentage buttons same as dashboard.

PIN entry: When prompted for PIN, you can either reply with bare digits (1234) or use the explicit command (/pin 1234). Both work. The PIN message is auto-deleted from chat after successful verification.
⚠

Troubleshooting

Dashboard shows 502 Bad Gateway

The FastAPI server on port 5005 is not running or crashed on startup.

VPS — diagnose
# Check service status systemctl status apexquant # View last 50 log lines journalctl -u apexquant -n 50 --no-pager # Run manually to see full error output cd /root/ApexQuant && source venv/bin/activate && python3 main.py 2>&1 | head -40 # Confirm port 5005 is listening ss -tlnp | grep 5005
⚠️
If the manual run shows ModuleNotFoundError — run pip install -r requirements.txt inside your venv first.
Dashboard loads but shows no data

All API calls are returning 401 or the JS file is not loading correctly.

VPS
# Confirm nginx passes Cookie header — this is critical grep "Cookie" /etc/nginx/sites-enabled/apexquant.tech # Must show: proxy_set_header Cookie $http_cookie; # Check the JS file is served correctly curl -I https://app.apexquant.tech/static/dashboard.js # Must return HTTP 200 # Force redeploy dashboard.js only cd /root && unzip -o ApexQuant-Setup.zip ApexQuant/api/dashboard.js && systemctl restart apexquant
Bot is running but not placing trades

Check which gate is blocking entries. On the dashboard → click the Gate Audit view or check logs.

VPS
# Live log stream — look for BLOCKING messages journalctl -u apexquant -f | grep -E "BLOCK|GATE|REGIME|ML|FOMC|MACRO|SENTIMENT"
ℹ️
Common blockers: regime is BEAR or CHOP · FOMC blackout window · ML confidence below threshold · Fear & Greed extreme · daily loss limit hit. Check each gate in the dashboard Live tab.
License validation failing / bot halted
Telegram or VPS
# Check license status via Telegram /license # Re-enter your key via Telegram /setkey AQP-XXXX-XXXX-XXXX-XXXX # Or via dashboard → Profile tab → paste key → Save & Validate # Check License Server is reachable curl -s https://app.apexquant.tech/health # Should return: {"status":"ok"}
💡
The bot has a 24-hour grace window — if the license server is temporarily unreachable, trading continues normally. It only halts if validation fails for more than 24 consecutive hours.
Binance API errors / order rejected
VPS
# Check for API key errors in logs journalctl -u apexquant -n 100 | grep -E "APIError|InvalidKey|403|401|USDT|USDC"
  • Confirm BINANCE_API_KEY (canonical: /root/apexquant-data/.env; /root/ApexQuant/.env should be a symlink to it) and BINANCE_API_SECRET are set in .env
  • In Testnet mode: use keys from testnet.binance.vision — live keys do NOT work on testnet
  • In Live mode: ensure the API key has Spot Trading enabled and IP whitelist includes your VPS IP
  • Wallet must hold the currency you chose (USDT or USDC) — other stablecoins are not traded
Telegram bot not responding
VPS
# Check Telegram token is set grep TELEGRAM /root/ApexQuant/.env # Check for Telegram errors in logs journalctl -u apexquant -n 50 | grep -i telegram
ℹ️
Only messages from Telegram Chat ID (TELEGRAM_CHAT_ID) are accepted. Make sure you're messaging from the correct account. Get your chat ID by messaging @userinfobot on Telegram.
Service fails to start / keeps restarting
VPS
# See exact failure reason journalctl -u apexquant -b --no-pager | tail -30 # Common fix: .env not found or missing required vars cat /root/ApexQuant/.env | grep -E "DASHBOARD_PASSWORD|BINANCE_API_KEY|TRADING_MODE" # TRADING_MODE in .env is now optional — dashboard value takes precedence # Test Python environment cd /root/ApexQuant && source venv/bin/activate && python3 -c "import fastapi, uvicorn, pandas, xgboost; print('OK')"
ML training fails or takes too long
ℹ️
ML training requires at least 500 historical bars. On a new install it fetches 1,000 1-minute bars and aggregates to 1-hour — this takes ~2 minutes. If training fails with NotEnoughData, wait 24 hours for more bars to accumulate, then retrain.
Telegram
# Trigger manual retrain via Telegram /trainml # Check ML status /ml

SELL BLOCKED by safety guard

Symptom: Telegram message: SELL BLOCKED <SYMBOL> qty requested: X.XXXXXX — BLOCKED: <guard> guard says zero owned

Cause: One of the three SELL safety guards detected the bot doesn't own enough of that asset to sell safely. Common reasons:

  • Ledger guard — the bot's local trade history shows it never bought this quantity (common after restoring from an old database backup)
  • Baseline guard — the current wallet quantity doesn't exceed the baseline snapshot (bot-acquired amount = 0)
  • Wallet guard — Binance free balance is below the requested quantity (funds may be locked in another open order)

Fix: The Telegram alert tells you which guard fired. Investigate that specific guard:

  • Ledger: review trade history for the symbol via /trades and confirm whether the guard was correct
  • Baseline: run /recalibrate <ASSET> to check baseline vs current wallet; use /recalibrate <ASSET> confirm if you legitimately added funds to be managed
  • Wallet: cancel any open orders on Binance UI that may be locking the balance, then retry
⚠️
This is the bot doing its job correctly. A blocked SELL means the safety system caught a potential mistake. Don't bypass it without understanding why it fired.

SELL CLAMPED — executed for less than expected quantity

Symptom: A sell executed but for less quantity than expected. Logs show SELL <SYMBOL> CLAMPED: X.XXXXXX → Y.YYYYYY. CLAMPED: requested X, allowed Y (limited by <guard>)

Cause: One of the three safety guards limited the sell quantity. The bot sold what was provably safe and protected the remainder.

Fix: Usually no action needed — the bot acted conservatively. If you expected the full quantity to sell, investigate which guard limited it and resolve using the same steps as "SELL BLOCKED" above.

GHOST order detected

Symptom: Telegram message: ⚠ GHOST ORDER DETECTED — intent <id> (<SYMBOL> <SIDE> qty=X) was sent but Binance has no record. Marked GHOST. Bot continuing normally.

Cause: The bot recorded its intent to send an order, but Binance has no record of that order arriving. Possible reasons:

  • Network hiccup between your server and Binance during the order transmission
  • Binance API rejected the order before logging it on their end
  • Bot crash mid-send before the order completed

Fix: This is informational. The bot continues operating normally and the intent is marked GHOST in the database for audit purposes. No immediate action required.

Investigate if:

  • Multiple GHOST messages appear in a short period — could indicate network instability or Binance API issues on their end
  • The GHOST is for a symbol or quantity you don't recognise — change your Binance API keys immediately and audit your account
ℹ️
Set Block on Ghost Positions (GUARD_BLOCK_ON_GHOST) to true in the Bot Config tab (Trading Mechanics group) to halt the bot automatically on any GHOST detection. This is a paranoid-mode setting — most users should leave the default false.
R

Recovery — Unaccounted Assets

After a database restore, a manual deposit, or certain restart scenarios, ApexQuant may detect holdings on your Binance account that don't match its internal records. The dashboard shows a Recovery banner above the equity card when this happens.

What it means

An "unaccounted asset" is a balance in a coin other than your account's currency in your Binance account that ApexQuant's own trade history doesn't explain — for example, a position you manually opened, a transfer from another account, or a trade from before this install. Only balances above the Reconciliation Minimum (USDT or USDC) setting (RECONCILE_MIN_USDT, default 50.0) are flagged — smaller amounts are treated as exchange dust and never surface here.

Why the banner sometimes says "Verifying" first

Before an item gets Sell/Adopt buttons, ApexQuant requires two consecutive reconciliation passes to agree on what it found — a single flaky Binance read is never enough to surface an item as actionable. Reconciliation runs on the Position Reconciliation Interval setting (RECONCILE_INTERVAL_SEC, default 6 hours), and each pass waits out the full interval first — so two agreeing passes can take up to twice the interval (up to 12 hours at the default) after a fresh restart. If the banner shows nothing but you know you have an unaccounted balance, this is normal — give it time before assuming something is wrong.

Why items shown here are safe to act on

ApexQuant only flags a balance in the first place if it can trace it to a bot BUY that was never matched by a later bot SELL — a genuine deposit or a manual transfer was never a bot purchase, so it's never even a candidate for this list. As an additional backstop, adopting also runs a check against Binance's own deposit and internal-transfer records (looking back 30 days) before completing — in the rare case that check finds a genuine deposit or transfer explaining the balance, the adopt is refused and the coins are instead folded into your wallet baseline (bookkeeping only, never sold or adopted). This is expected to almost never trigger for a normal Recovery-banner item, precisely because of the FIFO matching above — it exists as defense in depth, not as the primary gate.

Your two options, per item
  • Sell to USDT / Sell to USDC (the button names your account's currency): ApexQuant sells the exact flagged quantity at market price and removes it from tracking. Irreversible — you're asked to confirm the quantity and USD value first.
  • Adopt DCA or Adopt Directional: tell ApexQuant to start tracking this asset under the DCA basket or the Directional (exit-protected) strategy. It will then manage the exit with stops and take-profit as configured for whichever you choose.

There's no separate "dismiss" action — an item stays in the banner, unmanaged in your wallet, until you Sell or Adopt it.

PAPER mode

Recovery does not apply in PAPER mode — there is no real Binance wallet to reconcile against. The recovery banner does not appear in PAPER.

H

Held Positions

When ApexQuant stops actively managing a symbol — because you removed it from your configured list, switched strategies, or a grid/DCA/directional position was released for any other reason — the coins are never sold automatically and never silently dropped from tracking. They move to Held: visible on your Holdings tab, tracked at their average cost, and completely untouched by any automatic stop-loss, take-profit, or time-based exit until you decide what happens next.

Held is different from Recovery. Recovery (above) flags a balance ApexQuant's own trade history can't explain — a deposit, a manual trade, something it never bought. Held is the opposite: a position ApexQuant did buy and manage, that stopped being actively managed. Both eventually offer the same Sell/Adopt-style actions, but they start from different places.
Why coins move to Held instead of being sold

Automatically selling a released position the moment management stops would force a sale at whatever price happens to be current — even a brief, meaningless dip. ApexQuant never does this. A released position keeps its cost basis and quantity on record, with zero auto-exit machinery attached, until you make an explicit choice.

Your four options, per Held position
  • Keep: leave it exactly as it is — tracked, displayed, no auto-exit. The default state; you don't need to act.
  • Sell: sell the position at market price right now. The only way a Held position is ever sold — always your explicit choice, always confirmed before it executes.
  • Attach protection: choose a stop-loss and trailing-stop level and hand the position back to active management. Once attached, it behaves like any other auto-managed position and will exit automatically if the price hits your chosen stop.
  • Re-assign: hand the position to DCA, Grid, or Directional as a fresh starting position for that strategy, using the same adoption logic as Recovery's own Adopt actions above.

There's no time limit or forced decision — a Held position can stay Held indefinitely with no consequence.

DCA baskets

If a whole DCA basket (multiple buy-in legs across different prices) is released, ApexQuant collapses it into a single Held position at the basket's weighted average cost — matching how the position already displayed while it was active. The individual legs aren't tracked separately once Held.

Existing positions from before this feature

If you already had a position released under an earlier version of ApexQuant with its own protective stop already attached, that protection is left exactly as it was — this feature never silently removes an existing stop from a position you already had. Only newly released positions default to the unprotected Held state described above.

!

What Happens During API Outage

Binance and other API services (FRED macro, CoinGecko, Anthropic) occasionally go down for maintenance or technical issues. ApexQuant detects this automatically and pauses safely — no manual intervention needed.

Detection

3 consecutive Binance errors within 60 seconds triggers the API_DOWN state. This catches HTML error pages (Binance error 0), HTTP 5xx responses, connection timeouts, and stale ticker feeds.

What happens
  • ApexQuant says so once: “Binance is unreachable right now. ApexQuant keeps retrying on its own and trades nothing until it is back.” If it lasts, one reminder every 15 minutes says how long (“Binance still unreachable for 42 min; still retrying.”), and when Binance answers again one line says it is over and how long it lasted
  • All new entries blocked — engine tick, TradingView webhooks (coming soon), and Telegram /buy /sell all return immediately
  • All auto-exits paused — no sell attempts on a dead API (avoids partial fills and orphan orders)
  • Telegram spam suppressed — one "🚨 Binance API Down" alert fires, then silence until recovery
  • The dashboard still opens and loads quickly. It shows what ApexQuant last knew, and says “Waiting for Binance” instead of an error (while ApexQuant is starting up, it says what it is waiting for). The banner shows the outage status, its duration and the skipped operations count (updates every 10s)
  • Buttons that need Binance (manual buy and sell, the grid controls such as Pause, Drain, Resume and Reset, the recovery sells) are greyed out with the reason, and a request that gets through anyway is refused with one sentence: “Binance can't be reached right now, so this can't be done. It works again as soon as Binance is back.” A backtest or training run says it needs Binance's price history. Right after a restart it says “ApexQuant is still starting up. Try again in a moment.”
  • Settings, the Emergency Stop and reading your data keep working
  • Drawdown calc falls back to entry price for open positions — avoids false drawdown halt from missing ticker data
Auto-recovery

A background monitor pings api.binance.com/api/v3/time every 30 seconds. After 3 consecutive successful pings, the bot automatically resumes and sends a "✅ Binance API Recovered" Telegram alert with the outage duration and skipped operations count.

Manual override

If you need to halt the bot during or after an outage:

  • Dashboard → 🛑 EMERGENCY STOP button in the Bot Status card (asks for your dashboard password again; no PIN or 2FA code)
  • Telegram → /stop command (asks for nothing)

To go on afterwards, press Resume on the dashboard (or send /resume in Telegram).

⚠️
Existing positions are NOT closed during outage. Open positions remain with their stop-loss/take-profit targets intact. Exit management resumes automatically when the API recovers. Orders already resting on Binance (a grid's buys and sells) stay there. If the outage is prolonged and your stop-loss level is hit, you may want to manually close on the Binance UI.
↑

Updating to a New Version

Automatic Updates (on by default)

ApexQuant keeps itself up to date automatically. A daily check installs any new version, verifies it (SHA-256), preserves your settings, license and database, restarts the bot, and auto-rolls-back to the previous version if anything fails.

Automatic updates are enabled by default — you were asked during setup. You can change this any time:

Turn automatic updates off
sudo aq-update.sh --disable
Turn automatic updates on
sudo aq-update.sh --enable
Update now (manual)
curl -fsSL https://get.apexquant.tech/update | sudo bash

Automatic updates run around 04:30 server time (with a small random jitter). The full log is at /var/log/aq-update.log.

💡
Prefer to update only when flat? Leave automatic updates off (sudo aq-update.sh --disable) and run the manual command above when you have no open positions.
🔔
Telegram update notifications: When your bot installs a daily update, you'll get a Telegram message confirming the new version — or letting you know if an update was rolled back and the previous version restored. No action is needed; the bot restarts itself. Requires Telegram to be configured (Step 5). The dashboard's Auto-update card shows the same status with or without Telegram.

Prefer to update manually from a downloaded zip? The rename-and-clone steps below keep rollback simple and never touch your data, license, or settings.

Step 0 — Get the new version onto your VPS
  1. Visit apexquant.tech/download
  2. Download the latest ApexQuant-Setup.zip to your local machine
  3. Upload the zip to your VPS using SCP from your local machine:
    Upload via SCP
    scp ApexQuant-Setup.zip root@your-vps-ip:/root/
  4. Or use SFTP (FileZilla, WinSCP, Cyberduck) and upload to /root/
💡
Verify integrity: The download page shows the zip's SHA256 checksum. After uploading to the VPS, run sha256sum /root/ApexQuant-Setup.zip and confirm it matches before extracting.
Step 1 — Stop the bot
Stop the bot
systemctl stop apexquant
Step 2 — Extract the new version
Extract the new version
cd /root mv ApexQuant ApexQuant_OLD unzip /root/ApexQuant-Setup.zip
Step 3 — Run the updater
Run updater
cd /root/ApexQuant && bash install.sh --update

Re-creates symlinks to /root/apexquant-data/ and rebuilds the venv with any new dependencies. Your config, license, trial timer, and trade history are never touched.

Step 4 — Start and verify
Start and verify
systemctl start apexquant sleep 5 journalctl -u apexquant -n 30 --no-pager | grep -iE "license|tier"

Verify license shows [LICENSE] Valid | Tier: .... Open dashboard, check F12 console — no errors. Watch for 5–10 minutes.

Step 5 — Rollback (if anything fails)
Rollback
systemctl stop apexquant cd /root mv ApexQuant ApexQuant_FAILED mv ApexQuant_OLD ApexQuant cd ApexQuant && bash install.sh --update systemctl start apexquant

You'll be back on the previous working version. Report the issue to support.

⚠️
Keep ApexQuant_OLD for at least 24 hours after updating. Once confirmed stable, delete it: rm -rf /root/ApexQuant_OLD
💡
Database is symlinked, not copied. Your trade history, equity snapshots, and settings live in /root/apexquant-data/apexquant.db outside the app folder. Updates never touch this file.

Switching Binance Accounts

If you need to connect ApexQuant to a different Binance account, always follow the managed switch flow before editing your API keys. Changing keys directly without completing this flow may strand open orders on the old account — and on Binance testnet there is no manual cancel UI, so the bot is the only way to close them.

The safe switch procedure

  1. In the dashboard, go to Bot Config and click 🔄 Switch Binance Account.
  2. Enter your Admin PIN (and 2FA code if enabled).
  3. Choose your policy: Cancel orders only (default — your coins stay in your account, released to "Other"); or Also sell positions to your account's currency (opt-in — this realizes P&L and should be acknowledged).
  4. Tick the acknowledgement and type CONFIRM twice (two steps).
  5. Wait for the ✅ Current account CLEARED confirmation. Do not change keys until you see this.
  6. Run bash update_keys.sh on your VPS and enter the new API key and secret.
  7. Restart ApexQuant: systemctl restart apexquant.
  8. ApexQuant detects the new account and starts fresh automatically.
Never just edit .env and restart. ApexQuant will detect the new account and start fresh — but if you skipped the switch flow, any open bot orders on the old account are stranded forever (the bot loses access the moment the keys change).

What "fresh start" means

  • ApexQuant manages your account's currency (USDT or USDC, the one you chose). Your free balance in it = ApexQuant's trading capital.
  • All existing coins → "Other" (unmanaged). ApexQuant will not trade, sell, or adopt them.
  • To have ApexQuant trade a coin, convert it to your account's currency in Binance first. ApexQuant will then trade from that.
  • Your previous ApexQuant history (trades, equity chart, P&L) is archived, not deleted. It remains recoverable for audit purposes.

Returning to a previously connected account

If you switch back to an account ApexQuant has seen before, ApexQuant still starts fresh — it does not restore previous positions or orders. This is intentional: when you left that account, ApexQuant released it (cancelled its orders), so there is nothing meaningful to restore. Your previous data remains archived for audit.

Coins are never sold automatically. The default switch action cancels ApexQuant's orders only; your coins remain in your account (moved to "Other"). Force-selling positions to your account's currency is an explicit opt-in checkbox in the switch modal.
✕

Uninstalling ApexQuant

ApexQuant has two removal paths. Choose based on whether you plan to reinstall or want a full factory reset.

Path 1 — Remove software, keep your data (default)

Removes the bot software but preserves your license key, database, and configuration. You can reinstall at any time and everything re-attaches automatically. Your license seat stays bound — this is a "pause" not a release.

Manage open positions first. ApexQuant never touches your exchange account during removal, but if you have open grid or DCA orders you should close or pause them manually before uninstalling.
Keep data (safe default)
curl -fsSL https://get.apexquant.tech/uninstall | sudo bash
Path 2 — Full factory reset (purge)
⚠️ Irreversible. Purge deletes all local data (license key, database, configuration) and releases your license seat so you can activate on a different server. There is no undo. You will be prompted to type PURGE to confirm.

Use purge when you are decommissioning the server permanently or moving to a new one and want your license freed immediately.

Factory reset — releases license seat
curl -fsSL https://get.apexquant.tech/uninstall | sudo bash -s -- --purge

You can optionally include a reason (stored for analytics, not shared publicly):

With optional reason
curl -fsSL https://get.apexquant.tech/uninstall | sudo bash -s -- --purge --reason "Moving to new VPS"
Why the command looks like this

Flags for the uninstall script go after sudo bash -s --, not on the curl line. -s tells bash to read the script from the pipe; -- ends bash's own options so everything after (--purge, --force, etc.) is passed to the script. Putting flags directly after the curl URL would send them to curl instead, which errors with option --purge is unknown.

Open positions gate

If you have open bot-managed positions the uninstaller will warn you and pause. Use the command below to skip the gate — you will need to manage those positions manually on Binance.

Proceed despite open positions
curl -fsSL https://get.apexquant.tech/uninstall | sudo bash -s -- --force
Purge + skip confirmation + skip open-positions gate
curl -fsSL https://get.apexquant.tech/uninstall | sudo bash -s -- --purge --yes --force
?

Frequently Asked Questions

Frequently Asked Questions are available on a dedicated page. Browse 40+ questions on licensing, configuration, security, troubleshooting, and more:

Open FAQ →