IC Markets

Correlated Pairs = Correlated Risk

Master exponential money management, position sizing calculators, strict daily stop-loss limits, and overcoming FOMO on micro-timeframes.
PTScalper
Site Admin
Posts: 1114
Joined: Mon Jul 20, 2026 1:28 pm

Re: Correlated Pairs = Correlated Risk

Post by PTScalper »

I prepared version for trading view traders in Pine V5.

To transition this tool to TradingView (Pine Script v5), we have to address a fundamental difference between the platforms: TradingView cannot read your live brokerage account or open positions.

Because Pine Script runs securely in a web browser, it doesn't know what you are currently trading on your broker. To replicate the exact same logic—including the lot size filter—you will need to tell the indicator which pairs you are trading and what your position sizes are via the indicator's settings menu.

Here is the complete Pine Script adaptation. It creates a sleek, visual table (HUD) on your chart, calculates the correlation dynamically, applies your lot size filter, and uses TradingView's native alerting system.

The Pine Script (v5)

Code: Select all

//@version=5
indicator("Portfolio Correlation Monitor [HUD]", overlay=true, max_labels_count=0)

// --- Settings & Filters ---
lookback = input.int(100, "Correlation Periods", group="Core Settings")
minLot = input.float(0.50, "Minimum Lot Size Filter", group="Core Settings", tooltip="Positions smaller than this will be ignored in the calculation.")
alertThresh = input.float(0.80, "Alert Threshold", group="Core Settings")

// --- Manual Position Inputs ---
// Because TradingView cannot read your live broker data, you toggle your active trades here.
g1 = "Position 1"
u1 = input.bool(true, "Enable", inline="p1", group=g1)
s1 = input.symbol("FX:EURUSD", "", inline="p1", group=g1)
l1 = input.float(1.0, "Lot Size", inline="p1", group=g1)

g2 = "Position 2"
u2 = input.bool(true, "Enable", inline="p2", group=g2)
s2 = input.symbol("FX:GBPUSD", "", inline="p2", group=g2)
l2 = input.float(1.0, "Lot Size", inline="p2", group=g2)

g3 = "Position 3"
u3 = input.bool(false, "Enable", inline="p3", group=g3)
s3 = input.symbol("FX:USDJPY", "", inline="p3", group=g3)
l3 = input.float(0.1, "Lot Size", inline="p3", group=g3)

g4 = "Position 4"
u4 = input.bool(false, "Enable", inline="p4", group=g4)
s4 = input.symbol("FX:AUDUSD", "", inline="p4", group=g4)
l4 = input.float(1.0, "Lot Size", inline="p4", group=g4)

g5 = "Position 5"
u5 = input.bool(false, "Enable", inline="p5", group=g5)
s5 = input.symbol("FX:USDCAD", "", inline="p5", group=g5)
l5 = input.float(1.0, "Lot Size", inline="p5", group=g5)

// --- Fetch Price Data ---
c1 = request.security(s1, timeframe.period, close)
c2 = request.security(s2, timeframe.period, close)
c3 = request.security(s3, timeframe.period, close)
c4 = request.security(s4, timeframe.period, close)
c5 = request.security(s5, timeframe.period, close)

// --- Filter Logic ---
v1 = u1 and l1 >= minLot
v2 = u2 and l2 >= minLot
v3 = u3 and l3 >= minLot
v4 = u4 and l4 >= minLot
v5 = u5 and l5 >= minLot

// --- Calculate Correlations (Pearson) ---
corr12 = ta.correlation(c1, c2, lookback)
corr13 = ta.correlation(c1, c3, lookback)
corr14 = ta.correlation(c1, c4, lookback)
corr15 = ta.correlation(c1, c5, lookback)
corr23 = ta.correlation(c2, c3, lookback)
corr24 = ta.correlation(c2, c4, lookback)
corr25 = ta.correlation(c2, c5, lookback)
corr34 = ta.correlation(c3, c4, lookback)
corr35 = ta.correlation(c3, c5, lookback)
corr45 = ta.correlation(c4, c5, lookback)

// Build arrays to dynamically size the table
var pair_names = array.new_string()
var pair_corrs = array.new_float()

array.clear(pair_names)
array.clear(pair_corrs)

if v1 and v2
    array.push(pair_names, s1 + " & " + s2)
    array.push(pair_corrs, corr12)
if v1 and v3
    array.push(pair_names, s1 + " & " + s3)
    array.push(pair_corrs, corr13)
if v1 and v4
    array.push(pair_names, s1 + " & " + s4)
    array.push(pair_corrs, corr14)
if v1 and v5
    array.push(pair_names, s1 + " & " + s5)
    array.push(pair_corrs, corr15)
if v2 and v3
    array.push(pair_names, s2 + " & " + s3)
    array.push(pair_corrs, corr23)
if v2 and v4
    array.push(pair_names, s2 + " & " + s4)
    array.push(pair_corrs, corr24)
if v2 and v5
    array.push(pair_names, s2 + " & " + s5)
    array.push(pair_corrs, corr25)
if v3 and v4
    array.push(pair_names, s3 + " & " + s4)
    array.push(pair_corrs, corr34)
if v3 and v5
    array.push(pair_names, s3 + " & " + s5)
    array.push(pair_corrs, corr35)
if v4 and v5
    array.push(pair_names, s4 + " & " + s5)
    array.push(pair_corrs, corr45)

// --- Averages & Alerts ---
float sum_corr = 0.0
int cnt = array.size(pair_corrs)
if cnt > 0
    for i = 0 to cnt - 1
        sum_corr += array.get(pair_corrs, i)
        
avg_corr = cnt > 0 ? sum_corr / cnt : na

// Send TradingView Alert if correlation crosses the threshold
if ta.crossover(avg_corr, alertThresh)
    alert("RISK WARNING: Portfolio correlation crossed above " + str.tostring(alertThresh) + " (Currently: " + str.tostring(avg_corr, "#.##") + ")", alert.freq_once_per_bar)

// --- Table UI (HUD) ---
var table hud = table.new(position.top_right, 2, 12, border_width=1, border_color=color.new(color.gray, 50), frame_color=color.new(color.gray, 50), frame_width=1)

if barstate.islast
    if cnt < 1
        table.cell(hud, 0, 0, "Correlation Monitor", text_color=color.white, bgcolor=color.new(color.blue, 30), text_halign=text.align_center)
        table.cell(hud, 0, 1, "Not enough valid positions.\nCheck toggles & Lot Size filter.", text_color=color.gray, bgcolor=color.new(color.black, 10))
    else
        table.cell(hud, 0, 0, "Pair", text_color=color.white, bgcolor=color.new(color.blue, 30))
        table.cell(hud, 1, 0, "Correlation", text_color=color.white, bgcolor=color.new(color.blue, 30))
        
        for i = 0 to cnt - 1
            c_val = array.get(pair_corrs, i)
            // Clean up the prefix "FX:" or "OANDA:" to make the table readable
            clean_name = str.replace_all(array.get(pair_names, i), "FX:", "")
            clean_name := str.replace_all(clean_name, "OANDA:", "")
            
            row_color = c_val >= alertThresh ? color.new(color.red, 70) : color.new(color.black, 40)
            
            table.cell(hud, 0, i+1, clean_name, text_color=color.white, bgcolor=color.new(color.black, 50))
            table.cell(hud, 1, i+1, str.tostring(c_val, "#.##"), text_color=color.white, bgcolor=row_color)
            
        // Average Row
        avg_color = avg_corr >= alertThresh ? color.new(color.red, 30) : color.new(color.blue, 30)
        table.cell(hud, 0, cnt+1, "AVERAGE", text_color=color.white, bgcolor=color.new(color.blue, 30))
        table.cell(hud, 1, cnt+1, str.tostring(avg_corr, "#.##"), text_color=color.white, bgcolor=avg_color)
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 1114
Joined: Mon Jul 20, 2026 1:28 pm

Re: Correlated Pairs = Correlated Risk

Post by PTScalper »

How to use this in TradingView

1.Open Pine Editor:

At the bottom of your TradingView chart, click the Pine Editor tab.

2.Paste and Save:

Delete any existing code, paste the script above, and click Save.

3.Add to Chart:

Click Add to Chart. A table will appear in the top-right corner of your screen.

4.Configure your Positions:

Double-click the indicator (or click the gear icon) to open the settings menu. Check the box next to any pair you are actively trading, input your lot size, and the HUD will automatically calculate the math and drop the pairs that are under your 0.50 minimum lot threshold.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 1114
Joined: Mon Jul 20, 2026 1:28 pm

Re: Correlated Pairs = Correlated Risk

Post by PTScalper »

Setting up Mobile/Push Alerts

Unlike MetaTrader's built-in alert cooldown, TradingView handles alert spam automatically based on how you configure the trigger.

1.) Press Alt + A (or Option + A on Mac) to open the Alert menu.

2.) Under Condition, select Portfolio Correlation Monitor [HUD].

3.) Choose Any alert() function call.

4.) Select Once Per Bar Close to ensure you only get notified once when the correlation definitively closes above +0.80, rather than getting spammed by intra-minute price wicks.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 1114
Joined: Mon Jul 20, 2026 1:28 pm

Re: Correlated Pairs = Correlated Risk

Post by PTScalper »

To meet institutional or professional development standards, this version introduces strict naming conventions, modular logic segmentation, enhanced HUD aesthetics (using subtle, professional color palettes), and formalized risk-alert messaging.

Professional Pine Script (v5)

Code: Select all

//@version=5
indicator("Risk Management: Portfolio Correlation Monitor", overlay=true, max_labels_count=0)

// ========================================================================= //
// 1. RISK MANAGEMENT PARAMETERS
// ========================================================================= //
grp_risk = "Risk Management Settings"
int   lookback_period   = input.int(100, "Correlation Lookback (Bars)", group=grp_risk, tooltip="Lookback period for the Pearson correlation calculation.")
float min_position_size = input.float(0.50, "Minimum Position Size (Lots)", group=grp_risk, tooltip="Excludes nominal or micro positions from systemic risk calculations.")
float critical_thresh   = input.float(0.80, "Critical Correlation Threshold", group=grp_risk, tooltip="Triggers a system alert when aggregate correlation exceeds this limit.")

// ========================================================================= //
// 2. PORTFOLIO EXPOSURE INPUTS
// ========================================================================= //
grp_p1 = "Portfolio Asset 1"
bool   pos1_active = input.bool(true, "Enabled", inline="P1", group=grp_p1)
string pos1_symbol = input.symbol("FX:EURUSD", "", inline="P1", group=grp_p1)
float  pos1_volume = input.float(1.0, "Volume", inline="P1", group=grp_p1)

grp_p2 = "Portfolio Asset 2"
bool   pos2_active = input.bool(true, "Enabled", inline="P2", group=grp_p2)
string pos2_symbol = input.symbol("FX:GBPUSD", "", inline="P2", group=grp_p2)
float  pos2_volume = input.float(1.0, "Volume", inline="P2", group=grp_p2)

grp_p3 = "Portfolio Asset 3"
bool   pos3_active = input.bool(false, "Enabled", inline="P3", group=grp_p3)
string pos3_symbol = input.symbol("FX:USDJPY", "", inline="P3", group=grp_p3)
float  pos3_volume = input.float(0.1, "Volume", inline="P3", group=grp_p3)

grp_p4 = "Portfolio Asset 4"
bool   pos4_active = input.bool(false, "Enabled", inline="P4", group=grp_p4)
string pos4_symbol = input.symbol("FX:AUDUSD", "", inline="P4", group=grp_p4)
float  pos4_volume = input.float(1.0, "Volume", inline="P4", group=grp_p4)

grp_p5 = "Portfolio Asset 5"
bool   pos5_active = input.bool(false, "Enabled", inline="P5", group=grp_p5)
string pos5_symbol = input.symbol("FX:USDCAD", "", inline="P5", group=grp_p5)
float  pos5_volume = input.float(1.0, "Volume", inline="P5", group=grp_p5)

// ========================================================================= //
// 3. MARKET DATA ACQUISITION
// ========================================================================= //
float price1 = request.security(pos1_symbol, timeframe.period, close)
float price2 = request.security(pos2_symbol, timeframe.period, close)
float price3 = request.security(pos3_symbol, timeframe.period, close)
float price4 = request.security(pos4_symbol, timeframe.period, close)
float price5 = request.security(pos5_symbol, timeframe.period, close)

// ========================================================================= //
// 4. FILTERING & VALIDATION LOGIC
// ========================================================================= //
bool is_valid_p1 = pos1_active and (pos1_volume >= min_position_size)
bool is_valid_p2 = pos2_active and (pos2_volume >= min_position_size)
bool is_valid_p3 = pos3_active and (pos3_volume >= min_position_size)
bool is_valid_p4 = pos4_active and (pos4_volume >= min_position_size)
bool is_valid_p5 = pos5_active and (pos5_volume >= min_position_size)

// ========================================================================= //
// 5. STATISTICAL CALCULATIONS (PEARSON COEFFICIENT)
// ========================================================================= //
float corr_12 = ta.correlation(price1, price2, lookback_period)
float corr_13 = ta.correlation(price1, price3, lookback_period)
float corr_14 = ta.correlation(price1, price4, lookback_period)
float corr_15 = ta.correlation(price1, price5, lookback_period)
float corr_23 = ta.correlation(price2, price3, lookback_period)
float corr_24 = ta.correlation(price2, price4, lookback_period)
float corr_25 = ta.correlation(price2, price5, lookback_period)
float corr_34 = ta.correlation(price3, price4, lookback_period)
float corr_35 = ta.correlation(price3, price5, lookback_period)
float corr_45 = ta.correlation(price4, price5, lookback_period)

// Dynamic arrays for aggregation
var string[] active_pairs = array.new_string()
var float[]  active_corrs = array.new_float()

array.clear(active_pairs)
array.clear(active_corrs)

// Aggregate valid permutations
if is_valid_p1 and is_valid_p2
    array.push(active_pairs, pos1_symbol + " / " + pos2_symbol)
    array.push(active_corrs, corr_12)
if is_valid_p1 and is_valid_p3
    array.push(active_pairs, pos1_symbol + " / " + pos3_symbol)
    array.push(active_corrs, corr_13)
if is_valid_p1 and is_valid_p4
    array.push(active_pairs, pos1_symbol + " / " + pos4_symbol)
    array.push(active_corrs, corr_14)
if is_valid_p1 and is_valid_p5
    array.push(active_pairs, pos1_symbol + " / " + pos5_symbol)
    array.push(active_corrs, corr_15)
if is_valid_p2 and is_valid_p3
    array.push(active_pairs, pos2_symbol + " / " + pos3_symbol)
    array.push(active_corrs, corr_23)
if is_valid_p2 and is_valid_p4
    array.push(active_pairs, pos2_symbol + " / " + pos4_symbol)
    array.push(active_corrs, corr_24)
if is_valid_p2 and is_valid_p5
    array.push(active_pairs, pos2_symbol + " / " + pos5_symbol)
    array.push(active_corrs, corr_25)
if is_valid_p3 and is_valid_p4
    array.push(active_pairs, pos3_symbol + " / " + pos4_symbol)
    array.push(active_corrs, corr_34)
if is_valid_p3 and is_valid_p5
    array.push(active_pairs, pos3_symbol + " / " + pos5_symbol)
    array.push(active_corrs, corr_35)
if is_valid_p4 and is_valid_p5
    array.push(active_pairs, pos4_symbol + " / " + pos5_symbol)
    array.push(active_corrs, corr_45)

// ========================================================================= //
// 6. SYSTEM ALERTS & AGGREGATION
// ========================================================================= //
float aggregate_correlation = 0.0
int   valid_pair_count      = array.size(active_corrs)

if valid_pair_count > 0
    float sum = 0.0
    for i = 0 to valid_pair_count - 1
        sum += array.get(active_corrs, i)
    aggregate_correlation := sum / valid_pair_count
else
    aggregate_correlation := na

// Alert Generation
if ta.crossover(aggregate_correlation, critical_thresh)
    string alert_msg = "SYSTEM ALERT: Portfolio correlation breached critical threshold. Current Value: " + str.tostring(aggregate_correlation, "#.##")
    alert(alert_msg, alert.freq_once_per_bar_close)

// ========================================================================= //
// 7. HEADS UP DISPLAY (HUD) RENDERER
// ========================================================================= //
// Professional Institutional Color Palette
color col_bg_header = color.rgb(33, 37, 41)       // Dark Slate
color col_bg_row    = color.rgb(43, 48, 53)       // Muted Dark Gray
color col_warn_bg   = color.rgb(108, 30, 30)      // Muted Crimson
color col_text      = color.rgb(248, 249, 250)    // Off-White
color col_border    = color.rgb(73, 80, 87)       // Slate Border

var table risk_hud = table.new(position.top_right, 2, 12, border_width=1, border_color=col_border, frame_color=col_border, frame_width=1)

if barstate.islast
    if valid_pair_count < 1
        table.cell(risk_hud, 0, 0, "RISK MONITOR", text_color=col_text, bgcolor=col_bg_header, text_halign=text.align_center)
        table.cell(risk_hud, 0, 1, "Insufficient volume/positions.", text_color=color.gray, bgcolor=col_bg_row)
    else
        table.cell(risk_hud, 0, 0, "ASSET PAIR", text_color=col_text, bgcolor=col_bg_header)
        table.cell(risk_hud, 1, 0, "CORR COEFFICIENT", text_color=col_text, bgcolor=col_bg_header)
        
        for i = 0 to valid_pair_count - 1
            float  current_corr = array.get(active_corrs, i)
            string raw_name     = array.get(active_pairs, i)
            
            // Format symbol names for cleaner UI presentation
            string display_name = str.replace_all(raw_name, "FX:", "")
            display_name := str.replace_all(display_name, "OANDA:", "")
            display_name := str.replace_all(display_name, "FOREXCOM:", "")
            
            color row_bg = current_corr >= critical_thresh ? col_warn_bg : col_bg_row
            
            table.cell(risk_hud, 0, i+1, display_name, text_color=col_text, bgcolor=col_bg_row)
            table.cell(risk_hud, 1, i+1, str.tostring(current_corr, "#.##"), text_color=col_text, bgcolor=row_bg)
            
        // Render System Average
        color avg_bg = aggregate_correlation >= critical_thresh ? col_warn_bg : col_bg_header
        table.cell(risk_hud, 0, valid_pair_count+1, "PORTFOLIO AGGREGATE", text_color=col_text, bgcolor=col_bg_header)
        table.cell(risk_hud, 1, valid_pair_count+1, str.tostring(aggregate_correlation, "#.##"), text_color=col_text, bgcolor=avg_bg)
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 1114
Joined: Mon Jul 20, 2026 1:28 pm

Re: Correlated Pairs = Correlated Risk

Post by PTScalper »

Implementation Guide

1.Deploy via Pine Editor:

Access the Pine Editor at the bottom of your TradingView interface, clear the workspace, and paste the revised source code.

2.Initialize the HUD:

Click Add to Chart. The HUD will render in the top right corner using an institutional dark-mode color scheme.

3.Configure Portfolio Parameters:

Access the indicator settings via the gear icon. Expand the Risk Management Settings to define your volume threshold and alert criteria, then input your active trades under the respective Portfolio Asset dropdowns.

4.Establish Server-Side Alerts:

To receive notifications on your mobile device or via webhook, use Alt + A. Select Risk Management: Portfolio Correlation Monitor as the condition, choose Any alert() function call, and set the trigger to Once Per Bar Close.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 1114
Joined: Mon Jul 20, 2026 1:28 pm

Re: Correlated Pairs = Correlated Risk

Post by PTScalper »

Here is the professional-grade adaptation for cTrader (Automate / cBot) written in C#.

This cBot mimics the institutional risk-monitoring logic we built for TradingView and MetaTrader: it scans your active open positions, filters out micro-lots below your threshold, calculates the Pearson correlation coefficient across historical bars, displays a clean on-chart HUD panel, and triggers desktop/push alerts if portfolio correlation breaches your threshold.

The cTrader cBot (C#)

Code: Select all

using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class PortfolioCorrelationMonitor : Robot
    {
        [Parameter("Correlation Lookback (Bars)", Group = "Risk Management", DefaultValue = 100, MinValue = 10)]
        public int CorrelationPeriods { get; set; }

        [Parameter("Timeframe", Group = "Risk Management", DefaultValue = "Hour")]
        public TimeFrame TimeFrame { get; set; }

        [Parameter("Minimum Position Size (Lots)", Group = "Risk Management", DefaultValue = 0.50, MinValue = 0.01, Step = 0.01)]
        public double MinLotSize { get; set; }

        [Parameter("Critical Correlation Threshold", Group = "Risk Management", DefaultValue = 0.80, MinValue = -1.0, MaxValue = 1.0, Step = 0.05)]
        public double AlertThreshold { get; set; }

        [Parameter("Enable Notifications", Group = "Alerts", DefaultValue = true)]
        public bool EnableAlerts { get; set; }

        [Parameter("Cooldown (Minutes)", Group = "Alerts", DefaultValue = 60, MinValue = 1)]
        public int AlertCooldownMinutes { get; set; }

        private DateTime _lastAlertTime = DateTime.MinValue;
        private TextBlock _hudTextBlock;

        protected override void OnStart()
        {
            // Build a clean on-chart HUD panel
            CreateHudPanel();

            // Run an initial calculation tick
            EvaluatePortfolioCorrelation();
        }

        protected override void OnTick()
        {
            // cTrader updates positions dynamically on tick; evaluate correlation continuously
            EvaluatePortfolioCorrelation();
        }

        private void EvaluatePortfolioCorrelation()
        {
            // 1. Gather unique active symbols meeting the volume threshold
            var activePositions = Positions.Where(p => p.VolumeInUnits >= (MinLotSize * Symbol.VolumeInUnitsMin))
                                           .Select(p => p.SymbolName)
                                           .Distinct()
                                           .ToArray();

            if (activePositions.Length < 2)
            {
                UpdateHud("RISK MONITOR\n-------------------------\nInsufficient active positions\n(Min Volume: " + MinLotSize + " lots)");
                return;
            }

            double totalCorrelation = 0;
            int pairCount = 0;
            string hudText = "RISK MONITOR (HUD)\n-------------------------\n";

            // 2. Calculate pairwise Pearson correlation
            for (int i = 0; i < activePositions.Length - 1; i++)
            {
                for (int j = i + 1; j < activePositions.Length; j++)
                {
                    string sym1 = activePositions[i];
                    string sym2 = activePositions[j];

                    double corr = CalculatePearson(sym1, sym2, CorrelationPeriods, TimeFrame);
                    totalCorrelation += corr;
                    pairCount++;

                    hudText += $"{sym1} / {sym2} : {corr:F2}\n";
                }
            }

            // 3. Compute aggregate average portfolio correlation
            double avgCorrelation = totalCorrelation / pairCount;
            hudText += "-------------------------\n";
            hudText += $"PORTFOLIO AGGREGATE: {avgCorrelation:F2}";

            UpdateHud(hudText);

            // 4. Trigger Alerts if Threshold is Breached
            if (EnableAlerts && avgCorrelation >= AlertThreshold)
            {
                if ((DateTime.UtcNow - _lastAlertTime).TotalMinutes >= AlertCooldownMinutes)
                {
                    string alertMsg = $"SYSTEM ALERT: Portfolio correlation breached critical threshold ({avgCorrelation:F2}).";
                    Notifications.PlaySound("alert.wav");
                    Print(alertMsg);
                    _lastAlertTime = DateTime.UtcNow;
                }
            }
        }

        private double CalculatePearson(string sym1, string sym2, int periods, TimeFrame tf)
        {
            var bars1 = MarketData.GetBars(tf, sym1);
            var bars2 = MarketData.GetBars(tf, sym2);

            int count = Math.Min(periods, Math.Min(bars1.Count - 1, bars2.Count - 1));
            if (count < 2) return 0;

            double sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0, sumY2 = 0;
            int validBars = 0;

            // Loop backwards from the most recently closed bars
            for (int i = 1; i <= count; i++)
            {
                int index = bars1.Count - 1 - i;
                if (index < 0) continue;

                double p1 = bars1.ClosePrices[index];
                double p2 = bars2.ClosePrices[index];

                sumX += p1;
                sumY += p2;
                sumXY += (p1 * p2);
                sumX2 += Math.Pow(p1, 2);
                sumY2 += Math.Pow(p2, 2);
                validBars++;
            }

            if (validBars < 2) return 0;

            double numerator = (validBars * sumXY) - (sumX * sumY);
            double denominator = Math.Sqrt(((validBars * sumX2) - Math.Pow(sumX, 2)) * ((validBars * sumY2) - Math.Pow(sumY, 2)));

            if (denominator == 0) return 0;

            return numerator / denominator;
        }

        private void CreateHudPanel()
        {
            var border = new Border
            {
                HorizontalAlignment = HorizontalAlignment.Right,
                VerticalAlignment = VerticalAlignment.Top,
                Margin = "20 20 20 20",
                Padding = "10 10 10 10",
                BackgroundColor = Color.FromArgb(200, 33, 37, 41),
                BorderColor = Color.FromArgb(255, 73, 80, 87),
                BorderThickness = 1
            };

            _hudTextBlock = new TextBlock
            {
                Text = "Initializing Risk Monitor...",
                ForegroundColor = Color.White,
                FontSize = 12,
                FontFamily = "Consolas"
            };

            border.Child = _hudTextBlock;
            Chart.AddControl(border);
        }

        private void UpdateHud(string text)
        {
            if (_hudTextBlock != null)
            {
                _hudTextBlock.Text = text;
            }
        }
    }
}
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 1114
Joined: Mon Jul 20, 2026 1:28 pm

Re: Correlated Pairs = Correlated Risk

Post by PTScalper »

How to Install and Run in cTrader

1.Open cTrader Automate:

Launch your cTrader terminal, navigate to the Automate tab on the left-hand menu, and click New cBot.

2.Paste and Build:

Name the cBot PortfolioCorrelationMonitor, clear out the default template code, paste the script above into the editor, and click the Build button at the top. Ensure it compiles cleanly with zero errors.

3.Configure Parameters:

In the instances panel on the left, click Add Instance. Adjust your lookback periods, volume filters (in lots), and alert thresholds in the parameters panel.

4.Start the cBot:

Click the Play button to run the cBot. A sleek institutional HUD panel will anchor to the top-right corner of your chart, tracking your live market exposure in real time.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Post Reply