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; }
|
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; }
|
||||||
|
|
||||||
|
|||||||
@@ -157,9 +157,18 @@ namespace NT8.Strategies.Examples
|
|||||||
? context.Session.SessionStart
|
? context.Session.SessionStart
|
||||||
: context.CurrentTime.Date.AddHours(9.5);
|
: context.CurrentTime.Date.AddHours(9.5);
|
||||||
|
|
||||||
if (thisSessionStart != _openingRangeStart || _currentSessionDate == DateTime.MinValue)
|
// 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)
|
||||||
{
|
{
|
||||||
ResetSession(thisSessionStart);
|
if (thisSessionStart != _openingRangeStart || _currentSessionDate == DateTime.MinValue)
|
||||||
|
{
|
||||||
|
ResetSession(thisSessionStart);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only trade during RTH
|
// Only trade during RTH
|
||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user