Skip to content

Commit

Permalink
Add sample DxFeedSample
Browse files Browse the repository at this point in the history
  • Loading branch information
Montura committed Dec 13, 2023
1 parent 730dfb4 commit 6e783d8
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 0 deletions.
36 changes: 36 additions & 0 deletions src/main/c/samples/DxFeedSample/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
cmake_minimum_required(VERSION 3.15)
project(DxFeedSample)
enable_language(CXX)
set(CMAKE_CXX_STANDARD 14)

set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "valid configurations" FORCE)

if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif ()

message("--- DxFeedSample sample --- ")

# Specify include directory where to find API headers
include(../../cmake/FindJava.cmake)
include_directories(${PROJECT_NAME} INTERFACE ../../jni-lib/include)

# Specify a directory where to build
set(OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/build)
include(../../cmake/SetupOutputDirectory.cmake)

# Add source for our sample
add_executable(${PROJECT_NAME}
main.cpp
)

# Include common cmake file to find Java, specify linkage directory where to find and link
# DxFeedJniNativeSdk.dylib|dll|.so as SHARED dependency
include(../../cmake/FindJniNativeSdk.cmake)
link_lib_from_dir(${OUTPUT_PATH})

# Link DxFeedJniNativeSdk.dylib|dll|.so to our executable
target_link_libraries(${PROJECT_NAME} DX_FEED_JNI_NATIVE_SDK)

# Specify target compile options (e.g.: RPATH for MacOS executables fo find .dylib on app startup
specify_target_compile_options()
2 changes: 2 additions & 0 deletions src/main/c/samples/DxFeedSample/build_release.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release
cmake --build build --config Release --verbose
2 changes: 2 additions & 0 deletions src/main/c/samples/DxFeedSample/build_release.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release
cmake --build build --config Release --verbose
2 changes: 2 additions & 0 deletions src/main/c/samples/DxFeedSample/dxfeed.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Connection address for an endpoint with role Feed and OnDemandFeed.
dxfeed.address=demo.dxfeed.com:7300
128 changes: 128 additions & 0 deletions src/main/c/samples/DxFeedSample/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// SPDX-License-Identifier: MPL-2.0

#include <cstdio>
#include <iostream>
#include <thread>
#include <chrono>

#include "api/dxfg_api.h"

void printUsage() {
std::cout <<
"Usage:" << std::endl <<
"DxFeedSample <symbol>" << std::endl << std::endl <<

"Where:" << std::endl <<
" symbol - Is security symbol (e.g. IBM, AAPL, SPX etc.)." << std::endl;
}

void c_print(const char* listenerPrefix, const dxfg_event_type_t* pEvent){
if (pEvent && pEvent->clazz == DXFG_EVENT_QUOTE) {
auto quote = reinterpret_cast<const dxfg_quote_t*>(pEvent);
printf(
"%s: QUOTE{event_symbol=%s, bid_price=%f, bid_time=%lld, ask_price=%f, ask_time=%lld}\n",
listenerPrefix,
quote->market_event.event_symbol,
quote->bid_price,
quote->bid_time,
quote->ask_price,
quote->ask_time);
}
if (pEvent && pEvent->clazz == DXFG_EVENT_TRADE) {
auto trade = reinterpret_cast<const dxfg_trade_t*>(pEvent);
printf(
"%s: Trade{event_symbol=%s, price=%f, change=%f, day_volume=%f, day_turnover=%f}\n",
listenerPrefix,
trade->trade_base.market_event.event_symbol,
trade->trade_base.price,
trade->trade_base.change,
trade->trade_base.day_volume,
trade->trade_base.day_turnover);
}
}

struct Resources {
dxfg_subscription_t* subscription = nullptr;
dxfg_feed_event_listener_t* listener = nullptr;
};

void clear_resources(graal_isolatethread_t* thread, const Resources& resources){
dxfg_DXFeedSubscription_close(thread, resources.subscription);
dxfg_JavaObjectHandler_release(thread, &resources.listener->handler);
dxfg_JavaObjectHandler_release(thread, &resources.subscription->handler);
}

Resources testQuoteListener(graal_isolatethread_t* thread, dxfg_string_symbol_t& symbol) {
// Create feed and subscription with specified types attached to feed.
auto feed = dxfg_DXFeed_getInstance(thread);

dxfg_subscription_t* subscription = dxfg_DXFeed_createSubscription(thread, feed, DXFG_EVENT_QUOTE);

auto worker = [](graal_isolatethread_t* thread, dxfg_event_type_list* events, void* user_data) {
for (int i = 0; i < events->size; ++i) {
c_print("QuoteListener", events->elements[i]);
}
};

dxfg_feed_event_listener_t* listener = dxfg_DXFeedEventListener_new(thread, worker, nullptr);
dxfg_DXFeedSubscription_addEventListener(thread, subscription, listener);

dxfg_DXFeedSubscription_setSymbol(thread, subscription, &symbol.supper);

return Resources { subscription, listener};
}

Resources testQuoteAndTradeListener(graal_isolatethread_t* thread, dxfg_string_symbol_t& symbol) {
auto feed = dxfg_DXFeed_getInstance(thread);

auto* list = new dxfg_event_clazz_list_t[2];
list->size = 2;
list->elements = new dxfg_event_clazz_t*[2];
list->elements[0] = new dxfg_event_clazz_t(DXFG_EVENT_QUOTE);
list->elements[1] = new dxfg_event_clazz_t(DXFG_EVENT_TRADE);
dxfg_subscription_t* subscription = dxfg_DXFeed_createSubscription2(thread, feed, list);

auto worker = [](graal_isolatethread_t* thread, dxfg_event_type_list* events, void* user_data) {
for (int i = 0; i < events->size; ++i) {
c_print("QuoteOrTradeListener", events->elements[i]);
}
};

dxfg_feed_event_listener_t* listener = dxfg_DXFeedEventListener_new(thread, worker, nullptr);
dxfg_DXFeedSubscription_addEventListener(thread, subscription, listener);

dxfg_DXFeedSubscription_setSymbol(thread, subscription, &symbol.supper);

return Resources { subscription, listener};
}

int main(int argc, char** argv) {
if (argc < 2) {
printUsage();
return -1;
}

// Get args from console.
const auto symbol = argv[1]; // "AAPL";

// Create STRING symbol.
dxfg_string_symbol_t stringSymbol;
stringSymbol.supper.type = STRING;
stringSymbol.symbol = symbol;

// Create thread on which all the work will be executed.
auto thread = create_thread();
if (thread == nullptr) {
return -1;
}

const Resources& resources1 = testQuoteListener(thread, stringSymbol);
const Resources& resources2 = testQuoteAndTradeListener(thread, stringSymbol);

// Sleep 10 seconds waiting for the response about Quotes.
std::chrono::seconds seconds(10);
std::this_thread::sleep_for(seconds);

clear_resources(thread, resources1);
clear_resources(thread, resources2);
}

0 comments on commit 6e783d8

Please sign in to comment.