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

Add Profit Target and Stop Loss

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

    #46
    Or, I can put the strategy back into an Indicator. This seemed to track the trades properly.

    The other question: how can I isolate the transactions specific to the current trade so when I iterate thru the Orders collection I can limit what is displayed (to the current trade)? (This was the rationale behind clearing the Orders collection.)

    Btw, many traders (like myself) would like to automatically manage a manually entered ATM strategy. I have requested that the ATM be modified to accommodate what I am trying to do (ID #SFT-2965) using this strategy.

    Perhaps a request to allow a Strategy to chart trades (without requiring drawing objects or detaching the Strategy from the Chart) by adding a property should be submitted. Please submit.

    Thanks,
    Ron
    Last edited by ronhb107; 01-29-2018, 01:01 PM.

    Comment


      #47
      Hello,

      Yes as I noted you would want to avoid a strategy specifically if that is the effect you want. Strategies are intended for virtual account tracking which is isolated away from the overall account. This is described in the help guide here. To use the more advanced addon order methods in the correct way for this intended use, you would likely need to use an Indicator or an Addon and not a strategy. While you can use these in a strategy, the result would be what you are seeing due to the intended effect of applying a strategy to the chart.

      Regarding the current trade, I am not certain on your wording here, by transactions do you mean executions? Do you mean how to know what executions apply to create a pair or Trade? For example, a trade could consist of multiple partial fills or full fills, is this what you mean?

      Regarding the feature request, this already exists and is known as the Addon framework. What you are describing would be to combine strategies and add-ons into one but these are separate for a reason. Strategies are intended for a specific purpose which is to isolate their results into a virtual report that is separate from other tools in the platform. They are also not intended for manual trading use. If you want to make a tool that works based on the overall account or other manual actions you would use the Addon framework for that. An Indicator could be used in that case as the indicator has no previous stipulation about its results being virtual as it has no knowledge of any account. Using a strategy in other ways than a strategy is intended to be used would result in abnormalities in the way it reports or displays data associated with it.

      Please let me know if I may be of further assistance.
      JesseNinjaTrader Customer Service

      Comment


        #48
        Fair enough; back to the Indicator then.

        With regard to the tracking of a current position (from entry to exit), it should yield results similar to clearing the Orders collection whenever the account goes Flat (so only new transactions are collected afterwards).

        Btw, I am learning a lot from this conversation. I do appreciate your responses.

        Ron
        Last edited by ronhb107; 01-29-2018, 01:21 PM.

        Comment


          #49
          Hello,

          To clarify, what are you looking at right now where the orders collections are cleared or was this a result of your prior .Clear() syntax? If you are referring to how a strategy starts flat, the Account object would only do that if you are indeed flat as you are now working with the actual account. Or are you asking about how the chart trader shows the Long, Flat, Short indicator and how this toggles based on the account position?

          The Indicator showing the position would simply be the accounts current Position that is selected. This can be retrieved from OnPositionUpdate as the position object that passed in when it changes. There are two positions passed in, one being the current position, the other being the position of the update related to this specific execution. If you need to find the position of the account when you start the script, you would need to loop over the Account.Positions collection and collect that information. Otherwise, this would be passed in when it changes via the override.

          I look forward to being of further assistance.
          JesseNinjaTrader Customer Service

          Comment


            #50
            I guess I need to clarify further.

            I would be looking at OnPositionUpdate() e.MarketPosition to see if it's Flat. From slightly after that time to the next Flat indication would provide my time period for displaying Orders. I suspect that I would have to track the timeframe to limit the Orders display (which would be current orders; or the current Position from entry to exit).

            I was hoping there would be a unique ID (or something) that would make this simpler.

            Btw, fear not, I have stopped using account.Orders.Clear(); I am, however, still using: account.CancelAllOrders(instrument).

            Ron

            UPDATE: I may have already solved the problem by passing the Position to the method that iterates thru the Orders. It appears that this works: ClearOrders(e.Position.Account, doCancel). The doCancel is set to True by: e.MarketPosition.Equals(MarketPosition.Flat).

            UPDATE 2: unfortunately, that does not limit the iteration to the last (current) Position entry to exit.
            Last edited by ronhb107; 01-29-2018, 02:23 PM.

            Comment


              #51
              Hello,

              Thank you for clarifying.

              If the purpose of this logic would be to display the orders on the chart in some way, I would likely suggest storing the order objects for the active orders to display instead of trying to use OnPositionUpdate.

              I reviewed the initial concern again, along with some of your other comments describing the intended use. From what I can tell you want the script to observe and allow you to place manually an entry which is filled, and then apply/modify your targets using logic. Is this accurate? You also noted that you have requested that the ATM be modified to accommodate what you am trying to do (ID #SFT-2965) using this strategy.

              Will you specifically be using ATM strategies with this? do all manual entries need to be accounted for or is this to observe specifically entries with a specific ATM attached? That will make a difference in the resolution I believe.

              I reviewed the forum post for that other request, from the description and if you would be using specifically ATM orders attached to the entry, it sounds like you would need to just submit an Entry order with your ATM attached and then use your new script from this thread to watch for the targets from that manual entry. Both the entry and targets submitted from an ATM will have specific names which could be used to identify them. Once identified you could display them however you wanted from OnRender or other.

              If that is accurate, I believe that OnOrderUpdate and OnExecutionUpdate should be able to accomplish both tasks of tracking the current order and displaying them at the same time. If you need to care about all orders that are manual that would make it more difficult as those orders don't have a specific name that could be referenced.

              I look forward to being of further assistance.
              JesseNinjaTrader Customer Service

              Comment


                #52
                The output of the current position's orders is to the NinjaScript Output window; not the Chart. I will handle the display of trades on the Chart by going back to the Indicator approach (much easier this way). Btw, I am handling the limited display of Orders based on order.Time (using the last order in the Orders collection for a startAt time).

                With regard to the ATM: I will (in most instances) use an ATM (with OCO) manually positioned (based on my subjective placement approach given current market behavior). There will be times when I will need to manually add to the current position (outside of the ATM; thru the Chart) which the Strategy does NOT have to respond to.

                Hope this is clear.

                Ron

                UPDATE: limiting the iteration thru the Orders collection works fine based on startAt time. However, I did notice that when there is slippage on the Stop1 market order, the actual Stop1.Price is not reflected correctly on the order (it is correctly reflected on the Chart and the Trade Performance - Trades page). Any thoughts why the order does not reflect the actual fill price?

                UPDATE: I solved this with: order.AverageFillPrice.
                Attached Files
                Last edited by ronhb107; 01-29-2018, 06:23 PM.

                Comment


                  #53
                  Add Profit Target and Stop Loss

                  Jesse:

                  See attached pics for error msg during testing using Playback. This might be data related problem, or code problem.

                  I have attached three pics (including the Ninja Script Output window) plus the Indicator version of the code.

                  Code area to focus on is: OnOrderUpdate().

                  Thanks,
                  Ron
                  Attached Files
                  Last edited by ronhb107; 01-30-2018, 11:34 PM.

                  Comment


                    #54
                    Hello,

                    Thank you for the reply.

                    I tried the script but I was unable to see this error while playing through playback. Are you seeing this happen at a specific point in the playback and are able to reproduce this again?

                    I look forward to being of further assistance.
                    JesseNinjaTrader Customer Service

                    Comment


                      #55
                      Add Profit Target and Stop Loss

                      Jesse:

                      I've rebooted NT8 and that seemed to clear up the problem within Playback.

                      In the code snippet below, I've used Dispatcher.InvokeAsync(). Is this recommended?

                      Thanks, Ron

                      Code:
                      		private void OnOrderUpdate(object sender, OrderEventArgs e)
                      		{
                      			double price = (e.Order.LimitPrice > 0) ? e.Order.LimitPrice : e.Order.StopPrice;
                      			if (e.Order.OrderState.Equals(OrderState.Filled))
                      				price = e.Order.AverageFillPrice;
                      			
                      			NinjaTrader.Code.Output.Process(string.Format("OnOrderUpdate - OrderName: {0} Price: {1}  Quantity: {2}  OrderState: {3}", 
                      					e.Order.Name, price, e.Quantity, e.OrderState), PrintTo.OutputTab1);
                      
                      			// reset startAt for filled Entry (used in ClearOrders() )
                      			if (startAt == null && e.Order.Name == "Entry"  && e.Order.OrderState.Equals(OrderState.Filled))
                      				startAt = e.Order.Time;
                      			
                      			// if stop1 is filled, check that stopTarget price is 3 ticks away
                      			// if not, adjust stopTarget
                      			ChartControl.Dispatcher.InvokeAsync((Action)(() =>
                      			{			
                      				if (e.Order.Name == "Stop1" && e.Order.OrderState.Equals(OrderState.Filled))
                      				{
                      					if (e.Order.AverageFillPrice != e.Order.StopPrice)
                      					{
                      						if (e.Order.IsLong)
                      							stopTarget.LimitPriceChanged = price + 0.75;
                      						else if (e.Order.IsShort)
                      							stopTarget.LimitPriceChanged = price - 0.75;
                      						
                      						account.Change(new[] { stopTarget });
                      						Print("OnOrderUpdate - stopTarget price change: " + stopTarget);
                      						Print("OnOrderUpdate - stop1 fill change: " + e.Order);
                      					}
                      				}
                      			}));
                      		}

                      Comment


                        #56
                        Hello,

                        Thank you for the reply.

                        Dispatchers are generally used to submit to the UI thread some change to the UI from another thread. If you are not doing anything with the UI I couldn't suggest using a Dispatcher here. This would be used if you had done some work and now needed to access a UI element to update it as one example.

                        If you do need a dispatcher for some logic, generally you get an error complaining about accessing a different thread other than the current.

                        When you initially gather the account object and access the UI, that is one place where dispatching would be needed, for just using the stored account object that should not be needed.

                        Please let me now if I may be of additional assistance.
                        JesseNinjaTrader Customer Service

                        Comment


                          #57
                          Add Profit Target and Stop Loss

                          This is interesting since the initial code provided for this strategy included the Dispatcher within OnBarUpdate(). I thought this might be addressing Changes and Submits to the Orders collection (see below).

                          Code:
                          protected override void OnBarUpdate()
                          		{
                          //			Print("\nOnBarUpdate  and account: " + account);
                          			if (account == null) 
                          				return;
                          
                          			ChartControl.Dispatcher.InvokeAsync((Action)(() =>
                          			{
                          				if (account != null) 
                          				{
                          					foreach (Order order in account.Orders)
                          					{
                          						// if Entry order, get quantity and set stopOrderQty and stopTargetQty
                          						if (order.Name == "Entry" && order.Quantity > 0 && !order.OrderState.Equals(OrderState.Cancelled))
                          						{
                          //							Print("Entry Order: " + order);
                          							entryQuantity = order.Quantity;
                          							
                          							// calculate quantity for both stopOrder and stopTarget
                          							stopOrderQty = entryQuantity + (5 * entryQuantity);
                          							stopTargetQty = (5 * entryQuantity);
                          							
                          							if (order.OrderState.Equals(OrderState.Filled))
                          								entryOrder = order;
                          						}
                          							
                          						// change Stop1 quantity
                          						if (order.Name == "Stop1" && !order.OrderState.Equals(OrderState.Cancelled) && order.Quantity == entryQuantity)
                          						{
                          							stopOrder = order;
                          //							Print("\nOnBarUpdate   stopOrder: " + stopOrder);
                          							
                          							if (stopOrder.Quantity == entryQuantity && stopOrder.QuantityChanged < stopOrderQty)
                          								doOnce = true;
                          							
                          							if (doOnce)
                          							{					
                          								doOnce = false;
                          								doStopOrder = true;
                          								doStopTarget = true;
                          //								checkOrders = true;  Print("doOnce  checkOrders: " + checkOrders);
                          
                          								stopOrder.QuantityChanged = stopOrderQty;
                          								
                          								// add/submit stopTarget order
                          								if (stopOrder.IsLong)
                          								{
                          									stopTarget = account.CreateOrder(stopOrder.Instrument, OrderAction.Sell, OrderType.Limit, OrderEntry.Automated, TimeInForce.Day, 
                          										stopTargetQty, stopOrder.StopPrice + 0.75, 0, "", "stopTarget", Core.Globals.MaxDate, null);
                          								}
                          								else if (stopOrder.IsShort)
                          								{
                          									stopTarget = account.CreateOrder(stopOrder.Instrument, OrderAction.Buy, OrderType.Limit, OrderEntry.Automated, TimeInForce.Day, 
                          										stopTargetQty, stopOrder.StopPrice - 0.75, 0, "", "stopTarget", Core.Globals.MaxDate, null);
                          								}
                          								
                          								Print("\ndoOnce   stopOrder Price: " + stopOrder.StopPrice + "  stopOrder.Quantity: " + stopOrder.QuantityChanged);
                          								Print("doOnce   stopTarget Price: " + stopTarget.LimitPrice + "  stopTarget Qty: " + stopTarget.Quantity);  Print("");
                          								break;
                          							}
                          						}
                          					}
                          					
                          					// execute stopOrder and stopTarget changes outside of the FOREACH loop (to avoid error when count changes)
                          					if (stopOrder != null && stopTarget != null)
                          					{
                          						if (doStopOrder && stopOrder.Name.Trim().Length > 1) 
                          						{
                          							account.Change(new[] { stopOrder });
                          							doStopOrder = false;
                          							Print ("\nOnBarUpdate Change -  stopOrder.QuantityChanged: " + stopOrder.QuantityChanged);
                          						}
                          						
                          						if (doStopTarget && stopTarget.Name.Trim().Length > 1) 
                          						{
                          							account.Submit(new[] { stopTarget });
                          							doStopTarget = false;
                          							Print("OnBarUpdate Submit - stopTarget.Quantity: " + stopTarget.Quantity);
                          						}
                          					}
                          				}
                          			}));
                          		}

                          Comment


                            #58
                            Hello,

                            Thank you for the reply.

                            Yes potentially this was residual from some other test you had been working on, it would appear the script being used has been modified many times in this thread.

                            I see in post #11 you were checking for the account in OBU, this could be residual from that test. If you are in doubt about the syntax you are using, I would suggest testing both using the syntax and removing it, if one test fails that will give you the answer if it's needed or not. As noted if you are not using a dispatcher where one is needed, you will get an error so it is best to avoid using this unless specifically required. Dispatching will delay the logic you are executing as this is invoked so if it is not needed it would not be suggested to use it.


                            Please let me know if I may be of further assistance.
                            JesseNinjaTrader Customer Service

                            Comment


                              #59
                              Add Profit Target and Stop Loss

                              Here is the original code (see attached) from NT Alan that was the genesis for today's code.

                              Perhaps it's the call to Window.GetWindow() that required the Dispatcher.

                              If it's not required and could cause a problem, then I will remove this from my code.

                              Thanks,
                              Ron
                              Attached Files

                              Comment


                                #60
                                Hello,

                                Yes, this sample is different than your sample, this does actually require the dispatcher where it is used because it is accessing the UI.


                                Please let me know if I may be of further assistance.
                                JesseNinjaTrader Customer Service

                                Comment

                                Latest Posts

                                Collapse

                                Topics Statistics Last Post
                                Started by DayTradingDEMON, Today, 09:28 AM
                                4 responses
                                21 views
                                0 likes
                                Last Post DayTradingDEMON  
                                Started by geddyisodin, Yesterday, 05:20 AM
                                9 responses
                                50 views
                                0 likes
                                Last Post NinjaTrader_Gaby  
                                Started by George21, Today, 10:07 AM
                                1 response
                                12 views
                                0 likes
                                Last Post NinjaTrader_ChristopherJ  
                                Started by Stanfillirenfro, Today, 07:23 AM
                                9 responses
                                24 views
                                0 likes
                                Last Post NinjaTrader_ChelseaB  
                                Started by navyguy06, Today, 09:28 AM
                                1 response
                                9 views
                                0 likes
                                Last Post NinjaTrader_Gaby  
                                Working...
                                X