API Support Forum
OEC API > API Support > What is the proper way to send this OSO and OCO orders?
Author Topic: What is the proper way to send this OSO and OCO orders?
(11 messages, Page 1 of 1)
Moderators: VPfau
JGagnon
Posts: 95
Joined: Apr 11, 2011


Posted: Mar 01, 2012 @ 12:24 AM             Msg. 1 of 11
I'm still a little new to this so pardon my terminology, trying to use as much API syntax as possible to make this clear. Questions at end of post.

In the scenario I explain below, we are selling short 2 contracts with a StopLimit at prices 100.00 and 99.98 with an OSO for a Stop-Loss of 2 contracts at 100.10

Also we want to set a profit target order for 1 contract at 99.90 which changes (does OCO only cancel or can it change an existing order?) the Stop-Loss of 2 contracts described above to a Stop-Loss of the 1 remaining contract and change the Stop price to 100.00

Send Order 1
SellShort 2 @ StopLimit (100.00, 99.98) [becomes OECorderId #1] OSO Buy 2 @ Stop (100.10) [becomes OECorderId #2] -- 2nd half of the OSO is the Stop-Loss

Send Order 2
Buy 1 @ Stop (99.90) [becomes OECorderId #3] OCO (OECorderId #2) Buy 1 @ Stop (100.00) [stays OECorderId #2] -- 2nd half of the OCO is the new Stop-Loss of the remaining 1 contract

Q1) Do we need to only send the two orders I described above?
Q2) I found the method: OECClient.SendOCOOrders description says it cancels other orders - is this the method I need to use or do you offer a change order method?
Q3) I was not able to find a similar method such as: OECClient.SendOSOOrders - does it exist?
Q4) If our stop loss order on 2 contracts executes before our profit target order, does the system know to cancel the profit target order automatically or does our program need to do this some how? How do you recommend we send this contingent order?

John Gagnon
JGagnon
Posts: 95
Joined: Apr 11, 2011


Posted: Mar 01, 2012 @ 12:01 PM             Msg. 2 of 11
In the advanced example I found function:
private void btSendBracket_Click( object sender, EventArgs e )

and it ends up calling:
OECClient.Global.SendLinkedOrders( mainOrder, draft1, draft2 );

I think I am on the right track, mainOrder would be my:
SellShort 2 @ StopLimit (100.00, 99.98)

draft1 would be my:
Buy 1 @ Limit 99.90 // profit target #1

draft2 would be my:
Buy 2 @ Stop 100.10 // stop loss

So I think I am close, now I just need to figure out how to trap the event when one of these fires to link up additional trades.

For example if draft2 fires above - no linked trade, we're done.

However if draft1 fires above then I would want another set of order pairings (OCO?):

Buy 1 @ Stop 100.00 // stop loss
Buy 1 @ Limit 99.80

John Gagnon
JGagnon
Posts: 95
Joined: Apr 11, 2011


Posted: Mar 01, 2012 @ 09:13 PM             Msg. 3 of 11
Ok, I am getting closer - could use a response here please...

Here is the results of my sendlinkedorders code:

http://img29.imageshack.us/img29/176/sendlinkedorders.jpg

Here is the code I am using, do you see anything I am doing wrong to cause the 2nd one to get rejected??
-----------snip-----------
private void PlaceOrder()
{
foreach(var futureOrder in futureOrders)
{
try
{
OrderDraft mainOrder = GetOrderDraft(OECClient.Global.CreateDraft(), "Regular", futureOrder);
OrderDraft profit1Order = GetOrderDraft(OECClient.Global.CreateDraft(), "Regular", futureOrder);
OrderDraft stopLossOrder = GetOrderDraft(OECClient.Global.CreateDraft(), "Regular", futureOrder);
profit1Order.Quantity = futureOrder.OrderProfitTargetContracts;
profit1Order.Price = Convert.ToDouble(futureOrder.OrderTargetProfit1Price);
stopLossOrder.Quantity = mainOrder.Quantity;
stopLossOrder.Price = Convert.ToDouble(futureOrder.OrderTargetStopLossPrice);
profit1Order.Contract = stopLossOrder.Contract = mainOrder.Contract;
profit1Order.Type = OEC.Data.OrderType.Limit;
stopLossOrder.Type = OEC.Data.OrderType.Stop;

if (mainOrder.Side == OEC.Data.OrderSide.Buy)
{
profit1Order.Side = OEC.Data.OrderSide.Sell;
stopLossOrder.Side = OEC.Data.OrderSide.Sell;
}
else
{
profit1Order.Side = OEC.Data.OrderSide.Buy;
stopLossOrder.Side = OEC.Data.OrderSide.Buy;
}

if (mainOrder == null)
return;

if (profit1Order.Quantity > 0)
{
if (MessageBox.Show("Send linked orders \n" + mainOrder.ToString() + "\n" + profit1Order.ToString() + "\n" + stopLossOrder.ToString(), "Confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Question) ==
DialogResult.No)
return;

OECClient.Global.SendLinkedOrders(mainOrder, profit1Order, stopLossOrder);
}
else
{
if (MessageBox.Show("Send linked orders \n" + mainOrder.ToString() + "\n" + stopLossOrder.ToString(), "Confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Question) ==
DialogResult.No)
return;

OECClient.Global.SendLinkedOrders(mainOrder, stopLossOrder);
}

}
catch (Exception ex)
{
MessageBox.Show("Error sending order : " + ex.Message);
}
}
}
-----------snip-----------

John Gagnon
JGagnon
Posts: 95
Joined: Apr 11, 2011


Posted: Mar 02, 2012 @ 08:08 AM             Msg. 4 of 11
Ok, looks like the code above worked since when I woke up this morning the rejected trade actually filled (after the sellshort filled).

My next challenge is to capture the trade fills so I can create trades (stop loss and profit #2) for the remaining 1 contract.

John Gagnon
JGagnon
Posts: 95
Joined: Apr 11, 2011


Posted: Mar 02, 2012 @ 10:56 AM             Msg. 5 of 11
Actually I am still looking into this, the profit order was working and eventually filled, but the stoploss order was rejected (and hence never working) any ideas why?

John Gagnon
RuslanK
Posts: 69
Joined: Jun 02, 2010


Posted: Mar 07, 2012 @ 10:29 AM             Msg. 6 of 11
Hello,

SendOCOOrders method is intended to send OCO orders. If any leg of OCO order gets filled the other one gets cancelled automatically by server.

If you want to send an OSO order - you should use SendLinkedOrders method. So, your guess about this was correct.

About rejected order - I'm looking into this now and will come back with the results shortly.

Ruslan Kartokhin
Software Developer
RuslanK
Posts: 69
Joined: Jun 02, 2010


Posted: Mar 07, 2012 @ 10:36 AM             Msg. 7 of 11
Your order with id 202254138 got rejected with "Invalid trigger price" comment which means that stop price was lower than current at the moment of order execution.

Ruslan Kartokhin
Software Developer
JGagnon
Posts: 95
Joined: Apr 11, 2011


Posted: Mar 07, 2012 @ 10:40 AM             Msg. 8 of 11
Thanks ruslanK -

Problem I started having was that when using:

SendLinkedOrders

If the mainOrder (first order in the chain) was rejected, the 2nd and 3rd orders would become working causing unintended trades.

Is this normal?

I understand why the rejection was happening, but now I am trying to intercept filled orders to call SendOCOOrders so that only OCO orders are sent after mainOrder is filled.

John Gagnon
RuslanK
Posts: 69
Joined: Jun 02, 2010


Posted: Mar 07, 2012 @ 10:55 AM             Msg. 9 of 11
Yes, this is normal behaviour for linked orders.

According to our paradigm - it's up to 3rd party application to decide what to do with remaining orders - either cancel them or let them stay.

Your code should monitor order states by handling OnOrderStateChanged event.

Ruslan Kartokhin
Software Developer
JGagnon
Posts: 95
Joined: Apr 11, 2011


Posted: Mar 07, 2012 @ 02:18 PM             Msg. 10 of 11
Thanks Ruslan -

I am still having a problem - I am able to intercept the event OnOrderStateChanged - but the linked orders are not getting cancelled - do you see what the problem with my code is? I have included the console output at the end of this message too.

The "CancelOrder" code below executes, but the linked orders still go to "working" and "filled".
_______________
private void oecClient1_OnOrderStateChanged(OEC.API.Order Order, OEC.Data.OrderState OldOrderState)
{
Console.WriteLine("OnOrderStateChanged: {0}: {2} -> {1} ", Order.ID, Order.CurrentState, OldOrderState);

if (Order.Comments == "1" && Order.CurrentState == OEC.Data.OrderState.Rejected)
{
if (Order.Linked == null)
return;
else
OECClient.Global.CancelOrder(Order.Linked);
}
}
_______________
Console output:

OnOrderStateChanged: -1: Unknown -> Sent
OnOrderStateChanged: -2: Unknown -> Sent
OnOrderStateChanged: -3: Unknown -> Sent
Send order
Sell Short 2 6EH2 STP 1031.37 LMT 1031.37
OnOrderConfirmed: -1 -> 202257973
OnOrderStateChanged: 202257973: Sent -> Sent
OnOrderStateChanged: 202257973: Sent -> Sent
OnOrderConfirmed: -2 -> 202257974
OnOrderStateChanged: 202257974: Sent -> Sent
OnOrderStateChanged: 202257974: Sent -> Sent
OnOrderConfirmed: -3 -> 202257975
OnOrderStateChanged: 202257975: Sent -> Sent
OnOrderStateChanged: 202257975: Sent -> Sent
OnOrderStateChanged: 202257973: Sent -> Accepted
OnOrderStateChanged: 202257974: Sent -> Accepted
OnOrderStateChanged: 202257975: Sent -> Accepted
OnOrderStateChanged: 202257973: Accepted -> Rejected
OnOrderStateChanged: 202257974: Accepted -> Working
OnOrderStateChanged: 202257974: Working -> Working
Order #202257974 (Buy 1 6EH2 LMT 1031.36) filled : 1@131.44
OnOrderStateChanged: 202257974: Working -> Completed
OnOrderStateChanged: 202257975: Accepted -> Working
OnOrderStateChanged: 202257975: Working -> Working
OnOrderStateChanged: 202257975: Working -> Cancelled

John Gagnon
RuslanK
Posts: 69
Joined: Jun 02, 2010


Posted: Mar 07, 2012 @ 02:41 PM             Msg. 11 of 11
As I see in our database you sent three cancel requests for order #202257974.

First one failed because original order has been in processing by exchange at the moment.
Two others were sent after order became completed.

You should handle OnCommandUpdatedEvent to track state of each command execution. You can retrieve failure reason from ResultComments field of Command.

Also, for this specific case:
your limit price (1031.36) was a way higher than current price (131.44) - that's why order was executed by exchange momentarily leaving you without a chance to cancel it.

Ruslan Kartokhin
Software Developer