Put watchlist on chart and click to change stock symbols

Hi everybody

I wrote a piece of code to put the watchlist on the chart and clickable to change the stock symbols. It works but very slow. I know my code is completely inefficient. Can someone point out where it is and how to improve it?

AFL Code:

_SECTION_BEGIN("Price");
SetChartOptions(0,chartShowArrows|chartShowDates);
_N(Title = StrFormat("{{NAME}} - {{INTERVAL}} {{DATE}} Open %g, Hi %g, Lo %g, Close %g (%.1f%%) {{VALUES}}", O, H, L, C, SelectedValue( ROC( C, 1 ) ) ));
Plot( C, "Close", ParamColor("Color", colorLightBlue ), styleNoTitle | ParamStyle("Style") | GetPriceStyle() ); 

//watchlist

listnum = 0;
tickerlist = CategoryGetSymbols( categoryWatchlist, listnum );


bi = BarIndex();
fbr = Status("firstbarinrange");
explore = Status("action") == actionExplore;
fvb = IIf(explore, LastValue(ValueWhen(fbr,bi)), Status("firstvisiblebar"));
sym_num = StrCount(tickerlist, ",")+1;


GfxSetOverlayMode( 0 ); 
// formatted text output sample via low-level gfxfunctions  

CellHeight = Param("Cell Height",25,0,100,1); 
CellWidth = Param("Cell Width",150,0,200,1);
start_x = Param("Vi tri Table X",10,0,2000,1); 
start_y = Param("Vi tri Table Y",40,0,500,1); 

x1= start_x;
y1= start_y;
y2=y1 + CellHeight;
ex1 = x1;
ex2 = ex1 + CellWidth;

click = GetCursorMouseButtons() == 9;
Px = GetCursorXPosition( 1 );
Py = GetCursorYPosition( 1 );


GfxSelectFont( "Tahoma",CellHeight/3 ); 
GfxSetBkMode( 1 ); 

function PrintInCell(string, row, Col,color ) 
{
GfxSetTextColor(color);
GfxDrawText( string,3+start_x+Col * CellWidth, start_y+row * CellHeight, start_x+(Col + 1 )* CellWidth, start_y+(row + 1 )* CellHeight, 0 ); 

} 
n = 0;
col = Param("colnum",3,1,10,1);
row = floor(sym_num/col);
color = Null;

GfxSelectPen( colorGrey40 ); 
for( i = 0;i < row+1 && i < BarCount;i++ ) 
{ 
for( k = 0;k < col; k++ ) 
 { 
	for (j = 0; j < sym_num;j++)
	{
	symbol = StrExtract(tickerlist, n);
	fc = Foreign( symbol, "C" );
	rfc = lastvalue(ROC(fc,1));
	last_bar = BarCount-1;
	idx = Max(Min(NullCount(fc),last_bar), fvb);
	
		if (rfc[j] >= 6.7)
		color = ColorRGB(255,128,255);
			else if (rfc[j] >= 1 AND rfc[j]< 3)
			color = ColorRGB(115,251,4); 
				else if (rfc[j] > 0 AND rfc[j]< 1)
				color = ColorRGB(170,250,5); 
					else if (rfc[j] == 0 )
					color = ColorRGB(255,255,128); 
						else if (rfc[j] < 0 AND rfc[j] >= -1)
						color = ColorRGB(255,136,136); 
							else if (rfc[j] < -1 AND rfc[j] >= -3)
							color = ColorRGB(255,108,108);
								else if (rfc[j] < -3 AND rfc[j] >= -6.7)
								color = ColorRGB(255,62,62);
									else ColorRGB(0,255,255);
									
	}
	n++;
	if (! IsNull(fc[ idx ])) 
	{ 
	GfxSelectSolidBrush(  color);
	GfxRoundRect( ex1+k*CellWidth, y1+i*CellHeight, ex2+ k*CellWidth, y2+i*CellHeight , 10, 10 ) ;
	PrintInCell( symbol+WriteVal(rfc,8.1)+"%", i, k,colorBlack );

		if ( px > ex1+k*CellWidth AND px<ex2+ k*CellWidth AND py>y1+i*CellHeight AND py < y2+i*CellHeight AND Click )
		{
			AB = CreateObject( "Broker.Application" );
			doc = AB.ActiveDocument;
			doc.Name = symbol;
		}

	}
 } 

 } 

Saying that this code is ineffective is huge understatement.

Your code is potentially calling Foreign millions of times. I would never imagine anybody, anywhere and anytime would ever think it is workable idea.

Triple nested for-loop with Foreign inside most inner loop is the reason of your problems.
Do NOT call Foreign in a loop, and if you really must, NEVER EVER call it in multiple nested loop.
You should re-organize your code so Foreign is called in MOST OUTER LOOP.

1 Like

Thank you, I will try to improve according to your suggestions and come back

I successfully fixed the code using only 1 loop and it improved immediately. Also I found another better version using GUIBUTTON here so I'll leave this link for anyone who wants to learn more.

I don’t see the purpose of that. You can simply setup a watchlist and go up/down immediately using arrows (keyboard) that is faster than mouse and that without ANY coding at all