the code
namespace NinjaTrader.NinjaScript.Strategies
{
public class My_D_S_15min_210224 : Strategy
{
private EMA EMA_Fast;
private EMA EMA_Slow;
private SMA SMA;
private SlopeEnhancedOp SlopeEnhancedOp_Long;
private SlopeEnhancedOp SlopeEnhancedOp_Short;
private ParabolicSAR ParabolicSAR1;
private DifferencesIndicator DifferencesIndicator1;
private bool okToGoShort = true;
private bool okToGoLong = true;
private int currentTime;
private double CurrentTrail_Stop = 0.0;
private double GetDiff_EMASlow_SMA(double price1, double price2)
{
double difference = price1 - price2;
return Math.Abs(difference);
}
private double GetDiff_EMASlow_EMAFast(double price3, double price4)
{
double difference = price3 - price4;
return Math.Abs(difference);
}
private double GetDiff_EMASlow_Close(double price5, double price6)
{
double difference = price5 - price6;
return Math.Abs(difference);
}
private double GetDiff_SMA_Close(double price7, double price8)
{
double difference = price7 - price8;
return Math.Abs(difference);
}
private double GetDiff_EMAFast_Close(double price9, double price10)
{
double difference = price9 - price10;
return Math.Abs(difference);
}
// Helper method to convert DateTime to HHmm format
private int ToHHmm(DateTime time)
{
return time.Hour * 100 + time.Minute;
}
// Helper method to check if a given time falls within a time period
private bool IsWithinTimePeriod(int time, int startTime, int endTime)
{
return time >= startTime && time <= endTime;
}
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
Description = @"10.06.2023, 12.06.2023 Condition group added, EMA_Fast bar before direction added";
Name = "My_D_S_SP500_15min_210224";
Calculate = Calculate.OnPriceChange;
EntriesPerDirection = 1;
EntryHandling = EntryHandling.AllEntries;
IsExitOnSessionCloseStrategy = false;
ExitOnSessionCloseSeconds = 30;
IsFillLimitOnTouch = false;
MaximumBarsLookBack = MaximumBarsLookBack.TwoHundredFiftySix;
OrderFillResolution = OrderFillResolution.Standard;
Slippage = 0;
StartBehavior = StartBehavior.WaitUntilFlat;
TimeInForce = TimeInForce.Gtc;
TraceOrders = false;
RealtimeErrorHandling = RealtimeErrorHandling.IgnoreAllErrors; // Check alternative handling !!!!
StopTargetHandling = StopTargetHandling.PerEntryExecution;
BarsRequiredToTrade = 20;
IsInstantiatedOnEachOptimizationIteration = true;
LONG_Distance_EMA_Slow_EMA_Fast = 8;
LONG_Distance_EMA_Slow_SMA = 8;
LONG_Distance_EMA_Slow_Close = 10;
LONG_Distance_EMA_Fast_Close = 9;
LONG_Distance_SMA_Close = 5;
SHORT_Distance_EMA_Slow_EMA_Fast = 10;
SHORT_Distance_EMA_Slow_SMA = 10;
SHORT_Distance_EMA_Slow_Close = 12;
SHORT_Distance_EMA_Fast_Close = 9;
SHORT_Distance_SMA_Close = 10;
Init_Stop_long = 35;
Init_Stop_short = 35;
Bars_Since_Exit = 1;
Bars_Since_Entry = 3;
InitOrderQuant = 2;
Stop_Profit_Long = 6500;
Stop_Profit_Short = 7000;
EMA_Slow_Period = 50;
EMA_Fast_Period = 9;
SMA_Period = 40;
ParabAccelaration = 0.015d;
ParabAccelMax = 0.15d;
ParabAccelStep = 0.015d;
Min_Slope_Long = 0.75d;
Min_Slope_Short = 0.75d;
}
else if (State == State.Configure)
{
}
else if (State == State.DataLoaded)
{
EMA_Fast = EMA(Close, EMA_Fast_Period);
EMA_Slow = EMA(Close, EMA_Slow_Period);
SMA = SMA(Close, SMA_Period);
SlopeEnhancedOp_Long = SlopeEnhancedOp(Close, 3, 56, 3, false, InputSeriesType.EMA, NormType.None, Brushes.Green, Brushes.Red);
SlopeEnhancedOp_Short = SlopeEnhancedOp(Close, 3, 56, 3, false, InputSeriesType.EMA, NormType.None, Brushes.Green, Brushes.Red);
var DifferencesIndicator1 = DifferencesIndicator();
// define color MA's
EMA_Fast.Plots[0].Brush = Brushes.Goldenrod;
EMA_Fast.Plots[0].Width = 1;
EMA_Slow.Plots[0].Brush = Brushes.Purple;
EMA_Slow.Plots[0].Width = 2;
SMA.Plots[0].Brush = Brushes.Red;
SMA.Plots[0].Width = 2;
ParabolicSAR1 = ParabolicSAR(Close, ParabAccelaration, ParabAccelMax, ParabAccelStep);
ParabolicSAR1.Plots[0].Brush = Brushes.Snow;
ParabolicSAR1.Plots[0].Width = 1;
AddChartIndicator(EMA_Fast);
AddChartIndicator(EMA_Slow);
AddChartIndicator(SMA);
AddChartIndicator(ParabolicSAR1);
AddChartIndicator(SlopeEnhancedOp_Short);
AddChartIndicator(SlopeEnhancedOp_Long);
AddChartIndicator(DifferencesIndicator1);
}
}
protected override void OnBarUpdate()
{
double previousTrail_Stop = 0.0;
if (BarsInProgress != 0)
return;
if (CurrentBars[0] < 75)
return;
bool isFlat = Position.MarketPosition == MarketPosition.Flat;
if (Bars.IsFirstBarOfSession && isFlat)
{
CalculateAndSetLotSize();
}
int currentTime = ToHHmm(Time[0]);
bool isTradingTime = IsWithinTimePeriod(currentTime, startTimePeriod1, endTimePeriod1)
|| IsWithinTimePeriod(currentTime, startTimePeriod2, endTimePeriod2);
// check entry criteria
if ((isFlat) && (isTradingTime))
{
if ( ((BarsSinceExitExecution(0, "", 0) > Bars_Since_Exit) || (BarsSinceExitExecution(0, "", 0) == -1) ))
{
if (okToGoLong) // OK to test long entry
{
if ( (SlopeEnhancedOp_Long[0] > Min_Slope_Long)
&& ( (GetDiff_EMASlow_SMA (EMA_Slow[0], SMA[0]) <= LONG_Distance_EMA_Slow_SMA)
&& (GetDiff_EMASlow_EMAFast(EMA_Slow[0], EMA_Fast[0]) <= LONG_Distance_EMA_Slow_EMA_Fast)
&& (GetDiff_EMASlow_Close (EMA_Slow[0], Close[0]) <= LONG_Distance_EMA_Slow_Close)
&& (GetDiff_EMAFast_Close (EMA_Fast[0], Close[0]) <= LONG_Distance_EMA_Fast_Close)
&& (GetDiff_SMA_Close (SMA[0], Close[0]) <= LONG_Distance_SMA_Close)
)
)
{
if (Close[0] >= EMA_Fast[0])
{
if (EMA_Fast[0] >= EMA_Slow[0] && EMA_Fast[0] >= SMA[0])
{
EnterLong(Convert.ToInt32(InitOrderQuant), @"LONG");
SetStopLoss(CalculationMode.Ticks, Init_Stop_long);
SetProfitTarget(@"LONG",CalculationMode.Currency, Stop_Profit_Long);
}
}
}
}
if (okToGoShort) // OK to test short entry
{
if ( (SlopeEnhancedOp_Short[0] < -Min_Slope_Short)
&& ( (GetDiff_EMASlow_SMA (EMA_Slow[0], SMA[0]) <= SHORT_Distance_EMA_Slow_SMA)
&& (GetDiff_EMASlow_EMAFast(EMA_Slow[0], EMA_Fast[0]) <= SHORT_Distance_EMA_Slow_EMA_Fast)
&& (GetDiff_EMASlow_Close (EMA_Slow[0], Close[0]) <= SHORT_Distance_EMA_Slow_Close)
&& (GetDiff_EMAFast_Close (EMA_Fast[0], Close[0]) <= SHORT_Distance_EMA_Fast_Close)
&& (GetDiff_SMA_Close (SMA[0], Close[0]) <= SHORT_Distance_SMA_Close)
)
)
{
if (Close[0] <= EMA_Fast[0])
{
if (EMA_Fast[0] <= EMA_Slow[0] && EMA_Fast[0] <= SMA[0])
{
EnterShort(Convert.ToInt32(InitOrderQuant), @"SHORT");
SetStopLoss(CalculationMode.Ticks, Init_Stop_short);
SetProfitTarget(@"SHORT",CalculationMode.Currency, Stop_Profit_Short);
}
}
}
}
}
}
else // if not flat manage trade
{
if (Position.MarketPosition == MarketPosition.Long)
{
// before changing the current trailing stop price, keep a copy
previousTrail_Stop = CurrentTrail_Stop;
if (IsFirstTickOfBar)
{
if (BarsSinceEntryExecution(0, "", 0) > Bars_Since_Entry)
{
if (ParabolicSAR1[1] < Low[1])
{
if (ParabolicSAR1[1] > (Position.AveragePrice - (Init_Stop_long * TickSize)) )
{
if (Close[0] > ParabolicSAR1[1])
{
CurrentTrail_Stop = ParabolicSAR1[0];
}
}
}
}
}
// if the CurrentTrail_Stop has changed then set the new stop loss
if (CurrentTrail_Stop != previousTrail_Stop)
SetStopLoss(CalculationMode.Price, CurrentTrail_Stop);
}
else if (Position.MarketPosition == MarketPosition.Short)
{
// before changing the current trailing stop price, keep a copy
previousTrail_Stop = CurrentTrail_Stop;
if (IsFirstTickOfBar)
{
if (BarsSinceEntryExecution(0, "", 0) > Bars_Since_Entry)
{
if (ParabolicSAR1[1] > High[1])
{
if (ParabolicSAR1[1] < (Position.AveragePrice + (Init_Stop_short * TickSize)) )
{
if (Close[0] < ParabolicSAR1[1])
{
CurrentTrail_Stop = ParabolicSAR1[0];
}
}
}
}
}
// if the CurrentTrail_Stop has changed then set the new stop loss
if (CurrentTrail_Stop != previousTrail_Stop)
SetStopLoss(CalculationMode.Price, CurrentTrail_Stop);
}
}
}
protected override void OnExecution(Execution execution)
{
if (execution.Order != null && execution.Order.OrderState == OrderState.Filled)
{
// Check if manual position management is enabled
if (ManualPositionManagement) return;
// Your logic here, for example:
// Recalculate lot size or other actions after a trade is executed
if (Position.Quantity == 0) // This checks if your position is flat after execution
{
CalculateAndSetLotSize();
}
}
}
private void CalculateAndSetLotSize()
{
if (Position.MarketPosition != MarketPosition.Flat) return;
double accountBalance = Account.Get(AccountItem.CashValue, Currency.UsDollar);
double maxTradeAmount = accountBalance * (MaxAccountUtilizationPercent / 100.0);
int newLotSize = (int)(maxTradeAmount / MarginSize);
InitOrderQuant = Math.Max(newLotSize, 1); // Assuming InitOrderQuant is used for trade volume
}
Comment