Here is the custom indicator for cTrader using its native C# API (cAlgo).
Because cTrader is built on modern C#, its API is incredibly clean for risk calculations. You don't need to manually calculate pip multiples or tick values like you do in MT4. The API natively exposes Symbol.PipValue, which instantly returns the exact monetary value of 1 pip per 1 unit of volume directly in your account's deposit currency.
It also includes a powerful built-in method called NormalizeVolumeInUnits(). This automatically takes your raw mathematical lot size and rounds it safely down to your specific broker’s minimums, maximums, and allowed step sizes.
Position Sizing Formula Every Scalper Should Memorize
Re: Position Sizing Formula Every Scalper Should Memorize
cTrader Position Size Calculator (C#)
Code: Select all
using System;
using cAlgo.API;
namespace cAlgo
{
[Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class PositionSizeCalculator : Indicator
{
// --- User Inputs ---
[Parameter("Risk Percentage (%)", Group = "Risk Parameters", DefaultValue = 1.0, MinValue = 0.1, Step = 0.1)]
public double RiskPercentage { get; set; }
[Parameter("Stop Loss (Pips)", Group = "Trade Parameters", DefaultValue = 10.0, MinValue = 0.1, Step = 0.5)]
public double StopLossPips { get; set; }
public override void Calculate(int index)
{
// Only calculate on the current active bar to save CPU resources
if (!IsLastBar) return;
// 1. Get Live Account Balance and Currency
double balance = Account.Balance;
string currency = Account.Asset.Name;
// 2. Calculate Exact Risk Amount based on your currency
double riskAmount = balance * (RiskPercentage / 100.0);
// 3. Calculate Raw Volume in Units
// Symbol.PipValue automatically returns the pip value in your deposit currency per 1 Unit of volume.
double rawVolume = 0;
if (StopLossPips > 0 && Symbol.PipValue > 0)
{
rawVolume = riskAmount / (StopLossPips * Symbol.PipValue);
}
// 4. Normalize Volume
// Rounds safely down to your broker's exact allowed step size to prevent risk overshoot or execution errors.
double normalizedVolume = Symbol.NormalizeVolumeInUnits(rawVolume, RoundingMode.Down);
// 5. Convert Units to Lots for standard display
double lotSize = normalizedVolume / Symbol.LotSize;
// 6. Draw the Dashboard on the Top-Left of the Chart
string dashboard = "\n" +
" === POSITION SIZE CALCULATOR ===\n" +
$" Account Balance: {Math.Round(balance, 2)} {currency}\n" +
$" Risk Amount ({Math.Round(RiskPercentage, 1)}%): {Math.Round(riskAmount, 2)} {currency}\n" +
$" Stop Loss: {Math.Round(StopLossPips, 1)} Pips\n" +
" ------------------------------------------\n" +
$" UNITS: {normalizedVolume}\n" +
$" LOTS: {Math.Round(lotSize, 2)}";
Chart.DrawStaticText("PositionSizeCalc", dashboard, VerticalAlignment.Top, HorizontalAlignment.Left, Color.LimeGreen);
}
}
}Re: Position Sizing Formula Every Scalper Should Memorize
How to Install and Use in cTrader:
1.) Open cTrader and go to the Automate tab on the left-hand menu (the robot icon).
2.) Look at the menu on the left, right-click on Indicators, and select New.
3.) Name it PositionSizeCalculator.
4.) Delete all the default code in the editor that pops up, and paste the code above in its place.
5.) Click the Build button at the top (it looks like a hammer) or press Ctrl + B. You should see a "Build Succeeded" message at the bottom.
6.) Go back to your normal Trade charting screen. Right-click anywhere on the chart > Indicators > Custom > PositionSizeCalculator.
7.) In the settings pop-up, you can quickly define your Risk % and your current Stop Loss distance. The live green HUD on the top left will instantly tell you exactly how many Lots (and Units) to fire off.
1.) Open cTrader and go to the Automate tab on the left-hand menu (the robot icon).
2.) Look at the menu on the left, right-click on Indicators, and select New.
3.) Name it PositionSizeCalculator.
4.) Delete all the default code in the editor that pops up, and paste the code above in its place.
5.) Click the Build button at the top (it looks like a hammer) or press Ctrl + B. You should see a "Build Succeeded" message at the bottom.
6.) Go back to your normal Trade charting screen. Right-click anywhere on the chart > Indicators > Custom > PositionSizeCalculator.
7.) In the settings pop-up, you can quickly define your Risk % and your current Stop Loss distance. The live green HUD on the top left will instantly tell you exactly how many Lots (and Units) to fire off.
Re: Position Sizing Formula Every Scalper Should Memorize
To make this a truly professional, institutional-grade tool, we need to move away from printing plain text on the chart and leverage cTrader’s native Canvas UI.
This upgraded "Pro" version introduces four major enhancements:
Native GUI Panel: Uses cTrader’s internal control system to build a sleek, draggable floating HUD with proper styling, borders, and highlighted outputs.
Dynamic Capital Base: Gives you a dropdown to calculate your risk based on your Balance or your live Equity (crucial if you scale into trades while floating profits).
Real-Time Tick Updates: Calculates inside OnTick() instead of just on bar closures, ensuring your lot size adjusts instantly to live equity fluctuations.
Asset-Agnostic Lot Conversion: Uses the advanced Symbol.VolumeInUnitsToQuantity() method to flawlessly convert volume to lots, whether you are trading Forex, Crypto, or Metals with weird contract sizes.
This upgraded "Pro" version introduces four major enhancements:
Native GUI Panel: Uses cTrader’s internal control system to build a sleek, draggable floating HUD with proper styling, borders, and highlighted outputs.
Dynamic Capital Base: Gives you a dropdown to calculate your risk based on your Balance or your live Equity (crucial if you scale into trades while floating profits).
Real-Time Tick Updates: Calculates inside OnTick() instead of just on bar closures, ensuring your lot size adjusts instantly to live equity fluctuations.
Asset-Agnostic Lot Conversion: Uses the advanced Symbol.VolumeInUnitsToQuantity() method to flawlessly convert volume to lots, whether you are trading Forex, Crypto, or Metals with weird contract sizes.
Re: Position Sizing Formula Every Scalper Should Memorize
Pro cTrader Position Size Calculator (C#)
Code: Select all
using System;
using cAlgo.API;
namespace cAlgo
{
[Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class ProPositionSizeCalc : Indicator
{
public enum BaseCapital { Balance, Equity }
// ==========================================
// USER INPUTS
// ==========================================
[Parameter("Capital Base", Group = "1. Risk Settings", DefaultValue = BaseCapital.Balance)]
public BaseCapital CapitalType { get; set; }
[Parameter("Risk Percentage (%)", Group = "1. Risk Settings", DefaultValue = 1.0, MinValue = 0.1, Step = 0.1)]
public double RiskPercentage { get; set; }
[Parameter("Stop Loss (Pips)", Group = "2. Trade Settings", DefaultValue = 10.0, MinValue = 0.1, Step = 0.5)]
public double StopLossPips { get; set; }
[Parameter("Panel Position", Group = "3. UI Settings", DefaultValue = VerticalAlignment.Bottom)]
public VerticalAlignment VAlign { get; set; }
[Parameter("Panel Alignment", Group = "3. UI Settings", DefaultValue = HorizontalAlignment.Right)]
public HorizontalAlignment HAlign { get; set; }
// ==========================================
// UI ELEMENTS
// ==========================================
private TextBlock _detailsText;
private TextBlock _lotsText;
protected override void Initialize()
{
// 1. Build the main container panel
var border = new Border
{
BackgroundColor = Color.FromArgb(220, 20, 20, 20), // Semi-transparent dark background
BorderColor = Color.DodgerBlue, // Pro blue accent
BorderThickness = 2,
CornerRadius = 5,
Margin = new Thickness(15),
HorizontalAlignment = HAlign,
VerticalAlignment = VAlign,
Padding = new Thickness(15)
};
var stackPanel = new StackPanel { Orientation = Orientation.Vertical };
// 2. Build the Header
var headerText = new TextBlock
{
Text = "DYNAMIC POSITION SIZER",
ForegroundColor = Color.DodgerBlue,
FontWeight = FontWeight.ExtraBold,
FontSize = 14,
Margin = new Thickness(0, 0, 0, 10)
};
// 3. Build the Data Details (updated every tick)
_detailsText = new TextBlock
{
ForegroundColor = Color.WhiteSmoke,
FontFamily = "Segoe UI",
FontSize = 12,
LineHeight = 20
};
// 4. Build the Final Lot Size Highlight (updated every tick)
_lotsText = new TextBlock
{
ForegroundColor = Color.LimeGreen,
FontWeight = FontWeight.ExtraBold,
FontSize = 18,
Margin = new Thickness(0, 10, 0, 0)
};
// Assemble UI
stackPanel.AddChild(headerText);
stackPanel.AddChild(_detailsText);
stackPanel.AddChild(_lotsText);
border.Child = stackPanel;
// Paint to Chart
Chart.AddControl(border);
}
public override void Calculate(int index)
{
// Calculation logic is moved to OnTick to ensure real-time equity updates
}
protected override void OnTick()
{
// 1. Determine base capital
double accountBase = CapitalType == BaseCapital.Balance ? Account.Balance : Account.Equity;
// 2. Calculate exact dollar risk
double riskAmount = accountBase * (RiskPercentage / 100.0);
// 3. Handle zero-division errors gracefully
if (StopLossPips <= 0 || Symbol.PipValue == 0)
{
_detailsText.Text = "Awaiting valid parameters...";
_lotsText.Text = "LOTS: 0.00";
return;
}
// 4. Calculate Raw Volume in Units
double rawVolume = riskAmount / (StopLossPips * Symbol.PipValue);
// 5. Safely normalize to broker requirements (rounds down to prevent risk overshoot)
double normalizedVolume = Symbol.NormalizeVolumeInUnits(rawVolume, RoundingMode.Down);
// 6. Convert units back to standardized lots (handles Crypto/Indices flawlessly)
double lots = Symbol.VolumeInUnitsToQuantity(normalizedVolume);
// 7. Update UI Text
_detailsText.Text = $"Capital ({CapitalType}): \t{Math.Round(accountBase, 2):N2} {Account.Asset.Name}\n" +
$"Risk Amount ({Math.Round(RiskPercentage, 2)}%): \t{Math.Round(riskAmount, 2):N2} {Account.Asset.Name}\n" +
$"Stop Loss: \t\t{Math.Round(StopLossPips, 1)} Pips\n" +
$"Trade Volume: \t{normalizedVolume:N0} Units";
_lotsText.Text = $"EXECUTE: {Math.Round(lots, 2):N2} LOTS";
}
}
}Re: Position Sizing Formula Every Scalper Should Memorize
To add trade execution capabilities, we must make a fundamental shift in how cTrader handles the script: an Indicator cannot execute trades.
We must convert this script from an Indicator into a cBot (Robot). Visually, it will look exactly the same and run directly on your chart, but running it as a cBot gives it the required permissions to place live market orders.
We must convert this script from an Indicator into a cBot (Robot). Visually, it will look exactly the same and run directly on your chart, but running it as a cBot gives it the required permissions to place live market orders.
Re: Position Sizing Formula Every Scalper Should Memorize
Here is the upgraded one-click execution cBot. It calculates your exact lot size in real-time and uses two new UI buttons to instantly execute market orders with your exact predetermined Stop Loss attached.
Pro Position Size Executor (cBot)
Pro Position Size Executor (cBot)
Code: Select all
using System;
using cAlgo.API;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class ProPositionSizeExecutor : Robot
{
public enum BaseCapital { Balance, Equity }
// ==========================================
// USER INPUTS
// ==========================================
[Parameter("Capital Base", Group = "1. Risk Settings", DefaultValue = BaseCapital.Balance)]
public BaseCapital CapitalType { get; set; }
[Parameter("Risk Percentage (%)", Group = "1. Risk Settings", DefaultValue = 1.0, MinValue = 0.1, Step = 0.1)]
public double RiskPercentage { get; set; }
[Parameter("Stop Loss (Pips)", Group = "2. Trade Settings", DefaultValue = 10.0, MinValue = 0.1, Step = 0.5)]
public double StopLossPips { get; set; }
[Parameter("Panel Position", Group = "3. UI Settings", DefaultValue = VerticalAlignment.Bottom)]
public VerticalAlignment VAlign { get; set; }
[Parameter("Panel Alignment", Group = "3. UI Settings", DefaultValue = HorizontalAlignment.Right)]
public HorizontalAlignment HAlign { get; set; }
// ==========================================
// UI & LOGIC VARIABLES
// ==========================================
private TextBlock _detailsText;
private TextBlock _lotsText;
private Button _buyButton;
private Button _sellButton;
private double _currentVolumeInUnits;
protected override void OnStart()
{
// 1. Build the main container panel
var border = new Border
{
BackgroundColor = Color.FromArgb(220, 20, 20, 20),
BorderColor = Color.DodgerBlue,
BorderThickness = 2,
CornerRadius = 5,
Margin = new Thickness(15),
HorizontalAlignment = HAlign,
VerticalAlignment = VAlign,
Padding = new Thickness(15)
};
var stackPanel = new StackPanel { Orientation = Orientation.Vertical };
// 2. Build the Header
var headerText = new TextBlock
{
Text = "1-CLICK RISK EXECUTOR",
ForegroundColor = Color.DodgerBlue,
FontWeight = FontWeight.ExtraBold,
FontSize = 14,
Margin = new Thickness(0, 0, 0, 10),
HorizontalAlignment = HorizontalAlignment.Center
};
// 3. Build the Data Details
_detailsText = new TextBlock
{
ForegroundColor = Color.WhiteSmoke,
FontFamily = "Segoe UI",
FontSize = 12,
LineHeight = 20
};
// 4. Build the Lot Size Highlight
_lotsText = new TextBlock
{
ForegroundColor = Color.LimeGreen,
FontWeight = FontWeight.ExtraBold,
FontSize = 16,
Margin = new Thickness(0, 10, 0, 10),
HorizontalAlignment = HorizontalAlignment.Center
};
// 5. Build Execution Buttons
var buttonPanel = new WrapPanel { HorizontalAlignment = HorizontalAlignment.Center };
_buyButton = new Button
{
Text = "BUY",
BackgroundColor = Color.SeaGreen,
ForegroundColor = Color.White,
FontWeight = FontWeight.ExtraBold,
Margin = new Thickness(0, 0, 5, 0),
Width = 70,
Height = 30
};
_sellButton = new Button
{
Text = "SELL",
BackgroundColor = Color.Crimson,
ForegroundColor = Color.White,
FontWeight = FontWeight.ExtraBold,
Margin = new Thickness(5, 0, 0, 0),
Width = 70,
Height = 30
};
// Bind button click events
_buyButton.Click += OnBuyClicked;
_sellButton.Click += OnSellClicked;
buttonPanel.AddChild(_buyButton);
buttonPanel.AddChild(_sellButton);
// Assemble UI
stackPanel.AddChild(headerText);
stackPanel.AddChild(_detailsText);
stackPanel.AddChild(_lotsText);
stackPanel.AddChild(buttonPanel);
border.Child = stackPanel;
// Paint to Chart
Chart.AddControl(border);
// Force an initial calculation so the UI populates immediately
UpdateCalculations();
}
protected override void OnTick()
{
UpdateCalculations();
}
private void UpdateCalculations()
{
double accountBase = CapitalType == BaseCapital.Balance ? Account.Balance : Account.Equity;
double riskAmount = accountBase * (RiskPercentage / 100.0);
if (StopLossPips <= 0 || Symbol.PipValue == 0)
{
_detailsText.Text = "Awaiting valid parameters...";
_lotsText.Text = "LOTS: 0.00";
_currentVolumeInUnits = 0;
_buyButton.IsEnabled = false;
_sellButton.IsEnabled = false;
return;
}
double rawVolume = riskAmount / (StopLossPips * Symbol.PipValue);
_currentVolumeInUnits = Symbol.NormalizeVolumeInUnits(rawVolume, RoundingMode.Down);
double lots = Symbol.VolumeInUnitsToQuantity(_currentVolumeInUnits);
_detailsText.Text = $"Capital ({CapitalType}): \t{Math.Round(accountBase, 2):N2} {Account.Asset.Name}\n" +
$"Risk Amount ({Math.Round(RiskPercentage, 2)}%): \t{Math.Round(riskAmount, 2):N2} {Account.Asset.Name}\n" +
$"Stop Loss: \t\t{Math.Round(StopLossPips, 1)} Pips";
_lotsText.Text = $"SIZE: {Math.Round(lots, 2):N2} LOTS";
// Enable buttons only if we have a valid volume size
bool isValidTradeSize = _currentVolumeInUnits >= Symbol.VolumeInUnitsMin;
_buyButton.IsEnabled = isValidTradeSize;
_sellButton.IsEnabled = isValidTradeSize;
}
// ==========================================
// TRADE EXECUTION LOGIC
// ==========================================
private void OnBuyClicked(ButtonClickEventArgs args)
{
if (_currentVolumeInUnits >= Symbol.VolumeInUnitsMin)
{
ExecuteMarketOrderAsync(TradeType.Buy, SymbolName, _currentVolumeInUnits, "ProSizer", StopLossPips, null);
}
}
private void OnSellClicked(ButtonClickEventArgs args)
{
if (_currentVolumeInUnits >= Symbol.VolumeInUnitsMin)
{
ExecuteMarketOrderAsync(TradeType.Sell, SymbolName, _currentVolumeInUnits, "ProSizer", StopLossPips, null);
}
}
}
}Re: Position Sizing Formula Every Scalper Should Memorize
How to Install this as a cBot:
1.) Open the Automate tab in cTrader.
2.) This time, right-click on cBots (not Indicators) -> New.
3.) Name it ProPositionSizeExecutor.
4.) Paste the code above and click Build (Ctrl + B).
5.) Open your normal charting window. Under cBots in the left panel, drag the ProPositionSizeExecutor onto your chart.
6.) A window will pop up asking for your Risk % and Stop Loss. Enter them and click Apply.
7.) Important: Click the Play button at the top of the chart to start the cBot. The UI panel will appear.
You can now click Buy or Sell on the chart panel to instantly fire a market order. cTrader will automatically attach your specified Stop Loss based on the exact position size calculated.
1.) Open the Automate tab in cTrader.
2.) This time, right-click on cBots (not Indicators) -> New.
3.) Name it ProPositionSizeExecutor.
4.) Paste the code above and click Build (Ctrl + B).
5.) Open your normal charting window. Under cBots in the left panel, drag the ProPositionSizeExecutor onto your chart.
6.) A window will pop up asking for your Risk % and Stop Loss. Enter them and click Apply.
7.) Important: Click the Play button at the top of the chart to start the cBot. The UI panel will appear.
You can now click Buy or Sell on the chart panel to instantly fire a market order. cTrader will automatically attach your specified Stop Loss based on the exact position size calculated.
Re: Position Sizing Formula Every Scalper Should Memorize
A Real Example of Lot Size Calculation on Gold (XAUUSD)
Gold behaves differently from currency pairs, so position sizing needs extra care. Let's walk through an example.
Assumptions (always verify with your own broker, since contract specifications vary):
- Account balance: $2,000
- Risk per trade: 1% = $20
- Instrument: XAUUSD
- Typical contract: 1 standard lot = 100 ounces, so a $1 move in price equals $100 per lot
Trade idea: a buy with a stop $5 below entry.
Risk per lot = $5 x $100 = $500.
Lot size = $20 / $500 = 0.04 lots.
Check: at 0.04 lots, each $1 move equals $4. A $5 stop loses $20. That matches the 1% risk.
Important reminders:
1. Gold is volatile. Stops that work on forex may be too tight on gold. Let the chart decide, then adjust lot size accordingly.
2. Spreads matter. Gold spreads can widen sharply around news.
3. Verify contract size. Some brokers use different specifications, so check yours.
4. Use a calculator. Confirm your manual math.
5. Consider smaller sizes when learning. Gold moves fast, and small mistakes are expensive.
The same principle applies to every instrument: define risk in dollars, measure the stop, then calculate the size.
Never guess. The math takes thirty seconds and can save your account.
Gold behaves differently from currency pairs, so position sizing needs extra care. Let's walk through an example.
Assumptions (always verify with your own broker, since contract specifications vary):
- Account balance: $2,000
- Risk per trade: 1% = $20
- Instrument: XAUUSD
- Typical contract: 1 standard lot = 100 ounces, so a $1 move in price equals $100 per lot
Trade idea: a buy with a stop $5 below entry.
Risk per lot = $5 x $100 = $500.
Lot size = $20 / $500 = 0.04 lots.
Check: at 0.04 lots, each $1 move equals $4. A $5 stop loses $20. That matches the 1% risk.
Important reminders:
1. Gold is volatile. Stops that work on forex may be too tight on gold. Let the chart decide, then adjust lot size accordingly.
2. Spreads matter. Gold spreads can widen sharply around news.
3. Verify contract size. Some brokers use different specifications, so check yours.
4. Use a calculator. Confirm your manual math.
5. Consider smaller sizes when learning. Gold moves fast, and small mistakes are expensive.
The same principle applies to every instrument: define risk in dollars, measure the stop, then calculate the size.
Never guess. The math takes thirty seconds and can save your account.
It’s Fairman 