Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

ProfitChaseStopTrailUnmanagedExample Short Trail

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

    ProfitChaseStopTrailUnmanagedExample Short Trail

    Hey everyone,

    I've downloaded and applied the ProfitChaseStopTrailUnmanagedExample Strategy but for the love of god I somehow can't get it to work for both long and short trades respectively.

    Can anyone help? If you're curious or haven't seen the Example Script, here it is:

    Code:
            protected override void OnBarUpdate()
            {
                if (CurrentBars[0] < BarsRequiredToTrade || CurrentBars[1] < BarsRequiredToTrade)
                    return;
    
                if (BarsInProgress == 0)
                    sessionIterator.GetNextSession(Time[0], true);
    
                // if after the exit on close, prevent new orders until the new session
                if (Times[1][0] >= sessionIterator.ActualSessionEnd.AddSeconds(-ExitOnSessionCloseSeconds) && Times[1][0] <= sessionIterator.ActualSessionEnd)
                {
                    exitOnCloseWait = true;
                }
                
                // an exit on close occurred in the previous session, reset for a new entry on the first bar of a new session
                if (exitOnCloseWait && Bars.IsFirstBarOfSession)
                {
                    entryOrder            = null;
                    profitTarget        = null;
                    stopLoss            = null;
                    exitFlat            = null;
                    exitSession            = null;
                    exitOnCloseWait        = false;
                    suppressCancelExit    = false;
                }
    
                // the entry logic can be done when the primary series is processing
                if (BarsInProgress == 0)
                {
                    // because this is a demonstration, this code will cause any historical position
                    // to be exited on the last historical bar so the strategy will always start flat in real-time
                    if (State == State.Historical && CurrentBar == BarsArray[0].Count - 2)
                    {
                        if (entryOrder != null)
                        {
                            if (profitTarget != null &&    (profitTarget.OrderState == OrderState.Accepted || profitTarget.OrderState == OrderState.Working))
                                CancelOrder(profitTarget);
    
                            else if (stopLoss != null && (stopLoss.OrderState == OrderState.Accepted || stopLoss.OrderState == OrderState.Working))
                                CancelOrder(stopLoss);
    
                            ordersCancelled        = false;
                            suppressCancelExit    = true;
    
                            exitName            = "exit to start flat";
                            exitFlat            = placeHolderOrder;
                            SubmitOrderUnmanaged(1, OrderAction.Sell, OrderType.Market, 1, 0, 0, string.Empty, exitName);
                        }
                    }
                    // if this is not the last historical bar, and entryOrder is null, then place an entry order
                    else if (!exitOnCloseWait && entryOrder == null && profitTarget == null && stopLoss == null)
                    {
                        entryName            = "entry";
                        entryOrder            = placeHolderOrder;
                        SubmitOrderUnmanaged(1, OrderAction.Buy, OrderType.Market, 1, 0, 0, string.Empty, entryName);
                    }
                }
    
                // all code below this point takes places during BarsInProgress 1 when the secondary series is processing
                if (BarsInProgress != 1)
                    return;
    
                if (ordersCancelled)
                {
                    message = string.Format("{0} stop and/or target cancelled or rejected", Times[1][0]);
    
                    if (entryOrder == null || entryOrder.OrderState != OrderState.Filled && PrintDetails)
                        Print(string.Format("{0} | OBU | entry not filled or is null", Times[1][0]));
    
                    // if the orders were cancelled due to the exit on close, do not submit an order to flatten
                    if (!exitOnCloseWait && !suppressCancelExit && entryOrder != null && entryOrder.OrderState == OrderState.Filled)
                    {
                        message        += "; exiting and resetting";
                        if (PrintDetails)
                            Print(message);
    
                        exitName    = "exit for cancel";
                        exitFlat    = placeHolderOrder;
                        SubmitOrderUnmanaged(1, OrderAction.Sell, OrderType.Market, entryOrder.Filled, 0, 0, string.Empty, exitName);
                    }
    
                    ordersCancelled = false;
                    return;
                }
                
                // the profitTarget/stopLoss is first created when the entry order fills. If it exists then move it.
    
                // trigger the chase action when the current price is further than the set distance to the profit target
                if (ChaseProfitTarget &&
                    profitTarget != null && (profitTarget.OrderState == OrderState.Accepted || profitTarget.OrderState == OrderState.Working) &&
                    Close[0] < currentPtPrice - ProfitTargetDistance * tickSizeSecondary)
                {
                    currentPtPrice    = Close[0] + ProfitTargetDistance * tickSizeSecondary;
                    ChangeOrder(profitTarget, entryOrder.Filled, currentPtPrice, 0);
                }
    
                // trigger the trail action when the current price is further than the set distance to the stop loss
                if (TrailStopLoss &&
                    stopLoss != null && (stopLoss.OrderState == OrderState.Accepted || stopLoss.OrderState == OrderState.Working) &&
                    Close[0] > currentSlPrice + StopLossDistance * tickSizeSecondary)
                {
                    currentSlPrice    = Close[0] - ProfitTargetDistance * tickSizeSecondary;
                    ChangeOrder(stopLoss, entryOrder.Filled, 0, currentSlPrice);
                }
            }
    
            protected override void OnExecutionUpdate(Cbi.Execution execution, string executionId, double price, int quantity,
                Cbi.MarketPosition marketPosition, string orderId, DateTime time)
            {
                if (PrintDetails)
                    Print(string.Format("{0} | OEU | execution | {1} | {2}", Times[1][0], time, execution.ToString()));
    
                if (execution.Order.OrderState != OrderState.Filled)
                    return;
    
                // when the entry order fully fills, place the profit target and stop loss
                if (entryOrder != null && execution.Order == entryOrder)
                {
                    ocoString = Guid.NewGuid().ToString();
    
                    if (UseProfitTarget)
                    {
                        if (PrintDetails)
                            Print(string.Format("{0} | OEU | placing profit target", execution.Time));
    
                        // calculate  a price for the profit target using the secondary series ticksize
                        currentPtPrice    = execution.Order.AverageFillPrice + ProfitTargetDistance * tickSizeSecondary;
                        profitTarget    = placeHolderOrder;
                        SubmitOrderUnmanaged(1, OrderAction.Sell, OrderType.Limit, execution.Order.Filled, currentPtPrice, 0, ocoString, "profit target");
                    }
    
                    if (UseStopLoss)
                    {
                        if (PrintDetails)
                            Print(string.Format("{0} | OEU | placing stop loss", execution.Time));
    
                        currentSlPrice    = execution.Order.AverageFillPrice - StopLossDistance * tickSizeSecondary;
                        stopLoss        = placeHolderOrder;
                        SubmitOrderUnmanaged(1, OrderAction.Sell, OrderType.StopMarket, execution.Order.Filled, 0, currentSlPrice, ocoString, "stop loss");
                    }
                }
            }
    
            protected override void OnOrderUpdate(Cbi.Order order, double limitPrice, double stopPrice,
                int quantity, int filled, double averageFillPrice,
                Cbi.OrderState orderState, DateTime time, Cbi.ErrorCode error, string comment)
            {
                if (PrintDetails)
                    Print(string.Format("{0} | OOU | order | {1} | {2}", Times[1][0], time, order.ToString()));
    
                AssignOrderToVariable(ref order);
    
                // if either the profit target or stop loss is cancelled or rejected, then reset for a new entry
                if ( !suppressCancelExit && entryOrder != null && order != entryOrder &&
                    (!UseProfitTarget || (profitTarget != null &&
                            (profitTarget.OrderState == OrderState.Cancelled ||
                                profitTarget.OrderState == OrderState.Rejected))) &&
                    (!UseStopLoss || (stopLoss != null &&
                            (stopLoss.OrderState == OrderState.Cancelled ||
                                stopLoss.OrderState == OrderState.Rejected)) )
                    )
                {
                    // if either the stop or target is cancelled, wait 1 tick in OBU to check
                    // to see if this was because of the Exit on close occurring or if manually cancelled
                    ordersCancelled = true;
    
                    if (PrintDetails)
                        Print(string.Format("{0} stop or target cancelled or rejected", Times[1][0]));
                }
                
                // once the stop loss or profit target (or exit for flat / exit for manual cancel) fills, reset for a new entry
                if ( (profitTarget != null && profitTarget.OrderState == OrderState.Filled && (stopLoss == null || stopLoss.OrderState == OrderState.Cancelled)) ||
                    (stopLoss != null && stopLoss.OrderState == OrderState.Filled && (profitTarget == null || profitTarget.OrderState == OrderState.Cancelled)) ||
                    (exitFlat != null && exitFlat.OrderState == OrderState.Filled && (profitTarget == null || profitTarget.OrderState == OrderState.Cancelled) && (stopLoss == null || stopLoss.OrderState == OrderState.Cancelled)) )
                {
                    if (PrintDetails)
                        Print(string.Format( "{0} | OOU | resetting", Times[1][0] ));
    
                    entryOrder            = null;
                    profitTarget        = null;
                    stopLoss            = null;
                    exitFlat            = null;
                    suppressCancelExit    = false;
                }
    
                // when the Exit on close fills, wait for the new session to start the next entry
                // (so no orders are submitted between the exit on close and the end of the session)
                if (exitSession != null && exitSession.OrderState == OrderState.Filled)
                {
                    if (PrintDetails)
                        Print(string.Format("{0} | OOU | exit on close filled waiting for next session for reset\r\n{1}", Times[1][0], order.ToString()));
    
                    exitOnCloseWait = true;
                }
            }
    
        }
    }
    ​
    Thanks in advance for any pointers you might be able to give to me!

    PS: I had to delete the public class and and all parameters and OnStateChange for it to fit in a post.

    Cheers

    #2
    Hello totalnewbie,

    Below is a link to the support article where this example can be found.


    You will need to add additional variables and conditions for short orders.

    You will need variables for the short entry order, short stoploss, and short profit target.

    Then from OnOrderUpdate() these variables will need to be assigned orders based on the name. Further, you will need conditions to check when the stop and target are filled, rejected, or cancelled to reset for a new entry.

    From OnExecutionUpdate() when the short entry fills, you will need additional conditions to submit the limit and stop as a BuyToCover with the limit below the ask and the stop above the ask.

    In OnBarUpdate() you will need conditions that are opposite of the long position conditions.

    If you are not familiar with coding C# or NinjaScript, below is a link to a support article with helpful resources on getting started with C# and NinjaScript.
    Chelsea B.NinjaTrader Customer Service

    Comment


      #3
      Hey Chelsea,

      thank you for the reply!

      I am slowly getting there. I have added all the additional variables and changed existing ones plus their calculations to accommodate for long and short orders.
      Now the only thing I am having trouble with is the check to start the strategy flat. I have changed the example code like so:

      Code:
        if (State == State.Historical && CurrentBar == BarsArray[0].Count - 2)
      
        {
      
            if (entryOrderLong != null)
      
            {
      
                if (profitTargetLong != null && (profitTargetLong.OrderState == OrderState.Accepted || profitTargetLong.OrderState == OrderState.Working))
      
                    CancelOrder(profitTargetLong);
      
      
      
      
                else if (stopLossLong != null && (stopLossLong.OrderState == OrderState.Accepted || stopLossLong.OrderState == OrderState.Working))
      
                    CancelOrder(stopLossLong);
      
      
      
      
                ordersCancelled = false;
      
                suppressCancelExit = true;
      
      
      
      
                exitName = "exit to start flat";
      
                exitFlat = placeHolderOrder;
      
                SubmitOrderUnmanaged(1, OrderAction.Sell, OrderType.Market, 1, 0, 0, string.Empty, exitName);
      
            }
      
      
      
      
            if (entryOrderShort != null)
      
            {
      
                if (profitTargetShort != null && (profitTargetShort.OrderState == OrderState.Accepted || profitTargetShort.OrderState == OrderState.Working))
      
                    CancelOrder(profitTargetShort);
      
      
      
      
                else if (stopLossLong != null && (stopLossShort.OrderState == OrderState.Accepted || stopLossShort.OrderState == OrderState.Working))
      
                    CancelOrder(stopLossShort);
      
      
      
      
                ordersCancelled = false;
      
                suppressCancelExit = true;
      
      
      
      
                exitName = "exit to start flat";
      
                exitFlat = placeHolderOrder;
      
                SubmitOrderUnmanaged(1, OrderAction.BuyToCover, OrderType.Market, 1, 0, 0, string.Empty, exitName);
      
            }
      
      
      
      
        }
      
        // if this is not the last historical bar, and entryOrder is null, then place an entry order
      
        else if (!exitOnCloseWait)
      
        {
      
            if (entryOrderLong == null && profitTargetLong == null && stopLossLong == null && Close[0] > Close[1])
      
            {
      
                entryName = "entry";
      
                entryOrderLong = placeHolderOrder;
      
                SubmitOrderUnmanaged(1, OrderAction.Buy, OrderType.Market, 1, 0, 0, string.Empty, entryName);
      
            }
      
      
      
      
            if (entryOrderShort == null && profitTargetShort == null && stopLossShort == null && Close[0] < Close[1])
      
            {
      
                entryName = "entry";
      
                entryOrderLong = placeHolderOrder;
      
                SubmitOrderUnmanaged(1, OrderAction.SellShort, OrderType.Market, 1, 0, 0, string.Empty, entryName);
      
            }
      
      
      
      
        }
      ​
      But still the strategy starts with an open position and is stuck there. Any pointers?
      I do have some C# experience and learning everyday.

      I think I have mixed up some if / else scopes here, but can't seem to see the forest for the trees.

      Any help would be greatly appreciated.

      Comment


        #4
        Hello totalnewbie,

        In the entryOrderShort branching command be sure to reference stopLossShort instead of stopLossLong.

        Add debugging prints above the condition to understand the behavior.


        Print the time of the bar, print the Position, print if entryOrderShort is null.

        Ensure TraceOrders is enabled and the print in OnOrderUpdate() has not been removed.

        Re-run the script and save the output to a text file (right-click Save as) and attach this to your next post.

        I'll be happy to assist with analyzing the output.
        Chelsea B.NinjaTrader Customer Service

        Comment


          #5
          Ahhhh, like I said, the forest for the trees.
          Fixing those two variables solved my issues. Thank you again so much!
          Sometimes a second pair of eyes is invaluable.

          This can be closed.

          Comment

          Latest Posts

          Collapse

          Topics Statistics Last Post
          Started by NullPointStrategies, Today, 05:17 AM
          0 responses
          52 views
          0 likes
          Last Post NullPointStrategies  
          Started by argusthome, 03-08-2026, 10:06 AM
          0 responses
          130 views
          0 likes
          Last Post argusthome  
          Started by NabilKhattabi, 03-06-2026, 11:18 AM
          0 responses
          70 views
          0 likes
          Last Post NabilKhattabi  
          Started by Deep42, 03-06-2026, 12:28 AM
          0 responses
          44 views
          0 likes
          Last Post Deep42
          by Deep42
           
          Started by TheRealMorford, 03-05-2026, 06:15 PM
          0 responses
          48 views
          0 likes
          Last Post TheRealMorford  
          Working...
          X