Top-down futures analysis across timeframes - daily and 4h for context, 1h for bias, 15m for the setup, the trigger timeframe (3m/1m) for the entry. A mechanical read (the harness tool mtf_read) gives each timeframe's trend and labels a long or a short aligned, pullback, counter, or mixed. The trend rule is enforced in code - a trend strategy never enters against the prevailing 4h/1h/15m trend, only a reversal strategy (one marked mtf reversal) may fade it - by the scan, the backtester, and the order gate. Use for every bias, game plan, and trade plan, and whenever timeframes disagree.
Install
npx skillscat add johnamcruz/futures-trading-harness/multi-timeframe-analysis Install via the SkillsCat registry.
Multi-Timeframe Analysis
A trigger on 3-minute bars is worth more when the timeframes above it point
the same way, and it is a pullback (or a trap) when they don't. This skill
makes that read the same every time: one tool reads the trend on each
higher timeframe from the bars you already have, and labels each side.
When to Use
- Premarket: the bias per timeframe and the levels of the day.
- Every trade plan, before risk-manager phase 1: is this setup with the
higher timeframes, a pullback inside them, or against them? - Whenever the trigger timeframe and a higher timeframe disagree.
How It Works
1. Get the bars (one request per timeframe at most)
get_bars allows 50 requests per 30 s across all agents. The higher
intraday timeframes are built from the trigger bars, so you rarely need more
than two requests:
| Role | Timeframe | Source |
|---|---|---|
| Context | daily | bars_fetch with {"symbol": "<SYMBOL>", "timeframe": "daily"} (60 bars to <FTH_HOME>/bars-scratch/<SYMBOL>-1d.json) |
| Context | 4 hours | built from the trigger bars (its EMA50 vote needs 50 candles, about 4000 3m bars; with fewer it votes on two, and the line says so) |
| Bias | 1 hour | built from the trigger bars |
| Setup | 15 minutes | built from the trigger bars |
| Trigger | 3 minutes (1 minute for the flow strategies) | the runner's bars file (at least 2000 bars), or bars_fetch with {"symbol": "<SYMBOL>", "timeframe": 3, "record": true} (the runner's default, 5000 3-minute bars, to <FTH_HOME>/bars-scratch/<SYMBOL>-3m.json, and the read recorded for the gate) |
Without daily the highest timeframe is the 4-hour: the alignment is then
judged from it, and the plan says "no daily read". Fetch the daily bars once
a session (premarket) and reuse the file; if the fetch fails, go on without
them rather than retrying.
2. Run the read
In an autonomous cycle the bar briefing (bar_briefing, the harness-tools
skill) already holds this read for the bar: the 15m frame and the alignment
per side (m15), the 1h and 4h frames (h1), and the trend rule (m3). Use
it; run mtf_read only without a current briefing. The alignment and the
trend rule in a trade plan are the briefing's (intraday frames); a daily
read, if you have one (premarket's), is context only, never a second
alignment.
mtf_read {"bars": "<trigger bars>", "daily": "<the daily file bars_fetch returned>"}
mtf_read {"bars": "<trigger bars>", "timeframes": [15, 60, 240], "json": true} every number<trigger bars> is the runner's bars file by absolute path (e.g./home/u/.futures-trading-harness/bars/MNQ-3m.json; no ~) or abars_fetch file (the harness-tools skill says which files it reads). Candles align to the 18:00 ET open: 1-hour candles open
on the hour, 4-hour ones at 18:00, 22:00, 02:00, 06:00, 10:00, and 14:00 ET.
Only completed candles decide a trend; the one forming is reported apart.
Each timeframe's trend has three votes:
- The close against EMA 20.
- EMA 20 against EMA 50 (no vote with fewer than 50 candles, and the line
says so). - Swing structure: higher highs and higher lows (HH/HL), lower highs and
lower lows (LH/LL), or mixed.
Two votes the same way, and none against, set the trend (UP or DOWN);
anything else is RANGE. Each line also gives ADX, ATR, where the close sits
in the last 20 candles' range, and the swing high and low.
3. The trend rule (enforced, not advice)
The prevailing trend is the highest of 4h, 1h, and 15m (built from the
trigger bars) that has one: the 4h when it trends, else the 1h, else the 15m.
- Trend strategies (every strategy unless its STRATEGY.md says
mtf: reversal): never enter against the prevailing trend, and wait while
the 4h has fewer than 3 completed candles. With no trend on any of the three,
both sides are open. - Reversal strategies (
mtf: reversal:crt_1h,crt_4h,cisd_ote,ofi_absorption,value_area_reentry): may fade it. That is their setup, a raid at a
higher-timeframe level; when they do, the priority order (strategy-library,
step 2) decides them: level, size, target.
Where it is enforced:
strategies_scan: a trend strategy that fires against it is not a
candidate; its why-not (filtersFailedin its full result) saysmtf: against the prevailing 4h down trend .... The summary names the frames
and the prevailing trend; every full result hasmtf(frames,prevailing,longAllowed,shortAllowed).- The backtester uses the same scan, so its trades obey it.
- The order gate (
mtf-trend, hard: nothing switches it off) refuses a trend
strategy's entry against the trend recorded in<FTH_HOME>/mtf/<ROOT>.json, or with no record or one more than 15 minutes
(FTH_MTF_MAX_AGE_MIN) past its last bar's close. The autonomous runner
records it every bar and puts its line in the cycle prompt. Interactively,
record it yourself before any entry:mtf_readwith{"bars": "<bars>", "record": true, "symbol": "MNQ"}.
While the autonomous runner is running,recordis refused (the runner
records the symbols it trades): don't trade interactively next to it.
The last line of the read states it: Trend rule: prevailing trend 4h up; trend strategies may not go short; reversal strategies (mtf: reversal) may go short too.
The daily (daily) is context for your judgment; the rule reads the
intraday frames.
4. Read the alignment
From the highest timeframe down, for each side:
| Label | Means | What to do |
|---|---|---|
aligned |
no timeframe against it, most with it | Step 4 of the priority order (strategy-library) sets the size; with room to its trail activation and confluence it is the opportunity (the briefing's candidate facts show both) |
pullback |
every timeframe above the lowest is with it; the lowest is against it | The setup timeframe is pulling back. Wait for the trigger timeframe to turn back with the bias (a shift, a reclaim), then step 4 of the priority order (strategy-library) sets the size. Do not enter while it is still moving against you |
mixed |
timeframes disagree without a clear pullback | Step 4 of the priority order (strategy-library) sets the size. Target the nearest opposing level; skip in a quiet session |
counter |
the highest timeframe is against it | Step 4 of the priority order (strategy-library); a reversal at a higher-timeframe level is its step 2, and the plan says why |
A policy strategy's verdict is a ceiling: the read halves or skips it like
any setup (the priority order, strategy-library).
The bias (long, short, or neutral) weights the higher timeframes more
(score out of ±max): use it for the game plan's headline.
Reversal strategies (crt_1h, crt_4h, ofi_absorption, cisd_ote,value_area_reentry) trade
against the lower timeframes by design, and the trend rule lets them fade
the prevailing trend. Judge the setup against the timeframe above its range
candle (for crt_1h, the 4-hour trend; for crt_4h, the daily): against
that one too, it is a counter reversal (the priority order, step 2, decides it: level,
size, target).
5. Levels flow down
Take levels from the higher timeframes (the daily and 4-hour swing highs and
lows, the previous candle's high and low on each, the prior day's high and
low) and treat them as targets on the trigger timeframe, or as reasons to
skip a setup that runs straight into one.
6. Write it down
One line per timeframe and the verdict, in the plan entry and the premarket
note, so reviews can grade it:
Daily UP (HH/HL). 4h UP. 1h UP, ADX 26. 15m DOWN (pullback to the 1h EMA20).
Long: pullback (wait for a 3m shift up). Short: counter.7. In rules (mechanical strategies)
mtf_bias(m) is the same trend per bar, causal (each bar sees only candles
completed before it): 1 up, -1 down, 0 range. Add it to a strategy's rules
to keep its trades with the higher timeframe, and backtest both versions:
rules:
long:
- close crosses_above ema(20)
- mtf_bias(60) > 0 # the 1-hour trend is up
- mtf_bias(240) >= 0 # and the 4-hour isn't downThe ported strategies keep their source's rules (parity); try a filter in a
copy (e.g. strategies/ema_cross_mtf/) and compare the two withscripts/backtest.js.
Examples
mtf_read {"bars": "/home/u/.futures-trading-harness/bars/MNQ-3m.json", "daily": "/home/u/.futures-trading-harness/bars-scratch/MNQ-1d.json"}
daily: UP (close 21650 vs EMA20 21402.5, EMA20 vs EMA50 21180.25, structure HH/HL), ADX 24.1, ...
4h: UP (close 21652.25 vs EMA20 21590.75, EMA20 vs EMA50 21470.5, structure HH/HL), ADX 21.3, ...
1h: UP (close 21652.25 vs EMA20 21630.5, EMA20 vs EMA50 21588, structure HH/HL), ADX 26.0, ...
15m: DOWN (close 21652.25 vs EMA20 21661, EMA20 vs EMA50 21664.5, structure LH/LL), ADX 18.2, ...
Alignment: long pullback, short counter; bias long (score 8 of ±10).
Trend rule: prevailing trend 4h up; trend strategies may not go short; reversal strategies (mtf: reversal) may go short too.
-> Longs are a pullback: wait for a 3m shift up (ema_cross or bos long), target the 1h swing high.
Shorts are counter: a 3m keltner short is refused (scan and gate); only a
crt_1h raid of the 1h high could short (the priority order, step 2, decides it:
level, size, target).
mtf_read {"bars": "/home/u/.futures-trading-harness/bars/NQ-3m.csv"} (the parity fixture tests/fixtures/parity/NQ-3m.csv, copied to the bar directory by the user)
4h: UP (... structure HH/HL), ... (18 candles: no EMA50 vote, needs 50)
1h: RANGE (... structure mixed), ADX 14.14, ...
15m: DOWN (... structure LH/LL), ADX 22.59, ...
Alignment: long mixed, short counter; bias long (score 2 of ±6).
Trend rule: prevailing trend 4h up; trend strategies may not go short; reversal strategies (mtf: reversal) may go short too.
-> Longs: mixed (the priority order's step 4 sizes it). Shorts: against the 4-hour trend, refused for trend strategies.