Algorithm Complexity
You are tasked with assessing the efficiency of the trading algorithm.

Scenario
The algorithm evaluates all possible trade paths across 𝑃𝐴𝐼𝑅𝑆 currency pairs to identify the most profitable path. Each path must satisfy a profitability threshold that is adjusted dynamically based on real-time performance. Trades are executed only when the risk-adjusted profit surpasses the threshold. The system operates continuously, recalculating profitability every second.

Challenge Questions

Graph Analysis:

Given 𝑃𝐴𝐼𝑅𝑆=28, the graph has ∣𝑉∣=28 vertices. How many edges ∣𝐸∣ exist in this graph if all trades are considered? Assume the graph is fully connected but excludes self-loops.

Path Complexity:

How many possible paths can exist from a source currency pair 𝐶𝑠 to a target pair 𝐶𝑒 if loops and revisits are allowed?
Bellman-Ford Complexity:

The Bellman-Ford algorithm iterates over all edges ∣𝐸∣ for ∣𝑉∣−1 rounds. Calculate the total computational complexity in terms of ∣𝑉∣ and ∣𝐸∣. Dynamic Threshold Adjustment:

If the threshold Δ is recalculated using volatility data for each currency pair and there are 50 price data points per pair, what is the time complexity of the threshold update process?

Scalability:

If 𝑃𝐴𝐼𝑅𝑆 increases to 56, describe how the computational complexity changes for: Profitability matrix calculation. Bellman-Ford algorithm. Dynamic threshold adjustment. Real-Time Execution:

Assume profitability recalculations are triggered every second. What is the expected latency for processing
𝑃𝐴𝐼𝑅𝑆= 28 if the system can handle 100,000 operations per second?


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 ProfitMatrix[PAIRS][PAIRS]; // Edge weights (profitability)
int Previous[PAIRS];            // Stores the previous node in the path
vars PathProfit[PAIRS];         // Stores cumulative profit along the path
vars DynamicDeltaThreshold;     // Dynamic threshold to execute trades

// Function to calculate profitability matrix
function calculateProfitMatrix() {
    for (int i = 0; i < PAIRS; i++) {
        for (int j = 0; j < PAIRS; j++) {
            if (i != j) {
                var priceRatio = price(CurrencyPairs[i]) / price(CurrencyPairs[j]);
                ProfitMatrix[i][j] = log(priceRatio); // Logarithmic profitability
            } else {
                ProfitMatrix[i][j] = 0; // No self-loop
            }
        }
    }
}

// Calculate the Dynamic Delta Threshold with risk-adjustment and feedback
function calculateDynamicDeltaThreshold() {
    var totalRiskAdjustedProfit = 0;
    int count = 0;

    for (int i = 0; i < PAIRS; i++) {
        for (int j = 0; j < PAIRS; j++) {
            if (i != j && ProfitMatrix[i][j] > 0) {
                var volatility = StdDev(series(price(CurrencyPairs[i])), 50); // 50-period volatility
                var riskAdjustedProfit = ProfitMatrix[i][j] / volatility; // Risk-adjusted profit
                totalRiskAdjustedProfit += riskAdjustedProfit;
                count++;
            }
        }
    }

    if (count > 0) {
        var baselineThreshold = totalRiskAdjustedProfit / count; // Average risk-adjusted profit
        var performanceFactor = Equity / MaxEquity; // Performance feedback
        DynamicDeltaThreshold = baselineThreshold * performanceFactor; // Adjust threshold dynamically
    } else {
        DynamicDeltaThreshold = 0.001; // Default fallback
    }

    // Log the threshold for backtesting and analysis
    printf("DynamicDeltaThreshold: %.6f\n", DynamicDeltaThreshold);
}

// Bellman-Ford algorithm to find paths with the highest cumulative profit
function bellmanFord(int start) {
    for (int i = 0; i < PAIRS; i++) {
        PathProfit[i] = -1e10; // Negative infinity for unvisited nodes
        Previous[i] = -1;     // No predecessor
    }
    PathProfit[start] = 0; // Profit starts at 0 from the source

    for (int k = 0; k < PAIRS - 1; k++) {
        for (int i = 0; i < PAIRS; i++) {
            for (int j = 0; j < PAIRS; j++) {
                if (ProfitMatrix[i][j] != 0 && PathProfit[i] + ProfitMatrix[i][j] > PathProfit[j]) {
                    PathProfit[j] = PathProfit[i] + ProfitMatrix[i][j]; // Update cumulative profit
                    Previous[j] = i; // Track the path
                }
            }
        }
    }
}

// Execute trades along the highest cumulative profit path
function executePath(int start, int end) {
    int current = end;

    while (current != -1) {
        int previous = Previous[current];
        if (previous == -1) break;

        if (ProfitMatrix[previous][current] > 0) {
            enterLong(CurrencyPairs[previous]);
            enterShort(CurrencyPairs[current]);
        } else {
            enterShort(CurrencyPairs[previous]);
            enterLong(CurrencyPairs[current]);
        }

        current = previous;
    }
}

// Continuously execute trades while conditions exist
function executeContinuousTrades(int start) {
    while (1) {
        calculateProfitMatrix();          // Update the graph with live data
        calculateDynamicDeltaThreshold(); // Adjust the threshold dynamically
        bellmanFord(start);               // Recalculate paths with the highest cumulative profit

        for (int i = 0; i < PAIRS; i++) {
            for (int j = 0; j < PAIRS; j++) {
                if (i != j && ProfitMatrix[i][j] > DynamicDeltaThreshold) {
                    enterLong(CurrencyPairs[i]);
                    enterShort(CurrencyPairs[j]);
                    printf("Executing Trade: Long %s, Short %s\n", CurrencyPairs[i], CurrencyPairs[j]);
                }
            }
        }

        // Add a condition to exit the loop for backtesting or analysis
        if (isBacktest() && getBacktestPeriod() == "End") {
            break;
        }
    }
}

// Main trading function
function run() {
    set(PLOTNOW);
    int startPair = 0; // Start from the first currency pair

    executeContinuousTrades(startPair);
}