Sigma Matrix:

The Correlation Web
A web of nodes (N₁, N₂, ..., N₆) is interconnected, where each edge (Eᵢⱼ) between nodes Nᵢ and Nⱼ has a weight representing their correlation coefficient. The weights are given as follows:

| | N₁ | N₂ | N₃ | N₄ | N₅ | N₆ | |-------|------|------|------|------|------| | N₁ | 1.0 | 0.8 | 0.3 | 0.5 | 0.7 | 0.6 | | N₂ | 0.8 | 1.0 | 0.4 | 0.6 | 0.9 | 0.2 | | N₃ | 0.3 | 0.4 | 1.0 | 0.7 | 0.5 | 0.3 | | N₄ | 0.5 | 0.6 | 0.7 | 1.0 | 0.8 | 0.4 | | N₅ | 0.7 | 0.9 | 0.5 | 0.8 | 1.0 | 0.6 | | N₆ | 0.6 | 0.2 | 0.3 | 0.4 | 0.6 | 1.0 |

Your task:

Find the subset of nodes (clusters) such that the average weight of edges within each cluster is maximized.
Ensure that no node is part of more than one cluster.

Code
#define PAIRS 28 // Number of currency pairs

string CurrencyPairs[PAIRS] = {
    "EURUSD", "GBPUSD", "USDJPY", "GBPJPY", "USDCAD", "EURAUD", "EURJPY", 
    "AUDCAD", "AUDJPY", "AUDNZD", "AUDUSD", "CADJPY", "EURCAD", "EURCHF", 
    "EURGBP", "EURNZD", "GBPCAD", "GBPCHF", "NZDCAD", "NZDJPY", "NZDUSD", 
    "USDCHF", "CHFJPY", "AUDCHF", "GBPNZD", "NZDCHF", "CADCHF", "GBPAUD"
};

vars CorrelationMatrix[PAIRS][PAIRS]; // Correlation adjacency matrix
vars ArbitrageMatrix[PAIRS][PAIRS];  // Arbitrage adjacency matrix
int StateMatrix[PAIRS][3][3];        // Transition matrix for each pair
int LookBack = 200;                 // Lookback period for calculations

// Function to calculate correlation between two series
function calculateCorrelation(vars series1, vars series2, int len) {
    var mean1 = SMA(series1, len);
    var mean2 = SMA(series2, len);
    var numerator = 0, denom1 = 0, denom2 = 0;
    for (int i = 0; i < len; i++) {
        numerator += (series1[i] - mean1) * (series2[i] - mean2);
        denom1 += pow(series1[i] - mean1, 2);
        denom2 += pow(series2[i] - mean2, 2);
    }
    return numerator / sqrt(denom1 * denom2);
}

// Initialize the correlation network
function initializeCorrelationNetwork() {
    for (int i = 0; i < PAIRS; i++) {
        for (int j = 0; j < PAIRS; j++) {
            if (i != j) {
                vars series1 = series(price(CurrencyPairs[i]));
                vars series2 = series(price(CurrencyPairs[j]));
                CorrelationMatrix[i][j] = calculateCorrelation(series1, series2, LookBack);
            } else {
                CorrelationMatrix[i][j] = 1; // Self-correlation
            }
        }
    }
}

// Calculate arbitrage opportunities between pairs
function calculateArbitrage() {
    for (int i = 0; i < PAIRS; i++) {
        for (int j = 0; j < PAIRS; j++) {
            if (i != j) {
                ArbitrageMatrix[i][j] = log(price(CurrencyPairs[i]) / price(CurrencyPairs[j]));
            } else {
                ArbitrageMatrix[i][j] = 0; // No arbitrage within the same pair
            }
        }
    }
}

// Detect arbitrage cycles using a Bellman-Ford-like algorithm
function detectArbitrageCycles() {
    for (int k = 0; k < PAIRS; k++) {
        for (int i = 0; i < PAIRS; i++) {
            for (int j = 0; j < PAIRS; j++) {
                if (ArbitrageMatrix[i][k] + ArbitrageMatrix[k][j] < ArbitrageMatrix[i][j]) {
                    ArbitrageMatrix[i][j] = ArbitrageMatrix[i][k] + ArbitrageMatrix[k][j];
                }
            }
        }
    }
}

// Get the current market state for a currency pair
function getState(string pair) {
    var fastMA = SMA(series(price(pair)), 50);
    var slowMA = SMA(series(price(pair)), 200);
    if (fastMA > slowMA) return 1;  // Bull
    else if (fastMA < slowMA) return -1; // Bear
    return 0;  // Sideways
}

// Update the state transition matrix
function updateStateTransition(int pairIndex) {
    int currentState = getState(CurrencyPairs[pairIndex]);
    int lastState = StateMatrix[pairIndex][2]; // Store last state
    StateMatrix[pairIndex][lastState + 1][currentState + 1]++;
    StateMatrix[pairIndex][2] = currentState; // Update last state
}

// Main trading function
function run() {
    set(PLOTNOW);

    // Initialize networks
    initializeCorrelationNetwork();
    calculateArbitrage();

    // Update state transitions for each pair
    for (int i = 0; i < PAIRS; i++) {
        updateStateTransition(i);
    }

    // Example: Trade when arbitrage is detected
    for (int i = 0; i < PAIRS; i++) {
        for (int j = 0; j < PAIRS; j++) {
            if (ArbitrageMatrix[i][j] > 0.01) { // Arbitrage threshold
                enterLong(CurrencyPairs[i]);
                enterShort(CurrencyPairs[j]);
            }
        }
    }
}