Indicator using data from Watchlist symbols stops after 4 years

The code below references a custom function of mine that measures trend. That seems to work fine. The loop moves through 20 different industry groups of the S&P 500 Index and applies the custom function to each and then uses that metric to measure whether or not they are in an uptrend. Note this is using weekly data.

The resulting indicator looks correct but it only goes back to September of 2019 and is blank before that. All of the industry indexes in the Watchlist have data back to the mid-1990's so I don't think this is a data error.

Is this because of the memory needed to calculate the final indicator?
If so, what is a more efficient way to create something like this but have it run daily and appear on a chart as would a typical indicator?

Many thanks for your input.

//Include my custom functions
#include <KS_functions.afl>

/*
	THIS VERSION does not use ETFs but the price based groups from GICS that are available in
	Norgate's database. The history is longer and it avoids the issue of the change to the sectors
	in 2018 from Tech to Communications and Tech.


*/


//SetOption("WarningLevel", 1); //from Perplexity, should eliminate Warning 512 causeed by many SetForeign
								// calls in the loop below.

CT_BuyLevel = 11; //Level of CTMA represents an uptrend
BreadthBuy = 11;
BreadthSell = 2;

Uptrend_signal = Param("CT UpTrend", 11, 0, 14, 1);

//Get number for watchlist containing S&P 500 Industry Groups
ListName = "SP500_Industries";
ListNum = CategoryFind(ListName, categoryWatchlist);


//Cycle through symbols in watchlist
list = CategoryGetSymbols( categoryWatchlist, ListNum ); 

SecTrendSum = 0;

	   for( i = 0; ( sym = StrExtract( list, i ) ) != ""; i++ ) 
	   { 
	      SetForeign(sym); 
	      if( i == 0 ) ; 
	      CT_temp = CTMA_Kf(C, 0.3, 6);
	      SecTrendSum = SecTrendSum + IIf(CT_temp > CT_BuyLevel, 1, 0);
	      RestorePriceArrays();
	   } 	
	   

//Plot indicators with buy and sell levels
Plot(SecTrendSum, "SecTrendSum", colorGrey50, styleThick, 1);
Plot(BreadthBuy, "Buy level", colorBlue, 32); 
Plot(BreadthSell, "Sell level", colorRed, 32);

Hello PropKid, there are some raw errors in your code, for example:

  • in the #include statement you use the "<" and ">" characters to define the file to be included, which is incorrect
  • at line 36 you writed if( i == 0 ) ;

Are you really sure that your code (partially) works fine?

Both are fine <> and ", this follows the C/C++ convention of which paths to use when looking for a file.

With angular brackets: this way AmiBroker will look for the file in "standard include path" that is definable using new prefs setting in Tools->Preferences->AFL

1 Like

To get helpful help you should provide the code for the CTMA_Kf() function and share an executable example that demonstrates the problem.

Thank you nsm51

The function shown below is a simpler version than what I originally referred to but the error still occurs.

Here is the code for the indicator again:

//Include my custom functions
#include <KS_functions.afl>

/*
	THIS VERSION does not use ETFs but the price based groups from GICS that are available in
	Norgate's database. THe history is longer and it avoids the issue of the change to the sectors
	in 2018 from Tech to Communications and Tech.


*/


//SetOption("WarningLevel", 1); //from Perplexity, should eliminate Warning 512 causeed by many SetForeign
								// calls in the loop below.

CT_BuyLevel = 2; //Level of CTMA represents an uptrend
BreadthBuy = 11;


Uptrend_signal = 2; //Param("CT UpTrend", 2, 0, 14, 1);

//Get number for watchlist containing S&P 500 Industry Groups
ListName = "SP500_Industries";
ListNum = CategoryFind(ListName, categoryWatchlist);


//Cycle through symbols in watchlist
list = CategoryGetSymbols( categoryWatchlist, ListNum ); 

SecTrendSum = 0;

	   for( i = 0; ( sym = StrExtract( list, i ) ) != ""; i++ ) 
	   { 
	      SetForeign(sym); 
	      CT_temp = CTMA_Kf(C);
	      SecTrendSum = SecTrendSum + IIf(CT_temp >= CT_BuyLevel, 1, 0);
	      RestorePriceArrays();
	   } 	
	   

//Plot indicators with buy and sell levels
Plot(SecTrendSum, "SecTrendSum", colorGrey50, styleThick, 1);

And the simple code for the function referenced:


function CTMA_Kf(price_array)
{
	CT = IIf(MA(price_array,40) > Ref( MA(price_array,40), -1),1, 0) + IIf( MA(price_array, 10) > Ref( MA(price_array, 10), -1), 1, 0);

	return CT;	
}

Again, many thanks for taking the time to look at this for me and give feedback.
VERY much appreciated!

@PropKid, here are a few observations about your code:

  1. Custom Watchlist:
    The watchlist you're using doesn’t appear to be one of Norgate's default watchlists. I assume it's a custom watchlist you created. Since we don't have access to it, we can't directly test your code.

  2. Handling Null Values:
    Your loop is likely adding null values for stocks with shorter histories. This means the resulting array will only contain valid data when all the stocks in the list were actively trading.

    To further test and debug your code, you might consider modifying it as follows:

    SecTrendSum = 0;
    for( i = 0; ( sym = StrExtract( list, i ) ) != ""; i++ ) 
    { 
        fc = Foreign(sym, "C"); // Faster than SetForeign()
        CT_temp = iif(isNull(fc), 0, fc);
        SecTrendSum = SecTrendSum + IIf(CT_temp >= CT_BuyLevel, 1, 0);
    } 	
    

    (Note: This logic doesn’t account for variations in the number of stocks with valid data at different times. Does your custom watchlist include "Current & Past" stocks?)

  3. Watchlist Data and Plot Length:
    If I use any other watchlist (e.g., "S&P 500") and apply the script to a chart, the length of the displayed plot is determined by the data history of the stock selected in the "ticker" field.
    To get more reliable results, consider selecting a ticker with a longer trading history (e.g., SPY).

  4. Using Composites for Better Results:
    For this type of calculation, it’s usually better to create a "composite" or derive an equivalent result using a preliminary scan that saves the results to a static variable.

  5. Exploration and Debugging:
    If you plan to debug the calculations using an exploration, make sure to wrap your loop in a conditional block, as shown below:

    stockZero = Status("stocknum") == 0;
    if (stockZero)
    {
        // Clear any associated static variables
        // Perform your loop over the list
        // Save results to StaticVars
    }	   
    // Retrieve values from StaticVars
    
  6. Further Resources:
    You’ll find multiple examples in the forum that demonstrate similar concepts. Search for keywords like "composite" or "sequence", and make sure you also understand how to use "Pad & Align" effectively.

This response (and its formatting) comes from one I submitted to Chat-GPT for correction and revision

1 Like

It's beyond me why Bonariva has to repeat old threads and manual about this topic and others over and over again acting as if he has found out something new under the sun.

Long story short don't use loop but use Staticvaradd in Analysis and pad and align being enabled.

Search old threads. Everything has been covered already

@fxshrat, good to see you here again.
I often wonder what keeps you busy now that we don't read from you very often on this forum.

In any case there may be several answers to your question: it may be that I suffer from senile dementia and I don't remember that certain topics have already been covered... Or I think that some user with less experience than you has difficulty finding the right contents... or finally that I do it on purpose to see if you are still around and some of my posts will encourage you to delight us with one of your always wise answers!

2 Likes

@beppe great response :slight_smile: don't get discouraged. Good job.

1 Like