Inside the SymbolEngine class, modify the Evaluate() method. Place the global capacity check after the moving average crossover logic, but before you calculate volume or send the order to the exchange.
While capping total trades at 2 achieves your goal if you are only trading EURUSD and GBPUSD, it becomes insufficient if you scale the bot to 15 currency pairs. You might end up with EURUSD and USDJPY open (neutralizing USD exposure), or EURUSD and GBPUSD open (doubling USD short exposure).
To build a true institutional exposure matrix, you would replace TotalOpenPositions with a LINQ query that parses the symbol strings for specific currencies:
// Inside the Master Robot
public double GetNetCurrencyExposure(string currency)
{
double netExposure = 0;
var allPositions = Positions.FindAll("InstKellyMulti");
foreach (var pos in allPositions)
{
// Example: If Long EURUSD, we are Short USD
if (pos.SymbolName.EndsWith(currency))
netExposure += pos.TradeType == TradeType.Buy ? -pos.VolumeInUnits : pos.VolumeInUnits;
// Example: If Long USDJPY, we are Long USD
else if (pos.SymbolName.StartsWith(currency))
netExposure += pos.TradeType == TradeType.Buy ? pos.VolumeInUnits : -pos.VolumeInUnits;
}
return netExposure;
}
The engine would then query _algo.GetNetCurrencyExposure("USD") and block the trade if taking the new position would push your net aggregate USD volume past a defined threshold.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
To build a dynamic correlation matrix, you must calculate the Pearson Correlation Coefficient between the two assets at the exact moment your algorithm generates an entry signal.
Because you are scalping 1-minute or 5-minute price action, calculating correlation on raw closing prices is mathematically flawed (financial time series are non-stationary). You must calculate the correlation of their percentage returns over a rolling window.
Here is the architectural update to implement the Correlation Matrix into your cTrader engine.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
2. Update the Symbol Engine (The Directional Filter)
In your SymbolEngine class, before executing the trade, you must iterate over all currently open positions in the portfolio.
The logic requires a Directional Check. If you are buying EURUSD, and you are already long GBPUSD, a high positive correlation ($+0.85$) is dangerous. However, if you are buying EURUSD and you are already short USDCHF, a high negative correlation ($-0.90$) is equally dangerous, because buying EUR and shorting USDCHF is fundamentally the same directional USD exposure.
Update the Evaluate() method in the SymbolEngine class:
On-Demand Processing: The Pearson math uses a standard for loop instead of LINQ for speed. More importantly, it only fires when a trigger condition is met, saving massive CPU cycles compared to continuously updating a background correlation grid on every OnTick event.
Cross-Timeframe Portability: By passing TimeFrame dynamically into MarketData.GetBars(TimeFrame, symbolA), the correlation window perfectly matches your scalping horizon whether you attach the bot to a 1-minute or 15-minute chart.
Self-Exclusion Safe: The openPositions.Length == 0 check ensures that the engine only calculates correlation against other symbols' open trades, preventing the algorithm from accidentally blocking itself.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
To pivot from directional scalping to Statistical Arbitrage (Stat Arb), you fundamentally change the engine's objective. Instead of rejecting a trade because of correlation, you actively hunt the correlation matrix for a "partner" asset to absorb your systemic risk (e.g., delta-neutralizing your USD exposure).
If your algorithm signals a Long on EURUSD, and you find a highly negatively correlated asset (e.g., USDCHF at $r = -0.92$), you execute a Long/Long basket. Because they move inversely, going Long on both neutralizes the USD denominator. Your trade is no longer a bet on the US Dollar; it is a relative value bet that the Euro will outperform the Swiss Franc.
To execute this, we must introduce Volatility Parity. You cannot simply buy 1 Lot of A and 1 Lot of B. If USDCHF is currently twice as volatile as EURUSD, a 1:1 lot size leaves you severely exposed to CHF.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
We rewrite the Evaluate() method inside the SymbolEngine. When the SMA crossover fires, it pauses, scans for a hedge, calculates Volatility Parity, and fires a synchronized basket.
When executing a delta-neutral basket, managing the exit becomes the primary engineering challenge.
Because Leg B was executed with the label "StatArb_Hedge", your existing ManageOpenPositions() method will ignore it. This is intentional. In pairs trading, you usually do not scale out of legs independently based on static TP targets. If Leg A hits TP1 and you scale out half, but Leg B is left intact, you instantly lose delta-neutrality and are suddenly directionally exposed to the market on the remaining Leg B volume.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.