| IMPORTANT: TimeFrame functions are NOT intended to replace Periodicity setting. To switch periodicity/interval you should only use Periodicity setting. TimeFrame functions are ONLY for formulas that mix many different intervals at once in a single formula. |
Release 4.41 brings the ability to use multiple time frames (bar intervals) in a single formula. The time frame functions can be divided into three functional groups:
First group is used when your formula needs to perform some calculations on indicators in a different time frame than the currently selected one. For example, if you need to calculate a 13-bar moving average on 5-minute data and a 9-bar exponential average from hourly data while the current interval is 1 minute, you would write:
TimeFrameSet( in5Minute ); //
switch to 5 minute frame
/* MA now operates on 5 minute data, ma5_13 holds
time-compressed 13 bar MA of 5min bars */
ma5_13 = MA( C, 13 );
TimeFrameRestore(); //
restore time frame to original
TimeFrameSet( inHourly ); //
switch now to hourly
mah_9 = EMA( C, 9 ); //
9 bar moving average from hourly data
TimeFrameRestore(); //
restore time frame to original
Plot( Close, "Price", colorWhite, styleCandle );
// plot expanded average
Plot( TimeFrameExpand(
ma5_13, in5Minute), "13
bar moving average from 5 min bars", colorRed );
Plot( TimeFrameExpand(
mah_9, inHourly), "9
bar moving average from hourly bars", colorRed );
TimeFrameSet( interval ) - replaces current built-in price/volume arrays (Open, High, Low, Close, Volume, OpenInt, Avg) with time-compressed bars of a specified interval. Once you switch to a different time frame, all calculations and built-in indicators operate on the selected time frame. To get back to the original interval, call the TimeFrameRestore() function. If you want to call TimeFrameSet again with a different interval, you have to restore the original time frame first using TimeFrameRestore(). The interval is the time frame interval in seconds. For example, 60 is a one-minute bar. You should use convenient constants for common intervals: in1Minute, in5Minute, in15Minute, inHourly, inDaily, inWeekly, inMonthly.
With version 4.70 you can also specify N-tick intervals. This is done by passing a negative value as the interval. For example, -5 will give 5-tick bar compression, and -133 will give 133-tick compression. Please note that using N-tick intervals works only if your database uses a tick-base time interval set in File -> Database Settings dialog.
TimeFrameSet(
-133 ); //
switch to 133-tick interval
| IMPORTANT: TimeFrameSet() is NOT an equivalent of the periodicity setting in Analysis Settings. The only use for time-frame functions is when you want to have trading rules based on multiple time frames at once. See details in "How it works internally" below. |
TimeFrameRestore() - restores price arrays replaced by SetTimeFrame. Note that only OHLC, V, OI, and Avg built-in variables are restored to their original time frame when you call TimeFrameRestore(). All other variables created when being in a different time frame remain compressed. To decompress them to their original interval, you have to use TimeFrameExpand.
Once you switch the time frame using TimeFrameSet, all AFL functions operate on this time frame until you switch back the time frame to its original interval using TimeFrameRestore or set it to a different interval again using TimeFrameSet. It is a good idea to ALWAYS call TimeFrameRestore when you are done with processing in other time frames.
When the time frame is switched to an interval other than the original, the results of all functions called since TimeFrameSet are time-compressed, too. If you want to display them in the original time frame, you would need to 'expand' them as described later. Variables created and assigned before calling TimeFrameSet() remain in the time frame they were created. This behavior allows mixing unlimited different time frames in a single formula.
| PLEASE NOTE that you can only compress data from a shorter interval to a longer interval. So, when working with 1-minute data, you can compress to 2, 3, 4, 5, 6, ....N-minute data. But when working with 15-minute data, you cannot get 1-minute data bars. In a similar way, if you have only EOD data, you cannot access intraday time frames. |
Second group: TimeFrameCompress/TimeFrameExpand allow compressing and expanding single arrays to/from a different time frame. Especially worth mentioning is TimeFrameExpand, which is used to decompress array variables that were created in a different time frame. Decompressing is required to properly display an array created in a different time frame. For example, if you want to display a weekly moving average, it must be 'expanded' so that the data of one weekly bar covers five daily bars (Monday-Friday) of the corresponding week.
Caveat: expandFirst used on prices different from open may look into the future. For example, if you create weekly HIGH series, expanding it to daily interval using expandFirst will enable you to know on MONDAY what the high was for the entire week.
| IMPORTANT: TimeFrameExpand IS REQUIRED for any formula that uses TimeFrame* functions. If you don't expand time-compressed data, you will have incorrect timestamps (see description below in "How it works"). |
TimeFrameCompress is provided for completeness and it can be used when you want to compress a single array without affecting built-in OHLC, V arrays. If you call TimeFrameCompress, it does not affect the results of other functions.
wc = TimeFrameCompress( Close, inWeekly );
/* now the time frame is still unchanged (say
daily) and our MA will operate on daily data */
dailyma = MA( C, 14 );
/* but if we call MA on compressed array, it will
give MA from other time frame */
weeklyma = MA( wc, 14 ); //
note that argument is time-compressed array
Plot( dailyma, "DailyMA", colorRed );
weeklyma = TimeFrameExpand(
weeklyma, inWeekly ); //
expand for display
Plot( weeklyma, "WeeklyMA", colorBlue );
During this formula, the time frame remained at its original setting; we only compressed a single array.
TimeFrameCompress( array, interval, mode = compressLast
)
- compresses a single array to a given interval using a given compression mode. Available modes:
compressLast - last (close) value of the array within the interval
compressOpen - open value of the array within the interval
compressHigh - highest value of the array within the interval
compressLow - lowest value of the array within the interval
compressVolume - sum of the values of the array within the interval
Graph0 = TimeFrameExpand( TimeFrameCompress( Close, inWeekly, compressLast ), inWeekly, expandLast );
Graph1 = TimeFrameExpand( TimeFrameCompress( Open, inWeekly, compressOpen ), inWeekly, expandFirst );Third group consists of just one useful function: TimeFrameGetPrice, which allows referencing price and volume from other time frames without switching, compressing, or expanding time frames. Just one function call to retrieve price from a higher time frame. It also allows referencing not only current but also past bars from different time frames.
TimeFrameGetPrice( pricefield, interval, shift = 0, mode
= expandFirst );
- references OHLCV fields from other time frames. This works immediately
without the need to call TimeFrameSet at all.
The price field is one of the following: "O", "H", "L", "C", "V", "I" (open
interest). The interval is the bar interval in seconds. Shift allows referencing
past (negative values) and future (positive values) data in a higher time
frame. For example, -1 gives the previous bar's data (like in the Ref function,
but this works in a higher time frame).
Examples:
TimeFrameGetPrice( "O", inWeekly,
-1 ) //
gives you previous week Open price
TimeFrameGetPrice( "C", inWeekly,
-3 ) //
gives you weekly Close price 3 weeks ago
TimeFrameGetPrice( "H", inWeekly,
-2 ) //
gives you weekly High price 2 weeks ago
TimeFrameGetPrice( "O", inWeekly, 0 ) //
gives you this week Open price.
TimeFrameGetPrice( "H", inDaily,
-1 ) //
gives previous Day High when working on intraday dataShift works as in the Ref() function, but it is applied to a compressed time frame.
Note, these functions work like these three nested functions
TimeFrameExpand( Ref( TimeFrameCompress( array, interval, compress(depending
on field used) ), shift ), interval, expandFirst )
therefore, if shift = 0, compressed data may look into the future (a weekly
high can be known on Monday). If you want to write a trading system using
this function, please make sure to reference past data by using a negative
shift value.
The only difference is that TimeFrameGetPrice is 2x faster than nested Expand/Compress functions.
Note on performance of TimeFrame functions:
a) Measurements done on an Athlon 1.46GHz, 18,500 daily bars compressed to a weekly time frame
TimeFrameGetPrice( "C", inWeekly, 0 ) - 0.0098 sec (9.8 milliseconds)
TimeFrameSet( inWeekly ) - 0.012 sec (12 milliseconds)
TimeFrameRestore( ) - 0.006 sec (6 milliseconds)
TimeFrameCompress( Close, inWeekly, compressLast ); - 0.0097 sec (9.7 milliseconds)
TimeFrameExpand( array, inWeekly, expandLast ); - 0.0098 sec (9.8 milliseconds)b) Measurements done on an Athlon 1.46GHz, 1,000 daily bars compressed to a weekly time frame. All functions below 0.0007 sec (0.7 millisecond)
How does it work internally?
|
Time-frame functions do not change the BarCount; they just squeeze the arrays so that the first N-bars are filled with NULL values and then the last part of the array contains the actual time-compressed values. This is why it is essential to expand the data back to the original time frame with TimeFrameExpand. |
The following simple exploration shows what happens after you switch to a higher time frame. Run an Exploration on the current symbol, all quotations, periodicity set to daily, and you will see how the "weekly close compressed" column contains empty values at the beginning and weekly compressed data at the end of the array.
Filter = 1;
AddColumn(Close, "Daily
close");
TimeFrameSet(inWeekly);
AddColumn(wc = Close, "weekly
close compressed");
TimeFrameRestore();
AddColumn( TimeFrameExpand(wc, inWeekly), "weekly
close expanded");
EXAMPLES
EXAMPLE 1: Plotting weekly MACD and cross arrows from daily data
TimeFrameSet( inWeekly );
m = MACD(12, 26 ); //
MACD from WEEKLY data
TimeFrameRestore();
m1 = TimeFrameExpand(
m, inWeekly );
Plot( m1, "Weekly
MACD", colorRed );
PlotShapes( Cross(
m1, 0 ) * shapeUpArrow, colorGreen );
PlotShapes( Cross( 0,
m1 ) * shapeDownArrow, colorGreen );wo = TimeFrameGetPrice( "O", inWeekly, 0, expandPoint );
wh = TimeFrameGetPrice( "H", inWeekly, 0, expandPoint );
wl = TimeFrameGetPrice( "L", inWeekly, 0, expandPoint );
wc = TimeFrameGetPrice( "C", inWeekly, 0, expandPoint );
PlotOHLC( wo, wh, wl,
wc, "Weekly Close", colorWhite, styleCandle );
Plot( Close, "Daily
Close", colorBlue ); EXAMPLE 3: Simplified Triple Screen System
/* switch to weekly
time frame */
TimeFrameSet( inWeekly );
whist = MACD(12, 26 )
- Signal( 12, 26, 9 );
wtrend = ROC( whist, 1 ); //
weekly trend - one week change of weekly macd histogram
TimeFrameRestore();
/* expand calculated MACD to daily so we can use it
with daily signals */
wtrend = TimeFrameExpand(
wtrend, inWeekly );
/* elder ray */
bullpower= High - EMA(Close,13);
bearpower= Low - EMA(Close,13);
Buy = wtrend > 0 /*
1st screen: positive weekly trend */
AND
bearpower < 0 AND bearpower > Ref(
bearpower, -1 ) /*
2nd screen bear power negative but rising */
AND
H > Ref( H,
-1 ); /*
3rd screen, if prices make a new high */
BuyPrice = Ref( H,
-1 ); //
buy stop level;
Sell = 0 ; //
exit only by stops
ApplyStop( stopTypeProfit, stopModePercent, 30, True );
ApplyStop( stopTypeTrailing, stopModePercent, 20, True );