I'm interested in any additional information you have available on how StopTargetHandling.ByStrategyPosition functions. There is not a lot in the NinjaTrader manual about this option.
Specifically, is there a way to force the .ByStrategyPostion logic to sync the number of open Stop loss and Profit target orders to the number of contracts open in the strategy and/or the remaining contracts in an EntrySignal?
There are some issues I've noticed with .ByStrategyPostion when taking a partial exit order on a previous entry. The strategy takes one bar to update the quantity of stop loss and profit target orders Accepted/Working. This risks a mismatch of open contracts to open orders during that bar.
For example if your market position is 4 contracts Long with 4 stop loss and 4 target orders and you sell 1 contract in bar [0], the ByStrategyPosition logic lets you have 3 contracts Long with 4 stop loss and 4 profit target orders until the subsequent bar (bar [-1]). In that subsequent bar, the strategy will update to 3 contracts Long with 3 stop loss and 3 profit target orders. However, a lot can happen in that "processing" bar. I've seen all stop losses execute, resulting in a short position when you want to be flat. Also, the one bar delay can compound errors if there are 2 partial exits on subsequent bars etc.
It would be amazing if there was a way to force or call the .ByStrategyPosition logic in the OnExecutionUpdate or some other way to instantly get the stop loss and profit target orders synced with the strategy position and/or remaining contracts from a specific EntrySignal .
I know there is a .PerEntryExecution option where you can attach an EntrySignal to each stop/target, but I'm trying to understand how .ByStrategyPosition functions.
I have the NinjaScript I used below if that helps. I've also got the trade output showing the delays and errors, but that made the post too long
Thanks in advance for the help!
NINJASCRIPT:
public class ExpDevTradeOutputV2 : Strategy
{
private MIN MIN1;
public double StopLossTicks
{ get; set; }
public double TargetTicks
{ get; set; }
[NinjaScriptProperty]
[Range(1, int.MaxValue)]
[Display(Name = "Contracts", Description = "Number of contracts per entry", Order = 1, GroupName = "Parameters")]
public int Contracts
{ get; set; }
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
Description = @"Track order generation execution and errors in Output2 window";
Name = "ExpDevTradeOutputV2";
Calculate = Calculate.OnBarClose;
//OnPriceChange vs OnBarClose doesn't seem to affect errors in updating quantities of stop loss/tgt orders
EntriesPerDirection = 1;
EntryHandling = EntryHandling.UniqueEntries;
IsExitOnSessionCloseStrategy = true;
ExitOnSessionCloseSeconds = 30;
IsFillLimitOnTouch = false;
MaximumBarsLookBack = MaximumBarsLookBack.TwoHundredFiftySix;
OrderFillResolution = OrderFillResolution.Standard;
Slippage = 0;
StartBehavior = StartBehavior.WaitUntilFlat;
TimeInForce = TimeInForce.Gtc;
TraceOrders = false;
RealtimeErrorHandling = RealtimeErrorHandling.StopCancelClose;
StopTargetHandling = StopTargetHandling.ByStrategyPosition;
//this makes it better but the stop/targets are still off by 1 contract
BarsRequiredToTrade = 5;
IsInstantiatedOnEachOptimizationIteration = true;
//Use this variable to modify trade size
Contracts = 4;
TargetTicks = 60;
StopLossTicks = 12;
}
else if (State == State.Configure)
{
// Define list variables for stops and targets
PrintTo = PrintTo.OutputTab2;
ClearOutputWindow();
}
else if (State == State.DataLoaded)
{
//Min to set Stop Loss
MIN1 = MIN(Low, 55);
}
}
protected override void OnBarUpdate()
{
// Aviod out of bounds errors
if (BarsInProgress != 0)
return;
if (CurrentBars[0] < 1)
return;
//Initial Entry logic
if (Close[0] > Close[1] && Position.MarketPosition == MarketPosition.Flat) // figure something out so it doesn't place orders after it has partialed out (doesn't add orders)
{
//Need to set stop loss / profit target orders this way
//to ensure stop is submitted simultaneously with entry order
//Always handle stops and targets prior to order entry
//CalcMode.Ticks for convinience for tradeoutput script. Other strategies will use something different
SetProfitTarget(@"LongEntry1", CalculationMode.Ticks, TargetTicks);
//.Price mode can set any double as the price...call Min1[0] as that double
SetStopLoss(@"LongEntry1", CalculationMode.Price, MIN1[0], false);
EnterLong(Convert.ToInt32(Contracts), @"LongEntry1");
//Due to this entry method each open contract will not have a unique name and will not be uniquely tracable
}
//Partial out
if (Position.MarketPosition == MarketPosition.Long && Close[0] >= Position.AveragePrice + 2)
{
//Always handle stops & targets before entries and exits
//Move stop to breakeven
SetStopLoss(@"LongEntry1", CalculationMode.Price, Position.AveragePrice + 0.5, false);
ExitLong(1, @"Partial1", @"LongEntry1");
//this now moves the stops appropriately to breakeven but in the execution bar there is
//a mismatch between the Position.MarketPosition and the number of stoploss and target orders
//there is always one more stoploss and target order than there are open contracts in the execution bar
//with the .ByStrategyPosition selected there is a one bar delay in synching the number of
//stoploss and target orders with the number of open contracts on the strategy
//I have now also noticed an error where it may cancel all stop loss and profit target orders
//when there are still contracts open on the strategey
//2 COAs:
//COA1: accept the risk that strategy hits new breakeven stop but now you are short 1 contract
//unexpectedly. Add an if statement to exit all if Position.MarketPosition == MarketPosition.Short
//Will also have to add some code to mitigate situation where all stops are unintentionally cancelled
//COA2: figure out a way to make the program check the # of contracts to synch the stoploss and profit
//targets immediately after partial exit (OnPriceUpdate, OnPositionUpdate, etc)
}
//COA1 handle instance where breakeven stop executed with too many sell orders.
//This if statement must be cut and paste into all code with this type of order handling until
//COA2 can be solved
if (Position.MarketPosition == MarketPosition.Short)
{
ExitShort(Position.Quantity);
//This works but you are risking an entire bar of price movement before it gets filled
//Pursue COA2 as well
}
//Also has errors where it cancels all stops/tgts when there are still contracts on the strategy
}

Comment