The Practical Audit
To bridge the gap between theory and application, stress-test your current approach with this three-step framework:
The Hypothesis: Write the mechanics of your setup in one sentence. (e.g., "I buy first-pullbacks to the VWAP on small-cap stocks with relative volume greater than 5x.")
The Justification: Identify the engine. Why does this work? (e.g., "This exploits behavioral FOMO from retail momentum traders who missed the initial morning breakout.")
The Verification: Pull your last 100 trades of this specific setup. Calculate the win rate, average risk (1R), average reward, and deduct your broker fees and average slippage. If the resulting $E$ is not definitively positive, the edge is a localized illusion.
What Is an Edge, in Plain Numbers?
Re: What Is an Edge, in Plain Numbers?
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: What Is an Edge, in Plain Numbers?
This cBot (cTrader script) acts as a real-time Edge Auditor. It pulls your trading history, applies the expectancy formula directly to your actual data, and displays your mathematical edge live on the chart.
The Edge Auditor cBot
The Edge Auditor cBot
Code: Select all
using System;
using System.Linq;
using cAlgo.API;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class EdgeAuditor : Robot
{
[Parameter("Sample Size (0 = All History)", DefaultValue = 100, MinValue = 0)]
public int SampleSize { get; set; }
[Parameter("Current Symbol Only", DefaultValue = true)]
public bool CurrentSymbolOnly { get; set; }
protected override void OnStart()
{
// Calculate edge as soon as the cBot is attached
CalculateAndDisplayEdge();
}
protected override void OnPositionClosed(PositionClosedEventArgs args)
{
// Recalculate edge dynamically every time a trade finishes
CalculateAndDisplayEdge();
}
private void CalculateAndDisplayEdge()
{
// 1. Gather historical data
var trades = History.AsEnumerable();
if (CurrentSymbolOnly)
{
trades = trades.Where(x => x.SymbolName == SymbolName);
}
if (SampleSize > 0)
{
trades = trades.OrderByDescending(x => x.ClosingTime).Take(SampleSize);
}
if (!trades.Any())
{
Chart.DrawStaticText("EdgeStats", "Not enough history to calculate edge.", VerticalAlignment.Top, HorizontalAlignment.Left, Color.Gray);
return;
}
// 2. Parse win/loss data based on Gross Profit (ignoring costs initially)
int totalTrades = trades.Count();
var winningTrades = trades.Where(x => x.GrossProfit > 0).ToList();
var losingTrades = trades.Where(x => x.GrossProfit <= 0).ToList();
// 3. Calculate variables for the Expectancy Formula
double winRate = (double)winningTrades.Count / totalTrades;
double lossRate = 1.0 - winRate;
// W = Average Win, L = Average Loss (converted to positive number)
double avgWin = winningTrades.Any() ? winningTrades.Average(x => x.GrossProfit) : 0;
double avgLoss = losingTrades.Any() ? Math.Abs(losingTrades.Average(x => x.GrossProfit)) : 0;
// C = Frictional Costs (Commissions + Swaps). Slippage is inherently baked into the GrossProfit via execution price.
double totalCosts = trades.Sum(x => Math.Abs(x.Commissions) + Math.Abs(x.Swap));
double avgCost = totalCosts / totalTrades;
// 4. The Edge Formula: E = (Pw * W) - (Pl * L) - C
double expectancy = (winRate * avgWin) - (lossRate * avgLoss) - avgCost;
// 5. Format the dashboard output
string edgeStatus = expectancy > 0 ? "POSITIVE EDGE EXPLOIT" : "NEGATIVE EDGE (LEAKING CAPITAL)";
Color dashboardColor = expectancy > 0 ? Color.MediumSeaGreen : Color.Tomato;
string accountCurrency = Account.Asset.Name;
string text = $"=== THE EDGE AUDITOR ===\n" +
$"Sample Size: {totalTrades} trades\n\n" +
$"Win Rate (Pw): {Math.Round(winRate * 100, 1)}%\n" +
$"Avg Win (W): {Math.Round(avgWin, 2)} {accountCurrency}\n" +
$"Avg Loss (L): {Math.Round(avgLoss, 2)} {accountCurrency}\n" +
$"Avg Cost (C): {Math.Round(avgCost, 2)} {accountCurrency}\n" +
$"--------------------------------\n" +
$"EXPECTANCY (E): {Math.Round(expectancy, 2)} {accountCurrency} per trade\n" +
$"STATUS: {edgeStatus}";
// 6. Draw on chart
Chart.DrawStaticText("EdgeStats", text, VerticalAlignment.Top, HorizontalAlignment.Left, dashboardColor);
}
}
}Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: What Is an Edge, in Plain Numbers?
How to Install and Use in cTrader
1.) Open the cTrader Automate tab (the robot icon on the left sidebar).
2.) Click New cBot at the top left. Name it EdgeAuditor.
3.) Erase the default code and paste the script above into the editor.
4.) Click Build (or press Ctrl+B) to compile it.
5.) Go back to your chart, find EdgeAuditor under the cBots list, and drag it onto any chart.
1.) Open the cTrader Automate tab (the robot icon on the left sidebar).
2.) Click New cBot at the top left. Name it EdgeAuditor.
3.) Erase the default code and paste the script above into the editor.
4.) Click Build (or press Ctrl+B) to compile it.
5.) Go back to your chart, find EdgeAuditor under the cBots list, and drag it onto any chart.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: What Is an Edge, in Plain Numbers?
How the Script Works
Sample Size Control: By default, it audits your last 100 trades. If you change the parameter to 0, it will audit your entire account history.
Dynamic Updating: It uses the OnPositionClosed method, meaning the moment a trade closes, the dashboard recalculates your expectancy in real-time.
Separation of Costs: Notice how avgCost extracts commissions and swaps from the trades. This reveals whether a setup that looks profitable is actually being bled dry by broker friction. (Slippage is automatically accounted for, as GrossProfit calculates from your filled price, not your intended price).
Sample Size Control: By default, it audits your last 100 trades. If you change the parameter to 0, it will audit your entire account history.
Dynamic Updating: It uses the OnPositionClosed method, meaning the moment a trade closes, the dashboard recalculates your expectancy in real-time.
Separation of Costs: Notice how avgCost extracts commissions and swaps from the trades. This reveals whether a setup that looks profitable is actually being bled dry by broker friction. (Slippage is automatically accounted for, as GrossProfit calculates from your filled price, not your intended price).
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: What Is an Edge, in Plain Numbers?
How would you check it in practice? One way would be to take payrolls releases where the headline and the revisions or wage numbers pointed in opposite directions, and measure how long it took price to cross back over its pre-release level. If that time has fallen from a couple of minutes to under thirty seconds, the edge is mostly gone for anyone clicking manually. The awkward part is sample size, since there are only twelve payrolls a year and the conflicting ones are a fraction of those. Do you pool CPI and other releases to get enough cases, or does mixing them muddy the answer?
It’s Fairman 
-
Shadow Trader
- Posts: 2432
- Joined: Wed Sep 09, 2026 5:19 pm
Re: What Is an Edge, in Plain Numbers?
The 0.1R cost figure in the worked example depends heavily on stop size, which matters for anyone scalping. Costs are paid in pips while the edge is measured in R.
Say all in costs are 1 pip a round trip. On a 20 pip stop that is 0.05R, on a 10 pip stop 0.1R, and on a 5 pip stop 0.2R, which would wipe out the whole 0.2R gross edge from the 40 winners and 60 losers example.
So the same entry rules can carry an edge on a wider stop and none on a tight one, even if the tight version looks better in gross R. Running expectancy net at the actual stop size is the only version that counts.
On the question about pooling releases to check decay, mixing CPI and payrolls seems fair as long as each case is measured in the same unit. Seconds taken to get back through the price from just before the release works across events in a way that pips do not.
Twelve payrolls plus twelve CPI prints a year still only gives 24 cases, and if a third of them have conflicting details that is about 8. Is a few years of history enough, or does the decay itself make older cases useless?
Say all in costs are 1 pip a round trip. On a 20 pip stop that is 0.05R, on a 10 pip stop 0.1R, and on a 5 pip stop 0.2R, which would wipe out the whole 0.2R gross edge from the 40 winners and 60 losers example.
So the same entry rules can carry an edge on a wider stop and none on a tight one, even if the tight version looks better in gross R. Running expectancy net at the actual stop size is the only version that counts.
On the question about pooling releases to check decay, mixing CPI and payrolls seems fair as long as each case is measured in the same unit. Seconds taken to get back through the price from just before the release works across events in a way that pips do not.
Twelve payrolls plus twelve CPI prints a year still only gives 24 cases, and if a third of them have conflicting details that is about 8. Is a few years of history enough, or does the decay itself make older cases useless?
-
Shadow Trader
- Posts: 2432
- Joined: Wed Sep 09, 2026 5:19 pm
Re: What Is an Edge, in Plain Numbers?
The 0.2R worked example also needs a margin of error before it counts as an edge. With winners at 2R and losers at 1R the results are spread wide, so 100 trades leave real doubt.
The standard deviation for that mix is about 1.47R. The average of the squares is 0.4 times 4 plus 0.6 times 1, so 2.2, and taking away 0.2 squared leaves 2.16, whose square root is 1.47.
Divide by the square root of 100 and the standard error is about 0.15R. Two of those either side of 0.2R gives a range from about minus 0.09R to plus 0.49R, which still includes zero.
To push the lower end above zero, two standard errors have to be smaller than 0.2R. That needs 1.47 divided by the square root of the sample to fall below 0.1, which takes about 220 trades.
Costs make it worse, since the net average shrinks while the spread barely moves. At 0.1R net, the same sum asks for about 865 trades.
That is a lot for a setup seen a few times a week. Does anyone accept a lower bar, such as one standard error, before going live?
The standard deviation for that mix is about 1.47R. The average of the squares is 0.4 times 4 plus 0.6 times 1, so 2.2, and taking away 0.2 squared leaves 2.16, whose square root is 1.47.
Divide by the square root of 100 and the standard error is about 0.15R. Two of those either side of 0.2R gives a range from about minus 0.09R to plus 0.49R, which still includes zero.
To push the lower end above zero, two standard errors have to be smaller than 0.2R. That needs 1.47 divided by the square root of the sample to fall below 0.1, which takes about 220 trades.
Costs make it worse, since the net average shrinks while the spread barely moves. At 0.1R net, the same sum asks for about 865 trades.
That is a lot for a setup seen a few times a week. Does anyone accept a lower bar, such as one standard error, before going live?