Re: [racket-users] Advice for porting Interactive Brokers API to Racket

2019-07-14 Thread evdubs
Thanks for the feedback. I will check to see if there's some way to query 
for capabilities, but I doubt it, given the client code. 

The client code does most of this version checking in one class, so that 
seems localized enough and I think it will be straight forward. Maybe if I 
stumble on a better way to do this, I'll share.

Evan

On Thursday, July 11, 2019 at 3:09:09 AM UTC-10, Greg Hendershott wrote:
>
> Some systems provide a way to query for a capability: COM has 
> QueryInterface, Racket dynamic-require, Emacs fboundp, and so on. When 
> such a query method is available, you can simply ask for the thing you 
> need or prefer. If it's available, great. If not, act appropriately: 
> Fail, or use your own "back fill" that does something similar or is just 
> a no-op, or whatever is appropriate. 
>
> [IMHO this is more sensible than using version numbers as proxies for 
> the thing you really care about. Especially lawyerly systems like 
> so-called semantic versioning. But I digress. :)] 
>
> The Racket flavor is something like the following. Let's say 
> some/module/path maybe has a new fribble function. If that's not 
> present, or if indeed that whole module isn't even installed, we want to 
> use our own our-fribble function as a default: 
>
> (define (our-fribble _x) 
>   'some-default-value) 
>
> (define fribble 
>   (with-handlers ([exn:fail? (λ _ our-fribble)]) 
> (dynamic-require 'some/module/path 
>  'fribble))) 
>
> For example, I use this and also Emacs' fboundp in Racket Mode, to 
> support various versions of Racket and Emacs, both. 
>
>
> I don't know if/how this would help your case. Their API uses the 
> futzing-with-version-numbers approach. Even so, _maybe_ you'd want to 
> localize the version number checks in one module, which provides the 
> functions for your other code to use? The functions will end up being 
> either the real broker thing, or your own default. 
>

-- 
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 racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/54fdaf8b-2233-475e-b6ed-78c8fdeeeabf%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-users] Advice for porting Interactive Brokers API to Racket

2019-07-11 Thread Greg Hendershott
Some systems provide a way to query for a capability: COM has
QueryInterface, Racket dynamic-require, Emacs fboundp, and so on. When
such a query method is available, you can simply ask for the thing you
need or prefer. If it's available, great. If not, act appropriately:
Fail, or use your own "back fill" that does something similar or is just
a no-op, or whatever is appropriate.

[IMHO this is more sensible than using version numbers as proxies for
the thing you really care about. Especially lawyerly systems like
so-called semantic versioning. But I digress. :)]

The Racket flavor is something like the following. Let's say
some/module/path maybe has a new fribble function. If that's not
present, or if indeed that whole module isn't even installed, we want to
use our own our-fribble function as a default:

(define (our-fribble _x)
  'some-default-value)

(define fribble
  (with-handlers ([exn:fail? (λ _ our-fribble)])
(dynamic-require 'some/module/path
 'fribble)))

For example, I use this and also Emacs' fboundp in Racket Mode, to
support various versions of Racket and Emacs, both.


I don't know if/how this would help your case. Their API uses the
futzing-with-version-numbers approach. Even so, _maybe_ you'd want to
localize the version number checks in one module, which provides the
functions for your other code to use? The functions will end up being
either the real broker thing, or your own default.

-- 
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 racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/87ftncpvke.fsf%40greghendershott.com.
For more options, visit https://groups.google.com/d/optout.


[racket-users] Advice for porting Interactive Brokers API to Racket

2019-07-10 Thread evdubs
Hi,

I am currently investigating the effort required to port the Interactive 
Brokers Client API  
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 racket-users+unsubscr...@googlegroups.com.
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.