|
Attention! Read the forum rules carefully before posting a topic.
Try to find an answer in Wiki before asking a question. Submit programming questions in this forum only. Off topics are strictly forbidden.
Any topics which do not satisfy these rules will be deleted.
Closing order really fast |
[snelders]
|
Post subject: Closing order really fast |
Post rating: 0
|
Posted: Tue 17 Aug, 2010, 01:30
|
|
User rating: 0
Joined: Mon 07 Dec, 2009, 20:14 Posts: 14
|
I currently have a strategy which submits normal OrderCommand.BUY/SELL market orders. In some cases the market changes so fast that I directly need to close() an order even when the order only reached the OPENED state. When calling IOrder.close() I get in 100% percent of the cases a ORDER_CLOSE_REJECTED message back since the order is already being filled on the server. Even though I get the message that my close() call was rejected I do see however in the online trade log ( https://live-login.dukascopy.com/fo/reports/trader) that in case the order wasn't finally filled (ORDER_FILL_REJECTED message) the trade shows up in this log with a status CANCELLED. Orders which have have been REJECTED righ after submission (without the strategy trying to close it) show up with the status REJECTED. This difference drives me to the conclusion that somehow my close() call which generated the message ORDER_CLOSE_REJECTED did had some effect. I can imagine that Dukascopy sends a submitted order to its counterparties to get it filled. In my simple view this is a serial process: Your send the order first to counterparty A and wait if the order gets filled. If it doesn't get filled you send it to counterparty B etc. If in between this process Dukascopy receives my IOrder.close() this process is stopped and if the order is not yet filled shows up as CANCELED order in the trade log. I would like to know if this assumption is correct. If not, what effect do IOrder.close() call have on the server while the order is being filled on the server? Do subsequent(second, third etc) IOrder.close() calls have effect while the order is still being filled (in OPENED state) on the server? If my assumption is correct I would call IOrder.close() once during the OPENED state of the order to stop the filling process on the server. If this fails I need to call IOrder.close() once again once my order reaches the FILLED status (and watch the messages to see if it gets accepted of course). This causes one problem however: the second IOrder.close() during the FILLED status of the order will generate an ORDER_CLOSE_REJECTED message in 99% of the cases since this IOrder.close() call will be within 1 second distance from the first IOrder.close() call. Is this assumption true? If so, how can it be avoided. Thanks in advance for your help.
|
|
|
|
 |
[quantisan]
|
Post subject: Re: Closing order really fast |
Post rating: 0
|
Posted: Tue 17 Aug, 2010, 17:21
|
|
User rating: 1
Joined: Fri 26 Mar, 2010, 19:19 Posts: 116 Location: Canada
|
from the javadoc, IOrder.close() - Sends a request to fully close position by market price or cancel entry order.
You can implement a confirmation check after some delay.
|
|
|
|
 |
[snelders]
|
Post subject: Re: Closing order really fast |
Post rating: 0
|
Posted: Tue 17 Aug, 2010, 21:18
|
|
User rating: 0
Joined: Mon 07 Dec, 2009, 20:14 Posts: 14
|
Quantisan thanks for the help, I've seen the API docs. I'm not submitting 'entry orders' but 'market orders'. If I'm correct the term 'entry orders' is all about the type of order you are submitting ( https://www.onlineforextrading.com/gloss ... rder-types). It doesn't reflect the status of the order at any time. However I would like to get this question answered by Dukascopy support since I need to be absolutely sure about the API's/platforms behaviour.
|
|
|
|
 |
API Support
|
Post subject: Re: Closing order really fast |
Post rating: 0
|
Posted: Fri 20 Aug, 2010, 07:55
|
|
User rating: ∞
Joined: Fri 31 Aug, 2007, 09:17 Posts: 6139
|
Hi, Please provide us with the order number for the issue investigation.
|
|
|
|
 |
[snelders]
|
Post subject: Re: Closing order really fast |
Post rating: 0
|
Posted: Fri 20 Aug, 2010, 10:47
|
|
User rating: 0
Joined: Mon 07 Dec, 2009, 20:14 Posts: 14
|
EDIT: Dukascopy, please skip the logfiles I provided and scroll down to have a look at the strategy I wrote which runs into the problem described above. It's probably far more interesting and makes the problem better reproducableA few of my questions are assumptions/hypothetical. I can't provide real use cases for all of them. I think however that you are able to answer them anyway. My questions are in the the end about how the JForex API exactly works. A lot of exceptional cases aren't documented as those I described in my post. I shouldn't go through a lot of trial-and-error runs to find out what the API's behaviour exactly is in those cases and provide you with real positions and trades before you can answer those questions in my opinion. However I will dive into my log files to find some good examples of trades which come close to my questions asked. Position #9709674 (DEMO environment) is an example of an order which closed only after 1 second. Although the log file shows that the first close request was within the OPENED state of the order the order seems to got just filled by the time the close() method was really called. --- LOG FILE --- AUD/CHF - Order_AUDCHF1:State just before closing: OPENED AUD/CHF - Order_AUDCHF1:close() called
orderId:[Order_AUDCHF1]-OPENED / AUD/CHF / 0.92625 / 0.0010 / 0.0010 onMessage type:NOTIFICATION message: ORDER_FILLED-Order FILLED at 0.92625 CHF (#46411821 SELL 0.001 mil. AUD/CHF @ MKT MAX SLIPPAGE 0.0) - Position #9709674
orderId:[Order_AUDCHF1]-FILLED / AUD/CHF / 0.92625 / 0.0010 / 0.0010 onMessage type:ORDER_FILL_OK message:
AUD/CHF - Order_AUDCHF1:close() called orderId:[Order_AUDCHF1]-FILLED / AUD/CHF / 0.92625 / 0.0010 / 0.0010 onMessage type:ORDER_CLOSE_REJECTED message: Position #9709674 order close REJECTED, REASON: can't send request to fully close order more than once in a second ........ REPEAT PREVIOUS 3 LINE ~20 TIMES ..........
AUD/CHF - Order_AUDCHF1:close() called orderId:[Order_AUDCHF1]-FILLED / AUD/CHF / 0.92625 / 0.0010 / 0.0010 onMessage type:ORDER_CLOSE_REJECTED message: ORDER_ALREADY_FILLED-Order can't be processed: order in FILLED state, order #46411821 SELL 0.001 mil. AUD/CHF @ MKT MAX SLIPPAGE 0.0
AUD/CHF - Order_AUDCHF1:close() called orderId:[Order_AUDCHF1]-FILLED / AUD/CHF / 0.92625 / 0.0010 / 0.0010 onMessage type:ORDER_CLOSE_REJECTED message: REJECTED_COUNTERPARTY-Order 46411826 was REJECTED: Rejected by counterparty
........ REPEAT PREVIOUS 2 LINE ~3 TIMES ..........
orderId:[Order_AUDCHF1]-FILLED / AUD/CHF / 0.92625 / 0.0010 / 0.0010 onMessage type:NOTIFICATION message: ORDER_FILLED-Order FILLED at 0.92561 CHF (#46411836 BUY 0.001 mil. AUD/CHF @ MKT MAX SLIPPAGE 0.0005) - Position #9709674
I will try to post some other examples later.
|
|
|
|
 |
[snelders]
|
Post subject: Re: Closing order really fast |
Post rating: 0
|
Posted: Fri 20 Aug, 2010, 14:27
|
|
User rating: 0
Joined: Mon 07 Dec, 2009, 20:14 Posts: 14
|
Position #9730696 is an example of order which ends up in a cancelled state in the trade log --- LOG FILE --- NZD/CHF - Order_NZDCHF1:State just before closing: OPENED NZD/CHF - Order_NZDCHF1:close() called
orderId:[Order_NZDCHF1]-OPENED / NZD/CHF / 0.72795 / 0.0010 / 0.0010 onMessage type:ORDER_CLOSE_REJECTED message: ORDER_IN_EXEC_STATE-Order can't be processed: order in EXECUTING state, order#46499682 BUY 0.001 mil. NZD/CHF @ MKT MAX SLIPPAGE 0.0
orderId:[Order_NZDCHF1]-OPENED / NZD/CHF / 0.72795 / 0.0010 / 0.0010 onMessage type:NOTIFICATION message: ORDER_CANCELED-Order CANCELLED: #46499682 BUY 0.001 mil. NZD/CHF @ MKT MAX SLIPPAGE 0.0 - Position #9730696
orderId:[Order_NZDCHF1]-CANCELED / NZD/CHF / 0.72795 / 0.0010 / 0.0010 onMessage type:ORDER_FILL_REJECTED message: null
This in comparison to position 9736426 which ends up in a rejected state --- LOG FILE --- orderId:[Order_GBPCHF1]-OPENED / GBP/CHF / 1.60305 / 0.0010 / 0.0010 onMessage type:ORDER_SUBMIT_OK message:
GBP/CHF - Order_GBPCHF1:ABOUT TO CLOSE POSITION: 2010-08-20 11:00:52:750
GBP/CHF - Order_GBPCHF1:State just before closing: OPENED
GBP/CHF - Order_GBPCHF1:close() called orderId:[Order_GBPCHF1]-OPENED / GBP/CHF / 1.60305 / 0.0010 / 0.0010 onMessage type:ORDER_CLOSE_REJECTED message: REJECTED_COUNTERPARTY-Order 46506891 was REJECTED: Rejected by counterparty
orderId:[Order_GBPCHF1]-CANCELED / GBP/CHF / 1.60305 / 0.0010 / 0.0010 onMessage type:ORDER_FILL_REJECTED message: null
|
|
|
|
 |
[snelders]
|
Post subject: Re: Closing order really fast |
Post rating: 0
|
Posted: Fri 20 Aug, 2010, 20:12
|
|
User rating: 0
Joined: Mon 07 Dec, 2009, 20:14 Posts: 14
|
I took the time to write a little strategy runs into the problem which I described in my original question: The problem: Once an Iorder.close() on an order in OPENED state gets rejected since it is already filled in the meantime on the server or in execution state. A second IOrder.close() request during FILLED state gets rejected since it is within one second distance from the first IOrder.close() request. It's still possible to get the order closed of course but only after 1 second waiting which is quite a long time in forex landscape. In my opinion the timer which avoids me to send a second IOrder.close() request should be reset once the state of the order changes from OPENED to FILLED. The program:package com.forex.strategies;
import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.regex.Matcher;
import com.dukascopy.api.IAccount; import com.dukascopy.api.IBar; import com.dukascopy.api.IConsole; import com.dukascopy.api.IContext; import com.dukascopy.api.IEngine; import com.dukascopy.api.IMessage; import com.dukascopy.api.IOrder; import com.dukascopy.api.IStrategy; import com.dukascopy.api.ITick; import com.dukascopy.api.Instrument; import com.dukascopy.api.JFException; import com.dukascopy.api.Period; import com.dukascopy.api.IEngine.OrderCommand;
public class Trial implements IStrategy{ IContext context; IEngine engine; IConsole console; TrialThread trialThread; @Override public void onStart(IContext context) throws JFException { this.context = context; console = context.getConsole(); this.engine = context.getEngine(); console.getOut().println("Started!"); trialThread = new TrialThread(); trialThread.start(); }
@Override public void onMessage(IMessage message) throws JFException { IOrder order = message.getOrder(); if(order != null){ console.getOut().println(""); console.getOut().println("Message: type: " + message.getType() + " - " + message); console.getOut().println("Message content: " + message.getContent()); console.getOut().println("order: " + order); console.getOut().println(""); trialThread.sendOrderMessage(order, message.getType()); } }
long i = 1; @Override public void onTick(Instrument instrument, ITick tick) throws JFException { if(i%500 == 0){ console.getOut().println("Sending tick!"); trialThread.sendTick(instrument, tick); } i++; } class TrialThread extends Thread{ private Object tickWaitObject = new Object(); private ITick tick; private Instrument instrument; private IOrder order; private Object fillWaitObject = new Object(); public void sendTick(Instrument instrument, ITick tick){ synchronized(tickWaitObject){ if(this.tick == null){ this.tick = tick; this.instrument = instrument; tickWaitObject.notifyAll(); } } } public void sendOrderMessage(IOrder order, IMessage.Type type){ if(this.order != null && this.order == order){ if(type == IMessage.Type.ORDER_SUBMIT_REJECTED || type == IMessage.Type.ORDER_FILL_REJECTED || type == IMessage.Type.ORDER_FILL_OK || type == IMessage.Type.ORDER_SUBMIT_OK){ synchronized(fillWaitObject){ fillWaitObject.notify(); } } } } public void run(){ console.getOut().println("Thread started!!!!"); while(true){ tick = null; instrument = null; order = null; synchronized(tickWaitObject){ try { tickWaitObject.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } console.getOut().println(""); console.getOut().println(""); console.getOut().println("*******************************************"); console.getOut().println(instrument + "ABOUT TO PLACE ORDER!"); Future<IOrder> future = context.executeTask( new Callable<IOrder>() { public IOrder call() { try { int num = engine.getOrders(instrument).size(); return engine.submitOrder("Order_" + instrument.getPrimaryCurrency() + instrument.getSecondaryCurrency() + num, instrument, OrderCommand.BUY, 0.001, tick.getAsk(), 0.); } catch (JFException e) { e.printStackTrace(console.getOut()); return null; } } }); try { order = future.get(); if(order != null){
/* -------------------------------- * Wait for order to reach OPENED, FILLED, CLOSED, CANCELED state, -------------------------------- */ IOrder.State state = order.getState(); synchronized(fillWaitObject){ while(state != IOrder.State.CANCELED && state != IOrder.State.CLOSED && state != IOrder.State.FILLED && state != IOrder.State.OPENED){ try{ fillWaitObject.wait(); }catch(InterruptedException e){ e.printStackTrace(console.getOut()); } state = order.getState(); } } console.getOut().println(instrument + " - " + order.getLabel() + ": order reached OPENED, FILLED, CANCELED or CLOSED status: " + order.getState()); /* * Try to close one time during opened status */ if(state == IOrder.State.OPENED){ closeOrder(order); console.getOut().println("Close during OPENED state called"); }else{ console.getOut().println("Close during OPENED state skipped"); } /* -------------------------------- * Wait for order to reach CANCELED, CLOSED or FILLED state, -------------------------------- */ state = order.getState(); synchronized(fillWaitObject){ while(state != IOrder.State.CANCELED && state != IOrder.State.CLOSED && state != IOrder.State.FILLED){ try{ fillWaitObject.wait(); }catch(InterruptedException e){ e.printStackTrace(console.getOut()); } state = order.getState(); } } /* * Try to close once filled */ if(state == IOrder.State.FILLED){ closeOrder(order); console.getOut().println("Close during FILLED state called"); }else{ console.getOut().println("Close during FILLED state skipped"); } Thread.sleep(1000); console.getOut().println("*******************************************"); console.getOut().println(""); console.getOut().println(""); } } catch (InterruptedException e) { e.printStackTrace(console.getOut()); } catch (ExecutionException e) { e.printStackTrace(console.getOut()); } } } } private Future<Object> closeOrder(final IOrder order){ Future<Object> exitFuture = context.executeTask( new Callable<Object>() { public Object call() { // Correct state reached, close order IOrder.State state = order.getState(); if(state == IOrder.State.FILLED || state == IOrder.State.OPENED){ try { order.close(); console.getOut().println(order.getInstrument() + " - " + order.getLabel() + ":close() called" + state); } catch (JFException e) { e.printStackTrace(console.getOut()); } }else{ console.getOut().println(order.getInstrument() + " - " + order.getLabel() + ":Order was already in closed/cancelled state. state:" + state); } return null; } }); return exitFuture; } @Override public void onStop() throws JFException { } @Override public void onAccount(IAccount account) throws JFException { }
@Override public void onBar(Instrument instrument, Period period, IBar bar1, IBar bar2) throws JFException { } }
The output (You might need to run it for a while to run into the problem): Please note that the last message is actually related to the first IOrder.close() request while the order was in OPENED state. Sending tick!
******************************************* AUD/USDABOUT TO PLACE ORDER!
Message: type: ORDER_SUBMIT_OK - MessageType ORDER_SUBMIT_OK Text Related order [Order_AUDUSD0]-OPENED / AUD/USD / 0.89265 / 0.0010 / 0.0010 Message content: order: [Order_AUDUSD0]-OPENED / AUD/USD / 0.89265 / 0.0010 / 0.0010
AUD/USD - Order_AUDUSD0: order reached OPENED, FILLED, CANCELED or CLOSED status: OPENED Close during OPENED state called AUD/USD - Order_AUDUSD0:close() calledOPENED
Message: type: NOTIFICATION - MessageType NOTIFICATION Text ORDER_FILLED-Order FILLED at 0.89265 USD (#46549829 BUY 0.001 mil. AUD/USD @ MKT MAX SLIPPAGE 0.0) - Position #9746186 Related order [Order_AUDUSD0]-OPENED / AUD/USD / 0.89265 / 0.0010 / 0.0010 Message content: ORDER_FILLED-Order FILLED at 0.89265 USD (#46549829 BUY 0.001 mil. AUD/USD @ MKT MAX SLIPPAGE 0.0) - Position #9746186 order: [Order_AUDUSD0]-OPENED / AUD/USD / 0.89265 / 0.0010 / 0.0010
Message: type: ORDER_FILL_OK - MessageType ORDER_FILL_OK Text Related order [Order_AUDUSD0]-FILLED / AUD/USD / 0.89265 / 0.0010 / 0.0010 Message content: order: [Order_AUDUSD0]-FILLED / AUD/USD / 0.89265 / 0.0010 / 0.0010
Close during FILLED state called AUD/USD - Order_AUDUSD0:close() calledFILLED
Message: type: ORDER_CLOSE_REJECTED - MessageType ORDER_CLOSE_REJECTED Text Position #9746186 order close REJECTED, REASON: can't send request to fully close order more than once in a second Related order [Order_AUDUSD0]-FILLED / AUD/USD / 0.89265 / 0.0010 / 0.0010 Message content: Position #9746186 order close REJECTED, REASON: can't send request to fully close order more than once in a second order: [Order_AUDUSD0]-FILLED / AUD/USD / 0.89265 / 0.0010 / 0.0010
Message: type: ORDER_CLOSE_REJECTED - MessageType ORDER_CLOSE_REJECTED Text ORDER_ALREADY_FILLED-Order can't be processed: order in FILLED state, order #46549829 BUY 0.001 mil. AUD/USD @ MKT MAX SLIPPAGE 0.0 Related order [Order_AUDUSD0]-FILLED / AUD/USD / 0.89265 / 0.0010 / 0.0010 Message content: ORDER_ALREADY_FILLED-Order can't be processed: order in FILLED state, order #46549829 BUY 0.001 mil. AUD/USD @ MKT MAX SLIPPAGE 0.0 order: [Order_AUDUSD0]-FILLED / AUD/USD / 0.89265 / 0.0010 / 0.0010
*******************************************
|
|
|
|
 |
API Support
|
Post subject: Re: Closing order really fast |
Post rating: 0
|
Posted: Wed 25 Aug, 2010, 16:00
|
|
User rating: ∞
Joined: Fri 31 Aug, 2007, 09:17 Posts: 6139
|
Quote: I would like to know if this assumption is correct (about filling process) Yes, it's correct. You get ORDER_CLOSE_REJECTED because it's in filling process, but if the filling process didn't succeed on the current counterparty it's not sent to another, it's canceled. You will get ORDER_CLOSED_OK after it's CANCELED though Quote: Do subsequent(second, third etc) IOrder.close() calls have effect while the order is still being filled (in OPENED state) on the server? No, no effect. They will all be rejected Quote: the second IOrder.close() during the FILLED status of the order will generate an ORDER_CLOSE_REJECTED message in 99% of the cases since this IOrder.close() call will be within 1 second distance from the first IOrder.close() call. Is this assumption true? Yes, it's true. Current version doesn't reset timer after status is changed to FILLED. It does reset timer if ORDER_CLOSE_REJECTED message was received. We are changing "spam preventing" logic right now. In the next version you will be able to perform 180 actions per minute. After this limit is exceeded you will get rejects, until the next minute when counter will be reset. This hasn't been decided yet, but if nothing will make us change our minds, this mechanism will be implemented in the next version.
|
|
|
|
 |
[snelders]
|
Post subject: Re: Closing order really fast |
Post rating: 0
|
Posted: Thu 26 Aug, 2010, 15:12
|
|
User rating: 0
Joined: Mon 07 Dec, 2009, 20:14 Posts: 14
|
Thanks for the answer. Interesting to know and very clear. In which API version will this 180-actions-per-minute-limit be implemented and when can we expect it?
Will the 180-actions-per-minute-limit be per order or overall?
|
|
|
|
 |
API Support
|
Post subject: Re: Closing order really fast |
Post rating: 0
|
Posted: Fri 27 Aug, 2010, 19:02
|
|
User rating: ∞
Joined: Fri 31 Aug, 2007, 09:17 Posts: 6139
|
Currently 180 "limitation" is postponed.
|
|
|
|
 |
[snelders]
|
Post subject: Re: Closing order really fast |
Post rating: 0
|
Posted: Mon 30 Aug, 2010, 14:16
|
|
User rating: 0
Joined: Mon 07 Dec, 2009, 20:14 Posts: 14
|
Will there be another solution available? Resetting the timer once the status changes seems quite simple to implement and would be a perfect solution in this case.
|
|
|
|
 |
API Support
|
Post subject: Re: Closing order really fast |
Post rating: 0
|
Posted: Tue 31 Aug, 2010, 13:28
|
|
User rating: ∞
Joined: Fri 31 Aug, 2007, 09:17 Posts: 6139
|
Resetting the time on status change is implemented in our SNAPSHOT builds (internal builds) and will be on demo with the next version
|
|
|
|
 |
|
Pages: [
1
]
|
|
|
|
|