Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

2 entry orders help!

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

  • NinjaTrader_ChelseaB
    replied
    Hello PaulMohn,

    What is the line code that is not being reached?

    Print all values used in the condition that triggers the action one line above the condition.

    Below is a link to a forum post that demonstrates how to use prints to understand behavior.


    Leave a comment:


  • PaulMohn
    replied
    Hello Chelsea, and thanks for the tips! I'll check it out later.
    I've tried several modifications to the indicator.
    I've added the following KeyDown trigger event that works and submit the entryBuyMar****rder.
    PHP Code:
          else if (State == State.DataLoaded)
          {
            submissionAccount = Account.All.FirstOrDefault(a => a.Name == "Sim101");
    
            if (submissionAccount != null)
              submissionAccount.OrderUpdate += Account_OrderUpdate;
    
            if (ChartControl != null)
            {
              ChartControl.PreviewKeyDown += ChartControl_PreviewKeyDown;    
            }
          }
          else if (State == State.Terminated)
          {
            if (submissionAccount != null)
              submissionAccount.OrderUpdate -= Account_OrderUpdate;
    
            if (ChartControl != null)
            {
              ChartControl.PreviewKeyDown -= ChartControl_PreviewKeyDown;    
            }
          }
    
    
        protected void ChartControl_PreviewKeyDown(object sender, KeyEventArgs e)
        {
          TriggerCustomEvent(p =>
          {
            Order entryBuyMar****rder = null;
    
            if (Keyboard.IsKeyDown(Key.NumPad1))
            {
              entryBuyMar****rder = submissionAccount.CreateOrder(
                  Instrument,
                  OrderAction.Buy,
                  OrderType.Market,
                  OrderEntry.Manual,
                  TimeInForce.Day,
                  1,
                  0,
                  0,
                  string.Empty,
                  "Entry",
                  Core.Globals.MaxDate,
                  null);
            }
    
            submissionAccount.Submit(new[] { entryBuyMar****rder });
    
          }, null);
          e.Handled = true;
        } 
    


    Trying to check why the KeyDown Event is not picked up by either the Account_OrderUpdate() method or/and the OnBarUpdate() method,
    I've added prints to the Account_OrderUpdate() (highlighted in blue)
    private void Account_OrderUpdate(object sender, OrderEventArgs orderUpdateArgs)
    {
    Print("orderUpdateArgs.AverageFillPrice : " + orderUpdateArgs.AverageFillPrice);
    Print("profitTargetOrder : " + profitTargetOrder);
    Print("currentPtPrice : " + currentPtPrice);
    Print("stopLossOrder : " + stopLossOrder);


    Print("entryBuyMar****rder : " + entryBuyMar****rder);

    if (entryBuyMar****rder != null && entryBuyMar****rder == orderUpdateArgs.Order && orderUpdateArgs.Order.OrderState == OrderState.Filled)
    {
    string oco = Guid.NewGuid().ToString("N");
    submitOrdersArray = new List<Order>();

    if (UseProfitTarget)
    {
    currentPtPrice = orderUpdateArgs.AverageFillPrice + ProfitTargetDistance * TickSize;

    if (PrintDetails)
    Print(string.Format("{0} | Account_OrderUpdate | placing profit target | currentPtPrice: {1}", orderUpdateArgs.Time, currentPtPrice));

    profitTargetOrder = submissionAccount.CreateOrder(orderUpdateArgs.Orde r.Instrument, OrderAction.Sell, OrderType.Limit, OrderEntry.Automated, TimeInForce.Day, orderUpdateArgs.Quantity, currentPtPrice, 0, oco, "Profit Target", Core.Globals.MaxDate, null);
    submitOrdersArray.Add(profitTargetOrder);
    }

    if (UseStopLoss)
    {
    currentSlPrice = orderUpdateArgs.AverageFillPrice - StopLossDistance * TickSize;

    if (PrintDetails)
    Print(string.Format("{0} | Account_OrderUpdate | placing stop loss | currentSlPrice: {1}", orderUpdateArgs.Time, currentSlPrice));

    stopLossOrder = submissionAccount.CreateOrder(orderUpdateArgs.Orde r.Instrument, OrderAction.Sell, OrderType.StopMarket, OrderEntry.Automated, TimeInForce.Day, orderUpdateArgs.Quantity, 0, currentSlPrice, oco, "Stop Loss", Core.Globals.MaxDate, null);
    submitOrdersArray.Add(stopLossOrder);
    }

    submissionAccount.Submit(submitOrdersArray);
    }

    // once the exit orders are closed, reset for a new entry.
    else if ((profitTargetOrder != null && (profitTargetOrder.OrderState == OrderState.Filled || profitTargetOrder.OrderState == OrderState.Rejected || profitTargetOrder.OrderState == OrderState.Cancelled)) || (stopLossOrder != null && (stopLossOrder.OrderState == OrderState.Filled || stopLossOrder.OrderState == OrderState.Rejected || stopLossOrder.OrderState == OrderState.Cancelled)))
    {
    entryBuyMar****rder = null;
    profitTargetOrder = null;
    stopLossOrder = null;
    }
    }

    with Prints results as
    orderUpdateArgs.AverageFillPrice : 0
    profitTargetOrder :
    currentPtPrice : 0
    stopLossOrder :
    entryBuyMar****rder :
    orderUpdateArgs.AverageFillPrice : 0
    profitTargetOrder :
    currentPtPrice : 0
    stopLossOrder :
    entryBuyMar****rder :
    orderUpdateArgs.AverageFillPrice : 0
    profitTargetOrder :
    currentPtPrice : 0
    stopLossOrder :
    entryBuyMar****rder :
    orderUpdateArgs.AverageFillPrice : 0
    profitTargetOrder :
    currentPtPrice : 0
    stopLossOrder :
    entryBuyMar****rder :
    orderUpdateArgs.AverageFillPrice : 106.54
    profitTargetOrder :
    currentPtPrice : 0
    stopLossOrder :
    entryBuyMar****rder :


    and made the following reductions in the OnBarUpdate() method (highlighted in red)
    protected override void OnBarUpdate()
    {
    if (State != State.Realtime)
    return;

    // check if the account position for this instrument is flat, if so submit entry

    if (submissionAccount != null && submissionAccount.Positions.Where(o => o.Instrument == Instrument).Count() > 0)
    accountPosition = submissionAccount.Positions.Where(o => o.Instrument == Instrument).Last();
    else
    accountPosition = null;

    if (accountPosition == null || accountPosition.MarketPosition == MarketPosition.Flat)
    // if (entryBuyMar****rder != null && entryBuyMar****rder.OrderState == OrderState.Filled)

    {
    changeOrdersArray = new List<Order>();

    if (profitTargetOrder != null &&
    (profitTargetOrder.OrderState == OrderState.Accepted || profitTargetOrder.OrderState == OrderState.Working)
    )
    {
    currentPtPrice = Close[0] + ProfitTargetDistance * TickSize;
    profitTargetOrder.LimitPriceChanged = currentPtPrice;
    changeOrdersArray.Add(profitTargetOrder);

    if (PrintDetails)
    Print(string.Format("{0} | OOU | chasing target, currentPtPrice: {1}", Time[0], currentPtPrice));
    }

    if (stopLossOrder != null &&
    (stopLossOrder.OrderState == OrderState.Accepted || stopLossOrder.OrderState == OrderState.Working)
    )
    {
    currentSlPrice = Close[0] - StopLossDistance * TickSize;
    stopLossOrder.StopPriceChanged = currentSlPrice;
    changeOrdersArray.Add(stopLossOrder);

    if (PrintDetails)
    Print(string.Format("{0} | OOU | trailing stop, currentPtPrice: {1}", Time[0], currentSlPrice));
    }

    if (changeOrdersArray.Count() > 0)
    submissionAccount.Change(changeOrdersArray);
    }
    }



    The prints show entryBuyMar****rder / orderUpdateArgs.AverageFillPrice : 106.54 value does get picked up by the Account_OrderUpdate() method, but that's the only value that does.
    And the profitTargetOrder and stopLossOrder orders don't get sumbited.

    Then the OnBarUpdate() doesn't get a chance to operations since the profitTargetOrder and stopLossOrder orders don't get sumbited.

    Any Idea why the profitTargetOrder and stopLossOrder orders don't get triggered?
    Please find attached the script MyOCOKeyEvent1.zip
    Thanks!


    I thought of adding a condition in the OnBarUpdate modified If statement to check if the KeyDown method is true but I don't know if that would help nor how I can check a Key event with a bool.









    Attached Files

    Leave a comment:


  • NinjaTrader_ChelseaB
    replied
    Hello PaulMohn,

    When the entry fills, the average fill price is the entry point. This is used for the initial distance for the order. Then for the trailing action this is based on how far the current price has travelled.

    On each new bar update, if the current price is more ticks in distance, then the order price is moved toward the current price by the number of ticks.

    Check if close is greater than the current stop price plus number of ticks.
    Close[0] > currentSlPrice + StopLossDistance * TickSize

    If it is, set stop price to current price minus number of ticks
    currentSlPrice = Close[0] - StopLossDistance * TickSize;

    I don't see this as a cyclical algorithm.. the conditions are simply checked each time the bar updates.

    Leave a comment:


  • PaulMohn
    replied
    Thanks for the illustrations and tips! It still seems there's more to it than sheer unconscious competence, though it must be a semi conscious steps outline after some point in the reduction.

    I suspect you must know some things I don't know about cycling the algorithm in your foresight before committing that vision to script formulation.

    Do you still have your notes about the script? How specifically did you "see work" the transition from
    currentPtPrice = AverageFillPrice + ProfitTargetDistance (1st cycle in Close[0] < currentPtPrice - ProfitTargetDistance * TickSize) to
    currentPtPrice = Close[0] + ProfitTargetDistance (2nd cycle in Close[0] < currentPtPrice - ProfitTargetDistance * TickSize) to then
    currentPtPrice = Close[0] + ProfitTargetDistance (for all subsequent cycles)?

    What doesn't seem to go "well together" is all the subsequent cycles after the 2nd one to derive that the Close[0] values required for it to work must be less than the previous "stored" ones. I had to draw the coordinates on a paper graph to "see it work" (currentPtPrice doesn't change when Close[0] upticks back above its prior values after the 2nd cycle).

    The fact that you can derive all subsequent cycles is the foresight escaping part, and how it links to the first 2 cycles is also dizzying the forehead (cycles interrelations vs linear/parallels extrapolation). That is, how do you usually derive it will work for all up and down tick of the Close[0]? Do you "see work" cycle 1, then 2, then 3, then 4 etc. before generalizing the formula? Or do you use a known cyclical algorithm you refer to to "know" it does work for all cases?

    I would have thought (much lesser experienced that I am, but then I don't have that cyclical algorithm training I suspect you must have been made familiar to at some point, maybe some special algorithmic design training?) of storing the Close[0] since entry values and checking for new min/low/down ticks values to move the Target in reference to. But your way to do it seems a lot shorter/less efforts prone (but the downside with it is you can't easily see/outline the steps and their relations, a bit like with complex loops), provided you know how to "see work" the cyclical algorithm, not just the linear one (if you don't, you have to memorize the working figure without "seeing it work/understanding it yourself", knowing that it works and you can use it as arbitrary sign with no meaning, just known function), also the principle of reusability of already used variables we can't do without is better at work with your approach/less variables used (I think you couldn't reduce their number any further than with your approach).
    I'll try and look for resources to cyclical programming concepts if I can find some. Thanks!
    Last edited by PaulMohn; 05-11-2022, 03:59 PM.

    Leave a comment:


  • NinjaTrader_ChelseaB
    replied
    Hello PaulMohn,

    "How did you arrive at this algorithm? What principles did you use?"

    This seems like a simple question.. but I'm finding myself unable to answer.

    Its like asking someone how they drive a car. Its looking at the road seeing where you want to be and adjusting the steering wheel to point in that direction.

    To start, I write down explicitly the behavior I want to achieve. Like submit entry if flat, when entry fills submit stop and limit at preset distance, then after x many ticks of loss or gain set limit or stop to n distance.
    I didn't really start with anything else, just the rules of how C# works, order of operations which always needs to be in mind, and the documentation for working with NinjaScript properties as defined in the help guide.

    Unfortunately, our NinjaScript Engineering Support team does not get a lot guidance from development unless there is a glaring issue that needs to be resolved. Most of our examples come from seeing a need for an example to exist and conjuring one up.

    Thinking cyclically, OnBarUpdate() is the cycle. Its what's revolving that we run our code on each pass. So the next data is coming in, we check those numbers and see if the distance has been traveled since the last cycle.

    "Is there a specific Computer Science domain that trains that multiple / condensed operations "reasoning"? You condensed things that aren't seeming to go "well" together"

    What specifically doesn't seem to go together?

    I'm not actually sure what you are asking here. But I think in terms of explicit steps. To make my bed, i have to move my body to the foot of the bed, then extend right arm forward 1 foot, right 2 feet, and down 2 feet, then close hand to grasp sheet, the raise arm to pull corner of sheet up.... and it goes on until each step is completed in order removing the old sheet first, taking a new, and pulling the corners down. Just a sequence of explicit steps.

    Possibly the most difficult part is explicitly knowing the behavior you want to see.


    Close is the current price (either at the time a bar closes if Calculate.OnBarClose, or intra-bar with Calculate.OnEachTick or OnPriceChange). I'm working with the current price as I don't need the specific ask or bid from OnMarketData since I'm not working with volume or buy sell pressure or anything.

    Leave a comment:


  • PaulMohn
    replied
    Chelsea, that is a very interesting script. I learned new things.

    The use of Bool Variables/State.SetDefaults values
    PHP Code:
            ChaseProfitTarget  = true;
            PrintDetails        = false;                         
            TrailStopLoss        = true;                     
            UseProfitTarget     = true;
            UseStopLoss        = true; 
    

    as Properties Region Variables
    PHP Code:
     #region Properties
    [NinjaScriptProperty]
    [Display(Name = "Chase profit target", Order = 2, GroupName = "NinjaScriptStrategyParameters")]
    public bool ChaseProfitTarget
    { get; set; }
    
    [NinjaScriptProperty]
    [Display(Name = "Print details", Order = 7, GroupName = "NinjaScriptStrategyParameters")]
    public bool PrintDetails
    { get; set; }
    
    [NinjaScriptProperty]
    [Display(Name = "Trail stop loss", Order = 5, GroupName = "NinjaScriptStrategyParameters")]
    public bool TrailStopLoss
    { get; set; }
    
    [NinjaScriptProperty]
    [Display(Name = "Use profit target", Order = 1, GroupName = "NinjaScriptStrategyParameters")]
    public bool UseProfitTarget
    { get; set; }
    
    [NinjaScriptProperty]
    [Display(Name = "Use stop loss", Order = 4, GroupName = "NinjaScriptStrategyParameters")]
    public bool UseStopLoss
    { get; set; }
    #endregion 
    

    to create Checkboxes in the indicator Properties Windows (from the Chart window, Ctrl+I - attached image boolsascheckboxes).

    Then the use of a a List to store submitted and changed orders
    PHP Code:
    private List<Order>                    changeOrdersArray, submitOrdersArray; 
    

    Then changing an order using it's limitPrice/stopPrice parameter value only (new way to change order)
    PHP Code:
    profitTargetOrder.LimitPriceChanged = currentPtPrice; 
    
    PHP Code:
    stopLossOrder.StopPriceChanged        = currentSlPrice; 
    
    ​​​​​​​
    Then the way the chase is made

    currentPtPrice = orderUpdateArgs.AverageFillPrice + ProfitTargetDistance * TickSize;

    profitTargetOrder = submissionAccount.CreateOrder(orderUpdateArgs.Orde r.Instrument, OrderAction.Sell, OrderType.Limit, OrderEntry.Automated,
    TimeInForce.Day, orderUpdateArgs.Quantity, currentPtPrice, 0, oco, "Profit Target", Core.Globals.MaxDate, null);

    if (ChaseProfitTarget && profitTargetOrder != null &&
    (profitTargetOrder.OrderState == OrderState.Accepted || profitTargetOrder.OrderState == OrderState.Working) &&
    Close[0] < currentPtPrice - ProfitTargetDistance * TickSize)
    {
    currentPtPrice = Close[0] + ProfitTargetDistance * TickSize;
    profitTargetOrder.LimitPriceChanged = currentPtPrice;
    changeOrdersArray.Add(profitTargetOrder);
    }

    ensuring the Target is only moved to the downside, by manipulating the currentPtPrice variable.
    For example:
    The Target is set to EntryPrice + 10 Ticks initially.
    Then Price must move below EntryPrice to lower currentPrice as much.
    Then Price must move below Price at the time/level of previous currentPrice change for currentPrice to change again.

    How did you arrive at this algorithm? What principles did you use? it seems obvious but it's not for the uninitiated. it dizzies the forehead.
    ProfitTargetDistance
    currentPrice
    profitTargetOrder

    I see you keep ProfitTargetDistance constant, and use the Close[0] down ticks in reference to itself to move down exclusively the profitTargetOrder order. That I understand.

    I'm thinking it is some sort of cyclical algorithm/reasoning you use. How do you see the cyclical part of if before you code it? I'm struggling a lot with that part, so much so that I have to commit to memory the form of it to keep a hint/prompt of it as arbitrary figure to recall when needing that sort of "cyclical" algorithm, but I cannot "see it work" first and then code it myself.
    How do you yourself "see it work" first and then code it?

    I mean what training specifically made you able to derive that cyclical multiple layers processes operations condensed into one? Is there a specific Computer Science domain that trains that multiple / condensed operations "reasoning"? You condensed things that aren't seeming to go "well" together. And it's not just about algebra, nor just about rote experience/reading many scripts.

    I know the close is the key, i.e. that's the variable that will be used to move the Target (that's the basic idea that will need to be used anyway you turn the problem).
    I know currentPrice is the Target's order limitPrice variable so that will also need to be used to move the Target.
    What I don't know/I can't foresee is


    How do you/what do you do to see the cycle before coding it? What do you "train" to "think/see" the cycle in code. Is there a computer science domain that can train that cyclical reasoning? How do you personally approach the problem? Do you draw coordinates on some graph? Do you use some sort of flow chart? Do you use the number/numerical computation to derive the right formula? Do you use an app? Anything else?

    I managed to reproduce the steps for 2 down moves in a formula in cyclicalalgo attached picture but it's not enough to get the cyclical concept out of it.

    Thanks!


    Leave a comment:


  • PaulMohn
    replied
    Ah this is the indicator one? I'll check it now thanks!

    Leave a comment:


  • PaulMohn
    replied
    Oh you're right it did place the Target and Stop orders for 2 trades but then it stopped (but no OCO ID error).
    Here's a screenshot of the Orders tab, the previous trades don't show same ids.

    Do you have a a sample for regular indicator use? Thanks!
    Attached Files

    Leave a comment:


  • NinjaTrader_ChelseaB
    replied
    Hello PaulMohn,
    It doesn't look like you are generating the OCOID before placing the orders as advised. It appears this is being generated in order method and only for one order.

    Are you using the same OCOID for both orders shown on the Orders tab of the Control Center? (OCO is one-cancels-others, for all orders using the same OCOID if one order is cancelled or filled all other orders using the same OCOID will be cancelled)

    The ProfitChaseStopTrailUnmanagedExample_NT8 and ProfitChaseStopTrailIndicatorExample_NT8 demonstrate.

    Leave a comment:


  • PaulMohn
    replied
    Thanks! I tested with Guid.NewGuid().ToString() as
    PHP Code:
              buyMktOrder = account.CreateOrder(
                  Instrument,
                  OrderAction.Buy,
                  OrderType.Market,
                  OrderEntry.Manual,
                  TimeInForce.Day,
                  quantitySelector.Value,
                  0,
                  0,
                  Guid.NewGuid().ToString(),
                  "buyMktOrder"+DateTime.Now.ToString(),
                  DateTime.MaxValue,
                  null); 
    

    from this post and the error is not thrown anymore, and the order executes with the the Target order and the Stop Order.

    But the OCO doesn't work as expected because when either the Stop or the Target order gets filled the other one (Target/Stop order) isn't cancelled.

    What could be the cause? How to get the remaining OCO order to get cancelled? Thanks!

    Leave a comment:


  • NinjaTrader_ChelseaB
    replied
    Hello PaulMohn,

    GetAtmStrategyUniqueId() and Guid.NewGuid() can be used to generate unique id strings.


    Without output from debugging prints, printing the string, I wouldn't be able to give any direction.

    I can say you are using a static variable which is not making any sense to me. The string should be generated before each new order set, and it looks like you are only generating a string once when the variable is declared and not for each new order pairing.

    Leave a comment:


  • PaulMohn
    replied
    Originally posted by NinjaTrader_ChelseaB View Post
    Hello Andrea,

    To clarify your original question, you are wanting to have opposing orders working at the same time, is this correct?

    I have an example that you may find helpful that uses the unmanaged approach to submit a pair of opposing orders using oco (One Cancels Other) I've made for NinjaTrader 7.

    I've ported this to NT8 for you and I'm attaching both versions so you can compare.


    (Updated July 17th, 2018 - corrected assigning the variables to null when the exit on close occurs. Also corrected preventing orders after the exit on close until the new session)
    Hello Chelsea. I'm wondering if there is a simpler way just to get a unique OCO ID for an Indicator script (not an unmanaged strategy one)?

    I've tested using bitdavid's random Id

    PHP Code:
    private static Random MyRand = new Random(DateTime.Now.Millisecond); 
    

    but it still throws the error message

    Time Category Message
    10/05/2022 18:02:54 Order Failed to submit orders: System.NullReferenceException: Object reference not set to an instance of an object. at NinjaTrader.Cbi.Account.Submit(IEnumerable`1 orders)
    Time Category Message
    10/05/2022 18:02:53 Order Sim101, Order 'ff3e8b60dc954bdab38001b0c7b58669' can't be submitted: The OCO ID ‘myOCOSystem.Random’ cannot be reused. Please use a new OCO ID. affected Order: Buy 1 Market
    PHP Code:
    buyMktOrder = account.CreateOrder(
                  Instrument,
                  OrderAction.Buy,
                  OrderType.Market,
                  OrderEntry.Manual,
                  TimeInForce.Day,
                  quantitySelector.Value,
                  0,
                  0,
                  "myOCO" + MyRand,
                  "buyMktOrder"+DateTime.Now.ToString(),
                  DateTime.MaxValue,
                  null); 
    

    Why does it still keeps getting the same ID (I suspect it is because somehow buyMktOrder OCO ID wasn't reset)?
    What it the absolute minimum code required for the solution for an Indicator script?

    Thanks!
    Last edited by PaulMohn; 05-10-2022, 10:10 AM.

    Leave a comment:


  • NinjaTrader_ChelseaB
    replied
    Hello tgn55,

    I'm trying to pick a question out of this but I'm having a hard time understanding your inquiry.

    Can you clarify what you are asking?

    Leave a comment:


  • tgn55
    replied
    Thanks. I also got another script from Jim... will try to implement it today.

    I have a few challenges... as I am trying to achieve all of the following:
    a) OCO bracket setup
    b) ATM-style break-even and thereafer multiple scaled exits
    c) trailing stop on a final "runner" position, ie with no target.
    d) backtestable ;-)

    I've written plenty of substantial code... but not much (any?) previously that needed tick data, And i think to implement a "proper" ATM-style thing, I need tick data. I previously implemented ATM-style trailing stops... but only operated on bar close...It works... but clearly an intra-bar moving of stops would be better..
    Last edited by tgn55; 06-09-2020, 07:34 PM.

    Leave a comment:


  • NinjaTrader_ChelseaB
    replied
    Hello T,

    Orders that use OCO can be back-tested.

    The example I have created is not intended to be back-tested.

    The example is designed to show that when one order is filled, the other is cancelled which is not easy to demonstrate in historical data. So I have chosen to have the logic that places orders in OnMarketData() so that the demonstration happens in real-time so anyone testing the script can see it happen.

    Move this logic to OnBarUpdate() if you would like the example script to work historically.

    Leave a comment:

Latest Posts

Collapse

Topics Statistics Last Post
Started by CarlTrading, 05-11-2026, 05:56 AM
0 responses
56 views
0 likes
Last Post CarlTrading  
Started by CarlTrading, 05-10-2026, 08:12 PM
0 responses
33 views
0 likes
Last Post CarlTrading  
Started by Hwop38, 05-04-2026, 07:02 PM
0 responses
195 views
0 likes
Last Post Hwop38
by Hwop38
 
Started by CaptainJack, 04-24-2026, 11:07 PM
0 responses
359 views
0 likes
Last Post CaptainJack  
Started by Mindset, 04-21-2026, 06:46 AM
0 responses
280 views
0 likes
Last Post Mindset
by Mindset
 
Working...
X