Skip to content

Recipes

Six automations, ordered by risk. The first five cannot lose you money — they only read. The sixth can, and is built accordingly.

Every example assumes E8_API_KEY is set and Claude Code is connected as e8-terminal. Adapt freely; the point is the shape, not the exact wording.

# Recipe Scope Risk
1 Morning brief read:trade none
2 Risk watch read:trade none
3 Trade journal read:trade none
4 Custom screener any key none
5 Pre-trade check read:trade none
6 Guarded auto-execution trade:execute ⚠ real orders

1. Morning brief

What it does. Before you sit down, produces one paragraph: what moved overnight, what the news says, and where your open positions stand.

Ask for it directly:

claude -p "Using e8-terminal tools:
1. Get my account equity and daily-loss headroom (e8_account_limits).
2. List my open positions with unrealized P&L.
3. For each symbol I hold, get the last 24h of hourly candles and note the range.
4. Pull the last 12 hours of news.
Write me one paragraph: where I stand, what moved, what's on the calendar.
Report only. No trade suggestions."

On a schedule — see scripts/e8-morning-brief.sh:

0 7 * * 1-5  /path/to/e8-morning-brief.sh >> ~/e8/brief.log 2>&1

Watch out for: the final instruction. Without "report only, no trade suggestions", a model asked to summarise markets will drift into recommending things. Keep that line.


2. Risk watch

What it does. Polls e8_account_limits on an interval and alerts you when headroom before your daily loss limit drops under a threshold. This is the automation most funded traders should build first — it protects the account rather than trying to grow it.

The loop — see scripts/e8-risk-watch.sh:

#!/usr/bin/env bash
# Alert when less than 2 percentage points of daily drawdown remain.
THRESHOLD=2.0

RESULT=$(claude -p "Call e8_account_limits for account $E8_ACCOUNT_ID.
Reply with ONLY the JSON object it returned, no prose.")

ROOM=$(echo "$RESULT" | jq -r '.room.dailyPct')
BREACHED=$(echo "$RESULT" | jq -r '.breached.daily')

if [ "$BREACHED" = "true" ]; then
  notify "E8: DAILY LOSS LIMIT BREACHED"
elif (( $(echo "$ROOM < $THRESHOLD" | bc -l) )); then
  notify "E8 RISK: ${ROOM} percentage points of daily drawdown remaining"
fi

Units matter here. room.dailyPct is percentage points of drawdown still available, not a percentage of the limit. On a 5% daily limit, room.dailyPct starts at 5.0 and falls toward zero. A threshold of 2.0 fires when you are within two points of the limit; a threshold of 30 would never fire at all. See the e8_account_limits response shape.

Run it every fifteen minutes during your session:

*/15 * * * 1-5  /path/to/e8-risk-watch.sh

Watch out for: the alert channel. A log line you never read is not an alert — wire notify to something that reaches you (a push service, SMS, a desktop notification). And keep the interval sane: every 15 minutes is about 100 calls a day against a 10,000/day budget. Every 10 seconds would exceed the per-minute limit and get you throttled precisely when you need the data.


3. Trade journal

What it does. Turns your closed orders into a written journal. The value is not the data — you have that in the terminal — it is being made to review the week in prose.

claude -p "Using e8-terminal tools, list my FILLED and SETTLED orders from the last 7 days
(e8_orders_list, account $E8_ACCOUNT_ID). Then pull e8_analytics_account for the same
account with sections ['consistency','sl_tp_discipline','position_sizing'].

Write a journal entry with:
- A table of trades: symbol, side, size, result
- What the analytics say about my consistency and stop discipline this week
- Three factual observations about my behaviour, no advice

Append it to ~/e8/journal.md under a dated heading."

Watch out for: e8_orders_list paginates at 50 by default, 100 max. A busy week needs paging. And the sections filter on e8_analytics_account matters here — the full payload is 10–15 KB, most of which is irrelevant to a weekly review.


4. Custom screener

What it does. Ranks symbols against rules you define. Since there are no indicator tools over MCP, the maths is yours — which means the rules are genuinely yours, not someone's defaults.

claude -p "Using e8-terminal tools:
1. e8_trade_asset_list with assetClass 'forex' to get the majors.
2. For each, e8_trade_history with resolution '60' and countBack 120.
3. Compute for each: 14-period RSI, 20-period ATR, and position within the 24h range.
4. Rank by ATR relative to its own 20-period average — most volatile first.
Return a table. Facts only, no direction calls."

For anything you run often, compute the indicators in your own code rather than asking a model to do arithmetic on 120 candles — it is faster, cheaper, and correct every time. Building Your Own Harness has a worked Python example.

Watch out for: call volume. Forty symbols is forty e8_trade_history calls, which is most of a minute's budget in one pass. Screen a shortlist, cache candles between runs, or widen the interval.

A note on the numbers: the E8 chat assistant also reports indicators. Yours will not always match its. Different implementation, different defaults. Neither is wrong; do not try to reconcile them.


5. Pre-trade check

What it does. Before you place a trade by hand, checks it against your account state. Catches the two mistakes that end funded accounts: size that is wrong for the balance, and a trade taken when there is no room left in the day.

claude -p "I'm about to buy 0.5 lots of XAUUSD. Using e8-terminal tools, check:
1. e8_account_limits — free margin, and room before daily and total loss limits
2. e8_trade_asset_get XAUUSD — is the market open, what's the spread, what's minSize
3. e8_positions_list — do I already have exposure here

Tell me: does this size fit, and what's the worst case if it hits a full stop?
State the facts. Don't tell me whether to take it."

Wire it to a shell alias and it becomes muscle memory:

alias e8check='claude -p "Pre-trade check for: $*. Use e8-terminal tools..."'

Watch out for: this is a check, not a gate. It does not stop you doing something silly — it just makes sure you read the numbers first.


6. Guarded auto-execution

⚠️ This recipe places real orders.

Run it on a Demo account until you have watched it work for at least a week. On a funded account, a loop with a bug does not just lose a trade — it can breach a limit and end the account. Every guard below exists because removing it has consequences.

What it does. Once per run, evaluates a condition you defined and — if everything passes — places exactly one bracketed order. Then stops.

The guards

Non-negotiable, all of them:

Guard Why
Demo account, hard-coded id A script that cannot see the Live account cannot trade it
One order per run Bounds the damage from any single bad decision
Hard size cap in your code The model never chooses the size. You do
Headroom gate Refuses to trade when room.dailyPct is thin — well before the actual limit
Mandatory stop loss No naked entries. Ever
Market-open check Fails cleanly instead of erroring
clientOrderId A retry cannot double-place
Trip wire Consecutive losses or a headroom breach calls e8_positions_close_all and disables the job

The shape

This is a skeleton, not a drop-in script — e8_call and your_screener_here are yours to supply. e8_call is a thin curl wrapper around one tools/call request; the call() helper in Building Your Own Harness is the same thing in Python, and scripts/smoke-test.sh has a working bash version you can lift.

#!/usr/bin/env bash
set -euo pipefail

ACCOUNT_ID="<demo-account-uuid>"   # Demo. Not Live.
MAX_LOTS="0.10"
MIN_ROOM_PCT="3.0"                 # percentage points of daily drawdown
STATE=~/e8/auto-state.json

# --- Gate 1: is the account healthy enough to trade at all? -----------------
LIMITS=$(e8_call e8_account_limits "$ACCOUNT_ID")
ROOM=$(echo "$LIMITS" | jq -r '.room.dailyPct')
BREACHED=$(echo "$LIMITS" | jq -r '.breached.daily or .breached.total or .breached.margin')

if [ "$BREACHED" = "true" ]; then
  echo "Limit already breached — standing down and tripping the wire."
  jq '.disabled = true' "$STATE" > "$STATE.tmp" && mv "$STATE.tmp" "$STATE"
  exit 0
fi
if [ "$ROOM" = "null" ] || (( $(echo "$ROOM < $MIN_ROOM_PCT" | bc -l) )); then
  echo "Only ${ROOM} points of daily drawdown left (floor ${MIN_ROOM_PCT}) — standing down."
  exit 0
fi

# --- Gate 2: has the trip wire fired? --------------------------------------
if [ "$(jq -r '.disabled' "$STATE")" = "true" ]; then
  echo "Trip wire active. Manual reset required."
  exit 0
fi

# --- Decide (your logic, not the model's) ----------------------------------
SIGNAL=$(your_screener_here)          # → "buy EURUSD" | "sell EURUSD" | "none"
[ "$SIGNAL" = "none" ] && exit 0

# --- Place exactly one bracketed order -------------------------------------
e8_call e8_order_place "$(jq -n \
  --arg acct "$ACCOUNT_ID" --arg sym "$SYMBOL" --arg side "$SIDE" \
  --arg cid "auto-$(date +%Y%m%d%H%M)" \
  '{accountId:$acct, symbol:$sym, side:$side, type:"market",
    amount:'"$MAX_LOTS"', stopLoss:'"$SL"', takeProfit:'"$TP"',
    slippage:20, clientOrderId:$cid}')"

Note what the model is not doing: it does not choose the size, the account, or whether the guards pass. Those are in your code, where they can be tested and cannot be talked out of.

Graduation checklist

Do not skip steps. Each one catches a different class of bug.

  • [ ] Week 1 — read-only. Log what it would have done. Never call e8_order_place.
  • [ ] Review the log. Would those trades have been reasonable? If not, the logic is wrong and no amount of guarding fixes it.
  • [ ] Week 2 — Demo, live orders. Check every fill by hand. Confirm brackets attached at the prices you expected.
  • [ ] Test the trip wire deliberately. Force the condition. Confirm it closes positions and disables the job.
  • [ ] Only then consider Live — at a fraction of your normal size, with the headroom gate set tighter than you think necessary.

If it goes wrong

# 1. Stop the job
crontab -e     # comment the line

# 2. Flatten
claude -p "Call e8_positions_close_all for account <id>."

# 3. Revoke the key — the fastest kill switch when you're not sure what's running
#    https://trade.e8markets.com/settings → API Keys → Revoke

Revoking the key stops everything using it, immediately, without needing to find the process. When in doubt, revoke first and diagnose after.


Next: Building Your Own Harness for the maths and scheduling, or Safety & Limits for scopes and kill switches.