Static Variables with multiple timeframes

I want to do this

  1. compute and store some values in static variables.
  2. Run my afl in backtest in periodicity 1 minute.
  3. Open trades from backtest in chart in 5 minutes (show current trade arrows).
  4. Expand the stored static variables and view them.

I wrote the below code but it does not work as per my needs.

_TRACE( "!CLEAR!" );
lowerThanPrevious=L<Ref(L, -1);//lower timeframe
countLowerThanPrevious=Sum(lowerThanPrevious, 5);

countLowerThanPreviousCompressed=TimeFrameCompress(countLowerThanPrevious, in1Minute * 5);
StaticVarSet("countLowerThanPreviousCompressedStatic", countLowerThanPreviousCompressed);
//TimeFrameSet(in1Minute * 5);
countLowerThanPreviousExpanded=TimeFrameExpand(StaticVarGet("countLowerThanPreviousCompressedStatic"), in1Minute);

//TimeFrameRestore();
_TRACE("countLowerThanPreviousExpanded="+countLowerThanPreviousExpanded);
Buy=1;
Sell=1;
Short=1;Cover=1;

It's hard to tell what you're trying to do, but one error that jumps out is that you should be using the same interval for TimeFrameExpand that you used for TimeFrameCompress. In your example, that means both calls should use an interval of:

in1Minute * 5

This is stated explicitly in the documentation:

The TimeFrameExpand function expands time-compressed array from interval time frame to base time frame (interval parameter must match the value used in TimeFrameCompress or TimeFrameSet )

1 Like

I want to see values of lower timeframe in higher timeframe. I am running some code that executes only during backtest (periodicity = 1 minute) and not in chart. Now I am trying to access those values of lower time frame that i have compressed and stored in static variables in this higher time frame chart (interval = 5 minutes). see below.

_TRACE( "!CLEAR!" );
statusAction=Status("action");
if (statusAction==5 || statusAction==6)
{ 
lowerThanPrevious=L<Ref(L, -1);//lower timeframe
countLowerThanPrevious=Sum(lowerThanPrevious, 5);
countLowerThanPreviousCompressed=TimeFrameCompress(countLowerThanPrevious, in1Minute * 5);
StaticVarSet("countLowerThanPreviousCompressedStatic", countLowerThanPreviousCompressed);
}

countLowerThanPreviousExpanded=StaticVarGet("countLowerThanPreviousCompressedStatic");


_TRACE("countLowerThanPreviousExpanded="+countLowerThanPreviousExpanded);


Buy=1;
Sell=1;
Short=1;Cover=1;

For the most part, I think that StaticVar Set/Get should automatically adjust for different timeframes, as long as the Set was done in the most granular (1-min in your case) timeframe. You might find this post helpful: TimeFrameSet and staticvars

From what i understand from documentation of staticVarGet, and from what you mentioned, staticvarget does the compression by itself hence no need to compress explicitly. But then the question arises as to how the compression is done? What is the mode of compression? Is it compressLast, compressHigh etc. then there is some issue of last bar not being complete. In the post linked by you bobptz has mentioned a workaround but not elaborated on it. I modified the code further, removed timeframecompress() as this is done automatically by staticVarGet(), but no luck yet.

_TRACE( "!CLEAR!" );

//this block is executed only in backtest in 1 minute periodicity
statusAction=Status("action");
if (statusAction==5 || statusAction==6)
{
lowerThanPrevious=L<Ref(L, -1);//lower timeframe
countLowerThanPrevious=Sum(lowerThanPrevious, 5);
StaticVarSet("countLowerThanPreviousStatic", countLowerThanPrevious);
}

//the below lines are read in chart of 5 minute interval
countLowerThanPreviousCompressed=StaticVarGet("countLowerThanPreviousStatic");
_TRACE("countLowerThanPreviousCompressed="+countLowerThanPreviousCompressed);

Buy=1;
Sell=1;
Short=1;Cover=1;

I would assume the compression is done using the default mode, which is compressLast. I don't have 1-minute data readily available, but I tested your code by running the backtest on daily data and set the chart to Weekly. It appears to me to be working correctly. You'll need to show some examples of your output if you think it's still not working for you. It might be easier to run an Exploration on 5-min data instead of using the chart to validate how the compressed static variable is retrieved, because then you can easily see all of the numeric values rather than printing them one at a time with _TRACE or looking at a plotted line.

I have uploaded a 1 data minute file here https://file.io/52LFY7MYwazE

When I tried exploration The result is INCORRECT. see below

exploration1min

exploration5min

code (NOT WORKING) with exploration statement

_TRACE( "!CLEAR!" );

//this block is executed only in backtest in 1 minute periodicity
statusAction=Status("action");
if (statusAction==5 || statusAction==6)
{
lowerThanPrevious=L<Ref(L, -1);
countLowerThanPrevious=Sum(lowerThanPrevious, 5);
StaticVarSet("countLowerThanPreviousStatic", countLowerThanPrevious);
}

//the below lines are read in chart of 5 minute interval
countLowerThanPreviousCompressed=StaticVarGet("countLowerThanPreviousStatic");
_TRACE("countLowerThanPreviousCompressed="+countLowerThanPreviousCompressed);


filter = 1; 
AddColumn( countLowerThanPreviousCompressed, "countLowerThanPreviousCompressed" ); 

    
Buy=1;
Sell=1;
Short=1;Cover=1;

I have re-uploaded the data file to a different location. try this link
https://easyupload.io/7ksyy5

aasettings

settings

I think it's working, just not how you expect. The compressed 5-minute bar with timestamp 9:20:00 covers the 5-minute span from 9:20:00 - 9:24:59. The compressed value from the end of that time span is the one shown in the 1-minute exploration with a timestamp of 9:24:00, and has a value of 2.

Similarly, the compressed bar with timestamp 9:25:00 covers the span 9:25:00 - 9:29:59. The value from the 1-min exploration with timestamp 9:29:00 is 3, which matches the 9:25:00 value in the 5-min exploration.

You can control the timestamp for compressed intraday bars from the Intraday tab of the Preferences window, as shown below. The recommended value is also the default: START time of interval. If you change that to END time of interval, then the value in the 5-min exploration with timestamp 9:24:59 will match the value in the 1-min exploration with timestamp 9:24:00. However, there may be other repercussions from changing that setting; I don't do enough work with intraday data to be sure.

image

3 Likes

That is an excellent observation mradtke. Let me try. I shall report back. Thankyou for helping me.

Yes I checked. You are right. It is working if change the settings. However there are severe consequences. The timestamp on bars on the chart are all incorrect now.

Now I need to find a way to

  1. change the compression mode from default compressLast to compressHigh.
  2. access static variables stored in other time frames other than base interval. These are intervals lower than the chart interval. For example If i were to use my example I want to access values stored in 1minute, 90 Seconds, 100 Seconds, 135 seconds in 5 minute chart. We have achieved accessing values stored in 1 minute in the above example but how to access others because those require timeframeSet(), TimeframeRestore().

here is the updated code

_TRACE( "!CLEAR!" );

//this block is executed only in backtest in 1 minute periodicity
statusAction=Status("action");
if (statusAction==5 || statusAction==6)
{
lowerThanPrevious=L<Ref(L, -1);
countLowerThanPrevious=Sum(lowerThanPrevious, 5);
StaticVarSet("countLowerThanPreviousStatic", countLowerThanPrevious);

TimeFrameSet(2*in1Minute);
lowerThanPrevious=L<Ref(L, -1);
countLowerThanPrevious=Sum(lowerThanPrevious, 5);
TimeFrameRestore();
countLowerThanPrevious2MinExpanded=TimeFrameExpand(countLowerThanPrevious, 2*in1Minute);
StaticVarSet("countLowerThanPrevious2MinExpanded", countLowerThanPrevious2MinExpanded);

TimeFrameSet(5*in1Minute);
lowerThanPrevious=L<Ref(L, -1);
countLowerThanPrevious=Sum(lowerThanPrevious, 5);
TimeFrameRestore();
countLowerThanPrevious5MinExpanded=TimeFrameExpand(countLowerThanPrevious, 5*in1Minute);
StaticVarSet("countLowerThanPrevious5MinExpanded", countLowerThanPrevious5MinExpanded);

}

//the below lines are read in chart of 5 minute interval
//StaticVarGet() performs compression (if needed) implicitly in compressLast mode. How can i change this such that compression happens in compressHigh mode instead?
countLowerThanPrevious1MinCompressed=StaticVarGet("countLowerThanPreviousStatic");
countLowerThanPrevious2MinCompressed=StaticVarGet("countLowerThanPrevious2MinExpanded");
countLowerThanPrevious5MinCompressed=StaticVarGet("countLowerThanPrevious5MinExpanded");

lowerThanPrevious=L<Ref(L, -1);
countLowerThanPreviousThisInterval=Sum(lowerThanPrevious, 5);

_TRACE("countLowerThanPreviousCompressed="+countLowerThanPrevious1MinCompressed);
_TRACE("countLowerThanPrevious2MinCompressed="+countLowerThanPrevious2MinCompressed);
_TRACE("countLowerThanPrevious5MinCompressed="+countLowerThanPrevious5MinCompressed);
_TRACE("countLowerThanPreviousThisInterval="+countLowerThanPreviousThisInterval);

filter = 1; 
AddColumn( countLowerThanPrevious1MinCompressed, "countLowerThanPrevious1MinCompressed" ); 
AddColumn( countLowerThanPrevious2MinCompressed, "countLowerThanPrevious2MinCompressed" ); 
AddColumn( countLowerThanPrevious5MinCompressed, "countLowerThanPrevious5MinCompressed" ); 
AddColumn( countLowerThanPreviousThisInterval, "countLowerThanPreviousThisInterval" ); 
   
Buy=1;
Sell=1;
Short=1;Cover=1;

I am looking for a way to compressHigh with StaticVarGet() or a workaround.

Seems to me that you should be able to perform a TimeFrameCompress to 5-min bars with whatever compression mode you want, then do a TimeFrameExpand back to the base time interval, then store your static variable. That way when StaticVarGet does its automatic compression with mode compressLast, you'll be getting the right value in your chart.

Also, you should be able to use whatever timestamp method you prefer (sounds like START time of interval is better for you), and use Ref(...,-1) on the compressed array to shift things to the next interval if that's what you want.

But compressLast will only keep the last bar within that interval. So for example value of array on 1st, 2nd bars is 0 and in 3rd bar it is 1 and bar 4 and 5 the value is 0 then if i compressLast i will get 0 whereas if i compressHigh i shall get value 1 which is what i want. I still don't know how to fix this.

Something like this (not syntax checked):

lowerThanPrevious=L<Ref(L, -1);
countLowerThanPrevious=Sum(lowerThanPrevious, 5);
countLowerThanPreviousComp = TimeFrameCompress(countLowerThanPrevious, in5Minute, compressHigh);
countLowerThanPrevious = TimeFrameExpand(countLowerThanPreviousComp, in5Minute, expandLast);
StaticVarSet("countLowerThanPrevious", countLowerThanPrevious);

But the calculation would have to be done inside timeframeSet()...timeframeRestore() block else the values will be wrong.