How to use it in MetaTrader
Adding to Chart: Drag the indicator onto your chart.
Settings (F8): Double-click a Time input. MetaTrader has a built-in Date/Time picker in the inputs window. Simply click the dropdown, pick the date, and adjust the time to the specific candle where you made your decision. Type the price level.
Hover Tooltips: Because MetaTrader charts can get cluttered, you will only see the clean RBO or EH text on your chart. To read your journal notes (e.g., "Macro/News Proximity"), just rest your mouse cursor over the letters or the dotted line. The tooltip will appear automatically.
Tooltips Setting: If tooltips do not appear on hover, right click your MT4/MT5 chart -> Properties (F8) -> "Show object descriptions" must be checked.
Celebrating skipped trades as wins in the journal
Re: Celebrating skipped trades as wins in the journal
cTrader is uniquely suited for this because its API (cAlgo/C#) has a native, WPF-style UI framework built directly into the chart. We do not have to rely on clunky X/Y coordinates like in MetaTrader; we can build a sleek, docked institutional HUD that scales perfectly with your window.
Since cTrader’s native chart text does not support hover-tooltips, this version appends your custom filter/note directly to the label (e.g., RBO - HTF Invalidation) to maintain visibility without needing to open the indicator settings.
Since cTrader’s native chart text does not support hover-tooltips, this version appends your custom filter/note directly to the label (e.g., RBO - HTF Invalidation) to maintain visibility without needing to open the indicator settings.
Re: Celebrating skipped trades as wins in the journal
The cTrader C# Code: "Systematic Omission Journal"
1.) Open cTrader and go to the Automate tab on the left menu.
2.) Under the Indicators list, click New (the + icon).
3.) Name it SystematicOmissionJournal.
4.) Replace all the default code with the C# code below.
5.) Click Build (the hammer icon) at the top.
1.) Open cTrader and go to the Automate tab on the left menu.
2.) Under the Indicators list, click New (the + icon).
3.) Name it SystematicOmissionJournal.
4.) Replace all the default code with the C# code below.
5.) Click Build (the hammer icon) at the top.
Code: Select all
using System;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
namespace cAlgo
{
public enum LogType
{
RuleBasedOmission,
ExecutionHesitation
}
[Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class SystematicOmissionJournal : Indicator
{
// ---------------------------------------------------------------------------------------------
// INSTITUTIONAL COLOR PALETTE
// ---------------------------------------------------------------------------------------------
private readonly Color colRBO = Color.FromHex("#089981"); // Teal
private readonly Color colEH = Color.FromHex("#F23645"); // Red
private readonly Color colText = Color.White;
private readonly Color colBg = Color.FromHex("#131722");
private readonly Color colBorder = Color.FromHex("#363A45");
private int _rboCount = 0;
private int _ehCount = 0;
// ---------------------------------------------------------------------------------------------
// INPUTS (String based Time for safe cross-version parsing)
// ---------------------------------------------------------------------------------------------
[Parameter("Log 1 Active", Group = "Event 1", DefaultValue = false)]
public bool Log1Active { get; set; }
[Parameter("Time (YYYY-MM-DD HH:MM)", Group = "Event 1", DefaultValue = "2026-09-24 10:00")]
public string Log1Time { get; set; }
[Parameter("Price", Group = "Event 1", DefaultValue = 0.0)]
public double Log1Price { get; set; }
[Parameter("Classification", Group = "Event 1", DefaultValue = LogType.RuleBasedOmission)]
public LogType Log1Type { get; set; }
[Parameter("Filter / Note", Group = "Event 1", DefaultValue = "Spread/Cost Veto")]
public string Log1Note { get; set; }
[Parameter("Log 2 Active", Group = "Event 2", DefaultValue = false)]
public bool Log2Active { get; set; }
[Parameter("Time (YYYY-MM-DD HH:MM)", Group = "Event 2", DefaultValue = "2026-09-24 10:00")]
public string Log2Time { get; set; }
[Parameter("Price", Group = "Event 2", DefaultValue = 0.0)]
public double Log2Price { get; set; }
[Parameter("Classification", Group = "Event 2", DefaultValue = LogType.RuleBasedOmission)]
public LogType Log2Type { get; set; }
[Parameter("Filter / Note", Group = "Event 2", DefaultValue = "Macro/News Proximity")]
public string Log2Note { get; set; }
[Parameter("Log 3 Active", Group = "Event 3", DefaultValue = false)]
public bool Log3Active { get; set; }
[Parameter("Time (YYYY-MM-DD HH:MM)", Group = "Event 3", DefaultValue = "2026-09-24 10:00")]
public string Log3Time { get; set; }
[Parameter("Price", Group = "Event 3", DefaultValue = 0.0)]
public double Log3Price { get; set; }
[Parameter("Classification", Group = "Event 3", DefaultValue = LogType.RuleBasedOmission)]
public LogType Log3Type { get; set; }
[Parameter("Filter / Note", Group = "Event 3", DefaultValue = "HTF Invalidation")]
public string Log3Note { get; set; }
[Parameter("Log 4 Active", Group = "Event 4", DefaultValue = false)]
public bool Log4Active { get; set; }
[Parameter("Time (YYYY-MM-DD HH:MM)", Group = "Event 4", DefaultValue = "2026-09-24 10:00")]
public string Log4Time { get; set; }
[Parameter("Price", Group = "Event 4", DefaultValue = 0.0)]
public double Log4Price { get; set; }
[Parameter("Classification", Group = "Event 4", DefaultValue = LogType.RuleBasedOmission)]
public LogType Log4Type { get; set; }
[Parameter("Filter / Note", Group = "Event 4", DefaultValue = "Correlated Exposure")]
public string Log4Note { get; set; }
[Parameter("Log 5 Active", Group = "Event 5", DefaultValue = false)]
public bool Log5Active { get; set; }
[Parameter("Time (YYYY-MM-DD HH:MM)", Group = "Event 5", DefaultValue = "2026-09-24 10:00")]
public string Log5Time { get; set; }
[Parameter("Price", Group = "Event 5", DefaultValue = 0.0)]
public double Log5Price { get; set; }
[Parameter("Classification", Group = "Event 5", DefaultValue = LogType.ExecutionHesitation)]
public LogType Log5Type { get; set; }
[Parameter("Filter / Note", Group = "Event 5", DefaultValue = "Psychological Fatigue")]
public string Log5Note { get; set; }
protected override void Initialize()
{
_rboCount = 0;
_ehCount = 0;
ProcessLog(1, Log1Active, Log1Time, Log1Price, Log1Type, Log1Note);
ProcessLog(2, Log2Active, Log2Time, Log2Price, Log2Type, Log2Note);
ProcessLog(3, Log3Active, Log3Time, Log3Price, Log3Type, Log3Note);
ProcessLog(4, Log4Active, Log4Time, Log4Price, Log4Type, Log4Note);
ProcessLog(5, Log5Active, Log5Time, Log5Price, Log5Type, Log5Note);
DrawInstitutionalHUD();
}
public override void Calculate(int index)
{
// Calculation not required for static journaling annotations
}
// ---------------------------------------------------------------------------------------------
// DRAWING LOGIC: TAGS AND RAYS
// ---------------------------------------------------------------------------------------------
private void ProcessLog(int index, bool active, string timeStr, double price, LogType type, string note)
{
if (!active || price == 0) return;
if (!DateTime.TryParse(timeStr, out DateTime parsedTime))
{
Print($"SOJ Error: Could not parse time for Event {index}. Please use YYYY-MM-DD HH:MM format.");
return;
}
if (type == LogType.RuleBasedOmission) _rboCount++;
else _ehCount++;
Color tagColor = (type == LogType.RuleBasedOmission) ? colRBO : colEH;
string tag = (type == LogType.RuleBasedOmission) ? "RBO" : "EH";
// Text annotation on chart
string labelText = $"{tag} - {note}";
Chart.DrawText($"SOJ_TXT_{index}", labelText, parsedTime, price, tagColor);
// Calculate forward projection for the dotted line (approx 30 bars)
DateTime endTime = parsedTime.AddMinutes(Chart.TimeFrame.ToTimeSpan().TotalMinutes * 30);
// Draw dotted omission risk level
var line = Chart.DrawTrendLine($"SOJ_LINE_{index}", parsedTime, price, endTime, price, Color.FromArgb(100, tagColor));
line.LineStyle = LineStyle.Dots;
line.Thickness = 1;
}
// ---------------------------------------------------------------------------------------------
// UI CONSTRUCTION: DOCKED PERFORMANCE HUD
// ---------------------------------------------------------------------------------------------
private void DrawInstitutionalHUD()
{
int totalEvents = _rboCount + _ehCount;
double compliance = totalEvents > 0 ? ((double)_rboCount / totalEvents) * 100 : 0;
Color compColor = compliance >= 80 ? colRBO : colEH;
var mainPanel = new StackPanel
{
Orientation = Orientation.Vertical,
BackgroundColor = colBg,
Margin = new Thickness(10)
};
// Header
mainPanel.AddChild(new TextBlock { Text = "SESSION METRICS", Foreground = Color.Gray, FontWeight = FontWeight.Bold, Margin = new Thickness(0, 0, 0, 10) });
// Row 1: RBO
var row1 = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(0, 0, 0, 5) };
row1.AddChild(new TextBlock { Text = "Systematic Omissions (RBO): ", Foreground = colRBO, Width = 180 });
row1.AddChild(new TextBlock { Text = _rboCount.ToString(), Foreground = colText, FontWeight = FontWeight.Bold });
mainPanel.AddChild(row1);
// Row 2: EH
var row2 = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(0, 0, 0, 5) };
row2.AddChild(new TextBlock { Text = "Execution Hesitation (EH): ", Foreground = colEH, Width = 180 });
row2.AddChild(new TextBlock { Text = _ehCount.ToString(), Foreground = colText, FontWeight = FontWeight.Bold });
mainPanel.AddChild(row2);
// Row 3: Compliance Rate
var row3 = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(0, 5, 0, 0) };
row3.AddChild(new TextBlock { Text = "Filter Compliance Rate: ", Foreground = colText, Width = 180 });
row3.AddChild(new TextBlock { Text = $"{Math.Round(compliance, 1)}%", Foreground = compColor, FontWeight = FontWeight.Bold });
mainPanel.AddChild(row3);
// Wrap in Border for aesthetic styling
var border = new Border
{
BorderColor = colBorder,
BorderThickness = 1,
Child = mainPanel,
HorizontalAlignment = HorizontalAlignment.Right,
VerticalAlignment = VerticalAlignment.Bottom,
Margin = new Thickness(0, 0, 20, 30) // Offset slightly from exact corner
};
Chart.AddControl(border);
}
}
}Re: Celebrating skipped trades as wins in the journal
How to Use This in cTrader
Applying to Chart: Click the Indicators icon at the top of your chart, go to Custom, and select SystematicOmissionJournal.
Formatting Time Inputs: cTrader handles parameter inputs strictly. Type the time of the skipped trade as YYYY-MM-DD HH:MM (e.g., 2026-09-24 09:30). The indicator has a built-in safety check; if you misformat the date, it will print an error in the cTrader log rather than crashing.
The Institutional UI: The HUD is built using cTrader's native UI system (StackPanel and Border). This means it will render with crystal clear anti-aliasing in the bottom right corner, entirely immune to chart zooming or scrolling.
Visibility: The label will print right at the price level as RBO - Correlated Exposure or EH - Psychological Fatigue and draw a subtle dotted line extending forward, visualizing exactly the risk exposure you managed to bypass.
Applying to Chart: Click the Indicators icon at the top of your chart, go to Custom, and select SystematicOmissionJournal.
Formatting Time Inputs: cTrader handles parameter inputs strictly. Type the time of the skipped trade as YYYY-MM-DD HH:MM (e.g., 2026-09-24 09:30). The indicator has a built-in safety check; if you misformat the date, it will print an error in the cTrader log rather than crashing.
The Institutional UI: The HUD is built using cTrader's native UI system (StackPanel and Border). This means it will render with crystal clear anti-aliasing in the bottom right corner, entirely immune to chart zooming or scrolling.
Visibility: The label will print right at the price level as RBO - Correlated Exposure or EH - Psychological Fatigue and draw a subtle dotted line extending forward, visualizing exactly the risk exposure you managed to bypass.