Hi Jeff,

Thanks, it works very well!

For future references by others stumbling upon the same issue, here is the
code of what Jeff described:

I made a copy of the code of twsCALLBACK(), added my return condition, and
called it implVCALLBACK:

implVCALLBACK <-
function (twsCon, eWrapper, timestamp, file, playback = 1, ...)
{
    if (missing(eWrapper))
        eWrapper <- eWrapper()
    con <- twsCon[[1]]
    if (inherits(twsCon, "twsPlayback")) {
        sys.time <- NULL
        while (TRUE) {
            if (!is.null(timestamp)) {
                last.time <- sys.time
                sys.time <- as.POSIXct(strptime(paste(readBin(con,
                  character(), 2), collapse = " "), timestamp))
                if (!is.null(last.time)) {
                  Sys.sleep((sys.time - last.time) * playback)
                }
                curMsg <- .Internal(readBin(con, "character",
                  1L, NA_integer_, TRUE, FALSE))
                if (length(curMsg) < 1)
                  next
                processMsg(curMsg, con, eWrapper, format(sys.time,
                  timestamp), file, ...)
            }
            else {
                curMsg <- readBin(con, character(), 1)
                if (length(curMsg) < 1)
                  next
                processMsg(curMsg, con, eWrapper, timestamp,
                  file, ...)
                if (curMsg == .twsIncomingMSG$REAL_TIME_BARS)
                  Sys.sleep(5 * playback)
            }
        }
    }
    else {
        while (TRUE) {

    ########### Start my added conditional exit ###########

    # Notice that what you return here is returned by reqMktData()
    if(length(which(v <= 0)) == 0) return(length(v))

    ########### End my addition ###########################

            socketSelect(list(con), FALSE, NULL)
            curMsg <- .Internal(readBin(con, "character", 1L,
                NA_integer_, TRUE, FALSE))
            if (!is.null(timestamp)) {
                processMsg(curMsg, con, eWrapper, format(Sys.time(),
                  timestamp), file, ...)
            }
            else {
                processMsg(curMsg, con, eWrapper, timestamp,
                  file, ...)
            }
        }
    }
}

Now I can call reqktData() with my implVCALLBACK (and my implVWrapper):

> twsDisconnect(tws)
> tws = twsConnect(clientId=1)
> options = list(twsOption("AA    100320P00012000"), twsOption("AA
 100320C00014000"))
> v = vector(mode = "numeric", length = length(options))
> n = reqMktData(tws, options, eventWrapper=implVWrapper(),
CALLBACK=implVCALLBACK)
2 -1 2104 Market data farm connection is OK:cusfuture
2 -1 2104 Market data farm connection is OK:usfuture
2 -1 2104 Market data farm connection is OK:eurofarm
2 -1 2104 Market data farm connection is OK:hkfarm
2 -1 2104 Market data farm connection is OK:cashfarm
2 -1 2104 Market data farm connection is OK:usopt
2 -1 2104 Market data farm connection is OK:usfarm
2 -1 2106 HMDS data farm connection is OK:ushmds2a
[1] "id: 2 implVol: 0.431977549715779"
[1] "id: 1 implVol: 0.458139947283466"
> n
[1] 2
>
Notice that I now also have control over what reqMktData() will return. This
could be convenient in more complex situations...

Very nice... thank you Jeff!

Regards,

-Mark-

2010/2/19 Jeff Ryan <jeff.a.ryan@gmail.com>

> Hi Mark,
>
> The basic premise is that the eWrapper is just the collection of
> callbacks that manage each incoming message.  Either doing nothing
> with it, yet still processing correctly [eWrapper(NULL)], or handling
> each message type with some particular logic.
>
> It seems like you have extended that perfectly.
>
> What you need to customize is the CALLBACK that is passed in.  By
> default this is twsCALLBACK.
>
> In a nutshell, this is the main 'loop' that waits on the connection or
> connections you have established to the TWS or external data source,
> and it cycles though each new incoming message.  The messages
> themselves are handled by the eWrapper object's callback(s) you
> write/use.
>
> What you want to do is add a few lines of code in a new CALLBACK that
> test for the condition of the data you are storing (some n number of
> bars, or all values are now non-NA, etc), and when it evaluates to
> TRUE, simply return() from the call.  Easiest is just make a copy of
> the twsCALLBACK and modify.
>
> The function itself (reqMktData) should cancel the outstanding data
> subscription you made, but to be sure you can also call cancelMktData
> yourself.
>
> I'll be giving a tutorial on trading with IBrokers (and event
> processing in general with R) at the upcoming R/Finance 2010
> conference in Chicago this coming April 16 and 17.
>
> http://www.RinFinance.com
>
> If you can't make the conference or the workshop, the slides will
> eventually make their way to the website.
>
> Hope that helps,
> Jeff
>
>
> On Fri, Feb 19, 2010 at 12:34 PM, Mark Breman <breman.mark@gmail.com>
> wrote:
> > Hi everyone,
> >
> > I'm using the IBrokers package to get the implied volatility for options
> > from Interactive Brokers.
> >
> > To seperate the implied volatility field from the data stream you get
> after
> > calling reqMktData(), I had to write a specific EventWrapper:
> >
> > library(IBrokers)
> >
> > implVWrapper <-
> > function(n=1) {
> > eW <- eWrapper(NULL)
> > #eW$assign.Data("data", vector(mode = "numeric", length = 2))
> >
> > eW$tickOptionComputation <- function(curMsg, msg, timestamp, file, ...) {
> >        tickType = msg[3]
> >        msg <- as.numeric(msg)
> >         id <- as.numeric(msg[2])
> > value <- msg[4]
> > #file <- file[[id]]
> >         #data <- eW$get.Data("data")
> >
> > if(tickType == 13 & value != -1) {     # 14 is MODEL_OPTION, -1 is ???
> > print(paste("id:", id, "implVol:", msg[4]))
> > v[id] <<- value
> > #cancelMktData(tws, id)
> > }
> >
> > #eW$assign.Data("data", data)
> >        c(curMsg, msg)
> > }
> >
> > return(eW)
> > }
> >
> > Now I call the reqMktData() function with my special eventwrapper:
> >
> > options = list(twsOption("AA    100320P00012000"), twsOption("AA
> >  100320C00014000")) # specify the options
> > v = vector(mode = "numeric", length = length(options))    # v will hold
> the
> > implied volatilities for the options
> > tws = twsConnect(clientId=1)
> > reqMktData(tws, options, eventWrapper=implVWrapper())
> >
> > This all works as expected except that reqMktData() keeps on running
> until
> > it is stopped by the user (with the Esc key). What I would like is some
> way
> > to stop the function when both implied volatilities are "filled". How do
> I
> > do that?
> >
> > Kind regards,
> >
> > -Mark-
> >
> >        [[alternative HTML version deleted]]
> >
> > _______________________________________________
> > R-SIG-Finance@stat.math.ethz.ch mailing list
> > https://stat.ethz.ch/mailman/listinfo/r-sig-finance
> > -- Subscriber-posting only. If you want to post, subscribe first.
> > -- Also note that this is not the r-help list where general R questions
> should go.
> >
>
>
>
> --
> Jeffrey Ryan
> jeffrey.ryan@insightalgo.com
>
> ia: insight algorithmics
> www.insightalgo.com
>

	[[alternative HTML version deleted]]

