To make this a truly "Professional" grade indicator for cTrader, we need to upgrade it from a simple script to a robust trading tool.
Here is what makes this updated version "Pro":
Strictly Non-Repainting: Pro indicators evaluate signals on closed candles. This version looks at index - 1 to ensure a signal is permanently locked in and won't flicker on and off during live price movement.
The "Macro Trend" Filter (The Board of Directors): A good CEO doesn't fight the broader economy. I’ve added an optional 200 EMA filter. It will only show Buy signals if price is above the 200 EMA, and Sell signals if it's below.
ATR Dynamic Spacing: Instead of guessing the visual spacing for the arrows, it now uses the Average True Range (ATR). This means the arrows will perfectly scale their distance from the candles whether you are trading a 1-minute chart or a Daily chart.
Integrated Alerts: Added screen pop-ups and sound alerts for when a validated signal appears.
Signal to noise ratio from Business into forex trading?
Re: Signal to noise ratio from Business into forex trading?
The Professional cTrader (C#) Implementation
Code: Select all
using System;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
namespace cAlgo
{
[Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class CEOSignalVsNoisePro : Indicator
{
// --- 1. Moving Averages (The Idea) ---
[Parameter("Fast EMA Length", Group = "Signal Generation", DefaultValue = 9, MinValue = 1)]
public int FastPeriods { get; set; }
[Parameter("Slow EMA Length", Group = "Signal Generation", DefaultValue = 21, MinValue = 1)]
public int SlowPeriods { get; set; }
// --- 2. Noise Filter (The CEO) ---
[Parameter("ADX Length", Group = "Noise Filter (Momentum)", DefaultValue = 14, MinValue = 1)]
public int AdxPeriods { get; set; }
[Parameter("ADX Threshold", Group = "Noise Filter (Momentum)", DefaultValue = 20.0, MinValue = 0)]
public double AdxThreshold { get; set; }
// --- 3. Macro Trend Filter (The Board of Directors) ---
[Parameter("Use Macro Trend Filter", Group = "Macro Filter", DefaultValue = true)]
public bool UseMacroFilter { get; set; }
[Parameter("Macro EMA Length", Group = "Macro Filter", DefaultValue = 200, MinValue = 1)]
public int MacroPeriods { get; set; }
// --- 4. Alerts ---
[Parameter("Enable Desktop Alerts", Group = "Alerts", DefaultValue = true)]
public bool EnableAlerts { get; set; }
[Parameter("Enable Sound Alerts", Group = "Alerts", DefaultValue = true)]
public bool EnableSound { get; set; }
// --- Internal Variables ---
private ExponentialMovingAverage _fastEma;
private ExponentialMovingAverage _slowEma;
private ExponentialMovingAverage _macroEma;
private DirectionalMovementSystem _adx;
private AverageTrueRange _atr;
private DateTime _lastAlertTime;
protected override void Initialize()
{
// Initialize built-in indicators
_fastEma = Indicators.ExponentialMovingAverage(Bars.ClosePrices, FastPeriods);
_slowEma = Indicators.ExponentialMovingAverage(Bars.ClosePrices, SlowPeriods);
_macroEma = Indicators.ExponentialMovingAverage(Bars.ClosePrices, MacroPeriods);
_adx = Indicators.DirectionalMovementSystem(AdxPeriods);
// ATR used for professional visual spacing of chart objects
_atr = Indicators.AverageTrueRange(14, MovingAverageType.Simple);
}
public override void Calculate(int index)
{
// Ensure we have enough data to calculate the Macro EMA and ADX
if (index < MacroPeriods || index < AdxPeriods || index < 2)
return;
// --- EVALUATE ON CLOSED BARS ONLY (index - 1) TO PREVENT REPAINTING ---
int prev = index - 1;
int prev2 = index - 2;
// 1. Spotting the Crossover
bool crossedUp = _fastEma.Result[prev] > _slowEma.Result[prev] && _fastEma.Result[prev2] <= _slowEma.Result[prev2];
bool crossedDown = _fastEma.Result[prev] < _slowEma.Result[prev] && _fastEma.Result[prev2] >= _slowEma.Result[prev2];
if (!crossedUp && !crossedDown)
return;
// 2. Measure Noise (Momentum)
double currentAdx = _adx.ADX[prev];
bool hasMomentum = currentAdx > AdxThreshold;
// 3. Macro Trend Check (Board of Directors)
bool macroBullish = !UseMacroFilter || Bars.ClosePrices[prev] > _macroEma.Result[prev];
bool macroBearish = !UseMacroFilter || Bars.ClosePrices[prev] < _macroEma.Result[prev];
// 4. Dynamic Visual Spacing (ATR)
double spacing = _atr.Result[prev] * 0.6; // 60% of current ATR for clean spacing
string objectName = "CEO_Filter_" + prev;
// 5. Execution Logic
if (crossedUp)
{
if (hasMomentum && macroBullish)
{
// VALID BUY SIGNAL
Chart.DrawIcon(objectName, ChartIconType.UpArrow, prev, Bars.LowPrices[prev] - spacing, Color.LimeGreen);
TriggerAlert("BUY Signal - Momentum & Trend Aligned");
}
else
{
// NOISE (Filtered out)
Chart.DrawText(objectName, "X", prev, Bars.LowPrices[prev] - spacing, Color.DimGray);
}
}
else if (crossedDown)
{
if (hasMomentum && macroBearish)
{
// VALID SELL SIGNAL
Chart.DrawIcon(objectName, ChartIconType.DownArrow, prev, Bars.HighPrices[prev] + spacing, Color.Red);
TriggerAlert("SELL Signal - Momentum & Trend Aligned");
}
else
{
// NOISE (Filtered out)
Chart.DrawText(objectName, "X", prev, Bars.HighPrices[prev] + spacing, Color.DimGray);
}
}
}
// --- Alert Handler ---
private void TriggerAlert(string message)
{
// Only trigger alert if it's the live chart (IsLastBar) and we haven't already alerted for this specific candle
if (IsLastBar && Bars.LastBar.OpenTime != _lastAlertTime)
{
_lastAlertTime = Bars.LastBar.OpenTime;
string formattedMessage = string.Format("{0} | {1} {2} | {3}",
SymbolName, TimeFrame.ToString(), message, Server.Time.ToString("HH:mm"));
if (EnableAlerts)
{
Notifications.PlaySound(SoundType.Doorbell); // Play sound immediately
Chart.DrawStaticText("AlertText", formattedMessage, VerticalAlignment.Top, HorizontalAlignment.Right, Color.Gold);
// Note: cTrader's built in MessageBox pauses the thread.
// To avoid freezing the chart, we print to the log instead of a hard popup.
Print(formattedMessage);
}
}
}
}
}Re: Signal to noise ratio from Business into forex trading?
Key Changes to Notice in the UI:
Grouped Settings: When you add the indicator to your chart, the settings are now cleanly organized into categories (Signal Generation, Noise Filter, Macro Filter, Alerts).
The Log Window: When a real signal happens on the live edge of the chart, you will hear a chime, a golden text alert will flash on the top right of the chart, and the exact timestamp and pair will be printed in your cTrader Automate Log tab so you have a historical record of your signals.
Grouped Settings: When you add the indicator to your chart, the settings are now cleanly organized into categories (Signal Generation, Noise Filter, Macro Filter, Alerts).
The Log Window: When a real signal happens on the live edge of the chart, you will hear a chime, a golden text alert will flash on the top right of the chart, and the exact timestamp and pair will be printed in your cTrader Automate Log tab so you have a historical record of your signals.
Re: Signal to noise ratio from Business into forex trading?
Hi FTtrader,FTtrader wrote: Wed Sep 23, 2026 10:01 amHello PTscalper,PTScalper wrote: Sat Aug 22, 2026 12:46 pm Hi scalpers, traders.
As you all know if you made some business, that main purpose of CEO is to be able to understand what is just noise and actual signal.
I mean to understand what is important and what not. Because main purpose of business is to deliver value to customers and spend as low as possible in that process to create profit and keep alive.
The same it is with forex trading, you need to make as much as possible money with as low as possible losing trades.
You have to learn how to spot opportunity and how to filter noise.
You hit the nail on the head. In trading, just like in business, the "noise" will drain your capital (and your energy) through a thousand tiny cuts if you don't have a systematic way to filter it out and wait for the actual "signal."
Since your prompt is philosophical rather than a specific set of technical rules, I have designed a CEO Signal vs. Noise Filter in Pine Script (v5) based on your exact analogy.
Here is how it translates your business logic into code:
The Opportunity (The Idea): It uses a Fast and Slow Exponential Moving Average (EMA) crossover to spot potential momentum shifts.
The Noise Filter (The CEO's Desk): It uses the Average Directional Index (ADX) to measure market chop. If a crossover happens but the ADX is low, the script marks it as "Noise" (gray cross) so you don't waste your money. If the ADX is high, it marks it as a real "Signal" (Buy/Sell label).
Code: Select all
//@version=5 indicator("CEO Signal vs Noise Filter", overlay=true) // --- Inputs: Setting the CEO's Parameters --- fastLen = input.int(9, title="Fast EMA Length (Opportunity Spotter)") slowLen = input.int(21, title="Slow EMA Length (Baseline)") adxLen = input.int(14, title="ADX Length (Trend Measure)") adxThreshold = input.int(20, title="ADX Noise Filter Threshold") // --- 1. Spotting Potential Opportunities --- fastEma = ta.ema(close, fastLen) slowEma = ta.ema(close, slowLen) plot(fastEma, color=color.blue, title="Fast EMA") plot(slowEma, color=color.orange, title="Slow EMA") // --- 2. Filtering the Noise --- // ta.dmi returns three values; we only need the ADX to measure if the market is actually trending or just chopping. [diPlus, diMinus, adx] = ta.dmi(adxLen, adxLen) // --- 3. Business Logic (Signal vs Noise) --- // A real signal happens when EMAs cross AND the market has enough momentum to overcome the noise threshold. longSignal = ta.crossover(fastEma, slowEma) and adx > adxThreshold shortSignal = ta.crossunder(fastEma, slowEma) and adx > adxThreshold // Noise happens when EMAs cross, but the market has no real momentum (ADX is below threshold). noiseLong = ta.crossover(fastEma, slowEma) and adx <= adxThreshold noiseShort = ta.crossunder(fastEma, slowEma) and adx <= adxThreshold // --- 4. Chart Execution --- // Plotting Actual Signals (The high-probability trades) plotshape(series=longSignal, title="Actual Buy Signal", location=location.belowbar, color=color.green, style=shape.labelup, text="BUY\n(Signal)", textcolor=color.white) plotshape(series=shortSignal, title="Actual Sell Signal", location=location.abovebar, color=color.red, style=shape.labeldown, text="SELL\n(Signal)", textcolor=color.white) // Plotting the Noise (The trades you should ignore to save capital) plotshape(series=noiseLong, title="Ignored Noise Long", location=location.belowbar, color=color.gray, style=shape.xcross, text="Noise") plotshape(series=noiseShort, title="Ignored Noise Short", location=location.abovebar, color=color.gray, style=shape.xcross, text="Noise")
thank you, it seems to be cool to write such script to test it.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.