// This namespace holds Strategies in this folder and is required. Do not change it.
using System;
using NinjaTrader.Cbi;
namespace NinjaTrader.NinjaScript.Strategies
{
public class Auto_Trade_PriceCrossesEMA20_WithRSI_AndDirectiona lFilter_AndATMCallback : Strategy
{
private Series<double> ema20, ema4, tma20, rsi20;
private bool lineDrawnToday = false;
private DateTime lastDrawnDate;
private string atmStrategyId = string.Empty;
private string orderId = string.Empty;
private int dailyTradeCount = 0;
private const int maxDailyTrades = 2;
private const int startTime = 74500;
private const int endTime = 92000;
private const string atmTemplateName = "ZB 2 target trade"; // <- make sure this exactly matches your ATM template name in NinjaTrader
private void LogATMStrategyCallback(string reason, string message)
{
Print("ATM Strategy Callback - Reason: " + reason + ", Message: " + message);
}
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
Description = @"Strategy that trades when price crosses EMA20, RSI confirms, and direction is filtered. Uses ATM template and limits trades.";
Name = "PriceCrossesEMA20_WithRSI_AndDirectionalFilte r_An dATMCallback";
Calculate = Calculate.OnBarClose;
IsOverlay = true;
EntriesPerDirection = 1;
EntryHandling = EntryHandling.AllEntries;
IsExitOnSessionCloseStrategy = true;
ExitOnSessionCloseSeconds = 30;
MaximumBarsLookBack = MaximumBarsLookBack.Infinite;
BarsRequiredToTrade = 20;
}
else if (State == State.DataLoaded)
{
ema20 = EMA(20);
ema4 = EMA(4);
tma20 = TMA(20);
rsi20 = RSI(20, 1);
}
}
protected override void OnBarUpdate()
{
if (CurrentBar < 21) return;
// Filter: Only trade on Mondays and Fridays
DayOfWeek today = Time[0].DayOfWeek;
if (today != DayOfWeek.Monday && today != DayOfWeek.Friday)
return;
int currentTime = ToTime(Time[0]);
DateTime currentDate = Time[0].Date;
// Reset daily counter and line at start of new day
if (currentDate != lastDrawnDate)
{
lineDrawnToday = false;
lastDrawnDate = currentDate;
dailyTradeCount = 0;
}
// Draw 7:45 EMA line once per day
if (currentTime == startTime && !lineDrawnToday)
{
double emaValue = ema20[0];
Draw.HorizontalLine(this,
"EMA20Line_" + currentDate.ToString("yyyyMMdd"), emaValue, Brushes.Blue);
Draw.Text(this,
"EMA20Label_" + currentDate.ToString("yyyyMMdd"), "7:45 EMA", 0, emaValue + TickSize * 2);
lineDrawnToday = true;
}
// Display current trade count
Draw.TextFixed(this, "DailyTradeCount", "Trades Today: " + dailyTradeCount, TextPosition.TopRight, Brushes.Orange, new SimpleFont("Arial", 12), Brushes.Transparent, Brushes.Transparent, 0);
// Session time window check
if (currentTime < startTime || currentTime > endTime)
return;
// Enforce max trades per day
if (dailyTradeCount >= maxDailyTrades)
return;
// Wait for existing ATM strategy to complete
if (!string.IsNullOrEmpty(atmStrategyId))
{
OrderState entryState = AtmStrategyGetEntryOrderStatus(atmStrategyId);
MarketPosition pos = Position.MarketPosition;
if (pos == MarketPosition.Flat && (entryState == OrderState.Filled || entryState == OrderState.Cancelled))
{
atmStrategyId = string.Empty;
orderId = string.Empty;
}
else
{
return;
}
}
// Directional filter
bool isBuyDirection = ema4[0] > tma20[0];
bool isSellDirection = ema4[0] < tma20[0];
// Entry logic
if (isBuyDirection && CrossAbove(Close, ema20, 1) && CrossAbove(rsi20, 50, 1))
{
LaunchATM(OrderAction.Buy, "FilteredLong");
}
if (isSellDirection && CrossBelow(Close, ema20, 1) && CrossBelow(rsi20, 50, 1))
{
LaunchATM(OrderAction.SellShort, "FilteredShort");
}
}
private void LaunchATM(OrderAction action, string signalName)
{
atmStrategyId = GetAtmStrategyUniqueId();
orderId = GetAtmStrategyUniqueId();
AtmStrategyCreate(
orderId,
atmStrategyId,
atmTemplateName,
action,
OrderType.Market,
1, // quantity
0, // stop price for market order
TimeInForce.Day,
null, // parent order
signalName,
(atmCallbackReason, atmCallbackOrderId, atmCallbackOrderState, atmCallbackFillPrice, atmCallbackQuantity, atmCallbackId) =>
{
LogATMStrategyCallback(atmCallbackReason.ToString( ), action.ToString() + " via ATM: " + signalName);
if (atmCallbackReason == AtmStrategyCallbackReason.OrderFilled)
{
dailyTradeCount++;
Print("Trade Count Increased: " + dailyTradeCount);
}
}
);
}
}
}

Comment