Rules for running the trading harness unattended (headless, scheduled by scripts/autotrader.js on Claude Code, Codex, Qwen Code, or another harness) - one bounded cycle per run, no user questions, stand aside when unsure, and never touch guardrails. Use whenever a prompt says it is an autonomous or scheduled cycle.
Install
npx skillscat add johnamcruz/futures-trading-harness/autonomous-trading Install via the SkillsCat registry.
Autonomous Trading
When to Use
- The prompt comes from the autonomous runner ("autonomous cycle").
- Any headless run with no user to answer questions.
How It Works
One cycle per closed bar, then exit. The runner starts a cycle right
after each bar closes (the configured timeframe: 1, 3, ... minutes),
through the whole session (18:00 ET until 16:00 ET the next day, the regular
09:30-16:00 ET hours included), and hands you the closed bars in a
file. Run exactly one trade-session (or premarket / end-of-day when the
prompt says so). Don't wait, sleep, or poll inside a run; a bar that closes
while you are still running is skipped, so finish within one bar.No questions. Nobody is there to answer. Where the interactive workflow
would ask, take the conservative branch: stand aside, keep the stop, flatten
at end of day.Positions first. If a position is open, only manage it this cycle.
Before your cycle, the runner has already:- cancelled leftover orders on a flat contract;
- for strategies whose exit trails, applied the trailing stop: the initial
stop untiltrailActivateR, thentrailGivebackRbehind the best price
(both in the scan'sexit); - for strategies with a time stop (
exit.max_bars), closed a trade that
has been open that long.
Don't loosen a stop it set. To see why a setup did or didn't fire, read
that bar's record in<FTH_HOME>/logs/scans-<day>.jsonl(the runner's own
log is<FTH_HOME>/logs/autotrader-<day>.log; your earlier cycles, with
their prompts, tool calls, and skills loaded, are in<FTH_HOME>/logs/cycles-<day>.jsonlandlogs/cycles/<day>/; the gate's
decisions inlogs/gate-log.jsonl). The prompt also carries the last 10
closed bars and your last 10 cycle results: read them, and don't reverse a
recent decision without saying what changed. Those results are your past
conclusions, not facts: where one contradicts this prompt's account or
attempt line (e.g. it says no attempt is running and the prompt lists an
active one), the prompt's facts win, and you say the earlier result was
wrong. It carries today's premarket
plan, the news blackouts (in force, or the next one), the day so far (the
"day:" line; outside RTH the "overnight" line), each fired strategy's track
record (apaperone is marked: plan it only), and each open trade's state
(setup, initial risk, stop, target, R now, best and worst): thetrade-sessionskill says how to weigh them. Times are New York time. A
"Context unavailable" line names what couldn't be read this cycle: that is
unknown, not "none" (read it yourself, or trade smaller). The cycle's log
(logs/cycles/<day>/) holds the prompt and what it was built from.
Guardrails are final. A block from the order gate, the MCP gateway, or
the server ends the entry attempt. Fix what the block names when it is
yours to fix (for example, review a closed trade, cancel a leftover order),
otherwise end the cycle. Never edit harness files, settings, environment,
strategy status, blackouts (except adding them in premarket), or the journal
file to get past a limit.Kill switch. When
<FTH_HOME>/STOPexists the runner starts only
manage cycles and the gate refuses every entry; you don't need to check
the file (you can't read it). If an entry is refused with[kill-switch],
manage or flatten open positions only, and end.Leave a trail. Every cycle ends with a journal
note(or plan, review)
so the next cycle and the human can see what happened. Your last line
must be exactly:CYCLE RESULT: <no-trade | planned | executed | managed | flattened | blocked | error> - <reason>
(one outcome word, then-and the reason, as in the examples below).blockedonly when the order gate, the gateway or the broker refused an
order this cycle; nothing fired, or you stood aside, isno-trade.
The runner reads only that line, from your final message: a summary, a
table, or "Decision: NO TRADE" in its place is logged as "none reported",
even when the cycle did its work. Write it last, after every tool call,
as plain text in your final message: never as a tool call or a tool's
arguments.Budget. Keep the cycle short: reuse bar files fetched this cycle, at most
one plan, at most one entry. The bar briefing (bar_briefing) is the
runner's file for this bar: read it once per role and reuse it (it doesn't
change during the cycle), and take its numbers instead of recomputing them. Read once per cycle. For each symbol, each
role (you, each analyst, each call of a role; a role you play yourself
counts as that role) reads each of these at most once and reuses it:strategies_scan(one withnameis a separate read),mtf_read(one
call, withdailywhen you have the daily file),get_account_snapshot,get_quote,get_bars. A full cycle still runs its analysts in parallel,
except those whose report the prompt gives under "Cached reports"
(trade-session step 2): those reports are this cycle's; don't launch the
role again.
Don't repeat what the prompt or a role gave you (the trade-executor's
report is the after-order read of trade-session step 6), except:- The prompt lacks
remainingBeforeLimit(and, without a prop attempt,
today's P&L): a cycle that may enter readsget_account_snapshotonce
(trade-session step 1). It gives only a count of working orders, the
trend rule, and no scan details: readlist_open_ordersonce; take the
alignment and the scan's candidates from the bar briefing (m15alignment,m3candidates), and runmtf_readorstrategies_scan
only when it says there is no current briefing. Anything under "Context unavailable", read
once yourself. - Read the account and open orders once after each
place_order,modify_order,cancel_order,close_position, orpartial_close_position, including one that failed or timed out (its
order may be live), and before an order call unless you read them after
your last one (the Execution rule). - The scan again only after you fetched new bars. A trade review's
get_barsover a trade's hold is one read per trade reviewed. - A failed read may be retried once (broker-mcp skill, Failures and
limits). Never resend an order call blindly: after a failed or timed-out
one, readlist_open_ordersandget_account_snapshot, and send it
again only if they show it didn't go through and it is still needed (a
close or a[protect]stop always is). A gate refusal ends the entry
attempt unless you fixed what it named (rule 4).
A tool that fails twice ends the cycle as
error(after confirming any
open position has its stop). Never wait within a cycle: bars and fills
may not move until the next one. An order
that hasn't filled at its one check is journalled as working and the cycle
ends (executedormanaged, saying it is working); the next cycle checks
the fill (broker-mcp skill, Order mechanics). An unfilled entry without a
stop bracket is cancelled, not left working (it would fill with no stop),
and the cancel confirmed: cancelled, journal aresult:nofillreview and
end asno-trade(entry cancelled: no stop bracket); filled before the
cancel and protected,executed; still working after a second cancel,error(journal it as an entry without a stop bracket), and the next
cycle cancels it first. Any quantity that filled is protected first.- The prompt lacks
Harness tools, not scripts. Bars, scans, the snapshot, the
multi-timeframe read, blackouts, the prop status, lessons, and reconcile
are tools on theharnessMCP server (theharness-toolsskill): call
them; don't run the harness's scripts from a shell. Starting, stopping, or
recording a prop attempt, backtests, and replays (replay.js) are the
user's.
Examples
CYCLE RESULT: no-trade - orb fired but relative volume 0.8x (skip rule)
CYCLE RESULT: managed - MNQ long from 21503.25 (1R 5.25), peak 21515.75 (+2.38R); runner trailed the stop to 21513.00 (+1.86R)
CYCLE RESULT: blocked - [loss-streak] cooldown 18 min