/SKILL.md
# Agent Setup Guide — go-trader **Repository:** `https://github.com/richkuo/go-trader.git` This is a self-contained setup guide for AI agents. Give this file to any AI coding agent and it will handle the full installation — cloning the repo, installing dependencies, configuring Discord/strategies/risk, building, and starting the service. **For OpenClaw agents:** This is the skill entry point. Read it when a user says "set up go-trader", "install go trading bot", or "configure go-trader". ---
npx skillsauth add richkuo/go-trader go-traderInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Repository: https://github.com/richkuo/go-trader.git
This is a self-contained setup guide for AI agents. Give this file to any AI coding agent and it will handle the full installation — cloning the repo, installing dependencies, configuring Discord/strategies/risk, building, and starting the service.
For OpenClaw agents: This is the skill entry point. Read it when a user says "set up go-trader", "install go trading bot", or "configure go-trader".
Check each prerequisite. Install anything missing (ask user before installing).
python3 --version
If missing or < 3.12, ask:
Python 3.12+ is required. Want me to install it?
uv --version 2>/dev/null || echo "NOT_INSTALLED"
If missing, install:
curl -LsSf https://astral.sh/uv/install.sh | sh
go version 2>/dev/null || /usr/local/go/bin/go version 2>/dev/null || echo "NOT_INSTALLED"
If missing, ask:
Go 1.23+ is required to build the scheduler. Want me to install it?
Install with:
curl -sL https://go.dev/dl/go1.23.6.linux-amd64.tar.gz | tar -C /usr/local -xzf -
Note: Go may not be in PATH. Use /usr/local/go/bin/go if go doesn't resolve.
git --version
Check if already installed:
test -d go-trader/scheduler && echo "EXISTS" || echo "FRESH"
If EXISTS, ask:
go-trader is already installed. Do you want to:
- Reconfigure (keep code, redo setup)
- Update (pull latest + rebuild)
- Fresh install (delete and start over)
If FRESH, clone from GitHub:
git clone https://github.com/richkuo/go-trader.git
cd go-trader
If the clone fails (private repo or auth issue), ask:
I couldn't clone the repository. Do you have a GitHub token or SSH key configured? You can also download it manually: https://github.com/richkuo/go-trader
cd go-trader
uv sync
Verify: .venv/bin/python3 should exist after this.
No user input needed for this step.
go-trader init (Recommended for Human Users)Before proceeding with Steps 4–7 (manual config), build the binary first so the wizard is available:
cd scheduler && /usr/local/go/bin/go build -o ../go-trader . && cd ..
Then run the interactive wizard:
./go-trader init
The wizard walks through:
A summary is shown before writing. If scheduler/config.json already exists, you'll be prompted to confirm overwrite.
After go-trader init completes, skip to Step 8 (Build & Install). Steps 4–7 are only needed for manual or agent-driven config generation.
Note for agents: For scripted/automated config generation, use
--jsoninstead of Steps 4–7:./go-trader init --json '{"assets":["BTC","ETH"],"enableSpot":true,"spotStrategies":["momentum","rsi"],"spotCapital":1000,"spotDrawdown":60}' --output scheduler/config.jsonSteps 4–7 describe the manual procedure — use those only when you need fine-grained control (partial reconfiguration, custom strategy sets, etc.).
Ask:
Do you want Discord trade alerts? The bot will post summaries and trade notifications to Discord channels.
(yes / no)
Set discord.enabled = false in config. Skip to Step 5.
Ask:
I need your Discord bot token. This is used to post trade alerts.
Where to find it: Discord Developer Portal → your application → Bot → Token
Security: I'll store this as a systemd environment variable, not in config files.
Paste your bot token:
Store the token for use in Step 8 (systemd service). Do NOT write it to config.json.
Ask:
Which Discord channel should receive spot trading alerts?
This channel will get:
- Hourly summaries showing PnL for each spot strategy (BTC/ETH/SOL)
- Immediate notifications when a spot trade executes
I need the channel ID — right-click the channel → "Copy Channel ID" (Enable Developer Mode in Discord Settings → Advanced if you don't see this option)
Spot channel ID:
Ask (only if options strategies will be enabled):
Which Discord channel should receive options trading alerts?
This channel will get:
- Per-check summaries split by exchange (Deribit + IBKR)
- Individual strategy PnL with recent trade history
- Immediate trade notifications
This can be the same channel as spot, or a different one.
Options channel ID (or press Enter to skip):
Ask (only if perps/hyperliquid strategies will be enabled):
Which Discord channel should receive Hyperliquid perps alerts?
This channel will get:
- Hourly summaries of all Hyperliquid strategy PnL
- Immediate trade notifications
This can be the same channel as spot, or a different one.
Hyperliquid channel ID (or press Enter to skip):
Ask (only if futures/topstep strategies will be enabled):
Which Discord channel should receive TopStep futures alerts?
This channel will get:
- Hourly summaries of all TopStep strategy PnL
- Immediate trade notifications
This can be the same channel as spot, or a different one.
TopStep channel ID (or press Enter to skip):
Ask:
What's the Discord server (guild) ID where these channels are?
Right-click the server icon → "Copy Server ID"
Server ID:
Store this for OpenClaw allowlist configuration in Step 7.
Ask:
Would you like the bot to DM you directly when a new version is available, and offer to upgrade automatically?
If yes, I need your Discord user ID:
- Enable Developer Mode: Discord Settings → Advanced → Developer Mode
- Right-click your own username → "Copy User ID"
This enables:
- DM upgrade prompt — reply yes to auto-upgrade (git pull, rebuild, restart)
- Post-upgrade config migration — the bot DMs you about any new config fields
Owner Discord user ID (or press Enter to skip):
If provided, store as DISCORD_OWNER_ID for the systemd service (Step 8c). Do NOT write it to config.json.
Note: Summary frequency is automatic — spot and hyperliquid summaries post hourly (plus immediate trade alerts), options summaries post every check cycle. No configuration needed.
Ask:
Do you want to run in paper trading mode (simulated) or live trading?
Paper mode (recommended): No real money. Simulates trades with virtual capital. Good for testing strategies before going live.
Live mode: Requires exchange API keys. Real trades with real money.
(paper / live, default: paper)
If live, prompt for exchange API keys:
Binance API key: Binance API secret:
If futures/TopStep strategies are enabled:
TopStep API key: TopStep API secret: TopStep account ID:
Store these for the systemd environment in Step 8.
Ask:
How much starting capital per strategy (in USD)?
Default is $1,000 per strategy. With 30 strategies, that's $30,000 total paper capital.
You can change individual strategy amounts later in the config.
Capital per strategy: (default: 1000)
Ask:
What's your maximum drawdown tolerance? When a strategy's losses exceed this percentage, a circuit breaker pauses trading for 24 hours.
- Spot strategies default: 60%
- Options strategies default: 40% (measured from peak value)
Do you want to customize these, or use the defaults?
- Use defaults (recommended)
- Set custom values
(1 or 2, default: 1)
If 2:
Max drawdown for spot strategies (%, default: 60): Max drawdown for options strategies (%, default: 20):
Ask:
go-trader comes with strategies across four groups:
Spot (10 strategies) — BTC, ETH, SOL on Binance sma_crossover, ema_crossover, momentum, rsi, bollinger_bands, macd, mean_reversion, volume_weighted, triple_ema, rsi_macd_combo, pairs_spread
Deribit Options (8 strategies) — BTC, ETH options vol mean reversion, momentum, puts, calls, wheel, butterfly
IBKR/CME Options (8 strategies) — BTC, ETH options (CME Micro) Same 6 strategies as Deribit, for head-to-head comparison
Futures (5 strategies) — CME contracts on TopStep momentum, mean_reversion, rsi, macd, breakout
Do you want to:
- Run all (recommended for paper trading)
- Choose by group (enable/disable spot, Deribit, IBKR)
- Pick individual strategies
(1, 2, or 3, default: 1)
Use the full default strategy set. Skip to Step 6b.
Ask for each group:
Enable spot strategies (sma_crossover, ema_crossover, momentum, rsi, bollinger_bands, macd, mean_reversion, volume_weighted, triple_ema, rsi_macd_combo, pairs_spread on BTC/ETH/SOL)? (yes/no, default: yes) Enable Deribit options (vol MR, momentum, puts, calls, wheel, butterfly on BTC/ETH)? (yes/no, default: yes) Enable IBKR/CME options (same strategies as Deribit, CME Micro contracts)? (yes/no, default: yes)
Present each strategy and ask yes/no. Group them for readability:
Spot Strategies (5-minute checks):
| # | Strategy | Assets | Description | Enable? | |---|----------|--------|-------------|---------| | 1 | sma_crossover | BTC, ETH, SOL | Simple moving average crossover | (y/n) | | 2 | ema_crossover | BTC, ETH, SOL | Exponential moving average crossover | (y/n) | | 3 | momentum | BTC, ETH, SOL | Rate of change breakouts | (y/n) | | 4 | rsi | BTC, ETH, SOL | Buy oversold, sell overbought | (y/n) | | 5 | bollinger_bands | BTC, ETH, SOL | Mean reversion at band extremes | (y/n) | | 6 | macd | BTC, ETH, SOL | MACD/signal line crossovers | (y/n) | | 7 | mean_reversion | BTC, ETH, SOL | Statistical mean reversion | (y/n) | | 8 | volume_weighted | BTC, ETH, SOL | Trend + volume confirmation | (y/n) | | 9 | triple_ema | BTC, ETH, SOL | Triple EMA crossover | (y/n) | | 10 | rsi_macd_combo | BTC, ETH, SOL | RSI and MACD confluence | (y/n) | | 11 | pairs_spread | BTC/ETH, BTC/SOL, ETH/SOL | Spread z-score stat arb (1d) | (y/n) |
Which spot strategies do you want? (e.g., "1,3,11" or "all" or "none")
Then repeat for options:
Deribit Options (20-minute checks, BTC + ETH each):
| # | Strategy | Description | Enable? | |---|----------|-------------|---------| | 1 | vol_mean_reversion | High IV → sell strangles, Low IV → buy straddles | (y/n) | | 2 | momentum_options | ROC breakout → directional options | (y/n) | | 3 | protective_puts | Buy 12% OTM puts, 45 DTE | (y/n) | | 4 | covered_calls | Sell 12% OTM calls, 21 DTE | (y/n) | | 5 | wheel | Sell 6% OTM puts, 37 DTE | (y/n) | | 6 | butterfly | ±5% wing butterfly spread, 30 DTE | (y/n) |
Which Deribit strategies? (e.g., "1,3,6" or "all" or "none")
IBKR/CME Options — Same strategies as Deribit but using CME Micro contracts:
Run the same selection as Deribit, or choose differently?
- Same as Deribit
- Choose individually
- None
(1, 2, or 3)
Only ask if any options strategies were enabled:
Ask:
Theta harvesting lets the bot close sold options early instead of holding to expiry:
- Profit target: Close when X% of premium captured (e.g., 60%)
- Stop loss: Close if loss exceeds X% of premium (e.g., 200% = 2× premium)
- Min DTE: Force-close when fewer than N days to expiry (avoid gamma risk)
Do you want to configure theta harvesting?
- Enable with defaults (60% profit, 200% stop, 3 days min DTE) — recommended
- Custom values
- Disable (options ride to expiry or circuit breaker)
(1, 2, or 3, default: 1)
If 2:
Profit target (% of premium to capture before closing, default: 60): Stop loss (% of premium loss before closing, default: 200): Minimum DTE to force-close (days, default: 3):
Using all gathered inputs, generate scheduler/config.json.
Start from scheduler/config.example.json as a template. For each enabled strategy, add an entry with:
id: Use the naming convention {strategy}-{asset} for spot, deribit-{strategy}-{asset} or ibkr-{strategy}-{asset} for optionstype: "spot" or "options"script: "shared_scripts/check_strategy.py" (spot), "shared_scripts/check_options.py" (options — any platform), "shared_scripts/check_topstep.py" (futures)args: Strategy-specific arguments (see config.example.json for format)capital: User's chosen amountmax_drawdown_pct: User's chosen value (spot default: 60, options default: 40)interval_seconds: 300 for spot, 1200 for optionsparams: Optional — custom strategy parameter overrides (e.g. {"multiplier": 2.0, "atr_period": 10}). Merged with strategy defaults at runtime.theta_harvest: If enabled, include the config blockDiscord config:
discord.enabled: true/false based on Step 4discord.token: Always "" (token comes from env var)discord.channels: Map of channel IDs for enabled platform types, e.g. {"spot": "ID_FROM_4b", "options": "ID_FROM_4c", "hyperliquid": "ID_FROM_4d", "topstep": "ID_FROM_4e", "okx": "ID_FROM_4f"} — omit keys for platforms not in useIf the agent is running inside OpenClaw and Discord was configured, add the channels to OpenClaw's guild allowlist so the bot can post:
# Using OpenClaw gateway config.patch:
# channels.discord.guilds.<GUILD_ID>.channels.<SPOT_CHANNEL>.requireMention = false
# channels.discord.guilds.<GUILD_ID>.channels.<OPTIONS_CHANNEL>.requireMention = false
Or via CLI:
openclaw config set "channels.discord.guilds.${GUILD_ID}.channels.${SPOT_CHANNEL}.requireMention" false
openclaw config set "channels.discord.guilds.${GUILD_ID}.channels.${OPTIONS_CHANNEL}.requireMention" false
Show the user a summary before proceeding:
Here's your configuration:
Mode: Paper trading Strategies: {N} total ({spot_count} spot, {deribit_count} Deribit, {ibkr_count} IBKR) Capital: ${amount} per strategy (${total} total) Risk: {spot_drawdown}% max drawdown (spot), {options_drawdown}% (options) Theta harvesting: {enabled/disabled} {details if enabled} Discord: {enabled/disabled} 📈 Spot alerts → #{channel_name} (hourly + on trade) 🎯 Options alerts → #{channel_name} (per check) ⚡ Hyperliquid alerts → #{channel_name} (hourly + on trade) {if perps enabled}
Proceed? (yes / no)
If no, ask which part they want to change and loop back to the relevant step.
cd scheduler
/usr/local/go/bin/go build -o ../go-trader .
cd ..
If go is in PATH, just use go build. Check both.
Verify: ./go-trader --help should print usage.
./go-trader --config scheduler/config.json --once
Check for errors. If Discord is configured, a summary should appear in the channels.
Create or update the service file. Include the Discord token and any exchange API keys as environment variables:
[Unit]
Description=Go Trading Scheduler
After=network.target
[Service]
Type=simple
WorkingDirectory={PROJECT_DIR}
ExecStart={PROJECT_DIR}/go-trader --config scheduler/config.json
Environment="DISCORD_BOT_TOKEN={token}"
Environment="DISCORD_OWNER_ID={owner_discord_user_id}"
Restart=always
RestartSec=10
StandardOutput=append:{PROJECT_DIR}/logs/scheduler.log
StandardError=append:{PROJECT_DIR}/logs/scheduler.log
[Install]
WantedBy=multi-user.target
If live trading, also add:
Environment="BINANCE_API_KEY={key}"
Environment="BINANCE_API_SECRET={secret}"
If TopStep live trading:
Environment="TOPSTEP_API_KEY={key}"
Environment="TOPSTEP_API_SECRET={secret}"
Environment="TOPSTEP_ACCOUNT_ID={account_id}"
mkdir -p logs
sudo cp go-trader.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable go-trader
sudo systemctl start go-trader
go-trader checks for updates via git fetch and notifies all active Discord channels. If DISCORD_OWNER_ID is set, it also DMs the owner offering to upgrade automatically.
Configure during go-trader init (or set auto_update in config.json):
| Mode | Behavior |
|------|----------|
| off | No automatic checking (default) |
| daily | Checks once per day |
| heartbeat | Checks every scheduler cycle |
DM upgrade flow (when owner_id is configured):
abc123 → def456 — upgrade automatically? (yes/no)"git pull --ff-only, rebuilds binary, saves state, and restartsPost-upgrade config migration: On the first startup after an upgrade, if new config fields were introduced, the bot DMs you about each one (10-minute reply window). Defaults are applied silently if you don't respond or if no owner ID is set.
The scheduler will not re-notify for the same remote version until a newer one appears.
Manual update (always works regardless of setting):
cd /path/to/go-trader && git pull --ff-only
cd scheduler && /usr/local/go/bin/go build -o ../go-trader . && cd ..
sudo systemctl restart go-trader
Verify the update check is working:
journalctl -u go-trader -f | grep -i "\[update\]"
Ask:
Would you like to add a custom trading platform integration? This lets you connect go-trader to an exchange not included by default (spot, perps, or options).
(yes / no)
If no, skip to Step 10.
Ask:
Building a custom platform integration may consume 50,000–100,000+ tokens depending on complexity (adapter code, Go wiring, config generation, and testing). This will be a multi-step implementation.
Proceed? (yes / no)
If no, skip to Step 10.
Ask the following questions (can be asked all at once or one at a time):
Platform name (lowercase, no spaces — used for directory name and ID prefix, e.g.
kraken,okx,bybit):
Platform type — what does this exchange support? (select all that apply)
- Spot trading
- Perpetual futures (perps)
- Options
(e.g. "1", "1,2", "all")
API documentation — paste the URL to the exchange's REST API docs, or type
ccxtif this exchange is supported by the ccxt library (I'll fetch and read the docs):
API credential environment variable names — what env vars will hold the API keys? (e.g.
KRAKEN_API_KEY,KRAKEN_API_SECRET). Typenoneif this is paper-only (no live trading):
Fee structure:
- Taker fee %: (e.g.
0.1for 0.1%)- Maker fee %: (e.g.
0.05)- Per-contract fee (options only, in USD, or
none):
Assets to trade (e.g.
BTC, ETHorBTC/USDT, SOL/USDT):
Strategies to run — which strategy types should this platform use?
- Spot: sma_crossover, ema_crossover, momentum, rsi, bollinger_bands, macd, mean_reversion, volume_weighted, triple_ema, rsi_macd_combo, pairs_spread
- Perps: (same as spot strategies, executed via check_hyperliquid.py pattern)
- Options: vol_mean_reversion, momentum_options, protective_puts, covered_calls, wheel, butterfly
List the strategies, or type
allfor the appropriate type:
If API docs URL was provided (not ccxt), use WebFetch to read the docs before proceeding.
If ccxt was specified, note that the adapter should use ccxt.<ExchangeName>() — no custom HTTP needed.
Build the integration in this order. Each item is required unless noted.
Create platforms/<name>/__init__.py (empty file):
touch platforms/<name>/__init__.py
Create platforms/<name>/adapter.py with a class named <Name>ExchangeAdapter (must end in ExchangeAdapter for auto-discovery):
shared_tools/exchange_base.py ExchangeAdapterBase protocolget_price(symbol), get_orderbook(symbol), place_order(...), get_positions(), get_balance()get_funding_rate(symbol), set_leverage(symbol, leverage)get_options_chain(underlying), get_option_quote(instrument_id)platforms/binanceus/adapter.pyplatforms/hyperliquid/adapter.pyplatforms/topstep/adapter.pyplatforms/deribit/adapter.pyplatforms/<name>/state.jsonIf new entry script needed (perps or non-standard execution flow), create shared_scripts/check_<name>.py:
shared_scripts/check_hyperliquid.pyAdd the new platform's ID prefix to the LoadConfig platform inference block:
// In the switch/if-else that maps ID prefix → platform
case strings.HasPrefix(id, "<name>-"):
sc.Platform = "<name>"
Add a case to CalculatePlatformSpotFee:
case "<name>":
return value * 0.001 // replace with actual taker fee
If options, also add to CalculateOptionFee if it has per-platform dispatch.
If a new check_<name>.py was created, add the invocation pattern to executor.go following the existing RunHyperliquidExecute pattern (or add a new Run<Name>Execute function).
Only modify main.go if a brand-new strategy type is needed (not "spot", "options", or "perps"). If reusing an existing type, no change needed.
Channels are resolved dynamically via resolveChannel(channels, platform, stratType) — platform key takes priority over type key. No code change needed; just add the new platform's key to discord.channels in config.json (e.g. "myplatform": "CHANNEL_ID").
Add example strategy entries for the new platform:
{"id": "<name>-momentum-btc", "type": "spot", "script": "shared_scripts/check_strategy.py",
"args": ["momentum", "BTC/USDT", "1h"], "capital": 1000, "max_drawdown_pct": 60, "interval_seconds": 300}
Adjust type, script, and args for perps or options as appropriate.
If the adapter uses a platform-level state file, add a platforms entry to config.example.json:
"platforms": {
"<name>": {"state_file": "platforms/<name>/state.json"}
}
If live trading credentials are needed, add to the service file instructions:
Environment="<NAME>_API_KEY=..."
Environment="<NAME>_API_SECRET=..."
Document in Step 10 (Verification) and in the Adjustable Settings → Environment Variables section.
After implementation:
python3 -m py_compile platforms/<name>/adapter.py
If a new entry script was created:
python3 -m py_compile shared_scripts/check_<name>.py
cd scheduler && /usr/local/go/bin/go build .
./go-trader --config scheduler/config.json --once
Check that the new platform's strategies appear in the output without errors.
systemctl is-active go-trader
Expected: active
curl -s localhost:8099/status | python3 -c "
import json, sys
d = json.load(sys.stdin)
print(f'Cycle: {d[\"cycle_count\"]}')
print(f'Strategies: {len(d[\"strategies\"])}')
for sym, price in d.get('prices', {}).items():
print(f' {sym}: \${price:,.2f}')
"
If Discord is enabled, wait for the first cycle to complete (~5 minutes) and verify messages appear in the configured channels.
✅ go-trader is running!
Mode: {paper/live} Strategies: {N} active Status:
curl localhost:8099/statusLogs:journalctl -u go-trader -fSpot strategies check every 5 minutes (summaries {freq}). Options strategies check every 20 minutes (summaries per check). Trades post immediately to Discord.
Useful commands:
- Stop:
sudo systemctl stop go-trader- Restart:
sudo systemctl restart go-trader- Status:
curl -s localhost:8099/status | python3 -m json.tool- Reset positions:
cp scheduler/state.example.json scheduler/state.json && sudo systemctl restart go-trader
Run historical simulations using scripts in backtest/. All require .venv/bin/python3 since dependencies (ccxt, pandas, numpy) are installed in the venv.
backtest/run_backtest.py)# Single strategy run
.venv/bin/python3 backtest/run_backtest.py \
--strategy <name> --symbol BTC/USDT --timeframe 1h --mode single
# Compare two strategies
.venv/bin/python3 backtest/run_backtest.py \
--strategy <name> --symbol BTC/USDT --timeframe 1h --mode compare
# Multi-symbol sweep
.venv/bin/python3 backtest/run_backtest.py \
--strategy <name> --timeframe 1h --mode multi
# Parameter optimization
.venv/bin/python3 backtest/run_backtest.py \
--strategy <name> --symbol BTC/USDT --timeframe 1h --mode optimize
# Limit history (e.g. last 90 days)
.venv/bin/python3 backtest/run_backtest.py \
--strategy <name> --symbol BTC/USDT --timeframe 1h --since 90
Key flags: --strategy, --symbol, --timeframe, --mode (single/compare/multi/optimize), --since (days)
backtest/backtest_options.py)Self-contained (only imports ccxt).
.venv/bin/python3 backtest/backtest_options.py \
--underlying BTC --since 90 --capital 10000
# Verbose output
.venv/bin/python3 backtest/backtest_options.py \
--underlying BTC --since 90 --capital 10000 --verbose
Key flags: --underlying, --since (days), --capital, --verbose
backtest/backtest_theta.py)Self-contained.
.venv/bin/python3 backtest/backtest_theta.py \
--underlying BTC --since 90 --capital 10000
Key flags: --underlying, --since (days), --capital
These can be done after initial setup without re-running the full guide.
Run the interactive wizard to produce a fresh config.json (will prompt before overwriting):
./go-trader init
Or non-interactively (for agents or scripted setups):
./go-trader init --json '{"assets":["BTC"],"enableSpot":true,"spotStrategies":["momentum"],"spotCapital":1000,"spotDrawdown":60}' --output scheduler/config.json
Then restart: sudo systemctl restart go-trader
Edit scheduler/config.json → discord.channels (map keyed by platform/type), then restart:
sudo systemctl restart go-trader
If new channels, also add to OpenClaw allowlist.
sudo systemctl edit go-trader
# Add: Environment="DISCORD_BOT_TOKEN=new_token_here"
sudo systemctl restart go-trader
Edit scheduler/config.json → strategies array, then restart. Removed strategies are auto-pruned from state. New strategies initialize with fresh capital.
Edit max_drawdown_pct per strategy in config.json, then restart.
Add or remove the theta_harvest block from individual strategy entries in config.json, then restart.
Edit auto_update in scheduler/config.json ("off", "daily", or "heartbeat"), then restart:
sudo systemctl restart go-trader
To add a new exchange (spot, perps, or options), follow the guided flow in Step 9. It will walk through gathering platform details, building the Python adapter, wiring Go changes, and updating config.
Add exchange API keys to systemd environment:
sudo systemctl edit go-trader
# [Service]
# Environment="BINANCE_API_KEY=..."
# Environment="BINANCE_API_SECRET=..."
sudo systemctl restart go-trader
/go-trader CommandWhen the user says /go-trader, "check bot status", "show strategy health", or "how are the bots doing", run this:
curl -s localhost:8099/status | python3 -c "
import json, sys
d = json.load(sys.stdin)
prices = d.get('prices', {})
strats = d.get('strategies', {})
print(f'=== GO-TRADER (Cycle {d[\"cycle_count\"]}) ===')
for sym, p in sorted(prices.items()):
print(f' {sym}: \${p:,.2f}')
total_val = sum(s['portfolio_value'] for s in strats.values())
total_cap = sum(s['initial_capital'] for s in strats.values())
total_pnl = total_val - total_cap
pct = (total_pnl/total_cap)*100 if total_cap else 0
print(f'\nPortfolio: \${total_cap:,.0f} → \${total_val:,.0f} ({total_pnl:+,.0f} / {pct:+.1f}%)')
print(f'Strategies: {len(strats)}')
# Circuit breakers
cb_active = [(id,s) for id,s in strats.items()
if s['risk_state'].get('circuit_breaker_until','').startswith('20')]
print(f'Circuit breakers active: {len(cb_active)}')
# Rank by PnL
ranked = sorted(strats.items(), key=lambda x: x[1]['pnl_pct'], reverse=True)
print(f'\nTop 5:')
for id, s in ranked[:5]:
print(f' {id}: {s[\"pnl_pct\"]:+.1f}% (\${s[\"pnl\"]:+,.0f}) | {s[\"trade_count\"]} trades')
print(f'\nBottom 5:')
for id, s in ranked[-5:]:
print(f' {id}: {s[\"pnl_pct\"]:+.1f}% (\${s[\"pnl\"]:+,.0f}) | {s[\"trade_count\"]} trades')
# Dead strategies
dead = [id for id,s in strats.items() if s['trade_count'] == 0]
if dead:
print(f'\nDead (0 trades): {len(dead)} — {dead}')
# Circuit breaker details
if cb_active:
print(f'\nCircuit breaker details:')
for id, s in cb_active:
rs = s['risk_state']
print(f' {id}: dd={rs[\"current_drawdown_pct\"]:.1f}% / max={rs[\"max_drawdown_pct\"]:.0f}% | until {rs[\"circuit_breaker_until\"][:19]}')
"
Present the output to the user in a readable format. Highlight any circuit breakers, dead strategies, or notable PnL changes.
/menu CommandWhen the user says /menu, "show menu", "what can I configure", "what's available", or "help me get started", output the following overview directly (no bash command needed):
=== GO-TRADER MENU ===
1. TRADING PLATFORMS
• Binance US — spot trading: BTC, ETH, SOL
• Deribit — options trading: BTC, ETH
• IBKR / CME — options trading: BTC, ETH (CME Micro contracts, Black-Scholes pricing)
• Hyperliquid — perps trading: any HL-listed asset (paper + live)
• TopStep — futures trading: ES, NQ, MES, MNQ, CL, GC (paper + live)
• Robinhood — crypto trading: BTC, ETH, SOL, DOGE, etc. (paper via yfinance + live via robin_stocks)
• Robinhood — stock options: SPY, QQQ, AAPL, etc. (paper via Black-Scholes + live via robin_stocks)
• Custom — add your own exchange via Step 9 (guided setup)
2. AVAILABLE STRATEGIES
Spot (10 strategies):
sma_crossover, ema_crossover, momentum, rsi, bollinger_bands, macd,
mean_reversion, volume_weighted, triple_ema, rsi_macd_combo, pairs_spread
Deribit Options (8):
vol_mean_reversion, momentum_options, protective_puts, covered_calls,
wheel, butterfly — BTC + ETH each
IBKR Options (8):
same 6 strategies as Deribit — BTC + ETH each
Futures (5 strategies, TopStep/CME):
momentum, mean_reversion, rsi, macd, breakout
Robinhood Crypto (same 10 spot strategies):
sma_crossover, ema_crossover, momentum, rsi, bollinger_bands, macd,
mean_reversion, volume_weighted, triple_ema, rsi_macd_combo
3. ADJUSTABLE SETTINGS (edit scheduler/config.json, then: sudo systemctl restart go-trader)
Global:
interval_seconds — default cycle interval (seconds)
state_file — path to position/trade history file
max_drawdown_pct — portfolio-level circuit breaker
notional_cap_usd — max total notional exposure
correlation.* — per-asset directional exposure tracking (enabled, max_concentration_pct, max_same_direction_pct)
Per-strategy:
capital — starting capital (USD)
max_drawdown_pct — strategy-level circuit breaker
interval_seconds — per-strategy check frequency (0 = use global)
theta_harvest.* — profit_target_pct, stop_loss_pct, min_dte_close
Discord:
enabled — true/false
channels — map: "spot", "options", "hyperliquid", "topstep", "robinhood", "okx"
summary_interval — how often to post summaries
Environment (sudo systemctl edit go-trader):
DISCORD_BOT_TOKEN, STATUS_AUTH_TOKEN
BINANCE_API_KEY, BINANCE_API_SECRET
TOPSTEP_API_KEY, TOPSTEP_API_SECRET, TOPSTEP_ACCOUNT_ID
ROBINHOOD_USERNAME, ROBINHOOD_PASSWORD, ROBINHOOD_TOTP_SECRET
4. COMMANDS
/menu — this overview
/go-trader — live status dashboard (cycle, prices, PnL, circuit breakers)
Setup:
./go-trader init — interactive config wizard (regenerate config.json)
./go-trader init --json '{...}' — non-interactive config generation (agents/scripts)
Add custom platform — say "add a custom platform" (runs Step 9 guided flow)
System:
sudo systemctl start|stop|restart go-trader
sudo systemctl status go-trader
journalctl -u go-trader -n 50 --no-pager
curl -s localhost:8099/status | python3 -m json.tool
5. BACKTESTING
Spot:
.venv/bin/python3 backtest/run_backtest.py \
--strategy <n> --symbol BTC/USDT --timeframe 1h \
--mode single|compare|multi|optimize
Options:
.venv/bin/python3 backtest/backtest_options.py --underlying BTC --since YYYY-MM-DD --capital 10000
.venv/bin/python3 backtest/backtest_theta.py --underlying BTC --since YYYY-MM-DD --capital 10000
For full details on any section, ask about it or see the relevant section in SKILL.md.
All settings live in scheduler/config.json. After any change, restart the service:
sudo systemctl restart go-trader
Config changes are synced to state on startup — no need to reset positions.
| Setting | Key | Default | Description |
|---------|-----|---------|-------------|
| Check interval | interval_seconds | 300 (5 min) | Global default cycle interval in seconds |
| State file path | state_file | scheduler/state.json | Where positions and trade history are stored |
| Auto-update | auto_update | "off" | Update check mode: "off", "daily", "heartbeat" |
| Setting | Key | Default | Description |
|---------|-----|---------|-------------|
| Enable correlation | correlation.enabled | false | Track per-asset directional exposure across strategies |
| Max concentration | correlation.max_concentration_pct | 60 | Warn when one asset exceeds this % of portfolio gross exposure |
| Max same direction | correlation.max_same_direction_pct | 75 | Warn when more than this % of strategies on an asset share a direction |
When enabled, warnings are sent to all active Discord channels and DM'd to the owner. The correlation snapshot is also available via /status.
Each entry in the strategies array supports:
| Setting | Key | Default | Description |
|---------|-----|---------|-------------|
| Capital | capital | 1000 | Starting capital in USD for this strategy |
| Max drawdown | max_drawdown_pct | Spot: 60, Options: 40 | Circuit breaker triggers when drawdown from peak exceeds this %. Measured from the strategy's peak portfolio value, not initial capital. |
| Check interval | interval_seconds | Uses global | How often this strategy checks for signals (seconds). 0 = use global default. Spot typically 300 (5 min), options 1200 (20 min). |
| HTF filter | htf_filter | false | Enable higher-timeframe trend filter (filters counter-trend signals) |
| Custom params | params | null | JSON object of strategy parameter overrides (e.g. {"multiplier": 2.0, "atr_period": 10}). Merged with strategy defaults; runtime params like funding rates take priority. |
| Theta harvest | theta_harvest.enabled | false | Enable early exit on sold options |
| Theta profit target | theta_harvest.profit_target_pct | 60 | Close sold option when this % of premium is captured |
| Theta stop loss | theta_harvest.stop_loss_pct | 200 | Close sold option if loss exceeds this % of premium (200 = 2× premium) |
| Theta min DTE | theta_harvest.min_dte_close | 3 | Force-close positions with fewer than N days to expiry |
| Setting | Key | Default | Description |
|---------|-----|---------|-------------|
| Enable Discord | discord.enabled | true | Turn Discord notifications on/off |
| Channels | discord.channels | — | Map of channel IDs keyed by platform/type: "spot", "options", "hyperliquid", "topstep", "okx", etc. |
| Owner ID | discord.owner_id | — | Your Discord user ID — enables DM upgrade prompts and post-upgrade config migration. Use DISCORD_OWNER_ID env var (preferred). |
Set via systemd override (sudo systemctl edit go-trader):
| Variable | Description |
|----------|-------------|
| DISCORD_BOT_TOKEN | Discord bot token (never store in config.json) |
| DISCORD_OWNER_ID | Your Discord user ID for DM upgrades and config migration (optional) |
| STATUS_AUTH_TOKEN | Optional: require Bearer token for /status endpoint |
| BINANCE_API_KEY | Binance API key (live trading only) |
| BINANCE_API_SECRET | Binance API secret (live trading only) |
| TOPSTEP_API_KEY | TopStep API key (futures live trading only) |
| TOPSTEP_API_SECRET | TopStep API secret (futures live trading only) |
| TOPSTEP_ACCOUNT_ID | TopStep account ID (futures live trading only) |
| ROBINHOOD_USERNAME | Robinhood account email (crypto live trading only) |
| ROBINHOOD_PASSWORD | Robinhood account password (crypto live trading only) |
| ROBINHOOD_TOTP_SECRET | TOTP secret for Robinhood MFA (base32 string from authenticator setup) |
To change deribit-vol-btc to $2,000 capital with 50% max drawdown and theta harvesting:
{
"id": "deribit-vol-btc",
"type": "options",
"script": "shared_scripts/check_options.py",
"args": ["vol_mean_reversion", "BTC", "--platform=deribit"],
"capital": 2000,
"max_drawdown_pct": 50,
"interval_seconds": 1200,
"theta_harvest": {
"enabled": true,
"profit_target_pct": 60,
"stop_loss_pct": 200,
"min_dte_close": 3
}
}
Then restart: sudo systemctl restart go-trader
To run supertrend on ES futures with a tighter multiplier for faster signals:
{
"id": "ts-st-es",
"type": "futures",
"platform": "topstep",
"script": "shared_scripts/check_topstep.py",
"args": ["supertrend", "ES", "5m", "--mode=paper"],
"capital": 5000,
"max_drawdown_pct": 10,
"interval_seconds": 300,
"params": {"multiplier": 2.0, "atr_period": 10}
}
The params field overrides strategy defaults — here it uses a 2.0 multiplier (default 3.0) for faster trend-flip detection on 5-minute candles.
Note: Changing capital on an existing strategy does NOT reset its positions or cash. It only changes the initial_capital reference for PnL calculations. To fully reset a strategy, delete it from scheduler/state.json and restart.
Each spot strategy needs entries for each asset it supports:
{"id": "momentum-btc", "type": "spot", "script": "shared_scripts/check_strategy.py", "args": ["momentum", "BTC/USDT", "1h"], "capital": 1000, "max_drawdown_pct": 60, "interval_seconds": 300}
{"id": "momentum-eth", "type": "spot", "script": "shared_scripts/check_strategy.py", "args": ["momentum", "ETH/USDT", "1h"], "capital": 1000, "max_drawdown_pct": 60, "interval_seconds": 300}
{"id": "momentum-sol", "type": "spot", "script": "shared_scripts/check_strategy.py", "args": ["momentum", "SOL/USDT", "1h"], "capital": 1000, "max_drawdown_pct": 60, "interval_seconds": 300}
Strategies and their assets:
sma_crossover, ema_crossover, momentum, rsi, bollinger_bands, macd, mean_reversion, volume_weighted, triple_ema, rsi_macd_combo: BTC, ETH, SOLpairs_spread: Requires two assets — args: ["pairs_spread", "BTC/USDT", "1d", "ETH/USDT"]Pairs strategy IDs and args:
{"id": "pairs-btc-eth", "args": ["pairs_spread", "BTC/USDT", "1d", "ETH/USDT"], "interval_seconds": 86400}
{"id": "pairs-btc-sol", "args": ["pairs_spread", "BTC/USDT", "1d", "SOL/USDT"], "interval_seconds": 86400}
{"id": "pairs-eth-sol", "args": ["pairs_spread", "ETH/USDT", "1d", "SOL/USDT"], "interval_seconds": 86400}
Each Deribit strategy runs on BTC and ETH:
{"id": "deribit-vol-btc", "type": "options", "script": "shared_scripts/check_options.py", "args": ["vol_mean_reversion", "BTC", "--platform=deribit"], "capital": 1000, "max_drawdown_pct": 40, "interval_seconds": 1200}
{"id": "deribit-vol-eth", "type": "options", "script": "shared_scripts/check_options.py", "args": ["vol_mean_reversion", "ETH", "--platform=deribit"], "capital": 1000, "max_drawdown_pct": 40, "interval_seconds": 1200}
Strategy arg names: vol_mean_reversion, momentum_options, protective_puts, covered_calls, wheel, butterfly
ID convention: deribit-{strategy_short}-{asset} where strategy_short is:
vol_mean_reversion → volmomentum_options → momentumprotective_puts → putscovered_calls → callswheel → wheelbutterfly → butterflySame as Deribit but with different script and ID prefix:
{"id": "ibkr-vol-btc", "type": "options", "script": "shared_scripts/check_options.py", "args": ["vol_mean_reversion", "BTC", "--platform=ibkr"], "capital": 1000, "max_drawdown_pct": 40, "interval_seconds": 1200}
ID convention: ibkr-{strategy_short}-{asset} (same short names as Deribit)
Each TopStep strategy runs on CME futures symbols (ES, NQ, MES, MNQ, CL, GC):
{"id": "ts-momentum-es", "type": "futures", "script": "shared_scripts/check_topstep.py", "args": ["momentum", "ES", "1h", "--mode=paper"], "capital": 1000, "max_drawdown_pct": 5, "interval_seconds": 3600}
{"id": "ts-mean_reversion-es", "type": "futures", "script": "shared_scripts/check_topstep.py", "args": ["mean_reversion", "ES", "1h", "--mode=paper"], "capital": 1000, "max_drawdown_pct": 5, "interval_seconds": 3600}
Strategy arg names: momentum, mean_reversion, rsi, macd, breakout
ID convention: ts-{strategy}-{symbol} (e.g. ts-momentum-es, ts-rsi-nq)
For live trading, change --mode=paper to --mode=live and add --execute flag. Requires TOPSTEP_API_KEY, TOPSTEP_API_SECRET, TOPSTEP_ACCOUNT_ID env vars.
Each Robinhood strategy runs the spot strategy suite on crypto assets (BTC, ETH, SOL, etc.):
{"id": "rh-sma-btc", "type": "spot", "platform": "robinhood", "script": "shared_scripts/check_robinhood.py", "args": ["sma_crossover", "BTC", "1h", "--mode=paper"], "capital": 500, "max_drawdown_pct": 5, "interval_seconds": 3600}
{"id": "rh-momentum-eth", "type": "spot", "platform": "robinhood", "script": "shared_scripts/check_robinhood.py", "args": ["momentum", "ETH", "1h", "--mode=paper"], "capital": 500, "max_drawdown_pct": 5, "interval_seconds": 3600}
ID convention: rh-{strategy_short}-{asset} (e.g. rh-sma-btc, rh-rsi-eth)
Paper mode uses Yahoo Finance for OHLCV data (no credentials needed). For live trading, change --mode=paper to --mode=live. Requires ROBINHOOD_USERNAME, ROBINHOOD_PASSWORD, ROBINHOOD_TOTP_SECRET env vars.
Each Robinhood options strategy runs on US equity symbols (SPY, QQQ, AAPL, etc.):
{"id": "rh-ccall-spy", "type": "options", "platform": "robinhood", "script": "shared_scripts/check_options.py", "args": ["covered_calls", "SPY", "--platform=robinhood"], "capital": 5000, "max_drawdown_pct": 10, "interval_seconds": 14400, "theta_harvest": {"enabled": true, "profit_target_pct": 60, "stop_loss_pct": 200, "min_dte_close": 3}}
{"id": "rh-pput-qqq", "type": "options", "platform": "robinhood", "script": "shared_scripts/check_options.py", "args": ["protective_puts", "QQQ", "--platform=robinhood"], "capital": 5000, "max_drawdown_pct": 10, "interval_seconds": 14400, "theta_harvest": {"enabled": true, "profit_target_pct": 60, "stop_loss_pct": 200, "min_dte_close": 3}}
ID convention: rh-{strategy_short}-{symbol} (e.g. rh-ccall-spy, rh-vol-qqq)
Paper mode uses Black-Scholes pricing (no credentials needed). Live mode uses robin_stocks for real options chains and greeks. Requires ROBINHOOD_USERNAME, ROBINHOOD_PASSWORD, ROBINHOOD_TOTP_SECRET env vars.
Each OKX spot strategy runs the shared spot strategy suite on crypto assets:
{"id": "okx-sma-btc", "type": "spot", "platform": "okx", "script": "shared_scripts/check_okx.py", "args": ["sma_crossover", "BTC", "1h", "--mode=paper", "--inst-type=spot"], "capital": 1000, "max_drawdown_pct": 5, "interval_seconds": 3600}
{"id": "okx-momentum-eth", "type": "spot", "platform": "okx", "script": "shared_scripts/check_okx.py", "args": ["momentum", "ETH", "1h", "--mode=paper", "--inst-type=spot"], "capital": 1000, "max_drawdown_pct": 5, "interval_seconds": 3600}
Each OKX perps strategy runs on USDT-margined perpetual swaps:
{"id": "okx-sma-btc-perp", "type": "perps", "platform": "okx", "script": "shared_scripts/check_okx.py", "args": ["sma_crossover", "BTC", "1h", "--mode=paper", "--inst-type=swap"], "capital": 1000, "max_drawdown_pct": 5, "interval_seconds": 3600}
{"id": "okx-momentum-eth-perp", "type": "perps", "platform": "okx", "script": "shared_scripts/check_okx.py", "args": ["momentum", "ETH", "1h", "--mode=paper", "--inst-type=swap"], "capital": 1000, "max_drawdown_pct": 5, "interval_seconds": 3600}
OKX options use the unified check_options.py with --platform=okx:
{"id": "okx-mom-btc", "type": "options", "platform": "okx", "script": "shared_scripts/check_options.py", "args": ["momentum_options", "BTC", "--platform=okx"], "capital": 5000, "max_drawdown_pct": 10, "interval_seconds": 14400, "theta_harvest": {"enabled": true, "profit_target_pct": 60, "stop_loss_pct": 200, "min_dte_close": 3}}
ID convention: okx-{strategy_short}-{asset} (spot), okx-{strategy_short}-{asset}-perp (perps)
Paper mode uses public OKX API (no credentials). For live trading, change --mode=paper to --mode=live. Requires OKX_API_KEY, OKX_API_SECRET, OKX_PASSPHRASE env vars. Set OKX_SANDBOX=1 for the OKX demo trading environment.
Discord channel keys: "okx" for spot/perps, "okx-options" for options.
development
Maintainer-only workflow for handling GitHub Secret Scanning alerts on OpenClaw. Use when Codex needs to triage, redact, clean up, and resolve secret leakage found in issue comments, issue bodies, PR comments, or other GitHub content.
development
Maintainer workflow for OpenClaw releases, prereleases, changelog release notes, and publish validation. Use when Codex needs to prepare or verify stable or beta release steps, align version naming, assemble release notes, check release auth requirements, or validate publish-time commands and artifacts.
development
Run, watch, debug, and extend OpenClaw QA testing with qa-lab and qa-channel. Use when Codex needs to execute the repo-backed QA suite, inspect live QA artifacts, debug failing scenarios, add new QA scenarios, or explain the OpenClaw QA workflow. Prefer the live OpenAI lane with regular openai/gpt-5.4 in fast mode; do not use gpt-5.4-pro or gpt-5.4-mini unless the user explicitly overrides that policy.
development
End-to-end Parallels smoke, upgrade, and rerun workflow for OpenClaw across macOS, Windows, and Linux guests. Use when Codex needs to run, rerun, debug, or interpret VM-based install, onboarding, gateway smoke tests, latest-release-to-main upgrade checks, fresh snapshot retests, or optional Discord roundtrip verification under Parallels.