diff --git a/src/NT8.Adapters/Strategies/NT8StrategyBase.cs b/src/NT8.Adapters/Strategies/NT8StrategyBase.cs index 6eb7a8c..96532c0 100644 --- a/src/NT8.Adapters/Strategies/NT8StrategyBase.cs +++ b/src/NT8.Adapters/Strategies/NT8StrategyBase.cs @@ -96,6 +96,11 @@ namespace NinjaTrader.NinjaScript.Strategies [Display(Name = "Verbose Logging", GroupName = "Debug", Order = 1)] 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)] + [Range(0, 6)] + public int MinTradeGrade { get; set; } + [NinjaScriptProperty] [Display(Name = "Enable File Logging", GroupName = "Diagnostics", Order = 10)] public bool EnableFileLogging { get; set; } @@ -190,6 +195,7 @@ namespace NinjaTrader.NinjaScript.Strategies MaxContracts = 10; EnableKillSwitch = false; EnableVerboseLogging = false; + MinTradeGrade = 4; EnableFileLogging = true; LogDirectory = string.Empty; EnableLongTrades = true; @@ -941,6 +947,7 @@ namespace NinjaTrader.NinjaScript.Strategies lines.Add("--- Controls ---"); lines.Add(string.Format("EnableKillSwitch : {0}", EnableKillSwitch)); lines.Add(string.Format("EnableVerboseLogging: {0}", EnableVerboseLogging)); + lines.Add(string.Format("MinTradeGrade : {0}", MinTradeGrade)); lines.Add(string.Format("EnableFileLogging : {0}", EnableFileLogging)); lines.Add(string.Format("LogDirectory : {0}", string.IsNullOrEmpty(LogDirectory) ? "(default)" : LogDirectory)); lines.Add("--- Portfolio ---"); diff --git a/src/NT8.Adapters/Strategies/SimpleORBNT8.cs b/src/NT8.Adapters/Strategies/SimpleORBNT8.cs index be84fa7..b0b6560 100644 --- a/src/NT8.Adapters/Strategies/SimpleORBNT8.cs +++ b/src/NT8.Adapters/Strategies/SimpleORBNT8.cs @@ -118,6 +118,7 @@ namespace NinjaTrader.NinjaScript.Strategies _strategyConfig.Parameters["StopTicks"] = StopTicks; _strategyConfig.Parameters["TargetTicks"] = TargetTicks; _strategyConfig.Parameters["OpeningRangeMinutes"] = OpeningRangeMinutes; + _strategyConfig.Parameters["MinTradeGrade"] = MinTradeGrade; if (Instrument != null && Instrument.MasterInstrument != null) { @@ -150,14 +151,15 @@ namespace NinjaTrader.NinjaScript.Strategies lines.Insert(endIdx + 2, string.Format("StdDevMultiplier : {0:F2}", StdDevMultiplier)); lines.Insert(endIdx + 3, string.Format("StopTicks : {0}", StopTicks)); lines.Insert(endIdx + 4, string.Format("TargetTicks : {0}", TargetTicks)); + lines.Insert(endIdx + 5, string.Format("MinTradeGrade : {0}", MinTradeGrade)); double tickDollarValue = 0.25 * 50.0; if (Instrument != null && Instrument.MasterInstrument != null) tickDollarValue = Instrument.MasterInstrument.TickSize * Instrument.MasterInstrument.PointValue; - lines.Insert(endIdx + 5, string.Format("StopDollars : {0:C}", StopTicks * tickDollarValue)); - lines.Insert(endIdx + 6, string.Format("TargetDollars : {0:C}", TargetTicks * tickDollarValue)); - lines.Insert(endIdx + 7, string.Format("RR_Ratio : {0:F2}:1", (double)TargetTicks / StopTicks)); + lines.Insert(endIdx + 6, string.Format("StopDollars : {0:C}", StopTicks * tickDollarValue)); + lines.Insert(endIdx + 7, string.Format("TargetDollars : {0:C}", TargetTicks * tickDollarValue)); + lines.Insert(endIdx + 8, string.Format("RR_Ratio : {0:F2}:1", (double)TargetTicks / StopTicks)); return lines; } diff --git a/src/NT8.Core/Intelligence/GradeFilter.cs b/src/NT8.Core/Intelligence/GradeFilter.cs index b9477d6..838d543 100644 --- a/src/NT8.Core/Intelligence/GradeFilter.cs +++ b/src/NT8.Core/Intelligence/GradeFilter.cs @@ -109,8 +109,8 @@ namespace NT8.Core.Intelligence private void InitializeDefaults() { - _minimumGradeByMode.Add(RiskMode.ECP, TradeGrade.B); - _minimumGradeByMode.Add(RiskMode.PCP, TradeGrade.C); + _minimumGradeByMode.Add(RiskMode.ECP, TradeGrade.C); + _minimumGradeByMode.Add(RiskMode.PCP, TradeGrade.B); _minimumGradeByMode.Add(RiskMode.DCP, TradeGrade.A); _minimumGradeByMode.Add(RiskMode.HR, TradeGrade.APlus); diff --git a/src/NT8.Strategies/Examples/SimpleORBStrategy.cs b/src/NT8.Strategies/Examples/SimpleORBStrategy.cs index f95879a..97feea5 100644 --- a/src/NT8.Strategies/Examples/SimpleORBStrategy.cs +++ b/src/NT8.Strategies/Examples/SimpleORBStrategy.cs @@ -153,9 +153,13 @@ namespace NT8.Strategies.Examples UpdateRiskMode(context); UpdateConfluenceInputs(bar, context); - if (_currentSessionDate != context.CurrentTime.Date) + DateTime thisSessionStart = context.Session != null + ? context.Session.SessionStart + : context.CurrentTime.Date.AddHours(9.5); + + if (thisSessionStart != _openingRangeStart || _currentSessionDate == DateTime.MinValue) { - ResetSession(context.Session != null ? context.Session.SessionStart : context.CurrentTime.Date); + ResetSession(thisSessionStart); } // Only trade during RTH @@ -211,15 +215,23 @@ namespace NT8.Strategies.Examples var score = _scorer.CalculateScore(candidate, context, bar, _factorCalculators); var mode = _riskModeManager.GetCurrentMode(); - if (!_gradeFilter.ShouldAcceptTrade(score.Grade, mode)) + int minGradeValue = 4; + if (_config != null && _config.Parameters != null && _config.Parameters.ContainsKey("MinTradeGrade")) { - var reason = _gradeFilter.GetRejectionReason(score.Grade, mode); - _logger.LogInformation( - "SimpleORBStrategy rejected intent for {0}: Grade={1}, Mode={2}, Reason={3}", - candidate.Symbol, - score.Grade, - mode, - reason); + var mgv = _config.Parameters["MinTradeGrade"]; + if (mgv is int) + minGradeValue = (int)mgv; + } + + TradeGrade minGrade = (TradeGrade)minGradeValue; + if ((int)score.Grade < (int)minGrade) + { + if (_logger != null) + _logger.LogInformation( + "SimpleORBStrategy filtered by grade: Score={0:F3} Grade={1} MinGrade={2}", + score.WeightedScore, + score.Grade, + minGrade); return null; } @@ -343,6 +355,13 @@ namespace NT8.Strategies.Examples _openingRangeLow = Double.MaxValue; _openingRangeReady = false; _tradeTaken = false; + + if (_logger != null) + _logger.LogInformation( + "Session reset: Date={0:yyyy-MM-dd} ORB window={1:HH:mm}-{2:HH:mm}", + _currentSessionDate, + _openingRangeStart, + _openingRangeEnd); } private void UpdateOpeningRange(BarData bar) diff --git a/tests/NT8.Core.Tests/Sizing/GradeBasedSizerTests.cs b/tests/NT8.Core.Tests/Sizing/GradeBasedSizerTests.cs index 693ffe6..2407f7d 100644 --- a/tests/NT8.Core.Tests/Sizing/GradeBasedSizerTests.cs +++ b/tests/NT8.Core.Tests/Sizing/GradeBasedSizerTests.cs @@ -149,9 +149,9 @@ namespace NT8.Core.Tests.Sizing var intent = CreateIntent(); var context = CreateContext(); - var confluence = CreateScore(TradeGrade.C, 0.61); + var confluence = CreateScore(TradeGrade.B, 0.71); var config = new SizingConfig(SizingMethod.FixedDollarRisk, 2, 10, 500.0, new Dictionary()); - var modeConfig = CreateModeConfig(RiskMode.PCP, 1.0, TradeGrade.C); + var modeConfig = CreateModeConfig(RiskMode.PCP, 1.0, TradeGrade.B); var result = sizer.CalculateGradeBasedSize( intent,