3

Looking for either a python or R solution.


In R, I am able to retrieve DDE data into R from a third-party application using the following request:

library(tcltk2)
tk2dde.request(service = 'prortdde',topic='MNQXXXX', item='last')
"12262.75"

I'd like to continuously update this data. How can i create some kind of dde server or messaging system that would record all changes?

Including the above in a loop means losing data when updates are faster than loop execution... Thanks for any help.


In python, this is my current working code:

import win32ui
import dde

s=dde.CreateServer()
s.Create("prortdde")
c=dde.CreateConversation(s)
c.ConnectTo("prortdde", "MNQXXXX")
c.Connected()
c.Request("last")
# "12262.75"

BUT this will also miss values that are updated simultaneously (this occurs often). What I would need is some type of messaging system that would store all values, even those that are generated at the very same time, so that I can retrieve them later. Is that possible with DDE?

gaut
  • 5,771
  • 1
  • 14
  • 45

1 Answers1

3

I don't know a thing about R language. I just managed to put up this Frankenstein monster here to create a producer-consumer paradigm for your problem.

The plan is to run a non-blocking thread that would keep polling the values you are looking for and augment it to the list data_in_stock using the producer non-blocking function prortdde_produce_continuously. Then wait for you to consume the values at your ease using the function prortdde_consume_one which either returns the latest unconsumed value (if any) or the latest already consumed one old_value.

For the sake of demonstration, I made a loop of ten iterations to print the latest unconsumed value every 5 seconds. (I don't know a thing about your application and I am drawing lines in the sand as estimates of time).

Once you would like to see the infinite production loop stop, just set the flag keep_consuming to FALSE.

THIS CODE IS NOT TESTED. Sorry about that.

library(tcltk2)
library(future)

data_in_stock <- list()
old_value <- ""
keep_producing <- TRUE
last_consumed_value <- ""

prortdde_produce_continuously %<-% {
  while (keep_producing) {
    new_value <- tk2dde.request(service = 'prortdde', topic='MNQXXXX', item='last')
    if (new_value != old_value) {
      # The new value does not have to be pushed to `data_in_stock`
      data_in_stock <- append(data_in_stock, new_value)
            old_value <- new_value
    }
        # Wait for 0.1 seconds (I don't know how fast your data changes)
        sys.sleep(0.1)
  }
}

prortdde_consume_one <- function(){
    if (length(data_in_stock) > 0) {
        last_consumed_value = data_in_stock[1]
        data_in_stock[[1]] <- NULL
        return(last_consumed_value)
    }
    return(old_value)
}

# According to documentation, this line allows the non-blocking execution to happen
plan(multiprocess)

# Keeps polling and `producing` them indefinitely
prortdde_produce_continuously()

# Consumes 10 values
for (val in 1:10) {
    print(prortdde_consume_one)
    sys.sleep(5)
}

# Tells the `producing` to stop
keep_producing <- FALSE
Bilal Qandeel
  • 727
  • 3
  • 6
  • Thanks Bilal. I have updated my question with my latest python code. currently, I think your solution would be similar to mine, (we're both using loops, `for` or `while`, so we would miss data when updated at the same time). It would be totally fine for you to give python code, no need to translate to R. I agree that the consumer should be non-blocking but I can also run that in a separate process, so this isn't a hard requirement. – gaut Sep 03 '22 at 20:42
  • Does your application provide a handle for data change our should you pull continuously? Cause if the latter and the change is very rapid, then my provided code can rid of the `sys.sleep(0.1)` and you'll have to loop indefinitely calling `prortdde_consume_one`. I honestly don't see what are you looking for. – Bilal Qandeel Sep 03 '22 at 21:07
  • The changes can be simultaneous unfortunately (if someone places multiple orders at the same time), that's why I can't pull continuously, I need to buffer the pushed data somehow, otherwise I'm missing half the updates. – gaut Sep 03 '22 at 21:11
  • Please replace `multiprocess` with `multisession`. The formar has been deprecated for a long time (since 2020) and has now been fully removed from the **future** package (July 2023). – HenrikB Jul 02 '23 at 07:29