Using eTables with Amibroker

Hello all,

I recently decided to subscribe to IBD's eTables, because as a growth stock investor, I like IBD rankings, they are pretty useful to me and make for good data in the interpretation window (kind of like a poor man's Marketsmith).

eTables is a little known jem, hardly costs a thing compared to subscribing to their paper or other products (less than 20USD a month) so it definitely has a lot of bang for the buck. The best thing is, you can download the data into text files, which makes it ripe for use in Amibroker.

The code is simple, and I probably should've used functions, but whatever, it works!

Step 1:
Download as much data from eTables as you can. I do this by running a batch file that opens chrome with URLs defined that download the IBD50, IBD8585 IBD New America, and then their regular stock tables ranked in different ways. You can't download their entire database, but the above covers all the stocks you should care about if you are a growth investor

BATCH FILE (save as .bat file somewhere convenient)

start Chrome "https://research.investors.com/etables/ViewText.aspx?tabView=IBD100&columnsort1=ibd100rank&columnsorttype1=ASC&columnsort2=&columnsorttype2=DESC&search=&filter="

start Chrome "https://research.investors.com/etables/ViewText.aspx?tabView=NEWAMERICA&columnsort1=comprating&columnsorttype1=DESC&columnsort2=&columnsorttype2=DESC&search=&filter=&listType="

start Chrome "https://research.investors.com/etables/ViewText.aspx?tabView=IBD8585&columnsort1=comprating&columnsorttype1=DESC&columnsort2=&columnsorttype2=DESC&search=&filter=&listType="

start Chrome "https://research.investors.com/etables/ViewText.aspx?tabView=STOCKTABLES&columnsort1=comprating&columnsorttype1=DESC&columnsort2=&columnsorttype2=DESC&search=&filter=&listType="

start Chrome "https://research.investors.com/etables/ViewText.aspx?tabView=STOCKTABLES&columnsort1=epsrank&columnsorttype1=DESC&columnsort2=comprating&columnsorttype2=DESC&search=&filter=&listType="

start Chrome "https://research.investors.com/etables/ViewText.aspx?tabView=STOCKTABLES&columnsort1=relst&columnsorttype1=DESC&columnsort2=comprating&columnsorttype2=DESC&search=&filter=&listType="

start Chrome "https://research.investors.com/etables/ViewText.aspx?tabView=STOCKTABLES&columnsort1=grpstr&columnsorttype1=DESC&columnsort2=comprating&columnsorttype2=DESC&search=&filter=&listType="

start Chrome "https://research.investors.com/etables/ViewText.aspx?tabView=STOCKTABLES&columnsort1=smr&columnsorttype1=DESC&columnsort2=comprating&columnsorttype2=DESC&search=&filter=&listType="

start Chrome "https://research.investors.com/etables/ViewText.aspx?tabView=STOCKTABLES&columnsort1=accdis&columnsorttype1=DESC&columnsort2=comprating&columnsorttype2=DESC&search=&filter=&listType="

start Chrome "https://research.investors.com/etables/ViewText.aspx?tabView=STOCKTABLES&columnsort1=sponrating&columnsorttype1=DESC&columnsort2=comprating&columnsorttype2=DESC&search=&filter=&listType="

When you run the batch file, chrome will open a tab for each instance and you'll automatically get the download dialog box for each download. Put them somewhere convenient and keep the path in mind for the AFL code in step 2.

Step 2:
Run this AFL to scrape all the text file, from the AFL window (no need for apx). Fix the code to enter your path where you downloaded above files from step 1.

/* 
Scrape all IBD eTables and set static variables for all IBD prop ratings 
Author: Michael Angelo Mustillo
Original Date: 2019/10/11
Revision NC
*/

/* 
Update Log
----------
N/A
*/

//////////////////////////////////////////////////////////////////////////////////////
//   Master Watchlist Prep
{
// Prepare Watchlist by clearing it
IBDMLList = CategoryFind("eTables_MasterList", categoryWatchlist);
// retrive comma-separated list of symbols in watch list
MLlist = CategoryGetSymbols( categoryWatchlist, IBDMLList );
//iterate through watchlist members and remove
for( i = 0; ( sym = StrExtract( MLlist, i ) ) != ""; i++ )
{
	CategoryRemoveSymbol( sym, categoryWatchlist, IBDMLList );
}
}

//////////////////////////////////////////////////////////////////////////////////////
//   IBD50 Table Scrape
//
{
// Prepare Watchlist by clearing it
IBD50List = CategoryFind("eTables_IBD50", categoryWatchlist);
// retrive comma-separated list of symbols in watch list
list = CategoryGetSymbols( categoryWatchlist, IBD50List );
//iterate through watchlist members and remove
for( i = 0; ( sym = StrExtract( list, i ) ) != ""; i++ )
{
	CategoryRemoveSymbol( sym, categoryWatchlist, IBD50List );
}

// openfile
file = fopen("path/file", "r");

// Goto date and store for records
for(i = 0; i < 2; i++)
	CL = fgets(file);

IBDSTDate = StrMid(CL, 11);
StaticVarSetText("IBDSTUpdateDate", IBDSTDate, True);

// prep file position for loop
for(i = 0; i < 2; i++)
	CL = fgets(file);

// Loop to extract data of each IBD50 stock
for(i = 0; i < 50; i++)
{
	for(j = 0; j < 2; j++)
		CL = fgets(file);

	// Extract ticker
	DirtyTicker = StrMid(CL, 26, 6);
		
	// Clean up ticker
	char = "";
	Ticker = "";
	j = 0;
	while(char != ")")
	{
		char = StrMid(DirtyTicker, j++, 1);
		if (char != ")")
			Ticker = Ticker + char;
	}
	
	// Extract Summary
	Raw			= StrMid(CL, 30);
	StaticVarSetText(Ticker + "_Brief", Raw, True);
	
	// Goto Data Line
	CL = fgets(file);
	
	// Get IBD50 ranking
	Raw		 	= StrMid(CL, 0, 2);
	IBD50Rank 	= StrToNum(Raw);
	StaticVarSet(Ticker + "_IBD50Rank", IBD50Rank, True);
	
	// Get Composite Rating
	Raw 		= StrMid(CL, 8, 2);
	CR 			= StrToNum(Raw);
	StaticVarSet(Ticker + "_CR", 		CR, 		True);	
	
	// Get EPS Rating
	Raw 		= StrMid(CL, 26, 2);
	EPS 		= StrToNum(Raw);
	StaticVarSet(Ticker + "_EPS", 		EPS, 		True);	
	
	// Get RS Rating
	Raw 		= StrMid(CL, 34, 2);
	RS 			= StrToNum(Raw);
	StaticVarSet(Ticker + "_RS", 		RS, 		True);
	
	// Get IGRS Rating
	Raw 		= StrMid(CL, 42, 2);
	IGRS 		= StrTrim(Raw, " ");
	StaticVarSetText(Ticker + "_IGRS", 	IGRS, 		True);
	
	// Get SMR Rating
	Raw 		= StrMid(CL, 57, 2);
	SMR 		= StrTrim(Raw, " ");
	StaticVarSetText(Ticker + "_SMR", 	SMR, 		True);

	// Get Acc/Dis Rating
	Raw 		= StrMid(CL, 65, 2);
	AD 			= StrTrim(Raw, " ");
	StaticVarSetText(Ticker + "_AD", 	AD, 		True);

	// Get Sponsorship Rating
	Raw			= StrMid(CL, 74, 2);
	Spon		= StrTrim(Raw, " ");
	StaticVarSetText(Ticker + "_Spon", 	Spon, 		True);
	
	// Get P/E
	Raw 		= StrMid(CL, 142, 4);
	PE 			= StrToNum(Raw);	
	StaticVarSet(Ticker + "_PE", 		PE, 		True);		
	
	// Get Last Quarter Sales
	Raw 		= StrMid(CL, 158, 4);
	LQSales		= StrToNum(Raw);
	StaticVarSet(Ticker + "_LQSales", 	LQSales,	True);	

	// Get Last Quarter EPS
	Raw 		= StrMid(CL, 170, 4);
	LQEPS		= StrToNum(Raw);
	StaticVarSet(Ticker + "_LQEPS", 	LQEPS, 		True);	

	// Get Consecutive Quarters of +15% EPS
	Raw 		= StrMid(CL, 182, 4);
	CQEPS15		= StrToNum(Raw);
	StaticVarSet(Ticker + "_CQEPS15", 	CQEPS15, 	True);
	
	// Get Current Quarter EPS Estimated Change
	Raw 		= StrMid(CL, 194, 4);
	CQEPSEst	= StrToNum(Raw);
	StaticVarSet(Ticker + "_CQEPSEst", 	CQEPSEst, 	True);	
	
	// Get Current Year EPS Estimated Change
	Raw 		= StrMid(CL, 206, 4);
	CYEPSEst	= StrToNum(Raw);
	StaticVarSet(Ticker + "_CYEPSEst", 	CYEPSEst, 	True);	

	// Get Pretax Margin
	Raw 		= StrMid(CL, 218, 4);
	PTMargin	= StrToNum(Raw);
	StaticVarSet(Ticker + "_PTMargin", 	PTMargin, 	True);	
	
	// Get Return on Equity
	Raw 		= StrMid(CL, 226, 4);
	ROE			= StrToNum(Raw);
	StaticVarSet(Ticker + "_ROE", 		ROE, 		True);	
	
	// Add ticker to watchlist
	CategoryAddSymbol(Ticker, categoryWatchlist, IBD50List);
	CategoryAddSymbol(Ticker, categoryWatchlist, IBDMLList);
}

// Close IBD50 file
fclose(file);
}

//////////////////////////////////////////////////////////////////////////////////////
//   IBD8585 Table Scrape
//
{
// Prepare Watchlist by clearing it
IBD8585List = CategoryFind("eTables_IBD8585", categoryWatchlist);
// retrive comma-separated list of symbols in watch list
list = CategoryGetSymbols( categoryWatchlist, IBD8585List );
//iterate through watchlist members and remove
for( i = 0; ( sym = StrExtract( list, i ) ) != ""; i++ )
{
	CategoryRemoveSymbol( sym, categoryWatchlist, IBD8585List );
}

// openfile
file = fopen("path/file", "r");

// Goto date and store for records
for(i = 0; i < 2; i++)
	CL = fgets(file);

IBDSTDate = StrMid(CL, 11);
StaticVarSetText("IBDSTUpdateDate", IBDSTDate, True);

// prep file position for loop
for(i = 0; i < 4; i++)
	CL = fgets(file);

// Loop to extract data of each IBD8585 stock
loop = True;
while(loop)
{
	// Extract ticker
	DirtyTicker = StrMid(CL, 26, 6);
		
	// Clean up ticker
	char = "";
	Ticker = "";
	j = 0;
	while(char != ")")
	{
		char = StrMid(DirtyTicker, j++, 1);
		if (char != ")")
			Ticker = Ticker + char;
	}
	
	// Extract Summary
	Raw			= StrMid(CL, 30);
	StaticVarSetText(Ticker + "_Brief", 	  Raw, 	True);

	// Flag that stock is in IBD8585
	StaticVarSetText(Ticker + "_inIBD8585", "Yes", 	True);
	
	// Goto Data Line
	CL = fgets(file);
	
	// Get Composite Rating
	Raw 		= StrMid(CL, 0, 2);
	CR 			= StrToNum(Raw);
	StaticVarSet(Ticker + "_CR", 		CR, 		True);	
	
	// Get EPS Rating
	Raw 		= StrMid(CL, 18, 2);
	EPS 		= StrToNum(Raw);
	StaticVarSet(Ticker + "_EPS", 		EPS, 		True);	
	
	// Get RS Rating
	Raw 		= StrMid(CL, 26, 2);
	RS 			= StrToNum(Raw);
	StaticVarSet(Ticker + "_RS", 		RS, 		True);
	
	// Get IGRS Rating
	Raw 		= StrMid(CL, 34, 2);
	IGRS 		= StrTrim(Raw, " ");
	StaticVarSetText(Ticker + "_IGRS", 	IGRS, 		True);
	
	// Get SMR Rating
	Raw 		= StrMid(CL, 49, 2);
	SMR 		= StrTrim(Raw, " ");
	StaticVarSetText(Ticker + "_SMR", 	SMR, 		True);

	// Get Acc/Dis Rating
	Raw 		= StrMid(CL, 57, 2);
	AD 			= StrTrim(Raw, " ");
	StaticVarSetText(Ticker + "_AD", 	AD, 		True);

	// Get Sponsorship Rating
	Raw			= StrMid(CL, 66, 2);
	Spon		= StrTrim(Raw, " ");
	StaticVarSetText(Ticker + "_Spon", 	Spon, 		True);
	
	// Get P/E
	Raw 		= StrMid(CL, 134, 4);
	PE 			= StrToNum(Raw);	
	StaticVarSet(Ticker + "_PE", 		PE, 		True);		
	
	// Get Last Quarter Sales
	Raw 		= StrMid(CL, 150, 4);
	LQSales		= StrToNum(Raw);
	StaticVarSet(Ticker + "_LQSales", 	LQSales,	True);	

	// Get Last Quarter EPS
	Raw 		= StrMid(CL, 162, 4);
	LQEPS		= StrToNum(Raw);
	StaticVarSet(Ticker + "_LQEPS", 	LQEPS, 		True);	

	// Get Consecutive Quarters of +15% EPS
	Raw 		= StrMid(CL, 174, 4);
	CQEPS15		= StrToNum(Raw);
	StaticVarSet(Ticker + "_CQEPS15", 	CQEPS15, 	True);
	
	// Get Current Quarter EPS Estimated Change
	Raw 		= StrMid(CL, 186, 4);
	CQEPSEst	= StrToNum(Raw);
	StaticVarSet(Ticker + "_CQEPSEst", 	CQEPSEst, 	True);	
	
	// Get Current Year EPS Estimated Change
	Raw 		= StrMid(CL, 198, 4);
	CYEPSEst	= StrToNum(Raw);
	StaticVarSet(Ticker + "_CYEPSEst", 	CYEPSEst, 	True);	

	// Get Pretax Margin
	Raw 		= StrMid(CL, 210, 4);
	PTMargin	= StrToNum(Raw);
	StaticVarSet(Ticker + "_PTMargin", 	PTMargin, 	True);	
	
	// Get Return on Equity
	Raw 		= StrMid(CL, 218, 4);
	ROE			= StrToNum(Raw);
	StaticVarSet(Ticker + "_ROE", 		ROE, 		True);	
	
	// Add ticker to watchlist
	CategoryAddSymbol(Ticker, categoryWatchlist, IBD8585List);
	CategoryAddSymbol(Ticker, categoryWatchlist, IBDMLList);
	
	// go to next ticker
	for(j = 0; j < 2; j++)
		CL = fgets(file);
		
	if(StrMatch(CL, "*About IBD eTables*"))
		loop = False;
}

// Close IBD8585 file
fclose(file);
}

//////////////////////////////////////////////////////////////////////////////////////
//   IBD New America Table Scrape
//
{
// Prepare Watchlist by clearing it
IBDNAList = CategoryFind("eTables_IBDNewAm", categoryWatchlist);
// retrive comma-separated list of symbols in watch list
list = CategoryGetSymbols( categoryWatchlist, IBDNAList );
//iterate through watchlist members and remove
for( i = 0; ( sym = StrExtract( list, i ) ) != ""; i++ )
{
	CategoryRemoveSymbol( sym, categoryWatchlist, IBDNAList );
}

// openfile
file = fopen("path/file", "r");

// Goto date and store for records
for(i = 0; i < 2; i++)
	CL = fgets(file);

IBDSTDate = StrMid(CL, 11);
StaticVarSetText("IBDSTUpdateDate", IBDSTDate, True);

// prep file position for loop
for(i = 0; i < 4; i++)
	CL = fgets(file);

// Loop to extract data of each IBD8585 stock
loop = True;
while(loop)
{
	// Extract ticker
	DirtyTicker = StrMid(CL, 26, 6);
		
	// Clean up ticker
	char = "";
	Ticker = "";
	j = 0;
	while(char != ")")
	{
		char = StrMid(DirtyTicker, j++, 1);
		if (char != ")")
			Ticker = Ticker + char;
	}
	
	// Extract Summary
	Raw			= StrMid(CL, 30);
	StaticVarSetText(Ticker + "_Brief", 	  Raw, 	True);

	// Flag that stock is in IBD8585
	StaticVarSetText(Ticker + "_inIBDNA", "Yes", 	True);
	
	// Goto Data Line
	CL = fgets(file);
	
	// Get Composite Rating
	Raw 		= StrMid(CL, 0, 2);
	CR 			= StrToNum(Raw);
	StaticVarSet(Ticker + "_CR", 		CR, 		True);	
	
	// Get EPS Rating
	Raw 		= StrMid(CL, 18, 2);
	EPS 		= StrToNum(Raw);
	StaticVarSet(Ticker + "_EPS", 		EPS, 		True);	
	
	// Get RS Rating
	Raw 		= StrMid(CL, 26, 2);
	RS 			= StrToNum(Raw);
	StaticVarSet(Ticker + "_RS", 		RS, 		True);
	
	// Get IGRS Rating
	Raw 		= StrMid(CL, 34, 2);
	IGRS 		= StrTrim(Raw, " ");
	StaticVarSetText(Ticker + "_IGRS", 	IGRS, 		True);
	
	// Get SMR Rating
	Raw 		= StrMid(CL, 49, 2);
	SMR 		= StrTrim(Raw, " ");
	StaticVarSetText(Ticker + "_SMR", 	SMR, 		True);

	// Get Acc/Dis Rating
	Raw 		= StrMid(CL, 57, 2);
	AD 			= StrTrim(Raw, " ");
	StaticVarSetText(Ticker + "_AD", 	AD, 		True);

	// Get Sponsorship Rating
	Raw			= StrMid(CL, 66, 2);
	Spon		= StrTrim(Raw, " ");
	StaticVarSetText(Ticker + "_Spon", 	Spon, 		True);
	
	// Get P/E
	Raw 		= StrMid(CL, 134, 4);
	PE 			= StrToNum(Raw);	
	StaticVarSet(Ticker + "_PE", 		PE, 		True);		
	
	// Get Last Quarter Sales
	Raw 		= StrMid(CL, 150, 4);
	LQSales		= StrToNum(Raw);
	StaticVarSet(Ticker + "_LQSales", 	LQSales,	True);	

	// Get Last Quarter EPS
	Raw 		= StrMid(CL, 162, 4);
	LQEPS		= StrToNum(Raw);
	StaticVarSet(Ticker + "_LQEPS", 	LQEPS, 		True);	

	// Get Consecutive Quarters of +15% EPS
	Raw 		= StrMid(CL, 174, 4);
	CQEPS15		= StrToNum(Raw);
	StaticVarSet(Ticker + "_CQEPS15", 	CQEPS15, 	True);
	
	// Get Current Quarter EPS Estimated Change
	Raw 		= StrMid(CL, 186, 4);
	CQEPSEst	= StrToNum(Raw);
	StaticVarSet(Ticker + "_CQEPSEst", 	CQEPSEst, 	True);	
	
	// Get Current Year EPS Estimated Change
	Raw 		= StrMid(CL, 198, 4);
	CYEPSEst	= StrToNum(Raw);
	StaticVarSet(Ticker + "_CYEPSEst", 	CYEPSEst, 	True);	

	// Get Pretax Margin
	Raw 		= StrMid(CL, 210, 4);
	PTMargin	= StrToNum(Raw);
	StaticVarSet(Ticker + "_PTMargin", 	PTMargin, 	True);	
	
	// Get Return on Equity
	Raw 		= StrMid(CL, 218, 4);
	ROE			= StrToNum(Raw);
	StaticVarSet(Ticker + "_ROE", 		ROE, 		True);	
	
	// Add ticker to watchlist
	CategoryAddSymbol(Ticker, categoryWatchlist, IBDNAList);
	CategoryAddSymbol(Ticker, categoryWatchlist, IBDMLList);
	
	// go to next ticker
	for(j = 0; j < 2; j++)
		CL = fgets(file);
		
	if(StrMatch(CL, "*About IBD eTables*"))
		loop = False;
}

// Close IBDNA file
fclose(file);
}

//////////////////////////////////////////////////////////////////////////////////////
//   IBD Top Stock table list (repeat for as many as possible as you want but don't forget to edit the 
// batch file! (or make it a function which is smarter :) )

{
// openfile
file = fopen("path/file", "r");

// Goto date and store for records
for(i = 0; i < 2; i++)
	CL = fgets(file);

IBDSTDate = StrMid(CL, 11);
StaticVarSetText("IBDSTUpdateDate", IBDSTDate, True);

// prep file position for loop
for(i = 0; i < 4; i++)
	CL = fgets(file);

// Loop to extract data of each IBD Stock Tables stock
loop = True;
while(loop)
{
	// Extract ticker
	DirtyTicker = StrMid(CL, 26, 6);
		
	// Clean up ticker
	char = "";
	Ticker = "";
	j = 0;
	while(char != ")")
	{
		char = StrMid(DirtyTicker, j++, 1);
		if (char != ")")
			Ticker = Ticker + char;
	}
	
	// Extract Summary
	Raw			= StrMid(CL, 30);
	StaticVarSetText(Ticker + "_Brief", 	  Raw, 	True);
	
	// Goto Data Line
	CL = fgets(file);
	
	// Get Composite Rating
	Raw 		= StrMid(CL, 0, 2);
	CR 			= StrToNum(Raw);
	StaticVarSet(Ticker + "_CR", 		CR, 		True);	
	
	// Get EPS Rating
	Raw 		= StrMid(CL, 18, 2);
	EPS 		= StrToNum(Raw);
	StaticVarSet(Ticker + "_EPS", 		EPS, 		True);	
	
	// Get RS Rating
	Raw 		= StrMid(CL, 26, 2);
	RS 			= StrToNum(Raw);
	StaticVarSet(Ticker + "_RS", 		RS, 		True);
	
	// Get IGRS Rating
	Raw 		= StrMid(CL, 34, 2);
	IGRS 		= StrTrim(Raw, " ");
	StaticVarSetText(Ticker + "_IGRS", 	IGRS, 		True);
	
	// Get SMR Rating
	Raw 		= StrMid(CL, 49, 2);
	SMR 		= StrTrim(Raw, " ");
	StaticVarSetText(Ticker + "_SMR", 	SMR, 		True);

	// Get Acc/Dis Rating
	Raw 		= StrMid(CL, 57, 2);
	AD 			= StrTrim(Raw, " ");
	StaticVarSetText(Ticker + "_AD", 	AD, 		True);

	// Get Sponsorship Rating
	Raw			= StrMid(CL, 66, 2);
	Spon		= StrTrim(Raw, " ");
	StaticVarSetText(Ticker + "_Spon", 	Spon, 		True);
	
	// Get P/E
	Raw 		= StrMid(CL, 134, 4);
	PE 			= StrToNum(Raw);	
	StaticVarSet(Ticker + "_PE", 		PE, 		True);		
	
	// Get Last Quarter Sales
	Raw 		= StrMid(CL, 150, 4);
	LQSales		= StrToNum(Raw);
	StaticVarSet(Ticker + "_LQSales", 	LQSales,	True);	

	// Get Last Quarter EPS
	Raw 		= StrMid(CL, 162, 4);
	LQEPS		= StrToNum(Raw);
	StaticVarSet(Ticker + "_LQEPS", 	LQEPS, 		True);	

	// Get Consecutive Quarters of +15% EPS
	Raw 		= StrMid(CL, 174, 4);
	CQEPS15		= StrToNum(Raw);
	StaticVarSet(Ticker + "_CQEPS15", 	CQEPS15, 	True);
	
	// Get Current Quarter EPS Estimated Change
	Raw 		= StrMid(CL, 186, 4);
	CQEPSEst	= StrToNum(Raw);
	StaticVarSet(Ticker + "_CQEPSEst", 	CQEPSEst, 	True);	
	
	// Get Current Year EPS Estimated Change
	Raw 		= StrMid(CL, 198, 4);
	CYEPSEst	= StrToNum(Raw);
	StaticVarSet(Ticker + "_CYEPSEst", 	CYEPSEst, 	True);	

	// Get Pretax Margin
	Raw 		= StrMid(CL, 210, 4);
	PTMargin	= StrToNum(Raw);
	StaticVarSet(Ticker + "_PTMargin", 	PTMargin, 	True);	
	
	// Get Return on Equity
	Raw 		= StrMid(CL, 218, 4);
	ROE			= StrToNum(Raw);
	StaticVarSet(Ticker + "_ROE", 		ROE, 		True);	

	// go to next ticker
	for(j = 0; j < 2; j++)
		CL = fgets(file);
	
	CategoryAddSymbol(Ticker, categoryWatchlist, IBDMLList);
		
	if(StrMatch(CL, "*About IBD eTables*"))
		loop = False;
}

// Close ST file
fclose(file);
}

Note that uses a watchlist called IBDMLList. Make sure it exists before hand.

This AFL will make the watchlist empty when run, scrape all the rankings into permanent static vars, then add all found tickers into IBDMLList.

Step 3:
Now I simply run an analysis to get all the data into an easy to use table. It looks for uptrending stocks (Minervini style) and filters low scoring stocks based on IBD Composite rating and trend points assigned. It also adds the columns to the list with all the good stuff. I usually rank them by RS and dump them into another watchlist for review.

// Generate IBD Table

// determine parameters
SMA200 		= MA(C, 200);
SMA150 		= MA(C, 150);
SMA050 		= MA(C,  50);
High52pct 	= (C/HHV(C, 253)-1)*100;
Low52pct	        = (C/LLV(C, 253)-1)*100;
SMAV50		= MA(V,50);
RS                   = StaticVarGet(Name() + "_RS");
CR			= StaticVarGet(Name() + "_CR");

// determine trend template status
x1 = iif(C > SMA150 OR IsEmpty(SMA150),					1, 0);
x2 = iif(C > SMA200 OR IsEmpty(SMA200), 				        1, 0);
x3 = iif(SMA150 > SMA200 OR IsEmpty(SMA200), 			1, 0);
x4 = iif(SMA200 > Ref(SMA200, -20) OR IsEmpty(SMA200), 	1, 0);
x5 = iif(SMA050 > SMA150 OR IsEmpty(SMA150), 			1, 0);
x6 = iif(SMA050 > SMA200 OR IsEmpty(SMA200), 			1, 0);
x7 = iif(C > High52pct*0.75, 							        1, 0);
x8 = iif(C >  Low52pct*1.25, 							        1, 0);

Score = x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8;

Filter = Score > 6 AND CR > 93;

AddColumn(C, "Price");
AddColumn((C/Ref(C,-1)-1)*100, 				"% $ Ch",      1.1);
AddColumn((V/SMAV50-1)*100,  				"% Vol ch",    1.0);
AddColumn(High52pct,           				"% 52 WkHigh", 1.1);
AddColumn(CR,							"CR",			 1);
AddColumn(StaticVarGet(Name() + "_EPS"), 	"EPS", 			 1);
AddColumn(RS, 					                "RS", 			 1);

AddTextColumn(StaticVarGetText(Name() 	+ "_IGRS"), 	"IndGrp RS", 	1);
AddTextColumn(StaticVarGetText(Name()	+ "_SMR"), 	"SMR", 		1);
AddTextColumn(StaticVarGetText(Name() 	+ "_AD"), 	"A/D", 		1);
AddTextColumn(StaticVarGetText(Name() 	+ "_Spon"), 	"Spon", 		1);

AddColumn(StaticVarGet(Name() 	+ "_PE"), 		"P/E Ratio", 			1);
AddColumn(StaticVarGet(Name() 	+ "_LQEPS"), 	        "Last Qtr EPS %", 		1);
AddColumn(StaticVarGet(Name() 	+ "_CQEPS15"), 	"Consec Qtr EPS>15%", 1);
AddColumn(StaticVarGet(Name() 	+ "_CYEPSEst"),     "Curr Yr EPS %", 		1);
AddColumn(StaticVarGet(Name() 	+ "_LQSales"),	"Last Qtr Sales %",	 	1);
AddColumn(StaticVarGet(Name() 	+ "_PTMargin"),	"Pretax Margin",	 	1);
AddColumn(StaticVarGet(Name() 	+ "_ROE"),		"ROE",		 		1);
AddColumn(StaticVarGet(Name() 	+ "_IBD50Rank"),    "IBD50 Rank", 		1);

AddTextColumn(StaticVarGetText(Name() 	+ "_inIBD8585"), 	"IBD8585", 		1);
AddTextColumn(StaticVarGetText(Name() 	+ "_inIBDNA"),	"IBD New Am",	1);
AddColumn(Score, "Score", 1.0);

Step 4:
Next is to get the data into the interpretation window. I added these lines into the chart. I want to colorcode them based on value in the future, but was too lazy/busy.

printf(EncodeColor(colorBlack));
printf("Composite Rating:			" 			+ StaticVarGet(Name() 	+ "_CR") 		+ "\n");
printf("EPS Rating:				"     			+ StaticVarGet(Name() 	+ "_EPS") 		+ "\n");
printf("RS Rating:				" 				+ StaticVarGet(Name() 	+ "_RS") 		+ "\n\n");
printf("Ind Grp RS Rating:				" 		+ StaticVarGet(Name() 	+ "_IGRS") 		+ "\n\n");
printf("SMR Rating:				" 				+ StaticVarGet(Name() 	+ "_SMR") 		+ "\n");
printf("A/D Rating:				" 				+ StaticVarGet(Name() 	+ "_AD") 		+ "\n");
printf("Sponsorship Rating:			" 			+ StaticVarGet(Name() 	+ "_Spon") 		+ "\n\n");
printf("P/E:					" 				+ StaticVarGet(Name() 	+ "_PE") 		+ "\n\n");
printf("Last Qtr EPS Growth:			"		+ StaticVarGet(Name() 	+ "_LQEPS") 	+ "%%\n");
printf("Consecutive 15%%+ EPS Growth: 		"	+ StaticVarGet(Name() 	+ "_CQEPS15") 	+ "\n");
printf("Curr Qtr EPS Est Growth:			"	+ StaticVarGet(Name() 	+ "_CQEPSEst") 	+ "%%\n");
printf("Curr Year EPS Est Growth:			"	+ StaticVarGet(Name() 	+ "_CYEPSEst") 	+ "%%\n\n");

printf("Last Qtr Sales Growth:			"		+ StaticVarGet(Name() 	+ "_LQSales") 	+ "%%\n");
printf("Pretax Margin:				"			+ StaticVarGet(Name() 	+ "_PTMargin") 	+ "%%\n");
printf("Return on Equity:				"		+ StaticVarGet(Name() 	+ "_ROE")	 	+ "%%\n");


printf("\n");
printf("IBD50 Ranking:				" 			+ StaticVarGet(Name() 	+ "_IBD50Rank") + "\n");
printf("IBD 85-85:				" 				+ StaticVarGet(Name() 	+ "_inIBD8585") + "\n");
printf("IBD New America:				" 		+ StaticVarGet(Name() 	+ "_inIBDNA") 	+ "\n");

Note that since I kept track of whether the stock appears int the IBD50 (and save the rank as a static var), IBD8585, New America, I list this too in the interpretation.

That's basically it! Easy as pie but why reinvent the wheel twice :slight_smile:

Here is what it looks like:
poormansmarketsmith

22 Likes

Very cool and nicely done.

-S

1 Like

Thanks Sean! Glad you like it.

I don't use IBD (Investor's Business Daily) tables, but I always appreciate users showing interesting examples of using AmiBroker in less conventional ways. That's another proof that AmiBroker is much more than a typical technical analysis software I wish there were more similar examples on the forum and I encourage everyone to show their examples to inspire other users :slight_smile:

@rocketPower thanks for providing this tutorial :+1:

5 Likes

One hint - you can use URLGet tool or wget to download URLS directly to text files instead of using Chrome.

3 Likes

Hi Tomasz

I tried but the website detects a bot and blocks it.

That's why I do it this way, semi-automatic.

:slight_smile:

Cheers
Mike

Thanks! Glad you think I'm adding value!

1 Like

I recently went to Minervini's Master Trader Program and it was awesome. From what I learned, I modified the table generator considering this new info. Non-negotiable conditions are ANDed into the filter logic, while negotiable conditions are added up into a score, which I rank with at the end.

// Generate IBD Table

// determine parameters
SMA200 		= MA(C, 200);
SMA150 		= MA(C, 150);
SMA050 		= MA(C,  50);
High52pct 	= HHV(C, 253);
Low52pct	= LLV(C, 253);
SMAV50		= MA(V,50);
RS          = StaticVarGet(Name() + "_RS");
CR			= StaticVarGet(Name() + "_CR");
SF			= GetFnData("SharesFloat");
RSL			= C/Foreign("$SPX", "C");
EPS 		= StaticVarGet(Name() + "_EPS");
LQEPS		= StaticVarGet(Name() 	+ "_LQEPS");
LQsales		= StaticVarGet(Name() 	+ "_LQSales");
PTM			= StaticVarGet(Name() 	+ "_PTMargin");

// determine trend template status

// Non nego MTP2019 p52
x1a = C  	 > SMA150 OR IsEmpty(SMA150);
x1b = C 	 > SMA200 OR IsEmpty(SMA200);
x2  = SMA150 > SMA200 OR IsEmpty(SMA200);
x3  = SMA200 > Ref(SMA200, -20) OR IsEmpty(SMA200);
x4a = SMA050 > SMA150 OR IsEmpty(SMA150);
x4b = SMA050 > SMA200 OR IsEmpty(SMA200);
x5  = C   	 > Low52pct*1.25;
x6  = C      > High52pct*0.75;
x7  = RS     > 70;

Filter 	= x1a AND x1b AND x2 AND x3 AND x4a AND x4b AND x5 AND x6 AND x7;
StaticVarSet(Name() + "_Stage2", Filter, True);

// Nego
y1  = IIf(C   		> 10, 1, 0);
y2  = IIf(RS  		> 90, 1, 0);
y3  = IIf(SF  		< 50e6, 1, 0);
y4  = IIf(RSL 		> Ref(RSL, -30), 1, 0);
y5  = IIf(EPS 		> 85, 1, 0);
y6  = IIf(LQEPS		> 20, 1, 0);
y7  = IIf(LQsales 	> 10, 1, 0);
y8  = IIf(BarCount 	< 10*253, 1, 0);
y9  = IIf(PTM		> 10, 1, 0);
y10 = IIf(CR 		> 94, 1, 0);

Score = y1 + y2 + y3 + y4 + y5 + y6 + y7 + y8 + y9 + y10;
StaticVarSet(Name() + "_score", Score, True);

AddColumn(Score, "Score", 1.0);
AddColumn(C, "Price");
AddColumn((C/Ref(C,-1)-1)*100, 				"% $ Ch",      1.1);
AddColumn((V/SMAV50-1)*100,  				"% Vol ch",    1.0);
AddColumn(High52pct,           				"% 52 WkHigh", 1.1);
AddColumn(SF, "Float");
AddColumn(CR,								"CR",			 1);
AddColumn(StaticVarGet(Name() + "_EPS"), 	"EPS", 			 1);
AddColumn(RS, 					            "RS", 			 1);

AddTextColumn(StaticVarGetText(Name() 	+ "_IGRS"), 	"IndGrp RS", 	1);
AddTextColumn(StaticVarGetText(Name()	+ "_SMR"), 		"SMR", 			1);
AddTextColumn(StaticVarGetText(Name() 	+ "_AD"), 		"A/D", 			1);
AddTextColumn(StaticVarGetText(Name() 	+ "_Spon"), 	"Spon", 		1);

AddColumn(StaticVarGet(Name() 	+ "_PE"), 		"P/E Ratio", 			1);
AddColumn(StaticVarGet(Name() 	+ "_LQEPS"), 	"Last Qtr EPS %", 		1);
AddColumn(StaticVarGet(Name() 	+ "_CQEPS15"), 	"Consec Qtr EPS>15%", 	1);
AddColumn(StaticVarGet(Name() 	+ "_CYEPSEst"), "Curr Yr EPS %", 		1);
AddColumn(StaticVarGet(Name() 	+ "_LQSales"),	"Last Qtr Sales %",	 	1);
AddColumn(StaticVarGet(Name() 	+ "_PTMargin"),	"Pretax Margin",	 	1);
AddColumn(StaticVarGet(Name() 	+ "_ROE"),		"ROE",		 			1);
AddColumn(StaticVarGet(Name() 	+ "_IBD50Rank"),"IBD50 Rank", 			1);

AddTextColumn(StaticVarGetText(Name() 	+ "_inIBD8585"), 	"IBD8585", 		1);
AddTextColumn(StaticVarGetText(Name() 	+ "_inIBDNA"),	 	"IBD New Am",	1);

SetSortColumns(-3, -11, -10, -13);```
5 Likes

Also I noted an error with the 52wk high and low calculation. It's fixed now.

This is awesome rocketPower. I got eTables as well specifically for this. I have been able to complete step 1 and am now at step 2 but after going through the code I dont quite see how or where to "Fix the code to enter your path where you downloaded above files". I know where I have them but I am not sure where in the code it points to them. Any help would be greatly appreciated!

My guess is that it is in the line

CL = fgets (file)

Is that correct? I just don't want to mess anything up here.

No that wasn't right...I see it there identifying the file....now if I can just figure out how to correctly put it in there. I am so close!

Well I did find the correct spot to put the file was able to get the error it was pulling up on that line to clear but a new error has popped up. ERROR 26: File handle passed to the function is invalid (equal to zero). So I still have something that I am not doing quite right. It is that last line (and all subsequent similar lines, that I am getting the error):

// openfile
file = fopen ("C:\Program Files\AmiBroker\IBDeTables", "r");

// Goto date and store for records
for(i = 0; i < 2; i++)
CL = fgets(file);

@MCassICT please read the documentation for the fopen() function.

In particular, note this paragraph:

filename - STRING - contains the path to the file name. Please note that single backslash in path must be written in AFL as (double backslash)

So, as per your snippet, it should be:

file = fopen ("C:\\Program Files\\AmiBroker\\IBDeTables", "r");

Note that in the above line IDBeTables is the filename (without any extension) and C:\Program Files\AmiBroker\ is the file path.

But I suspect that this is still wrong....

If IBDeTables is actually the last part of the path (directory) where you downloaded the files, you need to add the correct filename (with its extension), doing something similar to:

file = fopen ("C:\\Program Files\\AmiBroker\\IBDeTables\\ibd50_eTables.txt", "r");

(You will need to provide the correct path and filename for each section of the original formula posted be @rocketPower where he used the "path/file" placeholder).

Moreover please, study the EXAMPLE section of the above function to learn how to handle opening files errors properly.

4 Likes

Thanks @beppe, couldn't have said it better! You have really to be careful with special characters in strings, especially if you scrape text off the web!

For example, when I extract the data for the brief:

// Extract Summary
	Raw			= StrMid(CL, 30);
	StaticVarSetText(Ticker + "_Brief", 	  Raw, 	True);

If this stock is in the IBD50 it will state the blurb that describes the price action of the stock, so inevitably the % symbol is used a lot. This was causing an error when I using printf in the action commentary, so I have to do this to avoid it:

brief = StrReplace(brief, "%", "%%");
printf(brief);

Then it would display correctly.

Take care,
Mike

2 Likes

Thanks @beppe and @rocketPower...I thought maybe that was the case. Yes you are correct that what I have listed for -fopen- is actually just the folder that the files are contained in AND I had left -fgets- unchanged from what rocketPower posted. I can see I have a little work to do to make this work correctly and its not quite as simple as cut and paste which is OK. Im not sure exactly which of the files to point to where but I will dig into tonight and see if I can't figure out. What you have pointed out though does make sense.

I can't say how much I appreciate all you have done here and the help you provide. Same for @beppe. Your last responses cleared this up so perfectly, I can't believe I did't see it before. While I am not completely done making the corrections, It makes sense now and I have already cleared up a couple of those issues. You were absolutely correct about what I had done wrong. I appreciate your patience and assistance!

OK I think Ive got this but I want to make sure I understand your note:

//////////////////////////////////////////////////////////////////////////////////////
// IBD Top Stock table list (repeat for as many as possible as you want but don't forget to edit the
// batch file! (or make it a function which is smarter :slight_smile: )

Am I correct in understanding that everything below this statement essentially needs to be copied for EACH of the remaining files:

51%20PM

Well I did just that and got all of the errors to clear so I must be getting closer. Still more to do. Ran as an exploration and nothing happened so I am still missing something. Not giving up though!

Im definitely missing something. After running it as an Exploration I went back to read your rules again and noticed that you said it didnt need to be run from Analysis. So then I saved it as a batch file and tried to run that and still nothing. Went back and read through this whole post again and delved into figuring out as you said to run this AFL, from the editor! Figured out that it could be run using the debugger (I think), yet still can not get anything to populate the IBDMLLIST. Is it possible that it is going somewhere else and I am looking in the wrong place?