Same result. In fact, even the Barcount variable does not change, although, from the refreshed chart display, the update is clearly working. Maybe @Tomasz can shed some light on why the internal amibroker arrays are not growing, as expected, while an afl script that runs Amiquote to add new quotes is executing.
@SwingTradeMonkey,
You do not mention anything about where you run your code but I suppose you run from chart pane. Also you just posted code snippet only.
But you should read following Knowledge Base article to understand what QuickAFL means
http://www.amibroker.com/kb/2008/07/03/quickafl/
Everything is there.
Just print LastValue BI
last_bi = LastValue(BarIndex());
printf( "%g", last_bi );
It doesn't matter whether you import additional quotes -> the original bar range (of chart) with QuickAFL enabled remains the same one as before import. Since chart's bar range remains the same as before barindex remains the same too.
Think about it... will previous chart range change just because of import. No, it won't (if not zoomed out completely). Import does not cause auto zoom out to include previous first visible bar of before import. So why should Barindex change (with QuickAFL enabled) if chart range remains the same one as before?
LastValue(BarIndex) will change after import if you disable QuickAFL via SetBarsRequired (also mentioned in upper article) or if you scroll to the very left of the chart (since LastValue() calls last index of array).
BarIndex may not change after import because BarIndex refers to AFL array, not to the database. As long as zoom level is kept constant you will just get the same number of bars displayed on chart and they will just be more recent. BarIndex() in that case will not change as QuickAFL uses only needed bars, not all. What you should be looking at is a TIMESTAMP of last bar
DateTimeToStr( LastValue( DateTime() ) );
@Tomasz After Amiquote import finishes, my chart's last displayed bar date changes from 7/17/2018 to 1/31/2019 (as expected) when the chart refreshes. However, the before import and after import result values for DateTimeToStr( LastValue( DateTime() ) );
remain identical while in the script that executed the import.
So, within the same executing script, and after Amiquote finishes it's import, is there any way to obtain the updated value from the Datetime() array?
Additional Information:
If the last date value imported is not current*, then I am adding the ticker to an exclusion list to prevent re-attempting the update, because it is likely the ticker is no longer valid.
*By current, I mean the last trading date available, excluding holidays and weekends.
@fxshrat - I execute this script to import a single quote within a chart, along with some added support code. I receive same before import and after import value for LastValue(BarIndex) after effectively disabling Quickfill by adding this to the top of my script:
SetBarsRequired( sbrAll, sbrAll );
It occurs to me that while executing, the AFL arrays (datetime() or BarIndex do NOT dynamically update.
Also, please see my reply to tomas' comment regarding the datetime() array.
Is there an alternate SetBarsRequired setting I should use?
Wrong! I don't know what exactly you are doing on your end. BUT it is definitely not the same last barindex received after import (if QuickAFL is disabled).
Watch below few seconds long video carefully from start to finish! (The barindex will change at second 7 of video.)
Also last date time with QuickAFL enabled does update! (of course it will also update if QuickAFL is disabled)
Watch! (it will change at around second 7 again)
You are apparently not using the actual script on chart.
Right click chart pane and choose "Edit Formula" and check your script.
(And BTW it is not called Quickfill but QuickAFL.)
This is the code I was using
/// https://forum.amibroker.com/t/how-to-specify-the-download-site-for-amiquote-in-batch-processor/1877/12
if( ParamTrigger( "Download", "Now" ) )
{
/// @link file:///C:/Program%20Files/AmiBroker/AmiQuote/ReadMe2.html
AQ = CreateObject( "AmiQuote.Document" );
AQ.AddSymbols( Name() );
// AQ.Source = 0; // change as needed
AQ.From = "2019-01-30 00:00:00";
AQ.To = Now();
AQ.AutoImport = True;
AQ.Download();
while( AQ.DownloadInProgress() OR AQ.ImportInProgress() )
{
ThreadSleep( 250 );
}
}
//SetBarsRequired(sbrAll);// disables QuickAFL
//last_bi = LastValue(BarIndex());
//printf( "last barindex: %g\n", last_bi );
printf( "QuickAFL enabled!\n");
printf( "last datetime: %s", DateTimeToStr( LastValue( DateTime() ) ) );
Bottom line. Listen to what advanced people say instead of questioning it. I am not posting here for making pranks!
BTW, OLE works on first instance only! So make sure that you actually import to first AB instance!
@fxshrat Fantastic proof! Thank you for posting the video.
I am running the script as a study / technical indicator. I have inserted the script onto a chart pane. I then invoke the script from the chart pane. If you do the same, does the trace statement output two different timestamp dates (assuming the onscreen last bar is outdated before invoking the script) for you? For me, i only get the same (pre-import) date for both trace statements.
if( ParamTrigger( "Download", "Now" ) )
{
SetBarsRequired( sbrAll, sbrAll );
_TRACE("AFL - Before Import Last Value Timestamp " + DateTimeToStr( LastValue( DateTime() ) ));
/// @link file:///C:/Program%20Files/AmiBroker/AmiQuote/ReadMe2.html
AQ = CreateObject( "AmiQuote.Document" );
AQ.AddSymbols( Name() );
// AQ.Source = 0; // change as needed
AQ.From = "2019-01-30 00:00:00";
AQ.To = Now();
AQ.AutoImport = True;
AQ.Download();
while( AQ.DownloadInProgress() OR AQ.ImportInProgress() )
{
ThreadSleep( 250 );
}
_TRACE("AFL - After Import Last Value Timestamp " + DateTimeToStr( LastValue( DateTime() ) ));
}
Note that I run the _Trace statement inside the If(ParamTrigger) section.
Looks like you were replying at the same time as I was. Here is my late reply...
Your _TRACE statement is inside the IF braces and only gets executed once when you trigger the download. The chart needs to refresh after importing data and _TRACE does not execute again to report the new value.
Try moving _TRACE to the end, outside of the braces. I don’t think there is any way to retrieve the newest data without a refresh.
@fxshrat Yes, you are correct! I have my Lastvalue(Datetime()) test inside of an if statement that runs only once when the import occurs. That explains why the timestamp was not updating. I'll update my code. Thanks again for your prompt and very helpful response!
Your code is plain and simply wrong.
Do NOT ever busy wait inside AFL formula. That is wrong and should never be done.
Instead you should setup timed refresh (RequestTimedRefresh()) and do whatever you want NEXT TIME it gets refreshed.
You also should NOT be calling SetBarsRequired inside conditional. This is wrong too.
Also you should NOT be calling AmiQuote from AFL. It is conceptually wrong. If you absolutely MUST do this for unknown reason, simply start the download and that's all.
DO NOT BUSY WAIT. Chart will be automatically refreshed when download and import finishes.
I already gave you correct formula here but for some reason you started to "improve" it. There is nothing to improve.
// the idea is flawed, but if you really must trigger AmiQuote from AFL
if( ParamTrigger("download", "Now") )
{
AQ = CreateObject("AmiQuote.Document");
AQ.AddSymbols( Name() );
AQ.AutoImport = True;
AQ.Download(); // just let the damn thing work in its own pace, don't wait!
}
// when new data are imported your chart will be
// automatically refreshed without ANY code
Again: busy waiting is PROHIBITED. Formulas MUST NOT wait for anything.
If you need time out just set up the timer (RequestTimedRefresh) and let the formula FINISH.
At the end one fundamental thing - the whole idea of triggering AmiQuote downloads inside AFL formula is a BAD idea. What you are doing now is using hammer for eye surgery. For heavens sake use correct tools. Eye surgery is better done with precise laser. If you need automation, use correct tool, i.e. batch processor http://www.amibroker.com/guide/h_batch.html or external script.
@thomas Again, I thank you for your thoughtful insight. I will clean up my code as you suggest. My reason for calling Amiquote from AFL was to facilitate obtaining the most recent quote for the symbol I am displaying, without me having to click anything. My management code adds a check on the last datetime() , and if it is outdated (by a few days) the data is automatically retrieved via Amiquote, or alternatively, I can invoke the ParamTrigger, and the data is immediately retrieved. I have other code to prevent the attempt to invalid tickers. It works well and saves me lots of time.
What I wrote still applies.
If it is just for "daily" update you should be using single click Tools->Auto update quotes menu. This can be triggered by batch on AmiBroker startup.
If automatic updates during the day are needed you should be using data source that delivers data for all symbols in one request such as Tiingo Current. This plus "Run every" feature that AmiQuote has built-in would give you constant updates without clicking anything.
Or (better) use real time data source via plugin http://www.amibroker.com/guide/h_quotes.html
Great information @beppe. Just trying to figure out how to automate the process of downloading my historical EOD quotations through Yahoo finance using an automated script. Since I have multiple TLS files, what would be the best way to automate it so that it starts the next TLS file automatically. My apologies as I'm still a rather novice programmer and there's a definite learning curve to all of this (a bit of info overload). Visual guides are often easier for me to follow and I wish there were more videos to explain concepts here, so it may take longer for me, but I'll try to adapt accordingly. Any advice is always apopreciated.
Actually, on further review, I think the simplest way is likely through the batch processor along with the scheduler........Amazing, each day I'm learning more and more useful tools. This truly is a program built with the end-user in mind.