Exporting optimization results automatically from my AFL code

Hi guys,

I know how to export manually my optimization results to a CSV file using File->Export HTML/CSV. I would like to do it automatically with my AFL code, but I am getting confused.

I don't want to run my AFL code automatically, using a batch or via OLE, but run it manually beeing the results saved in a CSV file automatically by my AFL code.

Searching information to approach that, I have found a lot of things about how to save results using "AnalysisDoc" object via OLE and one JScript example, but I don't see how to access to "AnalysisDoc" object directly from my AFL code. I mean, if I want to access to the "Backtester" object I can use GetBacktesterObject function, but I don't know how to do that with "AnalysisDoc" object directly from my AFL code (if it is possible).

I would appreciate some guidance on this.




Maybe the File functions could be a starting point. Also, there are probably alot of examples.

fputs(), fopen(),fclose(),fgets().


Thanks @Anthony. I have found some interesting examples there, but my doubt is more referred to how to access the results than how to manage file functions to store its info.

Those examples show how to store specific data but I haven't found one to save the analysis results as a whole, as I think it can be done via OLE and a Script. I would like to know if it could be done directly running an AFL code, too.


You do not need OLE to export result list after optimization.

You just need to save AFL to project file (APX).
Then create batch (file) as seen below.

First "Load project",
then insert "Optimize" action step,
then insert "Export to file" batch action (specify path of CSV or HTML file to be exported to).


Then run batch.
In upper batch link of manual also see ShellExecute() command to run batch file (on param click or interval...).

// from batch manual 
if( ParamTrigger("batch", "run me" ) )
    ShellExecute("runbatch", "path_to_batch_file.abb", "" );

To read/extract results via AFL after Optmization you can then use file functions to read through CSV file.

On the other hand (and as aside) to export backtest report of each optimization step then you may enable it via SetOption field plus value. Three modes (0,1,2) for field "GenerateReport" are available.

SetOption("GenerateReport", 2 ); // enable generation of full report 

Reports are in report folder then and you can view them in Report explorer of Analysis window (in realtime step after step).

Note: Optimization will run longer then.


@fxshrat, thank you very much for responding.

I found your tool for visualization of optimization results, that is a lot of interesting and useful to me. As I am doing manually the same optimization (of two parameters) for a group of watch lists (one by one), I wondered if I could automate this process, saving the optimization results (for each watch list), and then check them with your tool.

I didn't think about using a batch for this because - if I am not mistaken- I couldn't change from one watchlist to another in that process (before saving results). That's why I think about the possibility to use OLE if it was not possible to do it directly with an AFL code.

I want to take this opportunity to thank you for your interventions. They are very enriching for me and thanks many of these I constantly resolve doubts without having to ask in the forum.


I have activated my brain cells for few minutes and (after having checked AB devlog)
I came to realization that switching WL symbols with same project (automated -
as you want to do) can be done via batch too. You still do not need OLE. You would just need minimum AB 6.31/6.35. Will explain how the idea works when I'm back home. Actuallly it should be quite simple without any AFL or OLE code.


We have tested my idea in 6.35 and it works indeed. Again not a single programming code required (just file format code).

So let's say you have single project file and several WLs that you want to test with that project sequentially... Solution as mentioned... batch feature.

Now important action... first you need to export your WLs to file (e.g. tls file).
So in Symbols window right click each of your WL you want to include in same analysis project test and choose "Export" in context menu for each one of them:
Now in next appearing export window name them e.g. list0, list1, ..., list10, ... or whatever.

Next you need to create format file (e.g. name it TLSimport.format) to be placed to Formats folder.
Note: in below format code you can see defined WL 63. That sample WL is used for all exported WLs (tls files). You can specify different one (WL number) but it has to be same one in all further actions.

Single format file needed only (so don't create multiple ones. it is needed just single one):

$FORMAT Ticker, Skip, Skip, Skip, Skip, Skip, Skip
$GROUP 255

Now create project file and in Apply to: Filter window choose same sample WL 63 (or your own one).
Then save project file after everything is set.

Next we create batch (and save it). Picture below shows batch of two WL changes. You may add more (as much as you want -> e.g. same as number of existing TLS files). You just need to add commands: "Clear watch list", "Data import ASCII" with path to TLS file and parameter of format file location, "Optimize" command and then "Export to file" with path and separate CSV file name for each result list export. So four batch commands per each WL. (Project needs to be loaded just once at start of batch).


When you choose "Data import ASCII" action to browse to WL symbols file then choose Files of type -> All files so that you can find your saved TLS files on HDD.


When batch is finished then save it and run it (via whatever method).

That's it.

If you have dynamically changing WLs then you could possibly use TLS files of DataBase's subfolder WatchLists. But you would have to add "Save DataBase" batch command before each "Data Import ASCII" command. Not tested though!


Great! Thank you very much @fxshrat. I really appreciate the detail of your explanation. Tomorrow I will update my version of AmiBroker and try to do it following your instructions.

Hi @fxshrat,

I understand your idea and I am very clear that it works.


I have not managed to replicate it because the batch ends and generates the files... but without data. This is the notice that appears:


If I click in "Details" nothing appears but, since this is the first time I am using the batch, I may be making a mistake with my TLSimport.format file. I've tried it in different ways but I can't load the symbols.

I have found more topics in the forum about this type of files (new to me), so I will take a look at them to identify my mistake.

Thank you very much. This is a very good solution for my purposes and I am sure it will work perfectly. I'll let you know when I get it to work.

1 Like


There are three possible reasons for that analysis message (which means that no symbols are available to be analyzed):

  1. Either you have defined "incorrect" Filter in Analysis project (e.g. not the same WL as of other batch actions and one being empty).

  2. Or your TLS files are empty (because original WLs they were created from are empty).

  3. Or WL of format file is not right one (not the same one as of other actions) or no WL to import to is defined.

Investigate all three possibilities.

That being said... batch method has worked in our tests and CSV files were not empty and had different optimization result list content.


Hi @fxshrat,

Thanks for your comments and suggestions. I am trying to find my mistake.

My selected list in the filter is not empty.



However, every time I run the batch it becomes empty. I guess it is done by "clear watch list" instruction. I will look for it in the forum and the documentation to make me sure.

Checking my LTS files, both have symbols.



I think probably my TLSimport.format file is wrong. This kind of files are new to me, so today I will spend more time to deeply understand how they work (I think that is precisely my problem).


At first sight, I see I have "," as separator, when my LTS files haven't any comas inside.

I want to emphasize that I have no doubt that your idea works. I am sure that, for my lack of knowledge about this, I am not executing it well.

Thanks again,


Since your Filter settings are not visible entirely... but your WL 63 not being empty... so the issue appears to come from that analysis settings of yours.

Please set Filter settings the very same way as I did in my picture (also in same order of categories).. so please click "Clear" button in Filter window (also click "Clear" in "Exclude" tab). Then set WL 63 right of "Watch List" of "Include". Then save project and re-run batch.

1 Like

Hi @fxshrat,

Thanks for your time and patience.

I have done it, as you can see below... but I have the same problem.


I have done some tests without good results, too.
I see in "Import ASCII" documentation that "$WATCHLIST" command has a number argument (as I see in your ".format" file example, too). I wonder how does AmiBroker know that number 63 is precisely my named "List 63". I have seen this list has a number "576" before his name.


I have tested your idea again, modifying the TLSimport.format file with "$WATCHLIST 576", but I get a different error, as you can see.


It could be possible your "List 63" Watch list has the "63" number? In that case, I will try with another Database for tests, since I am a little afraid modifying Premium Data Watch Lists.

Thanks again. I really appreciate your help.

So we have finally found out your mistake. Name is irrelevant. You have to take care of having same number. Renaming list to "List 63" does not make it number 63. It keeps number 576 in your case. So if you want to do test with your Norgate DB then instead of using number 63 use number 576 for all batch actions.

As I wrote it does not matter which number it is. It just has to be same one for all batch steps (see my picture of batch window).

Yes, I have referred to WL number always. It has to be same number for all batch actions but not name:

This is just a guess but it could be that only numbers 0 to 63 are supported for import. But it is not fact. Tomasz knows reason for sure. Add a "Pause" action after each existing batch step and tell were crash window shows up (click play button after pause where there is no crash). It could also be out of memory issue. As I said rather ask @Tomasz about that one ( send crash report to technical support).

1 Like

First, in Premium Data databases watch lists are managed by Premium data. They will be overwritten by Premium Data updater.
Second import file is incorrect. There are no 7 fields in the TLS file. Just one. Your $FORMAT is bad.
Thirdly there is a dedicated tool for watch lists import see http://www.amibroker.com/guide/h_watchlist.html
Fourth - I see no reason to export watch lists then import them.
Fifth - you need to press "Copy to clip" button in Crash recovery and send the report as text, not screenshot.

All this wrestling seems redundant and unnecessary.

What you should do is to:

  1. Setup a number of Analysis projects .APX that have Filter set to each watch list you want to optimize
  2. Just use batch: Load Project / Optimize / Export results

No need to do watch list wresting.


FYI, format file has been created by ASCII Import WIzard so it has not been done any modifications other than removing comment created by wizard

# Format definition file generated automatically
# by AmiBroker's ASCII Import Wizard

So here is Format update:

$FORMAT Ticker

I do not understand what is bad about "Skip". If you have file with Date,O,H,L,C columns then you would have to add two times skip in import wizard too. So do you mean to say every time after format file creation by Import Wizard you would have to modify format file manually to remove skip in format file because it is bad to have it in there?

I kind of agree. But as aside multiple people I recommended that way in past didn't like that (and asked "But how can we do with just one single project file?"). :tired_face:

1 Like

The wizard is intended to import QUOTES, not watch lists. That is why it has minimum of 7 columns (Name/Date/OHLCV). It wasn't ever designed or intended to import watch lists.

There is nothing "wrong" with "Skip" except that it just adds unnecessary work for the parser.

And no, you don't need to modify import definition file manually. There is "Additional commands" field in the wizard where you can just type

$FORMAT Ticker

Anything that you type in Additional commands goes after what wizard creates and as such overwrites previous values.

Just because people don't like things done properly does not mean that they should do things improperly. In the long run initial (sometimes "harder") work gives better results.


Hi guys,

Thank you very much for your comments.

I am sorry. You said it clearly but I did not interpret it correctly due to my lack of knowledge about this. I realized that searching within the documentation. Your solution is perfect for me. Even more, is better than I was expected. I will save a lot of time.

Now it works without any problem. It works even using list number 576. The crash message was my fault.

Thanks a lot again. Thank you very much.

Thanks for your comments, too. @fxshrat's solution is very good for me in this case, but I understand what you mean. I will work with a considerable bunch of ".TLS" files that will remain untouchable. Nevertheless, I will be doing modifications to may .apx file for sure. This way is better for me to modify only one file than a bunch of them. I need only one watch list (few seconds to be created) to load different groups of symbols, so I am not worried about the Premium Data update (but I appreciate your comment because I didn't know it).

Yes, I have used it manually every time the batch make my "list 63" empty (to reload his symbols) :sweat_smile:

It was my fault. I sent you yesterday the crash report, but have seen it was my error. I left "$GROUP" command blank, when testing. When I tried to run the batch with my list number 576, I forgot to fix it in my .format file.

Thanks a lot.

1 Like