Here is the C# source code for cTrader (cAlgo).
Similar to the MT4 version, this renders in an oscillator subwindow using the PlotType.Histogram overlay. A blue line tracks the rolling Pearson correlation, while green, red, or gray histogram bars fill the space underneath when the specific regime conditions are met.
cTrader's API allows for highly accurate cross-asset data alignment. By using GetIndexByTime(), the script ensures that the exact timestamp on AUDUSD is matched with the corresponding timestamp on Gold, preventing errors if one asset has missing ticks during a quiet session.
AUDUSD commodity mood and short gold scalp hedges discussion
Re: AUDUSD commodity mood and short gold scalp hedges discussion
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: AUDUSD commodity mood and short gold scalp hedges discussion
cTrader (cAlgo) - Commodity Mood Indicator
In cTrader Automate, create a new Indicator, name it CommodityMood, paste the code below, and build it.
cTrader (cAlgo) - Commodity Mood Indicator
In cTrader Automate, create a new Indicator, name it CommodityMood, paste the code below, and build it.
In cTrader Automate, create a new Indicator, name it CommodityMood, paste the code below, and build it.
cTrader (cAlgo) - Commodity Mood Indicator
In cTrader Automate, create a new Indicator, name it CommodityMood, paste the code below, and build it.
Code: Select all
using cAlgo.API;
using cAlgo.API.Internals;
using System;
namespace cAlgo
{
[Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class CommodityMood : Indicator
{
// --- Inputs ---
[Parameter("Compare Asset (e.g. XAUUSD)", DefaultValue = "XAUUSD")]
public string CompareAsset { get; set; }
[Parameter("Correlation Length", DefaultValue = 20, MinValue = 5)]
public int CorrLen { get; set; }
[Parameter("Momentum Length (ROC)", DefaultValue = 10, MinValue = 2)]
public int MomLen { get; set; }
// --- Outputs ---
// Render order matters: put histograms first so the line draws on top of them
[Output("Bullish Theme", LineColor = "MediumSeaGreen", PlotType = PlotType.Histogram, Thickness = 3)]
public IndicatorDataSeries BullTheme { get; set; }
[Output("Bearish Theme", LineColor = "Crimson", PlotType = PlotType.Histogram, Thickness = 3)]
public IndicatorDataSeries BearTheme { get; set; }
[Output("Divergent Theme", LineColor = "Gray", PlotType = PlotType.Histogram, Thickness = 3)]
public IndicatorDataSeries DivTheme { get; set; }
[Output("Correlation", LineColor = "DodgerBlue", PlotType = PlotType.Line, Thickness = 2)]
public IndicatorDataSeries Correlation { get; set; }
// Variables
private Bars _compareBars;
protected override void Initialize()
{
// Load secondary symbol bars for the current timeframe
_compareBars = MarketData.GetBars(TimeFrame, CompareAsset);
// Draw static reference levels across the subwindow
Chart.DrawHorizontalLine("hline_70", 0.7, Color.FromArgb(80, Color.Green), 1, LineStyle.Lines);
Chart.DrawHorizontalLine("hline_minus70", -0.7, Color.FromArgb(80, Color.Red), 1, LineStyle.Lines);
Chart.DrawHorizontalLine("hline_zero", 0.0, Color.FromArgb(80, Color.Gray), 1, LineStyle.Lines);
}
public override void Calculate(int index)
{
// Ensure we have enough data to look back on the primary chart
if (index < Math.Max(CorrLen, MomLen)) return;
// Align secondary asset's index to current time on primary asset
int compareIndex = _compareBars.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]);
// If the time doesn't exist on the secondary asset (or lacks history), abort this tick
if (compareIndex < Math.Max(CorrLen, MomLen)) return;
// 1. Momentum (Rate of Change) to determine directional agreement
double roc1 = (Bars.ClosePrices[index] - Bars.ClosePrices[index - MomLen]) / Bars.ClosePrices[index - MomLen] * 100.0;
double roc2 = (_compareBars.ClosePrices[compareIndex] - _compareBars.ClosePrices[compareIndex - MomLen]) / _compareBars.ClosePrices[compareIndex - MomLen] * 100.0;
// 2. Pearson Correlation Calculation
double sumX = 0, sumY = 0;
for (int k = 0; k < CorrLen; k++)
{
sumX += Bars.ClosePrices[index - k];
sumY += _compareBars.ClosePrices[compareIndex - k];
}
double meanX = sumX / CorrLen;
double meanY = sumY / CorrLen;
double cov = 0, varX = 0, varY = 0;
for (int k = 0; k < CorrLen; k++)
{
double dx = Bars.ClosePrices[index - k] - meanX;
double dy = _compareBars.ClosePrices[compareIndex - k] - meanY;
cov += dx * dy;
varX += dx * dx;
varY += dy * dy;
}
double r = 0;
if (varX > 0 && varY > 0)
r = cov / Math.Sqrt(varX * varY);
Correlation[index] = r;
// 3. Directional Agreement
int agreement = 0;
if (roc1 > 0 && roc2 > 0) agreement = 1;
else if (roc1 < 0 && roc2 < 0) agreement = -1;
// 4. Regime Tagging
// Using NaN clears the histogram bars when conditions aren't met
BullTheme[index] = double.NaN;
BearTheme[index] = double.NaN;
DivTheme[index] = double.NaN;
if (r > 0.6 && agreement == 1) BullTheme[index] = r;
else if (r > 0.6 && agreement == -1) BearTheme[index] = r;
else if (r < 0.3 && agreement == 0) DivTheme[index] = r;
}
}
}Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: AUDUSD commodity mood and short gold scalp hedges discussion
To elevate this into a production-grade cTrader tool, we need to move past basic scripting and treat it like an enterprise C# component.
Here is the "Pro" version. It introduces:
Parameter Grouping: Clean UI organization in the cTrader instance panel.
Strong Typing: Replaces magic numbers (1, -1, 0) with a dedicated MarketRegime enum.
Signal Smoothing (Optional): Raw tick correlation is noisy. Added an EMA signal line to smooth the correlation output and prevent regime flickering.
Graceful Error Handling: Validates the secondary symbol on initialization to prevent silent crashes.
Subwindow HUD: Renders a clean text display in the subwindow showing live metrics (Current Correlation, XAU ROC, AUD ROC) for instant readability.
Here is the "Pro" version. It introduces:
Parameter Grouping: Clean UI organization in the cTrader instance panel.
Strong Typing: Replaces magic numbers (1, -1, 0) with a dedicated MarketRegime enum.
Signal Smoothing (Optional): Raw tick correlation is noisy. Added an EMA signal line to smooth the correlation output and prevent regime flickering.
Graceful Error Handling: Validates the secondary symbol on initialization to prevent silent crashes.
Subwindow HUD: Renders a clean text display in the subwindow showing live metrics (Current Correlation, XAU ROC, AUD ROC) for instant readability.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: AUDUSD commodity mood and short gold scalp hedges discussion
cTrader (cAlgo) - Pro Commodity Mood
Code: Select all
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using System;
namespace cAlgo
{
[Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class CommodityMoodPro : Indicator
{
private enum MarketRegime
{
BullishAgreement,
BearishAgreement,
Divergence,
Neutral
}
// --- Parameters: Symbols ---
[Parameter("Compare Asset", DefaultValue = "XAUUSD", Group = "Data Sources")]
public string CompareAsset { get; set; }
// --- Parameters: Periods ---
[Parameter("Correlation Length", DefaultValue = 20, MinValue = 5, Group = "Calculations")]
public int CorrLen { get; set; }
[Parameter("Momentum Length (ROC)", DefaultValue = 10, MinValue = 2, Group = "Calculations")]
public int MomLen { get; set; }
[Parameter("Smooth Correlation (EMA)", DefaultValue = 3, MinValue = 1, Group = "Calculations")]
public int SmoothLen { get; set; }
// --- Parameters: Thresholds ---
[Parameter("High Correlation Level", DefaultValue = 0.6, Step = 0.1, Group = "Thresholds")]
public double HighCorrLevel { get; set; }
[Parameter("Low Correlation Level", DefaultValue = 0.3, Step = 0.1, Group = "Thresholds")]
public double LowCorrLevel { get; set; }
// --- Outputs ---
[Output("Bullish Theme", LineColor = "MediumSeaGreen", PlotType = PlotType.Histogram, Thickness = 4)]
public IndicatorDataSeries BullTheme { get; set; }
[Output("Bearish Theme", LineColor = "Crimson", PlotType = PlotType.Histogram, Thickness = 4)]
public IndicatorDataSeries BearTheme { get; set; }
[Output("Divergent Theme", LineColor = "DimGray", PlotType = PlotType.Histogram, Thickness = 4)]
public IndicatorDataSeries DivTheme { get; set; }
[Output("Raw Correlation", LineColor = "FromArgb(80, 30, 144, 255)", PlotType = PlotType.Line, Thickness = 1)]
public IndicatorDataSeries RawCorrelation { get; set; }
[Output("Smoothed Correlation", LineColor = "DodgerBlue", PlotType = PlotType.Line, Thickness = 2)]
public IndicatorDataSeries SmoothedCorrelation { get; set; }
// --- Internal State ---
private Bars _compareBars;
private ExponentialMovingAverage _emaSmoothing;
private string _errorMessage;
protected override void Initialize()
{
try
{
_compareBars = MarketData.GetBars(TimeFrame, CompareAsset);
}
catch (Exception)
{
_errorMessage = $"ERROR: Cannot load symbol '{CompareAsset}'. Check naming convention.";
PrintError(_errorMessage);
return;
}
_emaSmoothing = Indicators.ExponentialMovingAverage(RawCorrelation, SmoothLen);
// Subwindow structural lines
Chart.DrawHorizontalLine("hline_upper", HighCorrLevel, Color.FromArgb(60, Color.Green), 1, LineStyle.Dots);
Chart.DrawHorizontalLine("hline_lower", -HighCorrLevel, Color.FromArgb(60, Color.Red), 1, LineStyle.Dots);
Chart.DrawHorizontalLine("hline_zero", 0.0, Color.FromArgb(100, Color.Gray), 1, LineStyle.Lines);
}
public override void Calculate(int index)
{
if (!string.IsNullOrEmpty(_errorMessage))
{
Chart.DrawText("ErrorMsg", _errorMessage, index, 0, Color.Red);
return;
}
if (index < Math.Max(CorrLen, MomLen)) return;
int compareIndex = _compareBars.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]);
if (compareIndex < Math.Max(CorrLen, MomLen)) return;
// 1. Momentum
double primaryPast = Bars.ClosePrices[index - MomLen];
double comparePast = _compareBars.ClosePrices[compareIndex - MomLen];
if (primaryPast == 0 || comparePast == 0) return; // Prevent division by zero
double rocPrimary = (Bars.ClosePrices[index] - primaryPast) / primaryPast * 100.0;
double rocCompare = (_compareBars.ClosePrices[compareIndex] - comparePast) / comparePast * 100.0;
// 2. Pearson Correlation
double r = CalculatePearsonCorrelation(index, compareIndex, CorrLen);
RawCorrelation[index] = r;
// Wait for EMA to seed properly
if (index < Math.Max(CorrLen, MomLen) + SmoothLen) return;
double smoothedR = _emaSmoothing.Result[index];
SmoothedCorrelation[index] = smoothedR;
// 3. Determine Regime
MarketRegime regime = DetermineRegime(smoothedR, rocPrimary, rocCompare);
// 4. Render Histograms
BullTheme[index] = regime == MarketRegime.BullishAgreement ? smoothedR : double.NaN;
BearTheme[index] = regime == MarketRegime.BearishAgreement ? smoothedR : double.NaN;
DivTheme[index] = regime == MarketRegime.Divergence ? smoothedR : double.NaN;
// 5. Update HUD on the last tick
if (IsLastBar)
{
UpdateHUD(regime, smoothedR, rocPrimary, rocCompare);
}
}
private double CalculatePearsonCorrelation(int primaryIndex, int compareIndex, int length)
{
double sumX = 0, sumY = 0;
for (int k = 0; k < length; k++)
{
sumX += Bars.ClosePrices[primaryIndex - k];
sumY += _compareBars.ClosePrices[compareIndex - k];
}
double meanX = sumX / length;
double meanY = sumY / length;
double cov = 0, varX = 0, varY = 0;
for (int k = 0; k < length; k++)
{
double dx = Bars.ClosePrices[primaryIndex - k] - meanX;
double dy = _compareBars.ClosePrices[compareIndex - k] - meanY;
cov += dx * dy;
varX += dx * dx;
varY += dy * dy;
}
return (varX > 0 && varY > 0) ? cov / Math.Sqrt(varX * varY) : 0;
}
private MarketRegime DetermineRegime(double correlation, double rocPrimary, double rocCompare)
{
bool bullishAgreed = rocPrimary > 0 && rocCompare > 0;
bool bearishAgreed = rocPrimary < 0 && rocCompare < 0;
if (correlation > HighCorrLevel && bullishAgreed)
return MarketRegime.BullishAgreement;
if (correlation > HighCorrLevel && bearishAgreed)
return MarketRegime.BearishAgreement;
if (correlation < LowCorrLevel && (!bullishAgreed && !bearishAgreed))
return MarketRegime.Divergence;
return MarketRegime.Neutral;
}
private void UpdateHUD(MarketRegime regime, double correlation, double rocPrimary, double rocCompare)
{
string hudText = $"Regime: {regime}\n" +
$"Corr: {Math.Round(correlation, 2)}\n" +
$"{SymbolName} ROC: {Math.Round(rocPrimary, 3)}%\n" +
$"{CompareAsset} ROC: {Math.Round(rocCompare, 3)}%";
Color hudColor = regime switch
{
MarketRegime.BullishAgreement => Color.MediumSeaGreen,
MarketRegime.BearishAgreement => Color.Crimson,
MarketRegime.Divergence => Color.DimGray,
_ => Color.DarkGray
};
Chart.DrawText("MoodHUD", hudText, Chart.FirstVisibleBarIndex, Chart.TopY, hudColor);
}
}
}Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
-
LondonScalper
- Posts: 770
- Joined: Sat Sep 05, 2026 7:54 am
Re: AUDUSD commodity mood and short gold scalp hedges discussion
Your copper-versus-haven explanation matches what I see most of the time. When AUD fades and gold holds its bid mid-London, it is usually two separate stories that happen to share a morning.
I would put the rule more bluntly than "trade pure microstructure": once they diverge for more than a couple of M5 bars, I stop using one as a filter for the other. Before that point, gold firming is a small plus for an AUD long. After it, the correlation is noise, and AUDUSD gets judged on its own levels and spread.
The trap I fell into years ago was the opposite — reading the divergence as a sign that AUD would "catch up". Sometimes it does, but not on a scalp horizon, and not reliably enough to pay the spread on a cross-asset hunch.
The day-type tag stays in the journal. Over a quarter it shows which mornings AUD trades like a commodity currency and which it trades like a China proxy, and that is more use to me than any hedge ratio.
I would put the rule more bluntly than "trade pure microstructure": once they diverge for more than a couple of M5 bars, I stop using one as a filter for the other. Before that point, gold firming is a small plus for an AUD long. After it, the correlation is noise, and AUDUSD gets judged on its own levels and spread.
The trap I fell into years ago was the opposite — reading the divergence as a sign that AUD would "catch up". Sometimes it does, but not on a scalp horizon, and not reliably enough to pay the spread on a cross-asset hunch.
The day-type tag stays in the journal. Over a quarter it shows which mornings AUD trades like a commodity currency and which it trades like a China proxy, and that is more use to me than any hedge ratio.