Posted 6/17/2008 10:42:27
|
|
|
|
Oanda's API wants to throw an exception and disconnect you for every simple problem. This inevitably causes all sorts of grief. For example, there is no way to avoid the potential exception of an order being closed out from under you when a stop or target price is hit after you check the order's existence but before you can take any action on the order.
check_order_exists();
<--- if order is hit here.
change_order(); <--- this now throws an exception and disconnects
When submitting a CloseAtMarket() from a trading system on an active position with stops & targets, RE calls the IBroker functions:
CancelOrder(target-order);
CancelOrder(stop-order);
SubmitOrder(close-order);
If one of the target/stop orders is hit (as described above) while this sequence is in progress; the plugin signals a disconnect by failing the CancelOrder() and setting the error state. the target/stop is left in a Submitted state.
It then appears that RE continues on with the sequence without checking the error state of the plugin. If the exception occurs when canceling the target, both CancelOrder(stop) and SubmitOrder(close) occur before RE calls Disconnect(). This causes a cascade of errors as the plugin is no longer even connected when these calls come in.
Would it be possible to have RE check the results and fail the CloseAtMarket()? Even better could it perform it's reconnect logic before continuing with the sequence ? Otherwise, since the plugin doesn't know where in a sequence it might be, the plugin will have to manually handle reconnects on every call.
Thanks,
Mark
|
|
Posted 7/16/2008 10:31:29
|
|
|
|
| Unfortunately for you I think you are going to have to modify the Oanda plugin so that it catches the errors itself and reconnects. When working with the Oanda plugin, I found it quite annoying that any error would cause a disconnect. If an order was filled while you were disconnected, you wouldn't get the fill notification. The way I worked around this was to have two connections to Oanda in the plugin. One would be for submitting orders and would get disconnected if a "bad" order was submitted or if there was another problem. The other connection would be the one used to get order updates. Whenever an exception was thrown that disconnected the first one, the Oanda plugin would reconnect it, and keep listening for fills and updates on the second one. If you wanted to use RightEdge's reconnection mechanism, you would risk missing updates to your orders from Oanda. From an architectural standpoint, I would like to avoid checking for a disconnect and automatically reconnecting whenever a call is made to the broker plugin. At that point your system is probably executing its code, and I wouldn't want to pause the system while waiting for the broker to reconnect. Thanks, Daniel
|
|
Posted 7/16/2008 17:37:58
|
|
|
|
Thanks for getting me some feedback on this. I have several results from the test build to submit as well. I'm hoping to get them all wrapped up and send you the details this evening.
I've found the oanda api's exception behavior to be irritating as well and ended up going to a dual channel setup as you suggested. It seemed to be the only way to prevent the message loss you described. I believe I have trapped most of the possible error states internally in the plugin in order to allow all the IBroker calls in one of these sequences to be passively accepted rather than pushing back an error. So while the current behavior complicates plugin logic, it is no longer an immediate issue.
As food for thought on any future design considerations...
I can understand your concern about blocking the system while waiting for a reconnect. However, the disconnect problem (while the main culprit earlier) is not the only reason one of the broker calls could fail. And considering that the position manager fires these sequences serially, I would think the return value of the last completed IBroker call could be tested. On detection of an error the position manager would then fail the entire sequence and return the error to the system.
Here's rough outline of what I was thinking...
class PositionManager
{
ReturnCode CloseAtMarket()
{
if(!IBroker.CancelOrder(target))
{
return ReturnCode.Fail("");
}
if(!IBroker.CancelOrder(stop))
{
return ReturnCode.Fail("");
}
if(!IBroker.SubmitOrder(close))
{
return ReturnCode.Fail("");
}
return ReturnCode.Success();
}
}
Cheers!
Mark
|
|
|
|