Fix BreakoutVolumeStrength and Volatility factor calculators, session reset gate
Some checks failed
Build and Test / build (push) Has been cancelled
Some checks failed
Build and Test / build (push) Has been cancelled
This commit is contained in:
@@ -97,7 +97,7 @@ namespace NinjaTrader.NinjaScript.Strategies
|
||||
public bool EnableVerboseLogging { get; set; }
|
||||
|
||||
[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)]
|
||||
public int MinTradeGrade { get; set; }
|
||||
|
||||
|
||||
@@ -157,10 +157,19 @@ namespace NT8.Strategies.Examples
|
||||
? context.Session.SessionStart
|
||||
: 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)
|
||||
{
|
||||
ResetSession(thisSessionStart);
|
||||
}
|
||||
}
|
||||
|
||||
// Only trade during RTH
|
||||
if (context.Session == null || !context.Session.IsRth)
|
||||
@@ -329,21 +338,48 @@ namespace NT8.Strategies.Examples
|
||||
var avwap = _avwapCalculator.GetCurrentValue();
|
||||
var avwapSlope = _avwapCalculator.GetSlope(10);
|
||||
|
||||
var bars = new List<BarData>();
|
||||
bars.Add(bar);
|
||||
var valueArea = _volumeProfileAnalyzer.CalculateValueArea(bars);
|
||||
|
||||
if (context.CustomData == null)
|
||||
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["avwap"] = avwap;
|
||||
context.CustomData["avwap_slope"] = avwapSlope;
|
||||
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["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["avg_volume"] = (double)bar.Volume;
|
||||
context.CustomData["avg_volume"] = avgVol;
|
||||
}
|
||||
|
||||
private void ResetSession(DateTime sessionStart)
|
||||
|
||||
Reference in New Issue
Block a user