Global OCO name?

When you use CreateOrder to generate an OCO, and you specify a string name for the OCO order, is that OCO name globally visible?

I have two Indicators, each of which is designed to handle its own entry direction (L/S). They each create their orders at the exact same time based on conditions. Right now, they each cancel the order they created if it doesn’t get filled within a certain amount of time, but I would also like them to cancel their orders if the order from the other Indicator gets filled. Would that OCO idea work?

Thank you!

It works great, as long as I only ever want to execute one trade in a session. After that, it gives me an error complaining about unique OCO IDs.

To counteract that problem, I wrote some code to generate an assuredly unique string in one of the Indicators, and then made that an exposed variable, which is then utilized by the other one.

Unfortunately, I’m getting the “Object reference not set to an instance of an object” error when I try to access the exposed variable.

I know that the variable is not null in the first Indicator, because I am setting it to a default value. And, in this very same Indicator, I am using a call to a variable exposed by another Indicator, so I know that the process works.

Here is the relevant code:

1st Indicator:

public class Indicator0 : Indicator
	{
		private string oCo;
		
......................


protected override void OnBarUpdate()
	{
		if (oCo == null)
		{ oCo	= "oCo"; }
		else if (oCo != null && orderPlaced == true)
		{ oCo	= myRandomString + CurrentBar.ToString(); }

......................

#region Properties

public string oCO
	{			
		get { Update(); return oCo; }
	}

And in the second Indicator:

public class Indicator1 : Indicator
{
	private Indicator0	Indicator01;
		
......................

protected override void OnStateChange()
{
	else if (State == State.DataLoaded)
		{
			Indicator01 = Indicator0(Close);

......................


protected override void OnBarUpdate()
	{
		if (Indicator01.oCO != null)
		{ oCo	= Indicator01.oCO; }
		else
		{ oCo 	= "oCo"; }
	

......................

#region Properties

	[Browsable(false)]
	[XmlIgnore]
	public string oCo
	{ get; set;}

I can’t see why it’s not working. It is identical to the process I used to access the other exposed variable. The only difference is that that other exposed variable is a boolean.

Any ideas?

Thanks in advance!

1 Like

Did you read the link? Why are you creating exposed variables and sharing between indicators when there is a global Orders collection which all scripts can see?

All you need to do when creating orders is make sure the OCO string is unique, and that’s it.

Make an order from Indicator1.cs, call it “Order_indi1” with “OCO_indi1_137269” or something, then in indicator2.cs you can simply find orders in the order collection that are from Indi1.

Because I don’t know whether it will be Indicator1’s order that executes, or Indicator2’s. I suppose I can have them both do a check against existing orders for an OCO, and then have them extract what that is from the most recent Working order, but in my code that would create a huge plate of spaghetti.

Suppose I just want this passing a variable from one Indicator to another to actually work. I know that it does, because both of these Indicators are using a variable passed from a third Indicator, and it works just fine.

Having realized what I stated in the first sentence of this post, and in light of what I stated in the second paragraph of this post, I have inserted the code to generate the random OCO ID into the third Indicator which is already successfully passing a variable to these two indicators.

The third Indicator uses OnPositionUpdate to generate a new OCO ID whenever a position is closed. That works perfectly. And, even though the other variable that it is passing to the other Indicators continues to be read properly, the OCO ID string doesn’t.

Same Indicator passing two variables, same two Indicators receiving them, one gets through, the other doesn’t. Regardless what other methodology may exist to achieve my ends, I want to solve this problem.

Now, let’s take a look…

Variable originating Indicator:

public class PassingIndicator : Indicator
{
	private bool var1;
	private string var2;

.........................

	private void OnPositionUpdate(object sender, PositionEventArgs e)
	{		
		if (e.MarketPosition == MarketPosition.Flat)
		{ 
			var2 = myrandomString + CurrentBar.ToString();
			Print("Generating new OCO ID: " + var2);
		}
	}

.........................

#region Properties

	[Browsable(false)]
	[XmlIgnore]
	public bool vaR1
	{
		get { Update(); return var1; }
	}
	
	[Browsable(false)]
	[XmlIgnore]
	public string vaR2
	{
		get { Update(); return var2; }
	}

Receiving Indicator:

public class ReceivingIndicator1 : Indicator
{
	private PassingIndicator	PassingIndicator1;

.........................

protected override void OnStateChange()
{	
	else if (State == State.DataLoaded)
	{
		PassingIndicator1	= PassingIndicator(Close);
	}

.........................

	protected override void OnBarUpdate()
	{
			variable1	= PassingIndicator1.vaR1;
			variable2	= PassingIndicator1.vaR2;

Now, why does var1 get sent through and read properly by the receiving Indicators, while var2 does not?

This is the problem I must solve.

Thanks again!

I couldn’t make it work with the exposed variable, but I did something else that is similar to what you/the link suggested.

I removed the random OCO generation code from the first Indicator and wrote a completely separate one that does only that and nothing else.

It writes the random sequence that it generates to the lower left corner of the screen in an unobtrusive font. It still uses OnPositionUpdate to maintain the value of that string until the next open position gets exited. So, that string remains constant from the closing of one position, through the opening and closing of the next position. This makes it available for both Indicators to use and assign to their respective OCO orders.

Then, using the following code inside each Indicator, I am able to assign the unique identifier to the OCO Name variable whenever a new order is generated.

	if (DrawObjects.Count > 0)
        {
            foreach (DrawingTool draw in DrawObjects.ToList())
            {    
                if (draw is DrawingTools.TextFixed)
                {
                    DrawingTools.TextFixed temp = draw as DrawingTools.TextFixed;
                    						
					if (draw.Tag == "New OCO ID")
					{
						if (temp.DisplayText != null)
						{ oCo	= temp.DisplayText; }
						else
						{ oCo	= "11235oCo"; }
					}
        		}
            }
        }

It works great!

Now, both Indicators have the same value as the default for the first execution of the session, and they both have the same value for the OCO Name when the next order placement is triggered.

Thank you!

Can I be honest. I feel like your questions are mostly a waste of people’s time because you ignore the basics of NinjaScript and instead invent super complicated ways to complete basic tasks which already functions exist for. Even when given the answer you’ll ignore it and try and do something else equally pointless.

“Because I don’t know whether it will be Indicator1’s order that executes, or Indicator2’”.

You have an access to the Orders collection and you know the name of the order. So that’s all you need. Inside OnExecutionUpdate

If (e.Execution.Order.Name == “OrderFromIndicator1”) { // do this }
If (e.Execution.Order.Name == “OrderFromIndicator2)” { // do this }

I don’t understand why you don’t use these functions and a simple random string generator to generate unique OCO and then this does literally everything:

If current execution Order.Name contains the string “Indicator1” && the OCO of this order contains “whateverString”, cancel all pending orders in the order collection that begin with the letter “X”.

1 Like

I explained this earlier. When you are working with an Indicator and not a Strategy, OnExecutionUpdate is useless. I don’t know why. It had something to do with the way I handle my order generation. It doesn’t really matter. All that’s important is that I remember struggling with that for days before I finally realized that it simply doesn’t work. You can see in my other threads that I eventually had to give up.

There’s nothing “super complicated” about my solution to this problem. It’s actually quite elegant. I get to see the upcoming order ID on my chart. I get to see the same value returned on the Orders tab, so I get constant verification that everything is working, and there is never any worry about timing/order of execution because both Indicators are updated with the new ID for the next order as soon as the last position is closed.

I posted this thread asking if the OCO ID for any given order was globally visible. You answered “Yes, it is,” but the machinery that you suggested using to access it doesn’t work in my environment. That isn’t your fault. I don’t know why you’re taking it personally.

I’m not taking anything personally, but again you say things like “When you are working with an Indicator and not a Strategy, OnExecutionUpdate is useless.”

which is complete bullshit, it works exactly the same as it does in a strategy. I use it all the time.

“I posted this thread asking if the OCO ID for any given order was globally visible. You answered “Yes, it is,” but the machinery that you suggested using to access it doesn’t work in my environment.”

Your environment is NINJASCRIPT. The Orders collection is an account level collection to which you have access. That’s it.

2 Likes

Okay, assuming I believe you, I should also expect you to be able to explain why I get the following when I try to use OnExecutionUpdate in my Indicator.

MasterIndicator.cs,‘MasterIndicator.OnExecutionUpdate(Execution string double int MarketPosition string DateTime)’: no suitable method found to override
MasterIndicator.cs,No overload for ‘OnExecutionUpdate’ matches delegate ‘EventHandler’
MasterIndicator.cs,No overload for ‘OnExecutionUpdate’ matches delegate ‘EventHandler’

The source code is basically cut-and-pasted:

	protected override void OnExecutionUpdate(Execution execution, string executionId, double price, int quantity, MarketPosition marketPosition, string orderId, DateTime time)
	{
		// Assign the order object when it is submitted/accepted
		if (execution.Order.Name.Contains("Stop1") == true && execution.Order.OrderState == OrderState.Accepted)
		{
    		Order stopOrder1 = execution.Order;
		}
		else if (execution.Order.Name.Contains("Stop2") == true && execution.Order.OrderState == OrderState.Accepted)
		{
    		Order stopOrder2 = execution.Order;
		}
			
	}
........................

	protected override void OnBarUpdate()
	{ ....
		if (myAccount != null && subbed == false)
			{
				myAccount.PositionUpdate += OnPositionUpdate;
				myAccount.ExecutionUpdate += OnExecutionUpdate;
				subbed	= true;
			}

Expect? :joy: You shouldn’t expect anything on here.

Because it’s coded slightly different in an addon/indicator script than it is in strategy.
Click Here for NT Documentation Reference for Addon/Indicator ExecutionUpdate

Be Safe in this Crazy World!
:smiling_face_with_sunglasses:

This is virtually the same discussion we had with you 3 months ago, the one where you said you won’t use AI because you don’t see how it would help you.

AI is a great tool for learning, you could have entered your error, and it would have told you exactly the issue straight away.

It’s okay. Everything seems to be working, at this point.

I just have to work through my own logic of what I want to do based on certain conditions. Once I do that, I should be able to tell the computer how to do it.

Thank you!