Re: The Market Will Be Here Tomorrow — Protect Your Ability to Trade It
Posted: Fri Sep 25, 2026 1:28 pm
Moving this over to cTrader is where the architecture really shines. Because cAlgo runs natively on C#, we can bypass the clunky object-parsing loops required in MQL and directly leverage a .NET WPF-style UI framework and native event handlers to make the dashboard perfectly responsive.
When you drag the lines on the chart, the Chart.ObjectsUpdated event fires instantly, recalculating your exact lot and unit sizes based on the asset's specific PipValue and minimum volume steps.
cTrader (cAlgo) C# Code
1.) In cTrader, go to the Automate tab.
2.) Click New Indicator and name it RiskManager.
3.) Paste this C# code, replacing the default template, and click Build (or press F8).
When you drag the lines on the chart, the Chart.ObjectsUpdated event fires instantly, recalculating your exact lot and unit sizes based on the asset's specific PipValue and minimum volume steps.
cTrader (cAlgo) C# Code
1.) In cTrader, go to the Automate tab.
2.) Click New Indicator and name it RiskManager.
3.) Paste this C# code, replacing the default template, and click Build (or press F8).
Code: Select all
using System;
using cAlgo.API;
using cAlgo.API.Internals;
namespace cAlgo
{
[Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class PriceActionRiskManager : Indicator
{
[Parameter("Risk per Trade (%)", DefaultValue = 1.0, MinValue = 0.1, Step = 0.1)]
public double RiskPercent { get; set; }
private ChartHorizontalLine _entryLine, _slLine, _tpLine;
private TextBlock _dashboardText;
protected override void Initialize()
{
// Build the WPF-style dashboard panel
_dashboardText = new TextBlock
{
ForegroundColor = Color.White,
Margin = new Thickness(10),
FontFamily = "Consolas",
FontSize = 13
};
var border = new Border
{
BackgroundColor = Color.FromArgb(180, 20, 20, 20),
BorderColor = Color.DodgerBlue,
BorderThickness = 1,
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Top,
Margin = new Thickness(15, 60, 0, 0),
Child = _dashboardText
};
Chart.AddControl(border);
// Initialize interactive lines at current price
double currentPrice = Symbol.Ask;
_entryLine = Chart.DrawHorizontalLine("RM_Entry", currentPrice, Color.DodgerBlue);
_slLine = Chart.DrawHorizontalLine("RM_SL", currentPrice - (10 * Symbol.PipSize), Color.Red);
_tpLine = Chart.DrawHorizontalLine("RM_TP", currentPrice + (20 * Symbol.PipSize), Color.MediumSeaGreen);
// Enable drag-and-drop directly on the chart
_entryLine.IsInteractive = true;
_slLine.IsInteractive = true;
_tpLine.IsInteractive = true;
// Subscribe to the native chart object update event
Chart.ObjectsUpdated += Chart_ObjectsUpdated;
UpdateDashboard();
}
private void Chart_ObjectsUpdated(ChartObjectsUpdatedEventArgs obj)
{
UpdateDashboard();
}
public override void Calculate(int index)
{
// Ensures calculations stay fresh even if balance changes
UpdateDashboard();
}
private void UpdateDashboard()
{
double entryPrice = _entryLine.Y;
double slPrice = _slLine.Y;
double tpPrice = _tpLine.Y;
double riskAmount = Account.Balance * (RiskPercent / 100);
double slDistancePips = Math.Abs(entryPrice - slPrice) / Symbol.PipSize;
double tpDistancePips = Math.Abs(tpPrice - entryPrice) / Symbol.PipSize;
double lots = 0;
double volumeUnits = 0;
if (slDistancePips > 0)
{
// Symbol.PipValue in cTrader is the value of 1 pip per 1 unit of volume
double rawVolume = riskAmount / (slDistancePips * Symbol.PipValue);
// Native API normalizes to broker's strict volume requirements
volumeUnits = Symbol.NormalizeVolumeInUnits(rawVolume, RoundingMode.Down);
// Convert pure units back to standard Lots for the UI
lots = Symbol.VolumeInUnitsToQuantity(volumeUnits);
}
double rrRatio = slDistancePips > 0 ? tpDistancePips / slDistancePips : 0;
string dir = entryPrice > slPrice ? "LONG" : "SHORT";
Color dirColor = entryPrice > slPrice ? Color.MediumSeaGreen : Color.Red;
_dashboardText.Text = "--- PRICE ACTION RISK MANAGER ---\n\n" +
$"Account Balance: {Math.Round(Account.Balance, 2)}\n" +
$"Max Risk ({RiskPercent}%): {Math.Round(riskAmount, 2)}\n\n" +
$"Direction: {dir}\n" +
$"Position: {Math.Round(lots, 2)} Lots ({volumeUnits} Units)\n" +
$"Reward/Risk: 1 : {Math.Round(rrRatio, 2)}\n\n" +
$"Distance to SL: {Math.Round(slDistancePips, 1)} pips";
}
}
}