Module H · Real-Time, Alerts & Automation - Chapter 33

Multiple Time Frames

Read a higher time frame on a lower-time-frame chart with TimeFrameSet, TimeFrameGetPrice and friends.

Realtime
What you'll learn
  • ·Why multi-timeframe
  • ·TimeFrameSet / Restore
  • ·TimeFrameGetPrice
  • ·TimeFrameExpand
  • ·A higher-TF trend filter
  • ·Pitfalls & alignment

Every chart you open shows one time frame, but no trade ever happens in just one. A 15-minute scalper still glances at the hourly trend before pressing the button; a swing trader checks the weekly before acting on the daily. That "glance up" is what professionals call multiple time frame analysis, and AmiBroker lets you bake it directly into a formula - so your system can see the bigger picture without you flipping charts.

Good to know

AmiBroker can compress and expand timeframes on the fly with TimeFrameSet, so a 5-minute chart can read its own hourly or daily trend - without you ever opening a second chart.

The idea is powerful and a little dangerous in equal measure. Done right, a higher time frame becomes a calm trend filter that keeps you on the correct side of the market. Done carelessly, it quietly leaks future information into your signals and produces a backtest that can never be repeated. This chapter teaches both the tools and the discipline.

Why look at a higher time frame

The same EMA crossover that looks like a great buy on the 15-minute chart can be a doomed counter-trend bet when the hourly is rolling over. A higher time frame answers a question the lower one cannot: which way is the larger tide flowing? The classic professional rule is simple - take lower-time-frame entries only in the direction of the higher-time-frame trend. We will build exactly that.

AmiBroker keeps your chart on its base interval (say, 15-minute) and lets you temporarily "switch up" to compute something on a coarser interval, then bring the answer back down. Three functions do all the work.

TimeFrameSet and TimeFrameRestore

TimeFrameSet(interval) compresses the price arrays to a higher interval. Everything you calculate after it - moving averages, RSI, anything - is computed on those bigger bars. TimeFrameRestore() switches you back to the chart's native interval. Always use them as a matched pair, like opening and closing a bracket.

// Switch up to the hourly bars
TimeFrameSet(inHourly);
    hourlyEMA = EMA(Close, 20);   // 20-period EMA of HOURLY closes
TimeFrameRestore();               // back to the chart's own interval

AmiBroker gives you ready-made interval constants: inDaily, inWeekly, inMonthly, inHourly, and in5Minute, in15Minute and friends. You can also build any custom interval in seconds with inDaily * n style arithmetic, but the named constants cover almost everything.

Heads up

Everything between TimeFrameSet and TimeFrameRestore runs on the higher interval. Forget the TimeFrameRestore() and the rest of your formula keeps calculating on hourly bars by accident - a classic source of baffling bugs. Treat the pair like brackets that must always close.

TimeFrameExpand: bringing the value back down

There is a catch. After TimeFrameRestore(), the hourlyEMA array has one value per hourly bar, but your chart has many 15-minute bars per hour. To plot or compare it against 15-minute price, you must stretch it back out so every 15-minute bar carries the right hourly value. That is what TimeFrameExpand does.

TimeFrameSet(inHourly);
    hourlyEMA = EMA(Close, 20);
TimeFrameRestore();

// stretch the hourly series back onto the 15-minute chart
hourlyEMA_exp = TimeFrameExpand(hourlyEMA, inHourly);

Plot(Close, "Price", colorDefault, styleCandle);
Plot(hourlyEMA_exp, "Hourly EMA(20)", colorYellow, styleThick);

The third argument controls how a higher-time-frame value fills the smaller bars beneath it, and the choice matters:

  • expandLast (the default) - each finished higher-TF bar's value appears on the lower bars after it closes. This is the honest, non-repainting choice for trading.
  • expandFirst - the value appears from the start of the higher bar. Convenient for display, but it shows the hourly close on 15-minute bars that formed before that hour finished - look-ahead.
  • expandPoint - the value is placed on a single bar only, leaving the rest empty.
Key idea

Use expandLast for any value that feeds a trading decision. It guarantees the higher-time-frame number you act on was already finalised when your lower-time-frame bar formed. expandFirst paints a prettier line but can hand your backtest information the market had not revealed yet.

TimeFrameGetPrice: a prior higher-TF value

Sometimes you just want a single higher-time-frame price - yesterday's daily close, last week's high - without setting and restoring. TimeFrameGetPrice is the shortcut:

// the PRIOR completed daily close, available on every intraday bar
prevDayClose = TimeFrameGetPrice("C", inDaily, -1);

// today's developing daily high (use with care - it is still forming)
todayHigh    = TimeFrameGetPrice("H", inDaily,  0);

The first argument is the field ("O", "H", "L", "C" or "V"), the second is the interval, and the third is the offset - 0 is the current higher bar, -1 is the one before it. The -1 is the safe one: the prior day has finished, so its close is fixed. Reaching for 0 on the current day means you are reading a value that is still changing, which is fine for a live readout but rarely safe inside a signal.

A higher-time-frame trend filter

Now we put it together into the professional rule: trade the 15-minute chart only in the direction of the hourly trend. The lower time frame gives the entry; the higher time frame gives permission.

// --- Higher time frame: hourly trend ---
TimeFrameSet(inHourly);
    hrEMA = EMA(Close, 20);
TimeFrameRestore();
hrEMA_exp = TimeFrameExpand(hrEMA, inHourly);   // expandLast by default

hourlyUp   = Close > hrEMA_exp;                 // hourly trend is up
hourlyDown = Close < hrEMA_exp;                 // hourly trend is down

// --- Lower time frame: 15-minute entry trigger ---
fast = EMA(Close, 9);
slow = EMA(Close, 21);

// Only take the 15-min cross in the hourly trend's direction
Buy   = Cross(fast, slow) AND hourlyUp;
Short = Cross(slow, fast) AND hourlyDown;

Sell  = Cross(slow, fast);     // exit long on the opposite 15-min cross
Cover = Cross(fast, slow);     // cover short on the opposite cross

Buy   = ExRem(Buy, Sell);
Sell  = ExRem(Sell, Buy);
Short = ExRem(Short, Cover);
Cover = ExRem(Cover, Short);

The hourly EMA filter throws away every 15-minute crossover that fights the bigger trend. You will take fewer trades, but the ones you take lean with the larger flow instead of against it - the multi-timeframe version of the trend filter we used for RSI pullbacks last chapter.

Pitfalls and alignment

Multi-timeframe code has a few sharp edges worth memorising:

  • Always pair Set and Restore. Unmatched calls silently corrupt the rest of the formula.
  • Expand before you compare or plot. A raw higher-TF array does not line up with your chart bars until you TimeFrameExpand it.
  • Prefer expandLast and -1 offsets for anything a signal depends on, so you never act on a higher-TF bar that has not closed.
  • Mind the data. To compute an hourly or daily value you must actually have enough intraday history loaded; thin data makes the higher series ragged or empty.
Note

A neat way to prove your filter is honest: plot the expanded higher-TF line and confirm it only ever steps at the boundary of a completed higher bar - never mid-way through one. If it bends inside an hour, you are almost certainly using expandFirst or a 0 offset and leaking the future.

Try it yourself

  • Plot an hourly EMA(20) on a 15-minute BANKNIFTY chart and watch how it steps once per hour.
  • Add prevDayClose = TimeFrameGetPrice("C", inDaily, -1) and plot it as a dashed line - your intraday pivot reference.
  • Run the multi-timeframe crossover as a backtest with and without the hourlyUp / hourlyDown filter and compare trade counts.
  • Switch the expand mode to expandFirst and look closely - can you see the line bending inside an hour? That is the look-ahead you are avoiding.

Recap

  • Multiple time frame analysis lets a lower-time-frame system see the higher-time-frame trend.
  • TimeFrameSet / TimeFrameRestore switch the calculation interval up and back - always as a pair.
  • TimeFrameExpand stretches a higher-TF array back onto your chart; use expandLast for trading.
  • TimeFrameGetPrice("C", inDaily, -1) grabs a single prior higher-TF value safely.
  • The professional rule - enter on the lower time frame only in the higher time frame's direction - filters out trades that fight the bigger tide.

Next we make a system speak up - firing alerts to a Telegram channel and even out loud the moment a signal triggers.