Pre-cleanup baseline snapshot
Some checks failed
Build and Test / build (push) Has been cancelled

This commit is contained in:
2026-04-05 16:50:18 -04:00
parent d856f3949d
commit 9a28a49292
12 changed files with 695 additions and 30 deletions

View File

@@ -182,6 +182,16 @@ namespace NinjaTrader.NinjaScript.Strategies
ExitShort("EmergencyFlatten");
}
/// <summary>
/// Returns true if the concrete strategy has ForceSessionReset enabled.
/// Override in subclass to expose the NinjaScript parameter value.
/// Default returns false so base class never forces a reset unless overridden.
/// </summary>
protected virtual bool GetForceSessionReset()
{
return false;
}
/// <summary>
/// Create the SDK strategy instance.
/// </summary>
@@ -207,7 +217,7 @@ namespace NinjaTrader.NinjaScript.Strategies
MaximumBarsLookBack = MaximumBarsLookBack.TwoHundredFiftySix;
OrderFillResolution = OrderFillResolution.Standard;
Slippage = 0;
StartBehavior = StartBehavior.WaitUntilFlat;
StartBehavior = StartBehavior.AdoptAccountPosition;
TimeInForce = TimeInForce.Gtc;
TraceOrders = false;
RealtimeErrorHandling = RealtimeErrorHandling.StopCancelClose;
@@ -220,7 +230,7 @@ namespace NinjaTrader.NinjaScript.Strategies
MaxOpenPositions = 3;
RiskPerTrade = 100.0;
MinContracts = 1;
MaxContracts = 10;
MaxContracts = 3;
EnableKillSwitch = false;
EnableVerboseLogging = false;
MinTradeGrade = 4;
@@ -229,10 +239,10 @@ namespace NinjaTrader.NinjaScript.Strategies
EnableLongTrades = true;
EnableShortTrades = true;
EnableAutoBreakeven = true;
BreakevenTriggerTicks = 12;
BreakevenTriggerTicks = 20;
BreakevenOffsetTicks = 1;
EnableRunner = true;
RunnerTrailTicks = 12;
RunnerTrailTicks = 20;
_killSwitchTriggered = false;
_connectionLost = false;
}
@@ -242,6 +252,14 @@ namespace NinjaTrader.NinjaScript.Strategies
{
try
{
// DIAGNOSTIC: Print actual runtime property values to confirm
// what NT8 loaded vs what SetDefaults specified.
Print(string.Format("[SDK-DIAG] SetDefaults check: BE={0} Trail={1} MaxC={2} SB={3} EPD={4}",
BreakevenTriggerTicks,
RunnerTrailTicks,
MaxContracts,
StartBehavior,
EntriesPerDirection));
InitFileLog();
InitializeSdkComponents();
_sdkInitialized = true;
@@ -260,6 +278,18 @@ namespace NinjaTrader.NinjaScript.Strategies
else if (State == State.Realtime)
{
_realtimeBarSeen = false;
// If ForceSessionReset is enabled, push a reset signal into the SDK strategy
// so _tradeTaken is cleared before any live bar is processed.
// This recovers from replay-burst scenarios where historical bars set _tradeTaken.
if (_sdkStrategy != null && GetForceSessionReset())
{
var resetParams = new Dictionary<string, object>();
resetParams.Add("force_session_reset", true);
_sdkStrategy.SetParameters(resetParams);
Print(string.Format("[SDK] ForceSessionReset: _tradeTaken cleared on live start at {0}", DateTime.Now.ToString("HH:mm:ss")));
}
WriteSettingsFile();
}
else if (State == State.Terminated)
@@ -748,9 +778,24 @@ namespace NinjaTrader.NinjaScript.Strategies
private BarData ConvertCurrentBar()
{
DateTime barTimeEt;
try
{
var centralZone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
var easternZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTime utcTime = TimeZoneInfo.ConvertTimeToUtc(
DateTime.SpecifyKind(Time[0], DateTimeKind.Unspecified),
centralZone);
barTimeEt = TimeZoneInfo.ConvertTimeFromUtc(utcTime, easternZone);
}
catch
{
barTimeEt = Time[0];
}
return NT8DataConverter.ConvertBar(
Instrument.MasterInstrument.Name,
Time[0],
barTimeEt,
Open[0],
High[0],
Low[0],

View File

@@ -40,6 +40,10 @@ namespace NinjaTrader.NinjaScript.Strategies
[Range(1, 50)]
public int StopTicks { get; set; }
[NinjaScriptProperty]
[Display(Name = "Force Session Reset On Start", GroupName = "ORB Strategy", Order = 10)]
public bool ForceSessionReset { get; set; }
[NinjaScriptProperty]
[Display(Name = "Profit Target Ticks", GroupName = "ORB Risk", Order = 2)]
[Range(1, 100)]
@@ -73,10 +77,12 @@ namespace NinjaTrader.NinjaScript.Strategies
// Long-only: short trades permanently disabled pending backtest confirmation
EnableShortTrades = false;
EnableAutoBreakeven = true;
BreakevenTriggerTicks = 12;
BreakevenTriggerTicks = 20;
BreakevenOffsetTicks = 1;
EnableRunner = true;
RunnerTrailTicks = 12;
RunnerTrailTicks = 20;
ForceSessionReset = false;
StartBehavior = StartBehavior.AdoptAccountPosition;
}
else if (State == State.Configure)
{
@@ -105,6 +111,11 @@ namespace NinjaTrader.NinjaScript.Strategies
}
}
protected override bool GetForceSessionReset()
{
return ForceSessionReset;
}
protected override IStrategy CreateSdkStrategy()
{
return new SdkSimpleORB(OpeningRangeMinutes, StdDevMultiplier);

View File

@@ -203,7 +203,15 @@ namespace NT8.Strategies.Examples
}
if (_tradeTaken)
{
if (_logger != null)
_logger.LogDebug(
"SimpleORBStrategy skip: trade already taken for session {0:yyyy-MM-dd}; bar={1:yyyy-MM-dd HH:mm}; symbol={2}",
_currentSessionDate,
bar.Time,
context.Symbol);
return null;
}
var openingRange = _openingRangeHigh - _openingRangeLow;
var volatilityBuffer = openingRange * (_stdDevMultiplier - 1.0);
@@ -286,6 +294,15 @@ namespace NT8.Strategies.Examples
_tradeTaken = true;
if (_logger != null)
_logger.LogDebug(
"SimpleORBStrategy flag set: tradeTaken={0} session={1:yyyy-MM-dd}; bar={2:yyyy-MM-dd HH:mm}; side={3}; symbol={4}",
_tradeTaken,
_currentSessionDate,
bar.Time,
candidate.Side,
candidate.Symbol);
if (_logger != null && score.Factors != null)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
@@ -347,7 +364,27 @@ namespace NT8.Strategies.Examples
/// <param name="parameters">Parameter map.</param>
public void SetParameters(Dictionary<string, object> parameters)
{
// Constructor-bound parameters intentionally remain immutable for deterministic behavior.
if (parameters == null)
return;
// force_session_reset: clear _tradeTaken and ORB state so a fresh live session
// can trade even if historical replay set _tradeTaken before going realtime.
if (parameters.ContainsKey("force_session_reset"))
{
var val = parameters["force_session_reset"];
if (val is bool && (bool)val)
{
lock (_lock)
{
_tradeTaken = false;
_openingRangeReady = false;
_openingRangeHigh = Double.MinValue;
_openingRangeLow = Double.MaxValue;
if (_logger != null)
_logger.LogInformation("ForceSessionReset: _tradeTaken cleared, ORB state reset for live session");
}
}
}
}
private void EnsureInitialized()