Announcement

Collapse

Looking for a User App or Add-On built by the NinjaTrader community?

Visit NinjaTrader EcoSystem and our free User App Share!

Have a question for the NinjaScript developer community? Open a new thread in our NinjaScript File Sharing Discussion Forum!
See more
See less

Partner 728x90

Collapse

Set Stop Loss and Profit Target Quantity issue

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Set Stop Loss and Profit Target Quantity issue

    Hi all, help please...any guidance will be greatly appreciated

    I have a strategy with 2 unique entries per trade. Trades can only be opened when I am flat.

    Longentry 1 (L1) and Longentry 2 (L2) have the same entry points but different exit points.

    however, on June 14 around 2:54 pm local time the strategy evoked a take profit order with a quantity of 2, so it exited L2 and L1 together.

    My SetProfitTarget command is assigned to unique entry (L1), so not sure why this is happening. Also L2's exit did not leave any signature on the chart, so i had to exit it manually in the end.

    SetProfitTarget(Longentry1, CalculationMode.Ticks, 2000, true);

    Complete codes are as follows....

    #region Using declarations
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Xml.Serialization;
    using NinjaTrader.Cbi;
    using NinjaTrader.Gui;
    using NinjaTrader.Gui.Chart;
    using NinjaTrader.Gui.SuperDom;
    using NinjaTrader.Gui.Tools;
    using NinjaTrader.Data;
    using NinjaTrader.NinjaScript;
    using NinjaTrader.Core.FloatingPoint;
    using NinjaTrader.NinjaScript.Indicators;
    using NinjaTrader.NinjaScript.DrawingTools;
    #endregion

    //This namespace holds Strategies in this folder and is required. Do not change it.
    namespace NinjaTrader.NinjaScript.Strategies
    {
    public class SCTchop : Strategy
    {
    private ZiSchaffTrendCycle ZiSchaffTrendCycle1;
    private ChoppinessIndex ChoppinessIndex1;
    private EMA EMA1;
    private EMA EMA2;
    private ATR ATR1;
    private MACD MACD1;
    private ADX ADX1;
    private EMA EMAADX;

    private const string Profit = "Profit target";
    private const string Long = "Long";
    private const string Short = "Short";
    private const string Longentry1 = "Longentry1";
    private const string Longentry2 = "Longentry2";
    private const string Shortentry1 = "Shortentry1";
    private const string Shortentry2 = "Shortentry2";

    private double boughtATR = 0;

    protected override void OnExecutionUpdate(Execution execution, string executionId, double price, int quantity, MarketPosition marketPosition, string orderId, DateTime time)
    {
    if (execution.IsEntryStrategy)
    {
    double stop, target;
    if (execution.Name.StartsWith(Long))
    {
    boughtATR = ATR1[0];
    stop = price - (boughtATR * ATRStop);
    SetStopLoss(execution.Name, CalculationMode.Price, stop, true);
    if (execution.Name == Longentry1)
    {
    target = price + (boughtATR * Entry1ATRTarget);
    SetProfitTarget(execution.Name, CalculationMode.Price, target, true);
    }
    }
    else if (execution.Name.StartsWith(Short))
    {
    boughtATR = ATR1[0];
    stop = price + (boughtATR * ATRStop);
    SetStopLoss(execution.Name, CalculationMode.Price, stop, true);
    if (execution.Name == Shortentry1)
    {
    target = price - (boughtATR * Entry1ATRTarget);
    SetProfitTarget(execution.Name, CalculationMode.Price, target, true);
    }
    }
    }
    else if (execution.IsExitStrategy)
    {
    if (execution.Name == Profit)
    {
    if (execution.Order.FromEntrySignal == Longentry1)
    {
    double breakEven = execution.Price - (boughtATR * Entry1ATRTarget);
    SetStopLoss(Longentry2, CalculationMode.Price, breakEven, true);
    }
    else if (execution.Order.FromEntrySignal == Shortentry1)
    {
    double breakEven = execution.Price + (boughtATR * Entry1ATRTarget);
    SetStopLoss(Shortentry2, CalculationMode.Price, breakEven, true);
    }
    }
    }
    }

    protected override void OnStateChange()
    {
    if (State == State.SetDefaults)
    {
    Description = @"Enter the description for your new custom Strategy here.";
    Name = "SCTchop";
    Calculate = Calculate.OnBarClose;
    EntriesPerDirection = 2;
    EntryHandling = EntryHandling.UniqueEntries;
    IsExitOnSessionCloseStrategy = true;
    ExitOnSessionCloseSeconds = 30;
    IsFillLimitOnTouch = false;
    MaximumBarsLookBack =
    MaximumBarsLookBack.TwoHundredFiftySix;
    OrderFillResolution = OrderFillResolution.High;
    OrderFillResolutionType = BarsPeriodType.Second;
    OrderFillResolutionValue = 1;
    Slippage = 0;
    StartBehavior = StartBehavior.WaitUntilFlat;
    TimeInForce = TimeInForce.Gtc;
    TraceOrders = true;
    RealtimeErrorHandling = RealtimeErrorHandling.StopCancelClose;
    StopTargetHandling = StopTargetHandling.ByStrategyPosition;
    BarsRequiredToTrade = 20;
    // Disable this property for performance gains in Strategy Analyzer optimizations
    // See the Help Guide for additional information
    IsInstantiatedOnEachOptimizationIteration = true;

    ATRStop = 1.5;
    Entry1ATRTarget = 3;
    }
    else if (State == State.Configure)
    {
    }
    else if (State == State.DataLoaded)
    {
    ZiSchaffTrendCycle1 = ZiSchaffTrendCycle(Close, 12, 26, 9, 14, 0.5);
    ChoppinessIndex1 = ChoppinessIndex(Close, 14);
    EMA1 = EMA(ChoppinessIndex1, 14);
    EMA2 = EMA(Close, 200);
    ATR1 = ATR(Close, 14);
    MACD1 = MACD(Close, 12, 26, 9);

    ADX1 = ADX(14);
    EMAADX = EMA(ADX1, 14);

    MACD1.Plots[0].Brush = Brushes.Green;
    AddChartIndicator(MACD1);

    ZiSchaffTrendCycle1.Plots[0].Brush = Brushes.Orange;
    AddChartIndicator(ZiSchaffTrendCycle1);

    EMA2.Plots[0].Brush = Brushes.Yellow;
    AddChartIndicator(EMA2);

    ResetProfitStop();
    }
    }

    private void ResetProfitStop()
    {
    SetProfitTarget(Longentry1, CalculationMode.Ticks, 2000, true);
    SetStopLoss(Longentry1, CalculationMode.Ticks, 2000, false);
    SetStopLoss(Longentry2, CalculationMode.Ticks, 2000, false);

    SetProfitTarget(Shortentry1, CalculationMode.Ticks, 2000, true);
    SetStopLoss(Shortentry1, CalculationMode.Ticks, 2000, false);
    SetStopLoss(Shortentry2, CalculationMode.Ticks, 2000, false);

    boughtATR = 0;
    }

    protected override void OnBarUpdate()
    {
    if (BarsInProgress != 0)
    return;
    if (CurrentBars[0] < 1 || CurrentBars[1] < 0)
    return;

    if (Position.MarketPosition == MarketPosition.Flat)
    {
    ResetProfitStop();

    if ((CrossAbove(ZiSchaffTrendCycle1, 30, 1) && ChoppinessIndex1[0] < EMA1[0] && Close[0] > EMA2[0] && ADX1[0] > EMAADX[0]) ||
    (Close[0] > EMA2[0] && ZiSchaffTrendCycle1[0] > 50 && CrossBelow(ChoppinessIndex1, EMA1, 1) && ADX1[0] > EMAADX[0]))
    {
    EnterLong(1, Longentry1);
    EnterLong(1, Longentry2);
    }
    else if ((CrossBelow(ZiSchaffTrendCycle1, 70, 1) && ChoppinessIndex1[0] < EMA1[0] && Close[0] < EMA2[0] && ADX1[0] > EMAADX[0]) ||
    (Close[0] < EMA2[0] && ZiSchaffTrendCycle1[0] < 50 && CrossBelow(ChoppinessIndex1, EMA1, 1) && ADX1[0] > EMAADX[0]))
    {
    EnterShort(1, Shortentry1);
    EnterShort(1, Shortentry2);
    }
    }
    else
    {
    if (Position.MarketPosition == MarketPosition.Long)
    {
    if (CrossBelow(MACD1.Default, MACD1.Avg, 1))
    ExitLong();
    }
    else
    {
    if (CrossAbove(MACD1.Default, MACD1.Avg, 1))
    ExitShort();
    }
    }
    }

    #region configuration
    [Range(1, double.MaxValue), NinjaScriptProperty]
    [Display(ResourceType = typeof(Custom.Resource), Name = "ATR Stop", GroupName = "Custom Parameters", Order = 0)]
    public double ATRStop
    { get; set; }

    [Range(1, double.MaxValue), NinjaScriptProperty]
    [Display(ResourceType = typeof(Custom.Resource), Name = "Entry1 ATR Target", GroupName = "Custom Parameters", Order = 1)]
    public double Entry1ATRTarget
    { get; set; }
    #endregion
    }
    }



    #2
    Hello lmfao,

    Thank you for your post.

    There's several issues here I can identify looking at both your code and your log and trace files. First, you're using the managed approach on a Rithmic connection which can have issues updating the position correctly as the order of Order/Execution/Position updates aren't guaranteed with Rithmic, which can cause issues.With Rithmic, especially with strategies that enter positions that are greater than 1 quantity, using the Unmanaged Approach and calculating the position and quantity internally to the strategy rather than relying on position updates from Rithmic would be recommended. I've attached an example of this below. Secondly, you're mixing Exit and Set orders for exits, which is often problematic and orders may be ignored. I also see some indications of an unstable connection, as earlier in the day before the issue you had a connection loss that caused the strategy to disable.

    However, what caused the profit target to update to 2 is this:

    StopTargetHandling = StopTargetHandling.ByStrategyPosition;

    This will cause the strategy to update stops and targets to the quantity of the position, not the individual order. With MIT orders like you're using for your Profit Target in particular, since these are not held on the brokerage servers, it's going to update that to the position quantity because of this setting. I'd try setting this to PerEntryExecution instead.

    Please let us know if we may be of further assistance to you.

    Attached Files
    Kate W.NinjaTrader Customer Service

    Comment


      #3
      Thank you Kate. The scope of changes proposed is a bit beyond my capability. Is there a trusted NJ8 consultant that I can hire for this piece of work?

      Comment


        #4
        Hello lmfao,

        Thank you for your post.

        You can search our list of NinjaScript consultants through the link below. Simply enter a consultant name or search by using our filter categories. Once you have identified your consultants of choice, please visit each consultant's site for more information or contact them directly to learn more:
        You can locate the contact information for the consultants on their direct websites for any additional questions you may have. Since these consultants are third-party services for NinjaTrader, all pricing and support information will need to be obtained through the consultant.

        The NinjaTrader Ecosystem website is for educational and informational purposes only and should not be considered a solicitation to buy or sell a futures contract or make any other type of investment decision. The companies and services listed on this website are not to be considered a recommendation and it is the reader's responsibility to evaluate any product, service, or company. NinjaTrader Ecosystem, LLC is not responsible for the accuracy or content of any product, service or company linked to on this website.

        Let me know if I may be of further assistance.
        Thomas C.NinjaTrader Customer Service

        Comment


          #5
          Thanks Kate (and Thanks Thomas).

          With reference to the earlier discussion, new codes have been implemented and logs attached. In the position highlighted (7:10pm June 18)

          it appears that S1 and S2 are now treated as unique entries, and first exit order was executed on S1, followed by a general, non-entry specific exit order.

          Kate - notwithstanding all other known existing issues you mentioned, is there a particular code fix for this trade attached?

          Latest code below.

          #region Using declarations
          using System;
          using System.Collections.Generic;
          using System.ComponentModel;
          using System.ComponentModel.DataAnnotations;
          using System.Linq;
          using System.Text;
          using System.Threading.Tasks;
          using System.Windows;
          using System.Windows.Input;
          using System.Windows.Media;
          using System.Xml.Serialization;
          using NinjaTrader.Cbi;
          using NinjaTrader.Gui;
          using NinjaTrader.Gui.Chart;
          using NinjaTrader.Gui.SuperDom;
          using NinjaTrader.Gui.Tools;
          using NinjaTrader.Data;
          using NinjaTrader.NinjaScript;
          using NinjaTrader.Core.FloatingPoint;
          using NinjaTrader.NinjaScript.Indicators;
          using NinjaTrader.NinjaScript.DrawingTools;
          #endregion

          //This namespace holds Strategies in this folder and is required. Do not change it.
          namespace NinjaTrader.NinjaScript.Strategies
          {
          public class SCTchop : Strategy
          {
          private ZiSchaffTrendCycle ZiSchaffTrendCycle1;
          private ChoppinessIndex ChoppinessIndex1;
          private EMA EMA1;
          private EMA EMA2;
          private ATR ATR1;
          private MACD MACD1;
          private ADX ADX1;
          private EMA EMAADX;

          private const string Profit = "Profit target";
          private const string Long = "Long";
          private const string Short = "Short";
          private const string Longentry1 = "Longentry1";
          private const string Longentry2 = "Longentry2";
          private const string Shortentry1 = "Shortentry1";
          private const string Shortentry2 = "Shortentry2";

          private double boughtATR = 0;

          protected override void OnExecutionUpdate(Execution execution, string executionId, double price, int quantity, MarketPosition marketPosition, string orderId, DateTime time)
          {
          if (execution.IsEntryStrategy)
          {
          double stop, target;
          if (execution.Name.StartsWith(Long))
          {
          boughtATR = ATR1[0];
          stop = price - (boughtATR * ATRStop);
          SetStopLoss(execution.Name, CalculationMode.Price, stop, false);
          if (execution.Name == Longentry1)
          {
          target = price + (boughtATR * Entry1ATRTarget);
          SetProfitTarget(execution.Name, CalculationMode.Price, target, false);
          }
          }
          else if (execution.Name.StartsWith(Short))
          {
          boughtATR = ATR1[0];
          stop = price + (boughtATR * ATRStop);
          SetStopLoss(execution.Name, CalculationMode.Price, stop, false);
          if (execution.Name == Shortentry1)
          {
          target = price - (boughtATR * Entry1ATRTarget);
          SetProfitTarget(execution.Name, CalculationMode.Price, target, false);
          }
          }
          }
          else if (execution.IsExitStrategy)
          {
          if (execution.Name == Profit)
          {
          if (execution.Order.FromEntrySignal == Longentry1)
          {
          double breakEven = execution.Price - (boughtATR * Entry1ATRTarget);
          SetStopLoss(Longentry2, CalculationMode.Price, breakEven, false);
          }
          else if (execution.Order.FromEntrySignal == Shortentry1)
          {
          double breakEven = execution.Price + (boughtATR * Entry1ATRTarget);
          SetStopLoss(Shortentry2, CalculationMode.Price, breakEven, false);
          }
          }
          }
          }

          protected override void OnStateChange()
          {
          if (State == State.SetDefaults)
          {
          Description = @"Enter the description for your new custom Strategy here.";
          Name = "SCTchop";
          Calculate = Calculate.OnBarClose;
          EntriesPerDirection = 2;
          EntryHandling = EntryHandling.UniqueEntries;
          IsExitOnSessionCloseStrategy = true;
          ExitOnSessionCloseSeconds = 30;
          IsFillLimitOnTouch = false;
          MaximumBarsLookBack = MaximumBarsLookBack.TwoHundredFiftySix;
          OrderFillResolution = OrderFillResolution.High;
          OrderFillResolutionType = BarsPeriodType.Second;
          OrderFillResolutionValue = 1;
          Slippage = 0;
          StartBehavior = StartBehavior.WaitUntilFlat;
          TimeInForce = TimeInForce.Gtc;
          TraceOrders = true;
          RealtimeErrorHandling = RealtimeErrorHandling.StopCancelClose;
          StopTargetHandling = StopTargetHandling.PerEntryExecution;
          BarsRequiredToTrade = 20;
          // Disable this property for performance gains in Strategy Analyzer optimizations
          // See the Help Guide for additional information
          IsInstantiatedOnEachOptimizationIteration = true;

          ATRStop = 1.5;
          Entry1ATRTarget = 3;
          }
          else if (State == State.Configure)
          {
          }
          else if (State == State.DataLoaded)
          {
          ZiSchaffTrendCycle1 = ZiSchaffTrendCycle(Close, 12, 26, 9, 14, 0.5);
          ChoppinessIndex1 = ChoppinessIndex(Close, 14);
          EMA1 = EMA(ChoppinessIndex1, 14);
          EMA2 = EMA(Close, 200);
          ATR1 = ATR(Close, 14);
          MACD1 = MACD(Close, 12, 26, 9);

          ADX1 = ADX(14);
          EMAADX = EMA(ADX1, 14);

          MACD1.Plots[0].Brush = Brushes.Green;
          AddChartIndicator(MACD1);

          ZiSchaffTrendCycle1.Plots[0].Brush = Brushes.Orange;
          AddChartIndicator(ZiSchaffTrendCycle1);

          EMA2.Plots[0].Brush = Brushes.Yellow;
          AddChartIndicator(EMA2);

          ResetProfitStop();
          }
          }

          private void ResetProfitStop()
          {
          SetProfitTarget(Longentry1, CalculationMode.Ticks, 20, false);
          SetStopLoss(Longentry1, CalculationMode.Ticks, 20, false);
          SetStopLoss(Longentry2, CalculationMode.Ticks, 20, false);

          SetProfitTarget(Shortentry1, CalculationMode.Ticks, 20, false);
          SetStopLoss(Shortentry1, CalculationMode.Ticks, 20, false);
          SetStopLoss(Shortentry2, CalculationMode.Ticks, 20, false);

          boughtATR = 0;
          }

          protected override void OnBarUpdate()
          {
          if (CurrentBar < BarsRequiredToTrade)
          return;

          if (BarsInProgress != 0)
          return;

          if (Position.MarketPosition == MarketPosition.Flat)
          {
          ResetProfitStop();

          if ((CrossAbove(ZiSchaffTrendCycle1, 30, 1) && ChoppinessIndex1[0] < EMA1[0] && Close[0] > EMA2[0] && ADX1[0] > EMAADX[0]) ||
          (Close[0] > EMA2[0] && ZiSchaffTrendCycle1[0] > 50 && CrossBelow(ChoppinessIndex1, EMA1, 1) && ADX1[0] > EMAADX[0]))
          {
          EnterLong(1, Longentry1);
          EnterLong(1, Longentry2);
          }
          else if ((CrossBelow(ZiSchaffTrendCycle1, 70, 1) && ChoppinessIndex1[0] < EMA1[0] && Close[0] < EMA2[0] && ADX1[0] > EMAADX[0]) ||
          (Close[0] < EMA2[0] && ZiSchaffTrendCycle1[0] < 50 && CrossBelow(ChoppinessIndex1, EMA1, 1) && ADX1[0] > EMAADX[0]))
          {
          EnterShort(1, Shortentry1);
          EnterShort(1, Shortentry2);
          }
          }
          else
          {
          if (Position.MarketPosition == MarketPosition.Long)
          {
          if (CrossBelow(MACD1.Default, MACD1.Avg, 1))
          ExitLong();
          }
          else
          {
          if (CrossAbove(MACD1.Default, MACD1.Avg, 1))
          ExitShort();
          }
          }
          }

          #region configuration
          [Range(1, double.MaxValue), NinjaScriptProperty]
          [Display(ResourceType = typeof(Custom.Resource), Name = "ATR Stop", GroupName = "Custom Parameters", Order = 0)]
          public double ATRStop
          { get; set; }

          [Range(1, double.MaxValue), NinjaScriptProperty]
          [Display(ResourceType = typeof(Custom.Resource), Name = "Entry1 ATR Target", GroupName = "Custom Parameters", Order = 1)]
          public double Entry1ATRTarget
          { get; set; }
          #endregion
          }
          }
          Attached Files
          Last edited by lmfao; 06-18-2021, 05:57 AM.

          Comment


            #6
            Hello lmfao,

            Thank you for your reply.

            We received an email from a third party programmer regarding this post, and I was just curious if you'd reached out to them from the link above and they perhaps replied back to our support email instead of directly to you?

            That being said, without seeing where the profit target was actually submitted it's hard to tell what may have occurred. To confirm, after making changes to the script, did you fully remove and re-add the strategy to a chart before starting it back up? This can cause changes not to be picked up and odd behavior can occur, especially if you've changed things in OnStateChange.

            I'm not seeing anything obvious that would cause a profit target to be set for multiple orders in your code. The first thing I would recommend would be to turn on the Order Trace function:

            Strategy Builder > Default Properties > More Properties > Trace Orders, or:

            if (State == State.SetDefaults)
            {
            TraceOrders = true;
            }

            Once you then recompile the strategy, you can open a new NinjaScript Output window under New > NinjaScript Output. This will print a log of any orders submitted by the strategy during while it's running, along with any ignored orders. You can then look through and see what may be occurring.

            Here is a link to our help guide that goes into more detail on tracing orders:

            https://ninjatrader.com/support/help...aceorders2.htm

            Trace orders alone may not give you the full picture of whether or not a order should have been entered on a given bar or for a given quantity, so adding prints to your strategy that will show in the NinjaScript Output window, with information on what the variables you're using for your conditions are on a particular bar, can be helpful.

            This forum post goes into great detail on how to use prints to help figure out where issues may stem from — this should get you going in the correct direction. You can even add these using the Strategy Builder.

            https://ninjatrader.com/support/foru...ns-not-working

            If you run into issues like we saw here, the above information will allow you to print out all values used in the condition in question that may be evaluating differently. With the printout information you can assess what is different between the two.

            Please let us know if we may be of further assistance to you.
            Kate W.NinjaTrader Customer Service

            Comment

            Latest Posts

            Collapse

            Topics Statistics Last Post
            Started by mjairg, 07-20-2023, 11:57 PM
            3 responses
            213 views
            1 like
            Last Post PaulMohn  
            Started by TheWhiteDragon, 01-21-2019, 12:44 PM
            4 responses
            544 views
            0 likes
            Last Post PaulMohn  
            Started by GLFX005, Today, 03:23 AM
            0 responses
            3 views
            0 likes
            Last Post GLFX005
            by GLFX005
             
            Started by XXtrader, Yesterday, 11:30 PM
            2 responses
            12 views
            0 likes
            Last Post XXtrader  
            Started by Waxavi, Today, 02:10 AM
            0 responses
            7 views
            0 likes
            Last Post Waxavi
            by Waxavi
             
            Working...
            X