Hi,
I am currently investigating the effort required to port the Interactive
Brokers Client API <https://www.interactivebrokers.com/en/index.php?f=5041>
to Racket. In general, there is not much complexity in the client; it
establishes an open socket, builds byte buffers to send to the server, and
receives byte buffer responses. Some of the code declares classes that can
be used by the client that can serialize to and deserialize from the byte
buffers being sent.
There are some warts in the implementation. For example, there are sections
like the following:
private static final int MIN_SERVER_VER_REAL_TIME_BARS = 34;
private static final int MIN_SERVER_VER_SCALE_ORDERS = 35;
private static final int MIN_SERVER_VER_SNAPSHOT_MKT_DATA = 35;
private static final int MIN_SERVER_VER_SSHORT_COMBO_LEGS = 35;
private static final int MIN_SERVER_VER_WHAT_IF_ORDERS = 36;
These values represent new feature releases that introduce things like
receiving real time bars, submitting scale orders (a way to break up a
large order into smaller orders that can scale as prices move favorably),
receiving a snapshot of bids and asks for a financial instrument (market
data), and submitting orders with conditions. These server version
declarations are paired with code like:
public synchronized void placeOrder(int id, Contract contract, Order order)
{
...
if (m_serverVersion < MIN_SERVER_VER_SCALE_ORDERS) {
if (order.scaleInitLevelSize() != Integer.MAX_VALUE ||
order.scalePriceIncrement() != Double.MAX_VALUE) {
error(id, EClientErrors.UPDATE_TWS,
" It does not support Scale orders.");
return;
}
}
...
if (m_serverVersion >= MIN_SERVER_VER_SCALE_ORDERS) {
if (m_serverVersion >= MIN_SERVER_VER_SCALE_ORDERS2) {
buffer.sendMax(order.scaleInitLevelSize());
buffer.sendMax(order.scaleSubsLevelSize());
}
else {
buffer.send("");
buffer.sendMax(order.scaleInitLevelSize());
}
buffer.sendMax(order.scalePriceIncrement());
}
...
}
In the above, buffer is a byte buffer that is prepared to be sent along to
the server. In this example, there are maybe 20 different buffers that can
be built that just represent an order to send, and they all depend on the
server version. It may have been a nicer design to have a small set of
fields that every order shares and a map of extra fields for special
orders, but we can't redesign the server-side of things.
I am wondering if there is a better way in Racket to port this code than to
just have a "straight port" of code like:
(cond [(>= server-version 'scale-orders-version)
(vector-append buffer (vector (order-scale-init-level-size order)
(order-scale-subs-level-size order)))])
Is there a clearer way of representing capabilities of a server and have
that be responsible for object serialization in Racket? Has anyone ported
code to Racket with implementations like the above and found better ways of
structuring the code in Racket?
Curiously,
Evan
--
You received this message because you are subscribed to the Google Groups
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/racket-users/e9507c6b-aa74-4605-a1ff-44dc1bef6d23%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.