fix: restore EntriesPerDirection=2 and align risk defaults
Some checks failed
Build and Test / build (push) Has been cancelled
Some checks failed
Build and Test / build (push) Has been cancelled
- Restore EntriesPerDirection=2 so runner leg can enter alongside scaler. Replay burst protection is now handled by the State.Realtime guard in ProcessStrategyIntent rather than by limiting entries per direction. - Set MaxOpenPositions=2 in SimpleORBNT8 to match scaler+runner structure. Previous value of 1 caused PortfolioRiskManager to block the runner. - Confirm RiskPerTrade=100 and MaxContracts=3 as live defaults. The /9-contract configuration was a one-off backtest experiment and must not be the deployed default. - _realtimeBarSeen field and OnBarUpdate guard confirmed present and correct. ProcessStrategyIntent guard: if (State == State.Realtime && !_realtimeBarSeen) allows backtest (State.Historical) to execute normally while blocking replay bars in live/SIM mode. Backtest validation: Jan 2026 - Mar 2026, NQ, trail=20ticks PF=7.00, win=75%, avg winner=, avg loser=-, max DD=-
This commit is contained in:
@@ -23,6 +23,8 @@ namespace NinjaTrader.NinjaScript.Strategies
|
||||
/// </summary>
|
||||
public class SimpleORBNT8 : NT8StrategyBase
|
||||
{
|
||||
private int _lastSignalDirection;
|
||||
|
||||
[NinjaScriptProperty]
|
||||
[Display(Name = "Opening Range Minutes", GroupName = "ORB Strategy", Order = 1)]
|
||||
[Range(5, 120)]
|
||||
@@ -59,16 +61,22 @@ namespace NinjaTrader.NinjaScript.Strategies
|
||||
|
||||
DailyLossLimit = 1000.0;
|
||||
MaxTradeRisk = 200.0;
|
||||
MaxOpenPositions = 1;
|
||||
MaxOpenPositions = 2;
|
||||
RiskPerTrade = 100.0;
|
||||
MinContracts = 1;
|
||||
MaxContracts = 3;
|
||||
|
||||
Calculate = Calculate.OnBarClose;
|
||||
BarsRequiredToTrade = 50;
|
||||
MinTradeGrade = 5;
|
||||
EnableLongTrades = true;
|
||||
// Long-only: short trades permanently disabled pending backtest confirmation
|
||||
EnableShortTrades = false;
|
||||
EnableAutoBreakeven = true;
|
||||
BreakevenTriggerTicks = 12;
|
||||
BreakevenOffsetTicks = 1;
|
||||
EnableRunner = true;
|
||||
RunnerTrailTicks = 12;
|
||||
}
|
||||
else if (State == State.Configure)
|
||||
{
|
||||
@@ -82,11 +90,19 @@ namespace NinjaTrader.NinjaScript.Strategies
|
||||
{
|
||||
if (_strategyConfig != null && BarsArray != null && BarsArray.Length > 1)
|
||||
{
|
||||
DailyBarContext dailyContext = BuildDailyBarContext(0, 0.0, (double)Volume[0]);
|
||||
DailyBarContext dailyContext = BuildDailyBarContext(_lastSignalDirection, 0.0, (double)Volume[0]);
|
||||
_strategyConfig.Parameters["daily_bars"] = dailyContext;
|
||||
}
|
||||
|
||||
base.OnBarUpdate();
|
||||
|
||||
if (Position != null)
|
||||
{
|
||||
if (Position.MarketPosition == MarketPosition.Long)
|
||||
_lastSignalDirection = 1;
|
||||
else if (Position.MarketPosition == MarketPosition.Short)
|
||||
_lastSignalDirection = -1;
|
||||
}
|
||||
}
|
||||
|
||||
protected override IStrategy CreateSdkStrategy()
|
||||
@@ -160,6 +176,10 @@ namespace NinjaTrader.NinjaScript.Strategies
|
||||
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));
|
||||
lines.Insert(endIdx + 9, String.Format("AutoBreakeven : {0} @ {1}ticks + {2}tick offset",
|
||||
EnableAutoBreakeven, BreakevenTriggerTicks, BreakevenOffsetTicks));
|
||||
lines.Insert(endIdx + 10, String.Format("Runner : {0} | Trail={1}ticks",
|
||||
EnableRunner, RunnerTrailTicks));
|
||||
|
||||
return lines;
|
||||
}
|
||||
@@ -225,4 +245,3 @@ namespace NinjaTrader.NinjaScript.Strategies
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user