Access to Subcategories

Hello! I am using Norgate with Amibroker and I am trying to access the symbols of Subsectors in AFL:

image

The following code allows me to get this list when I add the main sectors such as "Technology":

list = CategoryGetSymbols( categorySector, CategoryFind( "Technology", categorySector ));
_TRACE(""+list);

But this does not work for subsectors such as "Internet Services":

list = CategoryGetSymbols( categorySector, CategoryFind( "Internet Services", categorySector ));
_TRACE(""+list);

I get empty results here even though "Internet Services" has a category number, which is 84.

list = CategoryGetSymbols( categorySector, 84);
_TRACE(""+list);

Does not work either.

The "subsectors" are called Industries and are retrievable using categoryIndustry (not categorySector), see http://www.amibroker.com/guide/h_categories.html

2 Likes

Is it possible to check if ticker belongs to a list of groups such as GroupID() in (1,2,5,8)? I'm not sure AFL can access a list of numbers.

A symbol can be member of just one group, market, sector, industry (but of multiple watchlists).

If you want to find out whether a symbol is part of a group of a group id list e.g. from 1 to 8 then just iterate between start id and end id and print result.

EnableTextOutput(0);

gid = GroupID();
nm = Name();

for ( i = 1; i <= 8; i++ ) {
	if ( gid == i ) printf( "Group membership of %s: %g", nm, i );
	else { printf( "Symbol %s is member of different group (%g) not being within iteration range!", nm, gid ); break; }
}
3 Likes

Or use Matrix

EnableTextOutput(0);

gid = GroupID();
nm = Name();

mat = MxFromString( "[[1;2;5;8]]" );
printf( "Group ID list:\n%s", MxtoString(mat) );

for ( i = 0; i < MxGetSize(mat,0); i++ ) {
	if ( gid == mat[i][0] ){ printf( "\nGroup membership of %s: %g", nm, gid ); break;}
	else { printf( "\nSymbol %s is member of different group (%g) not being within iteration range!", nm, gid ); break; }
}

315

3 Likes

Thank you, but it’s not possible to do something like StrFind with a list of numbers? In Python it would be something like:

if 2 in [2,3,5,6] == True

What do you need StrFind for when you have an Mx array of numbers?
Because you do not have AmiBroker version higher than 6.0?

The above examples do what you where asking.

Below line is doing same thing

//...
if ( gid == mat[i][0] ) 
    //then do something...

As your Python line

if 2 in [2,3,5,6] == True 
    # then do something...

gid = GroupID();

mat = MxFromString( "[[2;3;5;6]]" );

x = false;
for ( i = 0; i < MxGetSize(mat,0); i++ ) 
   if ( gid == mat[i][0] ){ x = true; break;}
   
printf( "\nx:%s", StrExtract( "False,True", x) );

Sorry, but I find using Str* functions stupid idea and I'm not applying stupid ideas.

2 Likes

But if you want to use Str* instead of Mx functions then do something like below one.

gid = GroupID();

list = "2,3,5,6";

x = False;
for( i = 0; ( id = StrExtract( list, i ) ) != ""; i++ )
	if ( gid == StrToNum(id) ) { x = true; break; }
   
printf( "\nx:%s", StrExtract( "False,True", x) );
2 Likes

GICS(1) returns the last Subcategory such as "25201030 Homebuilding", but there is also "252010 Household Durables" and "2520 Consumer Durables & Apparel" and "25 Consumer Discretionary" before that. Is there a way to get those as well?

Found it:

AddTextColumn(NorgateClassificationNameAtLevel("GICS",1),"GICS1");
AddTextColumn(NorgateClassificationNameAtLevel("GICS",2),"GICS2");
AddTextColumn(NorgateClassificationNameAtLevel("GICS",3),"GICS3");
AddTextColumn(NorgateClassificationNameAtLevel("GICS",4),"GICS4");

Norgage* are NOT native functions. They are 3rd party plugin functions. They will NOT work for databases that are NOT feed from norgate.

You should use native functions whenever possible and it is really easy and documented
http://www.amibroker.com/guide/afl/categorygetname.html

gics = GicsID( 0 );

level1 = StrToNum( StrLeft( gics, 2 ) );
level2 = StrToNum( StrLeft( gics, 4 ) );
level3 = StrToNum( StrLeft( gics, 6 ) );

printf("Level 1 %s\n", CategoryGetName( categoryGICS, level1 ) );
printf("Level 2 %s\n", CategoryGetName( categoryGICS, level2 ) );
printf("Level 3 %s\n", CategoryGetName( categoryGICS, level3 ) );
printf("Level 4 %s\n", GicsID( 1 ) );
5 Likes

Based on Tomasz's upper post I made AFL function (yes, I could have used StrLeft but I didn't want to copy and since multiple roads lead to Rome... :slight_smile: ):

function GicsGetName(level) {
	/// function by fxshrat
	/// based on Tomasz Janeczko post:
	/// @link https://forum.amibroker.com/t/access-to-subcategories/6546/11
	gicsnum = StrToNum(GicsID(0));
	gicslevel = Max(0, level-1);
	gicslevel = Min(2*gicslevel+2, 8);
	catnum = int(gicsnum / 10^(8-gicslevel));
	gicsname = CategoryGetName(categoryGICS, catnum);
	return gicsname;
}

gicslevel = 1;// 1 to 4
gicsname = GicsGetName( gicslevel );

But if you want to use StrLeft then here is alternative

function GicsGetName2(level) {
	/// function by fxshrat
	/// based on Tomasz Janeczko post:
	/// @link https://forum.amibroker.com/t/access-to-subcategories/6546/11
	gicsstr = GicsID(0);
	gicslevel = Max(0, level-1);
	gicslevel = Min(2*gicslevel+2, 8);
	catnum = StrToNum(StrLeft(gicsstr, gicslevel));
	gicsname = CategoryGetName(categoryGICS, catnum);
	return gicsname;
}

gicslevel = 1;// 1 to 4
gicsname = GicsGetName2( gicslevel );
3 Likes

@fxshrat your first code is incorrect. Second code may fail in level 4. StrLeft technique I have shown is the only one that works reliably due to the fact that full level 4 Gics code is 8 digits which is too much for lEEE float. That is why I wrote the code that uses StrLeft and only for 3 levels, leaving 4 th level to gicsid(1). I always write codes the way I do for a reason.

3 Likes

Tomasz, thanks for your comment.
As I don't use GICS I tested with string codes only (and I only posted 1st one because of trying to come up with alternative). Yes, I am aware of >7 digits reliability issue. So you are right, first one was a mistake to post as AFL.

As for StrLeft may failing at level 4 (since also here >7 digits reliability issue would step in) here is corrected StrLeft version ...

function GetGicsName(level) {
	// function by fxshrat
	// based on Tomasz Janeczko post:
	// https://forum.amibroker.com/t/access-to-subcategories/6546/11
	// set level from 1 to 4
	local gicsstr, gicslevel, catnum, gicsname;
	if ( level > 0 && level < 4 ) {
		gicsstr = GicsID(0);
		gicslevel = Max(0, level-1);
		gicslevel = 2*gicslevel+2;
		catnum = StrToNum(StrLeft(gicsstr, gicslevel));
		gicsname = CategoryGetName(categoryGICS, catnum);
	} else if ( level == 4 )
		gicsname = GicsID(1);
	else 
		Error( "GetGicsName(): Set level from 1 to 4!" );
	return gicsname;
}
2 Likes