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

Modified Sample with stops gets order contract count and stop count out of sync

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

    Modified Sample with stops gets order contract count and stop count out of sync

    Using a modified version of the SampleSMACrossover.cs, if I add stop losses to the code, then the stop loss contract count will get out of sync with the buy/sell-short contract count. Any idea why this is and most importantly, how to prevent it?

    I'll post a reply with the source code.

    See in the attached images how the orders and stop losses are in-sync at first and can fall out of sync at certain points. It's very important that the stop losses be in-sync with the order contract count to avoid disaster if the Internet loses connectivity, for instance. My test settings:

    MNQ 09-22
    20 Range
    Playback date: 7/4/2022
    Play at high speed until about 02:33 AM EST, see all orders and stops match in count.
    Play past 02:33 AM EST, see that there are 2 orders (correct), but only 1 stop loss (incorrect).
    Continue to play forward to see more discrepencies.
    Attached Files
    Last edited by bfalls; 07-10-2022, 05:17 PM.

    #2
    //
    // Copyright (C) 2021, NinjaTrader LLC <www.ninjatrader.com>.
    // NinjaTrader reserves the right to modify or overwrite this NinjaScript component with each release.
    //
    #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.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 MACrossover : Strategy
    {
    private SMA smaFast;
    private SMA smaSlow;
    private int quantity;

    protected override void OnStateChange()
    {
    if (State == State.SetDefaults)
    {
    Description = "Reverse position when price closes across the SMA.";
    Name = "MA Crossover";
    Fast = 14;
    Slow = 34;
    // This strategy has been designed to take advantage of performance gains in Strategy Analyzer optimizations
    // See the Help Guide for additional information
    IsInstantiatedOnEachOptimizationIteration = false;
    }
    else if (State == State.DataLoaded)
    {
    smaFast = SMA(Fast);
    smaSlow = SMA(Slow);

    smaFast.Plots[0].Brush = Brushes.Goldenrod;
    smaSlow.Plots[0].Brush = Brushes.SeaGreen;


    AddChartIndicator(smaFast);
    AddChartIndicator(smaSlow);
    }
    }


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

    double upnl = 0;
    if (Position.MarketPosition != MarketPosition.Flat)
    upnl = Position.GetUnrealizedProfitLoss(PerformanceUnit.T icks);


    if (CrossAbove(Close, smaFast, 1)) {
    quantity = upnl < 0 ? quantity + 1 : 1;
    SetStopLoss(CalculationMode.Ticks, 50);
    EnterLong(quantity);
    }
    else if (CrossBelow(Close, smaFast, 1)) {
    quantity = upnl < 0 ? quantity + 1 : 1;
    SetStopLoss(CalculationMode.Ticks, 50);
    EnterShort(quantity);
    }
    }

    #region Properties
    [Range(1, int.MaxValue), NinjaScriptProperty]
    [Display(ResourceType = typeof(Custom.Resource), Name = "Fast", GroupName = "NinjaScriptStrategyParameters", Order = 0)]
    public int Fast
    { get; set; }


    [Range(1, int.MaxValue), NinjaScriptProperty]
    [Display(ResourceType = typeof(Custom.Resource), Name = "Slow", GroupName = "NinjaScriptStrategyParameters", Order = 1)]
    public int Slow
    { get; set; }
    #endregion
    }
    }
    Last edited by bfalls; 07-10-2022, 05:29 PM.

    Comment


      #3
      Hello bfalls,

      You will need to provide output from Print() and TraceOrders to diagnose an issue.

      Below is a link to a forum post that discusses debugging.


      Specifically, print the order object in OnOrderUpdate() and enable TraceOrders.

      We want to see if there are part fills, see if the quantity is being applied to the set method correctly, etc.

      Save the output to a text file and attach the text file to your next post.


      As a tip, to export a NinjaTrader 8 NinjaScript so this can be shared and imported by the recipient do the following:
      1. Click Tools -> Export -> NinjaScript...
      2. Click the 'add' link -> check the box(es) for the script(s) and reference(s) you want to include
      3. Click the 'Export' button
      4. Enter a unique name for the file in the value for 'File name:'
      5. Choose a save location -> click Save
      6. Click OK to clear the export location message
      By default your exported file will be in the following location:
      • (My) Documents/NinjaTrader 8/bin/Custom/ExportNinjaScript/<export_file_name.zip>
      Below is a link to the help guide on Exporting NinjaScripts.
      http://ninjatrader.com/support/helpG...-us/export.htm
      Chelsea B.NinjaTrader Customer Service

      Comment


        #4
        My apologies, I believe the NinjaTrader order execution is working correctly with the addition of the stop loss orders using the sample code; There were two problems that made the symptoms confusing. First, there is a visual problem. When the screen is squeezed tight and when the open order shows 5 contracts on the screen, for instance, it can also show stop loss orders that executed at different prices 4 at one price and 1 at the next tick, for instance, for a proper total of 5. When the display is squeezed like this it tricked me because the stop loss orders are stacked visually, and I thought they are getting out of sync.

        Second, the ExitLong or ExitShort should be called before calling SetStopLoss when an existing order is active because it can set it to an invalid value. Thus, in this case of a continuous oscillating order strategy it appears the best sequence is (when swapping from Long to Short):

        Code:
        ExitLong();
        contracts++;
        SetStopLoss(CalculationMode.Ticks, 25);
        EnterShort(contracts);
        However, this is just the order of operations. I have found that testing with live data that still the SetStopLoss call can change the order that is trying to be canceled, causing an error. So, in OnBarUpdate() call ExitLong() and set some variable to note that the intention here is to open a position in the opposite direction, then in OnOrderUpdate() call SetStopLoss() only when the order.Name == "Stop Loss" and orderState == OrderState.Cancelled. Now SetStopLoss() is safe to call in preparation of the EnterShort() to go in the opposite direction. This has been very solid with no errors at all so far.

        Code:
        protected override void OnOrderUpdate(Order order, double limitPrice, double stopPrice, int quantity, int filled, double averageFillPrice, OrderState orderState, DateTime time, ErrorCode error, string nativeError)
        {
            if (orderName == STOP_LOSS)
            {
                if (orderState == OrderState.Cancelled)
                { // the stop loss has been canceled, now safe to enter opposite direction (call SetStopLoss)
                    if (exitingPosition == MarketPosition.Long)
                    {
                        exitingPosition = MarketPosition.Flat;
                        SetStopLoss(CalculationMode.Price, open0 + stopOffset);
                        EnterShort(numberOfContracts);
                    }
                    else if (exitingPosition == MarketPosition.Short)
                    {
                        exitingPosition = MarketPosition.Flat;
                        SetStopLoss(CalculationMode.Price, open0 - stopOffset);
                        EnterLong(numberOfContracts);
                    }
                }
            }
        }
        
        protected override void OnBarUpdate()
        ​{
            if (marketPosition == MarketPosition.Flat)
            {
        
            }
            else // manage position
            {
                if (marketPosition == MarketPosition.Long)
                {
                    if (sellSignal) // switch from Long to Short
                    {
                        exitingPosition = marketPosition;
                        ExitLong();
                    }
                }
                if (marketPosition == MarketPosition.Short)
                {
                    if (buySignal) // switch from Short to Long
                    {
                        exitingPosition = marketPosition;
                        ExitShort();
                    }
                }
        ​    }
        }
        ​
        Last edited by bfalls; 11-11-2022, 07:52 PM.

        Comment

        Latest Posts

        Collapse

        Topics Statistics Last Post
        Started by futtrader, 04-21-2024, 01:50 AM
        4 responses
        41 views
        0 likes
        Last Post futtrader  
        Started by Option Whisperer, Today, 09:55 AM
        1 response
        11 views
        0 likes
        Last Post bltdavid  
        Started by port119, Today, 02:43 PM
        0 responses
        1 view
        0 likes
        Last Post port119
        by port119
         
        Started by Philippe56140, Today, 02:35 PM
        0 responses
        3 views
        0 likes
        Last Post Philippe56140  
        Started by 00nevest, Today, 02:27 PM
        0 responses
        2 views
        0 likes
        Last Post 00nevest  
        Working...
        X