Fix BreakoutVolumeStrength and Volatility factor calculators, session reset gate
Some checks failed
Build and Test / build (push) Has been cancelled

This commit is contained in:
2026-03-22 19:12:08 -04:00
parent c094e65b10
commit 229f4e413e
2 changed files with 45 additions and 9 deletions

View File

@@ -97,7 +97,7 @@ namespace NinjaTrader.NinjaScript.Strategies
public bool EnableVerboseLogging { get; set; } public bool EnableVerboseLogging { get; set; }
[NinjaScriptProperty] [NinjaScriptProperty]
[Display(Name = "Min Trade Grade (0=F,1=D,2=C,3=B,4=A,5=A+)", GroupName = "Confluence", Order = 1)] [Display(Name = "Min Trade Grade (1=F,2=D,3=C,4=B,5=A,6=A+)", GroupName = "Confluence", Order = 1)]
[Range(0, 6)] [Range(0, 6)]
public int MinTradeGrade { get; set; } public int MinTradeGrade { get; set; }

View File

@@ -157,10 +157,19 @@ namespace NT8.Strategies.Examples
? context.Session.SessionStart ? context.Session.SessionStart
: context.CurrentTime.Date.AddHours(9.5); : context.CurrentTime.Date.AddHours(9.5);
// Validate session start is a legitimate RTH boundary (08:00-10:30 ET).
// Rejects spurious ETH-derived session boundaries that can reset _tradeTaken mid-session.
TimeSpan sessionStartTime = thisSessionStart.TimeOfDay;
bool isValidRthSessionStart = sessionStartTime >= new TimeSpan(8, 0, 0)
&& sessionStartTime <= new TimeSpan(10, 30, 0);
if (isValidRthSessionStart)
{
if (thisSessionStart != _openingRangeStart || _currentSessionDate == DateTime.MinValue) if (thisSessionStart != _openingRangeStart || _currentSessionDate == DateTime.MinValue)
{ {
ResetSession(thisSessionStart); ResetSession(thisSessionStart);
} }
}
// Only trade during RTH // Only trade during RTH
if (context.Session == null || !context.Session.IsRth) if (context.Session == null || !context.Session.IsRth)
@@ -329,21 +338,48 @@ namespace NT8.Strategies.Examples
var avwap = _avwapCalculator.GetCurrentValue(); var avwap = _avwapCalculator.GetCurrentValue();
var avwapSlope = _avwapCalculator.GetSlope(10); var avwapSlope = _avwapCalculator.GetSlope(10);
var bars = new List<BarData>();
bars.Add(bar);
var valueArea = _volumeProfileAnalyzer.CalculateValueArea(bars);
if (context.CustomData == null) if (context.CustomData == null)
context.CustomData = new Dictionary<string, object>(); context.CustomData = new Dictionary<string, object>();
// Use pre-calculated intraday average from daily bar context when available.
// Fall back to current bar volume only if daily context is not yet populated.
double avgVol = (double)bar.Volume;
double normalAtr = bar.High - bar.Low;
if (_config != null && _config.Parameters != null && _config.Parameters.ContainsKey("daily_bars"))
{
var src = _config.Parameters["daily_bars"];
if (src is DailyBarContext)
{
DailyBarContext dc = (DailyBarContext)src;
if (dc.AvgIntradayBarVolume > 0.0)
avgVol = dc.AvgIntradayBarVolume;
// Use 10-day average daily range as the volatility baseline.
if (dc.Count >= 5 && dc.Highs != null && dc.Lows != null)
{
double sumRanges = 0.0;
int lookback = Math.Min(10, dc.Count - 1);
int start = dc.Count - 1 - lookback;
int end = dc.Count - 2;
for (int i = start; i <= end; i++)
sumRanges += dc.Highs[i] - dc.Lows[i];
if (lookback > 0)
normalAtr = sumRanges / lookback;
}
}
}
context.CustomData["current_bar"] = bar; context.CustomData["current_bar"] = bar;
context.CustomData["avwap"] = avwap; context.CustomData["avwap"] = avwap;
context.CustomData["avwap_slope"] = avwapSlope; context.CustomData["avwap_slope"] = avwapSlope;
context.CustomData["trend_confirm"] = avwapSlope > 0.0 ? 1.0 : 0.0; context.CustomData["trend_confirm"] = avwapSlope > 0.0 ? 1.0 : 0.0;
context.CustomData["current_atr"] = Math.Max(0.01, bar.High - bar.Low); context.CustomData["current_atr"] = Math.Max(0.01, bar.High - bar.Low);
context.CustomData["normal_atr"] = Math.Max(0.01, valueArea.ValueAreaHigh - valueArea.ValueAreaLow); context.CustomData["normal_atr"] = Math.Max(0.01, normalAtr);
context.CustomData["recent_execution_quality"] = 0.8; context.CustomData["recent_execution_quality"] = 0.8;
context.CustomData["avg_volume"] = (double)bar.Volume; context.CustomData["avg_volume"] = avgVol;
} }
private void ResetSession(DateTime sessionStart) private void ResetSession(DateTime sessionStart)