Excel RTD (Real Time Data) client other than Excel? - c++

I have been looking all over, and couldn't find any example for an RTD CLIENT (many RTD server samples, though).
My goal is to 'pull' data from an RTD server into my application for algo-trading purposes.
If possible, without using C# / .Net, as I am looking for a lightweight, deploy-able solution.
Can you give me any tips?

Here is a C# client I built as a test harness for Excel RTD servers (both in-process DLL and out-of-process EXE):
using System;
using System.Reflection;
using System.Threading;
namespace MyRTD
{
class Program
{
// ProgIDs for COM classes.
private const String RTDProgID = "MyRTD.RTD";
private const String RTDUpdateEventProgID = "MyRTD.UpdateEvent";
private const String RTDEXEProgID = "MyRTDEXE.RTD";
private const String RTDEXEUpdateEventProgID = "MyRTDEXE.UpdateEvent";
// Dummy topic.
private const int topicID = 12345;
private const String topic = "topic";
static void Main(string[] args)
{
Console.WriteLine("Test in-process (DLL) RTD server.");
TestMyRTD(RTDProgID,RTDUpdateEventProgID);
Console.WriteLine("Test out-of-process (EXE) RTD server.");
TestMyRTD(RTDEXEProgID,RTDEXEUpdateEventProgID);
Console.WriteLine("Press enter to exit ...");
Console.ReadLine();
}
static void TestMyRTD(String rtdID, String eventID)
{
try
{
// Create the RTD server.
Type rtd;
Object rtdServer = null;
rtd = Type.GetTypeFromProgID(rtdID);
rtdServer = Activator.CreateInstance(rtd);
Console.WriteLine("rtdServer = {0}", rtdServer.ToString());
// Create a callback event.
Type update;
Object updateEvent = null;
update = Type.GetTypeFromProgID(eventID);
updateEvent = Activator.CreateInstance(update);
Console.WriteLine("updateEvent = {0}", updateEvent.ToString());
// Start the RTD server.
Object[] param = new Object[1];
param[0] = updateEvent;
MethodInfo method = rtd.GetMethod("ServerStart");
Object ret; // Return value.
ret = method.Invoke(rtdServer, param);
Console.WriteLine("ret for 'ServerStart()' = {0}", ret.ToString());
// Request data from the RTD server.
Object[] topics = new Object[1];
topics[0] = topic;
Boolean newData = true; // Request new data, not cached data.
param = new Object[3];
param[0] = topicID;
param[1] = topics;
param[2] = newData;
method = rtd.GetMethod("ConnectData");
ret = method.Invoke(rtdServer, param);
Console.WriteLine("ret for 'ConnectData()' = {0}", ret.ToString());
// Loop and wait for RTD to notify (via callback) that
// data is available.
int count = 0;
do
{
count++;
// Check that the RTD server is still alive.
Object status;
param = null;
method = rtd.GetMethod("Heartbeat");
status = method.Invoke(rtdServer, param);
Console.WriteLine("status for 'Heartbeat()' = {0}", status.ToString());
// Get data from the RTD server.
int topicCount = 0;
param = new Object[1];
param[0] = topicCount;
method = rtd.GetMethod("RefreshData");
Object[,] retval = new Object[2, 1];
retval = (Object[,])method.Invoke(rtdServer, param);
Console.WriteLine("retval for 'RefreshData()' = {0}", retval[1,0].ToString());
// Wait for 2 seconds before getting
// more data from the RTD server.
Thread.Sleep(2000);
} while (count < 5); // Loop 5 times.
// Disconnect from data topic.
param = new Object[1];
param[0] = topicID;
method = rtd.GetMethod("DisconnectData");
method.Invoke(rtdServer, param);
// Shutdown the RTD server.
param = null;
method = rtd.GetMethod("ServerTerminate");
method.Invoke(rtdServer, param);
}
catch (Exception e)
{
Console.WriteLine("Error: {0} ", e.Message);
}
}
}
}

You can indeed create RTD "clients" outside Excel by emulating the calls that Excel would make to the RTD server. The RTD server is, after all, just a COM component that implements IRtdServer (and IRTDUpdateEvent for the callback).
You must follow the call sequence that Excel itself uses when interacting with the RTD. But once you do that, the RTD should quite happily pump data into your "client". Indeed, there might be an advantage to doing this because whereas Excel will only pull data from the RTD about every two seconds, your client can pull data as fast as it wants. This is certainly an advantage for algorithmic trading.
Whether such a client can work side-by-side with Excel is something I have not tested.

You would use RTD because RTD is normally free and the API access adds $100/month/cient or more to the datafeed cost for the dataservice we are using

Related

How to make POST request to a web server with C++ and Core Foundation APIs for macOS?

I'm trying to follow this example to let me make a POST request to a web server and receive its response in pure C++ using Core Foundation functions. I'll copy and paste it here:
void PostRequest()
{
// Create the POST request payload.
CFStringRef payloadString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("{\"test-data-key\" : \"test-data-value\"}"));
CFDataRef payloadData = CFStringCreateExternalRepresentation(kCFAllocatorDefault, payloadString, kCFStringEncodingUTF8, 0);
CFRelease(payloadString);
//create request
CFURLRef theURL = CFURLCreateWithString(kCFAllocatorDefault, CFSTR("https://httpbin.org/post"), NULL); //https://httpbin.org/post returns post data
CFHTTPMessageRef request = CFHTTPMessageCreateRequest(kCFAllocatorDefault, CFSTR("POST"), theURL, kCFHTTPVersion1_1);
CFHTTPMessageSetBody(request, payloadData);
//add some headers
CFStringRef hostString = CFURLCopyHostName(theURL);
CFHTTPMessageSetHeaderFieldValue(request, CFSTR("HOST"), hostString);
CFRelease(hostString);
CFRelease(theURL);
if (payloadData)
{
CFStringRef lengthString = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%ld"), CFDataGetLength(payloadData));
CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Content-Length"), lengthString);
CFRelease(lengthString);
}
CFHTTPMessageSetHeaderFieldValue(request, CFSTR("Content-Type"), CFSTR("charset=utf-8"));
//create read stream for response
CFReadStreamRef requestStream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, request);
CFRelease(request);
//set up on separate runloop (with own thread) to avoid blocking the UI
CFReadStreamScheduleWithRunLoop(requestStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
CFOptionFlags optionFlags = (kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered);
CFStreamClientContext clientContext = {0, (void *)payloadData, RetainSocketStreamHandle, ReleaseSocketStreamHandle, NULL};
CFReadStreamSetClient(requestStream, optionFlags, ReadStreamCallBack, &clientContext);
//start request
CFReadStreamOpen(requestStream);
if (payloadData)
{
CFRelease(payloadData);
}
}
And the callback:
void LogData(CFDataRef responseData)
{
CFIndex dataLength = CFDataGetLength(responseData);
UInt8 *bytes = (UInt8 *)malloc(dataLength);
CFDataGetBytes(responseData, CFRangeMake(0, CFDataGetLength(responseData)), bytes);
CFStringRef responseString = CFStringCreateWithBytes(kCFAllocatorDefault, bytes, dataLength, kCFStringEncodingUTF8, TRUE);
CFShow(responseString);
CFRelease(responseString);
free(bytes);
}
static void ReadStreamCallBack(CFReadStreamRef readStream, CFStreamEventType type, void *clientCallBackInfo)
{
CFDataRef passedInData = (CFDataRef)(clientCallBackInfo);
CFShow(CFSTR("Passed In Data:"));
LogData(passedInData);
//append data as we receive it
CFMutableDataRef responseBytes = CFDataCreateMutable(kCFAllocatorDefault, 0);
CFIndex numberOfBytesRead = 0;
do
{
UInt8 buf[1024];
numberOfBytesRead = CFReadStreamRead(readStream, buf, sizeof(buf));
if (numberOfBytesRead > 0)
{
CFDataAppendBytes(responseBytes, buf, numberOfBytesRead);
}
} while (numberOfBytesRead > 0);
//once all data is appended, package it all together - create a response from the response headers, and add the data received.
//note: just having the data received is not enough, you need to finish the response by retrieving the response headers here...
CFHTTPMessageRef response = (CFHTTPMessageRef)CFReadStreamCopyProperty(readStream, kCFStreamPropertyHTTPResponseHeader);
if (responseBytes)
{
if (response)
{
CFHTTPMessageSetBody(response, responseBytes);
}
CFRelease(responseBytes);
}
//close and cleanup
CFReadStreamClose(readStream);
CFReadStreamUnscheduleFromRunLoop(readStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
CFRelease(readStream);
//just keep the response body and release requests
CFDataRef responseBodyData = CFHTTPMessageCopyBody(response);
if (response)
{
CFRelease(response);
}
//get the response as a string
if (responseBodyData)
{
CFShow(CFSTR("\nResponse Data:"));
LogData(responseBodyData);
CFRelease(responseBodyData);
}
}
I understood how it works, and started implementing it ..... only to get this error:
'CFReadStreamCreateForHTTPRequest' is deprecated: first deprecated in
macOS 10.11 - Use NSURLSession API for http requests
There's absolutely zero examples how to use NSURLSession for C++, or how to bypass that idiotic "is deprecated" error.
Any help on how am I supposed to code this in C++ now?
PS. I don't want to use any third-party libraries. This is a simple task that was available with simple API calls (as I showed above.)
PS2. Sorry I am not an Apple developer, and I'm not used to features being deprecated on the whim.
There are 3 options.
Ignore the warning.
Use ObjC runtme.
Use libcurl
The first one is the easiest and the second one is the hardest solutions for your skills. The third option is easy and the most advanced solution - if you extend you software with new features, CFNetwork will lack of functionality.

how do i process Flux<Object> returned by webflux at client side in plain java code

I have written a webservice using spring webflux and reactive mongodb connectors, but my client side could be non spring based client.
So, how do I write a plain java code to consume flex at client side?
ServerSide code:
#GetMapping(value = "/findAll")
public Flux<Security> findAll() {
Flux<Security> flux = service.findAll();
return flux;
}
Client side code:
public static void sendRequest() {
try {
long start = System.currentTimeMillis();
for (int i = 0; i <= 100; i++) {
long start1 = System.currentTimeMillis();
URL url = new URL("http://localhost:8080/findAll/");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept", "application/stream+json");
if (conn.getResponseCode() == 200) {
// url = new URL("http://localhost:8182/status/");
String json = "";
try (BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())))) {
json = br.lines().collect(Collectors.joining());
}
conn.disconnect();
System.out.println("size of each Security: " + json.length());
ArrayList<Security> list = getListOfsecurities(json);
System.out.println(list.get(0).getIsin());
}
}
The above client side gives me an empty array.
I don't think it is possible. It's an asynchronous response.At least you have to use Java 5 Futures to invoke asynchronous response.

Multiple USB to RS485 FTDI Device ID

I need some help. I'm programming a Win 10 App in C++/CX. I am using two USB to RS485 devices, both of which have the same VID number. In days of old, I could write a bit software and connect to ports using good old COMx etc.
I'm now following the example here Serial Sample which uses the approach gathering the device info so when looking for connected devices, what I see in the list of available devices is the following.
\?\FTDIBUS#VID_0403+PID_6001
Both devices have the same VID and PID. This leads to the problem of me being cable to connect to the correct USB device. I think my app is trying to connect to both devices at the same time? Does anyone have any ideas about how I can resolve this hitch?
void MainPage::Get_Serial_Devices() {
cancellationTokenSource_Port1 = new Concurrency::cancellation_token_source();
cancellationTokenSource_Port2 = new Concurrency::cancellation_token_source();
// THIS USES ASYNCRONOUS OPERATION. GET A LIST OF SERIAL DEVICES AND POPULATE THE COMBO BOX
Concurrency::create_task(ListAvailablePortsAsync()).then([this](DeviceInformationCollection^ serialDeviceCollectioin)
{
// serialDeviceCollection CONTAINS ALL SERIAL DEVICES FOUND, COPY INTO _deviceCollection
DeviceInformationCollection^ _deviceCollection = serialDeviceCollectioin;
// CLEAR EXISTING DEVICES FOR OUR OBJECT COLLECTION
_availableDevices->Clear();
// FOR EVERY DEVICE IN _deviceCollection
for (auto &&device : _deviceCollection) {
if (device->Name->Equals("USB-RS485 Cable")) {
// CREATE A NEW DEVICE TYPE AND APPEND TO OUR OBJECT COLLECTION
_availableDevices->Append(ref new Device(device->Id, device));
Total_Ports++;
this->DeviceLists->Items->Append(device->Id);
}
}
});
void MainPage::ConnectButton_Click(Object^ sender, RoutedEventArgs^ e) {
if (Port1_Connected == false) {
// CAST INDEX TO CORRELATING Device IN _availableDevices
Device^ selectedDevice = static_cast<Device^>(_availableDevices->GetAt(Port_1_ID));
// GET THE DEVICE INFO
DeviceInformation^ entry = selectedDevice->DeviceInfo;
Concurrency::create_task(ConnectToSerialDeviceAsync_Port1(entry, cancellationTokenSource_Port1->get_token())).then([this]( ) {
Get_Echo();
Waiting_For_Ack = true;
});
}
Concurrency::task<void> MainPage::ConnectToSerialDeviceAsync_Port1(DeviceInformation^ device, Concurrency::cancellation_token cancellationToken) {
// CREATE A LINKED TOKEN WHICH IS CANCELLED WHEN THE PROVIDED TOKEN IS CANCELLED
auto childTokenSource = Concurrency::cancellation_token_source::create_linked_source(cancellationToken);
// GET THE TOKEN
auto childToken = childTokenSource.get_token();
// CONNECT TO ARDUINO TASK
return Concurrency::create_task(SerialDevice::FromIdAsync(device->Id), childToken).then([this](SerialDevice^ serial_device) {
try {
_serialPort_Port1 = serial_device;
TimeSpan _timeOut; _timeOut.Duration = 10;
// CONFIGURE SERIAL PORT SETTINGS
_serialPort_Port1->WriteTimeout = _timeOut;
_serialPort_Port1->ReadTimeout = _timeOut;
_serialPort_Port1->BaudRate = 57600;
_serialPort_Port1->Parity = Windows::Devices::SerialCommunication::SerialParity::None;
_serialPort_Port1->StopBits = Windows::Devices::SerialCommunication::SerialStopBitCount::One;
_serialPort_Port1->DataBits = 8;
_serialPort_Port1->Handshake = Windows::Devices::SerialCommunication::SerialHandshake::None;
// CREATE OUR DATA READER OBJECT
_dataReaderObject_Port1 = ref new DataReader(_serialPort_Port1->InputStream);
_dataReaderObject_Port1->InputStreamOptions = InputStreamOptions::None;
// CREATE OUR DATA WRITE OBJECT
_dataWriterObject_Port1 = ref new DataWriter(_serialPort_Port1->OutputStream);
this->ConnectButton->IsEnabled = false;
this->DisconnectButton->IsEnabled = true;
// KICK OF THE SERIAL PORT LISTENING PROCESS
Listen_Port1();
}
catch (Platform::Exception^ ex) {
this->Error_Window->Text = (ex->Message);
CloseDevice(PORT_1);
}
});
FT_PROG is a free EEPROM programming utility for use with FTDI devices. It is used for modifying EEPROM contents that store the FTDI device descriptors to customize designs.
The full FT_PROG User Guide can be downloaded here.

how to set time of web service in windows phone

i have a web service.
it takes 10-15 seconds to upload completely. But some time due to slow internet connection it takes more than 15 second.
I want to open a message box or pop up box which open when the service takes more than 15 seconds, to display message "Slow Internet Connection".
How can i add timer in my code so that a pop up block open(Or alert says Slow Connection) on page load event when web service takes time more than 15 second to load ?
Please help me on this...
public Quiz()
{
InitializeComponent();
DispatchTimer timer = new DispatcherTimer();
int serviceCount = 15;
Loaded += Quiz_Loaded;
}
protected void Quiz_Loaded(object sender, RoutedEventArgs e)
{
SystemTray.ProgressIndicator = new ProgressIndicator();
SystemTray.ProgressIndicator.IsIndeterminate = true;
SystemTray.ProgressIndicator.IsVisible = true;
SystemTray.ProgressIndicator.Text = "Loading Questions...";
pg2.Visibility = Visibility.Visible;
txtloading.Visibility = Visibility.Visible;
if (!timer.IsEnabled)
{
timer.Tick += timer_Tick;
timer.Interval = new TimeSpan(0, 0, 1);
timer.Start();
}
}
void timer_Tick(object sender, object e)
{
serviceCount--;
if (serviceCount < 15)
{
PostData();
}
else
{
txtloading.Text = "slow connection.....";
}
}
private void PostData()
{
Uri uri = new Uri("my web service url");
string data = "device_id=test123&quiz_type=all";
WebClient wc = new WebClient();
wc.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
wc.UploadStringAsync(uri, data);
wc.UploadStringCompleted += wc_UploadComplete;
}
public void wc_UploadComplete(object sender, UploadStringCompletedEventArgs e)
{
var rootObject = JsonConvert.DeserializeObject<RootObject>(e.Result);
question = rootObject.questions;
DisplayQuestion();
SystemTray.ProgressIndicator.IsVisible = false;
pg2.Visibility = Visibility.Collapsed;
txtloading.Visibility = Visibility.Collapsed;
}
i want to call message block when web service takes time more than 15 second. & also have a retry button which reload the page again to get all data from service..
You could use a DispatcherTimer that is initialized whenever the first call to the web service is initiated. That way, whenever a given timespan elapses, you can trigger a custom action (such as a notification).

Why does SQL Server CLR procedure hang in GetResponse() call to web service

Environment: C#, .Net 3.5, Sql Server 2005
I have a method that works in a stand-alone C# console application project. It creates an XMLElement from data in the database and uses a private method to send it to a web service on our local network. When run from VS in this test project, it runs in < 5 seconds.
I copied the class into a CLR project, built it, and installed it in SQL Server (WITH PERMISSION_SET = EXTERNAL_ACCESS). The only difference is the SqlContext.Pipe.Send() calls that I added for debugging.
I am testing it by using an EXECUTE command one stored procedure (in the CLR) from an SSMS query window. It never returns. When I stop execution of the call after a minute, the last thing displayed is "Calling GetResponse() using http://servername:53694/odata.svc/Customers/". Any ideas as to why the GetResponse() call doesn't return when executing within SQL Server?
private static string SendPost(XElement entry, SqlString url, SqlString entityName)
{
// Send the HTTP request
string serviceURL = url.ToString() + entityName.ToString() + "/";
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(serviceURL);
request.Method = "POST";
request.Accept = "application/atom+xml,application/xml";
request.ContentType = "application/atom+xml";
request.Timeout = 20000;
request.Proxy = null;
using (var writer = XmlWriter.Create(request.GetRequestStream()))
{
entry.WriteTo(writer);
}
try
{
SqlContext.Pipe.Send("Calling GetResponse() using " + request.RequestUri);
WebResponse response = request.GetResponse();
SqlContext.Pipe.Send("Back from GetResponse()");
/*
string feedData = string.Empty;
Stream stream = response.GetResponseStream();
using (StreamReader streamReader = new StreamReader(stream))
{
feedData = streamReader.ReadToEnd();
}
*/
HttpStatusCode StatusCode = ((HttpWebResponse)response).StatusCode;
response.Close();
if (StatusCode == HttpStatusCode.Created /* 201 */ )
{
return "Created # Location= " + response.Headers["Location"];
}
return "Creation failed; StatusCode=" + StatusCode.ToString();
}
catch (WebException ex)
{
return ex.Message.ToString();
}
finally
{
if (request != null)
request.Abort();
}
}
The problem turned out to be the creation of the request content from the XML. The original:
using (var writer = XmlWriter.Create(request.GetRequestStream()))
{
entry.WriteTo(writer);
}
The working replacement:
using (Stream requestStream = request.GetRequestStream())
{
using (var writer = XmlWriter.Create(requestStream))
{
entry.WriteTo(writer);
}
}
You need to dispose the WebResponse. Otherwise, after a few calls it goes to timeout.
You are asking for trouble doing this in the CLR. And you say you are calling this from a trigger? This belongs in the application tier.
Stuff like this is why when the CLR functionality came out, DBAs were very concerned about how it would be misused.