@reds here is a possible way to do it (a bit unorthodox approach):

```
/****** Constants *****/
// Change these as needed
MAX_ALLOWED_TICKERS = 1000; // Over this size probably it is too slow...
MAX_PAIRS_IN_TABLE = 250; // To avoid using too many columns and hit a Windows limit
/***** Parameters *****/
// Number of the watchlist to use to create the correlation matrix
wlNumber = Param("Watchlist Number", 1, 0, 63, 1);
// Number of columns pair to display in resulting table
maxColRes = Param("Number of (pair) columns in results (0 = max)", 5, 0, MAX_PAIRS_IN_TABLE, 1);
// Daily correlation look-back period
corrLB = Param("Daily correlation lookback period", 252, 50, 300, 1);
// Send trace messages for debugging purpose on progess
debugTrace = ParamToggle("Enable _TRACE()", "No|Yes", 1);
/***** Functions *****/
function _TRACE_(msg) {
if (debugTrace)
_TRACE(msg);
}
/***** Exploration *****/
actionStatus = Status("action");
if (( actionStatus == actionExplore ) OR (actionStatus == actionBacktest)) {
symlist = GetCategorySymbols( categoryWatchlist, wlNumber);
Filter = 0;
stockNum = Status("stocknum");
if (stockNum == 0)
{
// Do this only ONCE
if (symList != "") {
EnableTextOutput( 0 );
size = 1 + StrCount( symlist, ",");
if (maxColRes >= size) {
maxColRes = size-1;
}
if (maxColRes <= 0) {
maxColRes = size-1;
}
if (maxColRes >= MAX_PAIRS_IN_TABLE) {
maxColRes = MAX_PAIRS_IN_TABLE; //
}
_TRACE_("Selected watchlist: " + WriteVal(wlNumber, 2.0) + " - Size: " + WriteVal(size, 3.0));
_TRACE_("Symbols: " + symList);
if (size < MAX_ALLOWED_TICKERS+1) {
Filter = 0;
SetOption("NoDefaultColumns", True );
AddColumn(Null, "Ticker", 1.2, -1, -1, 60);
for (i = 1; i <= maxColRes; i++) {
AddColumn(Null, "T" + WriteVal(i, 1.0), 1.2, -1, -1, 60);
AddColumn(Null, "C" + WriteVal(i, 1.0), 1.2, -1, -1, 60);
}
// Get Tickers and do calculations ONCE
_TRACE_("Parsing tickers");
for( i = 0; ( sym = StrExtract( symlist, i ) ) != ""; i++ )
{
VarSetText("T_" + i, sym);
CFrgn = Foreign( sym, "C" );
logCFrgn = log( CFrgn / Ref( CFrgn, -1 ) );
VarSet("L_" + i, logCFrgn);
}
_TRACE_("Parsing tickers. Done");
// Add top row used for ticker index
mx = Matrix(size+1, size, 0);
_TRACE_("Created matrix. " + WriteVal(size+1, 3.0) + "*" + WriteVal(size, 3.0));
_TRACE_("Filling matrix with correlations.... ");
// First row is reserved to ticker indexes
for( col = 0; col < size; col++ )
mx[0][col] = col;
// Filling a matrix with correlation values
startCol = 0;
for( row = 0; row < size; row++ )
{
symRow = VarGetText("T_" + row);
// CRow = Foreign( symRow, "C" );
// logCRow = log( CRow / Ref( CRow, -1 ) );
if (row % 10 == 0)
_TRACE_("Row " + WriteVal(row, 3.0));
for( col = startCol; col < size; col++ )
{
symCol = VarGetText("T_" + col);
// _TRACE_("R " + WriteVal(row, 2.0) + " C " + WriteVal(col, 3.0) + " " + symRow + " * " + symCol);
// CCol = Foreign( symCol, "C" ); // store Foreign to variable since it is called multiple times
// LogCCol = log( CCol / Ref( CCol, -1 ) );
// corrARray = Correlation( LogCRow, LogCCol, corrLB );
// corr = LastValue(corrArray);
corr = LastValue(Correlation( VarGet("L_" + row), VarGet("L_" + col), corrLB ));
// corr is a columm
mx[col+1][row] = corr;
// Filling the symmetrical cell
mx[row+1][col] = corr;
}
startCol += 1; // reducing number of cells to fill thanks to to this matrix symmetry
}
_TRACE_("Matrix done. Sorting - Ignoring header");
_TRACE_("Coupling elements");
// Print result in the Analisys window using AddRow (to output too if needed)
for( row = 0; row < size; row++ ) {
// we need to transpose the matrix to sort by columns - then restore
// each iteration we sort on a different row for each ticker (rows headers)
// and row 0 will have the orders of correlated tickers (columns headers)
mx2 = MxTranspose(mx);
mx3 = MxSortRows(mx2, False, row+1); // sort descending
mx2 = MxTranspose(mx3);
symRow = VarGetText("T_" + row);
s = symRow + "\t";
// Skip col 0 since it is 1.0 for the ticker own correlation....
for( col = 1; col <= maxColRes; col++ )
{
symIdx = mx2[0][col]; // get the index from row 0
symCol = VarGetText("T_" + symIdx);
corr = mx2[row+1][col];
s = s + symCol + "\t" + WriteVal( corr, 3.3 ) + "\t";
}
AddRow(s);
}
_TRACE_("Coupling elements/Add rows done");
} else {
_TRACE_("Too many tickers. Skipping");
}
} else {
_TRACE_("Empty watchlist. Skipping");
}
}
_TRACE_("Script completed for stock " + WriteVal(stockNum, 4.0));
} else {
_TRACE_("Script ignored. Status " + WriteVal(actionStatus, 1.0));
}
w = 0; // used to set a breakpoint when using the debugger
```

I too used matrices and addRow().

(In this sample I applied the correlation logic used by @portfoliobuilder - using only the last value of the correlation arrays; you may want to change it as needed).

I use a matrix to store the correlations and then sort it multiple times; one for each ticker row - using the first row of my original unsorted matrix as an index for the tickers to display in the correlation table.

Seems to work well enough for medium/sized watchlists (I used a max of 500 tickers)

To display the resulting data in the Analysis window I used the AddRow() function with the filter set to 0 (search here in the forum other examples about its usage). Unfortunately as said also in the previous message no colors…

For the exploration, you have to choose a watchlist (selecting its corresponding number as a parameter).

In order to get the table a little faster, I suggest setting the analysis filter to “current” (it is actually ignored but the process will be done only once).

This sample raw code (where I left on purpose many commented lines to show how some code was developed/moved/replaced) is provided “as it is” (it is not fully tested); take it mainly as a starting point for your own further development.

(All **suggestions to do it in a better way are welcome!**)