Unable to fetch the correct Previous Day close Price from 5 min Timeframe

Hello @nsm51 ,

Below excerpt from my initial post.

Dint include that code, though I have tried it already and dint get the actual daily close price.
Thanks anyways.

Karthik P

Hello @nsm51,

For now, I have changed the Intraday Settings - Trading Hours timing to 15:34 instead of 15.29 and that seems to address the issue. I have checked couple of symbols and it seems fine - fetching the actual previous day close.
Will post if i see any discrepancies. If i still face an issue, I have to resort to populating an artificial tick for 4 PM, as you have mentioned in the other post.

Thanks for your inputs.

Thanks,
Karthik P

1 Like

15:29 would be incorrect, should be 15:30 or higher but all the methods if understood and used properly should sort the issue. Next time if you have different data vendor, you can use another fix.

another note is AB has groups (symbol > categories) from there each group can set its own intraday settings.
The global one you have used can then break Forex and MCX ( just fyi :slight_smile: ) in same DB

1 Like

Thanks @nsm51. I have set it as 15:35 now and validating/testing.
Appreciate your time & inputs.

1 Like

That is totally wrong code. Please DO READ instructions CAREFULLY:
https://www.amibroker.com/guide/h_timeframe.html

TimeFrameCompress is used wrongly.

@karthikeyanp: Many thanks for raising this question. Coincidentally enough I was also facing the same problem.

@brajeevn: Looking at your code

TimeFrameSet( C,inDaily );
	 PDH =  TimeFrameGetPrice( "H", inDaily, -1 );
	 PDL =  TimeFrameGetPrice( "L", inDaily, -1 );
	 PDC =  TimeFrameGetPrice( "C", inDaily, -1 );
TimeFrameRestore();

The TimeFrameSet function only accepts one parameter, not two.
When I tried the corrected version in chart AFL, as follows, it still doesn't work:

TimeFrameSet(inDaily);
CDC = TimeFrameGetPrice( "C", inDaily);
PDC = TimeFrameGetPrice( "C", inDaily, -1);
PPDC = TimeFrameGetPrice( "C", inDaily, -2);
_TRACE(ticker + ": CDC " + CDC + ", PDC " + PDC + ", PPDC " + PPDC);
TimeFrameRestore();

@MESZ23: CDC 4573.75, PDC 0, PPDC 0

Looking at the page quoted by @Tomasz: the function TimeFrameGetPrice is not used:

TimeFrameSet(in5Minute); // switch to 5 minute frame
ma5_13 = MA( C, 13 );
TimeFrameRestore(); // restore time frame to original

However, using the following seems to work:

TimeFrameSet(inDaily);
CDC = C;
PDC = Ref(C,-1);
PPDC = Ref(C,-2);
_TRACE(ticker + ": CDC " + CDC + ", PDC " + PDC + ", PPDC " + PPDC);
TimeFrameRestore();

Update to my reply.

The above works, so long that no bar is selected on the intraday screen in which case the Close for the current day and the previous day are displayed. That is: C and Ref(C,-1) taken from the daily timeframe, as expected.

However, if for example the 2nd last bar is selected on the intraday, the Close for the previous day and the day before that are displayed. That is Ref(C,-1) and Ref(C,-2) taken from the Daily timeframe, instead of displaying C and Ref(C,-1) as before.

In summary:

Selected bar on intraday TF     Current C on day TF     Previous C on day TF
last (or none)                  C                       Ref(C,-1)
-1                              Ref(C,-1)               Ref(C,-2)
-2                              Ref(C,-2)               Ref(C,-3)
-3                              Ref(C,-3)               Ref(C,-4)

The behaviour is consistent with AB, that is why TImeFrameExpand() is there to align Higher TF with the lower one when it is required.
So it is up to individual to understand whether expansion is required or not in proper context.

Hello @nsm51 ,

Thanks for the reply. In the meantime I discovered that the following also works, without the surrounding TimeFrameSet() and TimeFrameRestore():

  CDC = TimeFrameGetPrice( "C", inDaily);
  PDC = TimeFrameGetPrice( "C", inDaily, -1);
1 Like

This is the intended way to use but this whole thread and the other one is about some edge cases where the exchange or data vendor sends last ticks that are not aligned because of different "last" timestamps in post-closing session.

Also OP had mistakenly set the wrong closing time in intraday settings for the exchange there by losing last tick, so OP has mentioned/corrected that.

2 Likes

(Kicking up the topic just in time)

I'm trying to get PDC and PDH as a line in a chart.
As for PDH, thanks @polomora , this displays the line, but not quite as wanted:

PDH = TimeFrameGetPrice( "H", inDaily, -1); 
Plot(PDH, "PDH", colorLightBlue, styleThick | styleNoRescale);

My problem is, that when calculating Daily High it uses data from the whole day, whereas I would like it to use only the trading hours as set in intraday settings, regardless of what times I have displayed. I have tried several settings, but it seems to me that the only way to get Daily High calculated within trading hours is to display trading hours only, but that's not what I want to do.
Example (CET):
capture_001_12022024_124106

I drew the yellow line to show what I would like the blue line to do.
Am I mising a setting or can this not be done?

As for PDC, thanks @PeterD , Valuewhen() works for PDC and solves this problem (but this obviously does not work for PDH):

TimeFrameSet(in1minute);
PDC = ValueWhen(TimeNum() == 215900, C,  1);
TimeFrameRestore();
Plot(TimeFrameExpand(PDC, in1Minute, expandLast),"PDC",colorRed, styleLine | styleNoRescale); 

The only (minor) problem here is that it does not show up in timeframes that do not have a bar ending 215900 (currently 4min and 60 min). But as I have many timeframes open, I can live with that.

Any suggestions, especially regarding PDH, will be appreciated.

That depends on FILTERING that you have enabled in the VIEW menu.
If you have no filtering (24 hours) then it would use all data.

It is all described in the KB:

AFL functions always work WITHIN selected context. So if your chart is NOT using filtering, then AFL functions would also use no filtering.

OK thanks. Filtering through the view menu would help. (Better than changing the database settings all the time).
It would be cool though if in the future this could be done both at the same time: Full day view, and at the same time have daily values calculated according to trading hours.

You could also use SparseCompress() and SparseExpand() to filter out non-RTH bars while in 24hr mode.

For the missing closing bars, you can get a little more sophisticated with ValueWhen() so that you don't pinpoint a certain time, but look for a time that is greater than the time before the scheduled close and less than the time after the scheduled close. This way, if the market closes early like on a holiday the code would return the last price during RTH. This is obviously more complicated than simply using RTH filtering. It also adds complexity and CPU time to the charts.

The bar alignment issue is harder to tackle so I just avoid it.

Personally I use an exploration using daily bars and Tomasz's way of using day filtering and I save the prior day data, along with some other stats, as persistent static variables, so that my charts can look them up quickly. This way I calculate all my daily data once in the morning and my charts just look up the data all day, regardless of bar alignment, etc.

Just look at old threads .
It has been posted several times already.

daysback = 2;
SetBarsRequired(daysback*inDaily/Max(1,Interval()));

tn = TimeNum();
time_window = tn >= 93000 AND tn < 160000;
session_start = time_window AND NOT Ref(time_window,-1);

prev_high = Ref(HighestSince(session_start, H, 1), -1);
prev_high = ValueWhen(session_start, prev_high);

prev_low = Ref(LowestSince(session_start, L, 1), -1);
prev_low = ValueWhen(session_start, prev_low);

Plot( C, "Price", colorDefault, styleBar );

Plot(prev_low, "prev session LL", colorRed, styleStaircase);
Plot(prev_high, "prev session HH", colorGreen, styleStaircase);
1 Like

Thank you both for your help, I will look into it.

@fxshrat
It gives strange results. Partly because the 'switch' (when the line changes) happens at the opening bell, whereas it should switch at the end of the trading session (as soon as the High is a fact), not at the beginning.
After the opening, it gives as PDH the highest value of the preceding 24 hours, not the high of the previous RTH trading session. So at times this is a high occurring in the overnight (European day) session, not the high of the RTH trading hours.
At times, during the European day, it looks back two days, not one. (e.g.MESH4 feb 1 before opening), or it gives the high of the previous overnight session.
I tried changing a few things in your code, but so far I did not succeed.

@PeterD
So far, I could not construct anything workable with SparseCompress.

The best thing I can do is use Tomasz' way, using View>Filter in the morning, draw my lines, and then switch back to 24 hrs.

It is not strange. The code is supposed to draw the previous session's high and low but not high and low of current session! So it does not look into future.

So of course at the start of current session it starts to plot extremes of previous day's session.

But there was code missing in previous post:

for ( i = 0; i < 4; i++ ) {  
  field = StrExtract("O,H,L,C", i);
  VarSet(field, IIf(time_window, VarGet(field), Null));
}

Of another threads code

So updated code

daysback = 2;
SetBarsRequired(daysback*inDaily/Max(1,Interval()));

tn = TimeNum();
time_window = tn >= 93000 AND tn < 160000;
session_start = time_window AND NOT Ref(time_window,-1);

for ( i = 0; i < 4; i++ ) {  
  field = StrExtract("O,H,L,C", i);
  VarSet(field, IIf(time_window, VarGet(field), Null));
}

prev_high = Ref(HighestSince(session_start, H, 1), -1);
prev_high = ValueWhen(session_start, prev_high);

prev_low = Ref(LowestSince(session_start,Nz(L,1e9), 1), -1);
prev_low = ValueWhen(session_start, prev_low);

// PLOT SESSION PRICE ONLY
Plot( C, "Price", colorRed, styleBar );

RestorePriceArrays();// Restore Price arrays #############################################################

// PLOT ALL PRICE
Plot( C, "Price", colorDefault, styleBar );

Plot(prev_low, "LL", colorRed, styleStaircase);
Plot(prev_high, "HH", colorGreen, styleStaircase);

And here is picture where you can see that it plots previous dession high low at current session.

If you want to draw from previous session's end then you have to add variable session_end.

daysback = 2;
SetBarsRequired(daysback*inDaily/Max(1,Interval()));

tn = TimeNum();
time_window = tn >= 93000 AND tn < 160000;
session_start = time_window AND NOT Ref(time_window,-1);
session_end = NOT time_window AND Ref(time_window,-1);

for ( i = 0; i < 4; i++ ) {  
  field = StrExtract("O,H,L,C", i);
  VarSet(field, IIf(time_window, VarGet(field), Null));
}

prev_high = Ref(HighestSince(session_start, H, 1), -1);
prev_high = ValueWhen(session_end, prev_high);

prev_low = Ref(LowestSince(session_start,Nz(L,1e9), 1), -1);
prev_low = ValueWhen(session_end, prev_low);

// PLOT SESSION PRICE ONLY
Plot( C, "Price", colorRed, styleBar );

RestorePriceArrays();// Restore Price arrays #############################################################

// PLOT ALL PRICE
Plot( C, "Price", colorDefault, styleBar );

Plot(prev_low, "LL", colorRed, styleStaircase);
Plot(prev_high, "HH", colorGreen, styleStaircase);

Then it would look like this

2 Likes

This does the trick! Thank you very much! You made my day!
Your last code is indeed what I had intended.

I (experimentally, as a guess to be honest) added the PDC, in an attempt to solve the alignment problem with my own PDC code (see above).
I added this to your last code:

prev_close = Ref(C, -1);
prev_close = ValueWhen(session_end, prev_close);

Plus the according Plot line:

Plot(prev_close, "CC", colorBrightGreen, styleStaircase | styleNoRescale);

It worked, and it partially solved the alignment problem on 4min and 60min charts. Partially, as although the CC (=PDC) line does appear in the 4 and 60min charts, it just 'rounds' it to the nearest bar end. On a 60 min chart this can mean a 30min deviation from the real Close of that day.
Do you see a solution to this?