Skip to content

Commit

Permalink
[MDAPI-38][C++] Add DxFeedMarketDepth sample (#65)
Browse files Browse the repository at this point in the history
  • Loading branch information
AnatolyKalin authored Dec 12, 2024
2 parents 4848385 + bc7749e commit f12b270
Show file tree
Hide file tree
Showing 37 changed files with 1,502 additions and 414 deletions.
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,7 @@ if (DXFCXX_BUILD_UNIT_TESTS)
endif ()

if (DXFCXX_BUILD_SAMPLES)
add_subdirectory(samples/cpp/AuthSample)
add_subdirectory(samples/cpp/PrintQuoteEvents)
add_subdirectory(samples/cpp/PublishProfiles)
add_subdirectory(samples/cpp/DxFeedSample)
Expand All @@ -569,6 +570,9 @@ if (DXFCXX_BUILD_SAMPLES)
add_subdirectory(samples/cpp/DxFeedLiveIpfSample)
add_subdirectory(samples/cpp/ScheduleSample)
add_subdirectory(samples/cpp/OnDemandSample)
add_subdirectory(samples/cpp/ReconnectSample)
add_subdirectory(samples/cpp/IncOrderSnapshotSample)
add_subdirectory(samples/cpp/MultipleMarketDepthSample)
endif ()

add_subdirectory(docs)
Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ be downloaded from [Release](https://github.com/dxFeed/dxfeed-graal-cxx-api/rele

### API

- [ ] [AuthSample](samples/cpp/AuthSample/src/main.cpp)
- [x] [AuthSample](samples/cpp/AuthSample/src/main.cpp)
demonstrates how to connect to an endpoint that requires an authentication token,
subscribe to market data events, and handle periodic token updates
- [x] [ConnectSample](samples/cpp/DxFeedConnect/src/main.cpp)
Expand All @@ -346,7 +346,7 @@ be downloaded from [Release](https://github.com/dxFeed/dxfeed-graal-cxx-api/rele
and `dxfeed.properties` file
- [x] [QuoteAndTradeSample](samples/cpp/DxFeedSample/src/main.cpp)
demonstrates how to create multiple event listeners and subscribe to `Quote` and `Trade` events
- [ ] [ReconnectSample](samples/cpp/ReconnectSample/src/main.cpp)
- [x] [ReconnectSample](samples/cpp/ReconnectSample/src/main.cpp)
demonstrates how to connect to an endpoint, subscribe to market data events, handle reconnections
and re-subscribing

Expand Down Expand Up @@ -387,9 +387,9 @@ be downloaded from [Release](https://github.com/dxFeed/dxfeed-graal-cxx-api/rele

### Model

- [ ] [IncOrderSnapshotSample](samples/cpp/IncOrderSnapshotSample/src/main.cpp)
- [x] [IncOrderSnapshotSample](samples/cpp/IncOrderSnapshotSample/src/main.cpp)
demonstrates how to subscribe to the Order event and handle snapshots and updates
- [ ] [MultipleMarketDepthSample](samples/cpp/MultipleMarketDepthSample/src/main.cpp)
- [x] [MultipleMarketDepthSample](samples/cpp/MultipleMarketDepthSample/src/main.cpp)
demonstrates how to use the `MarketDepthModel` to manage and display order books for multiple symbols

### Schedule
Expand All @@ -405,9 +405,9 @@ be downloaded from [Release](https://github.com/dxFeed/dxfeed-graal-cxx-api/rele
### UI

- [ ] [MarketDepthModelSample](samples/cpp/MarketDepthModelSample/src/main.cpp)
demonstrates how to draw a Market Depth using Avalonia UI
demonstrates how to draw a Market Depth.
- [ ] [CandleChartSample](samples/cpp/CandleChartSample/src/main.cpp)
demonstrates how to draw a Candlestick Chart using Avalonia UI
demonstrates how to draw a Candlestick Chart.
- [ ] [PriceLevelBookSample](samples/cpp/PriceLevelBookSample/src/main.cpp)
demonstrates how to compile a price level book (market by price) that aggregates individual orders
(market by order)
Expand Down
3 changes: 3 additions & 0 deletions include/dxfeed_graal_cpp_api/api.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4996)
#include "internal/StopWatch.hpp"
#include "internal/Timer.hpp"
#include "internal/TimeFormat.hpp"
#include "internal/Handler.hpp"

#include "internal/context/ApiContext.hpp"

Expand Down Expand Up @@ -49,6 +50,8 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251 4996)
#include "model/TxModelListener.hpp"
#include "model/IndexedTxModel.hpp"
#include "model/TimeSeriesTxModel.hpp"
#include "model/MarketDepthModelListener.hpp"
#include "model/MarketDepthModel.hpp"

#include "exceptions/RuntimeException.hpp"
#include "exceptions/InvalidArgumentException.hpp"
Expand Down
8 changes: 4 additions & 4 deletions include/dxfeed_graal_cpp_api/api/DXFeed.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ DXFCPP_BEGIN_NAMESPACE

struct DXEndpoint;
class EventTypeEnum;
struct IndexedTxModel;
struct TimeSeriesTxModel;
struct IndexedTxModelImpl;
struct TimeSeriesTxModelImpl;

/**
* Main entry class for dxFeed API (<b>read it first</b>).
Expand Down Expand Up @@ -122,8 +122,8 @@ struct DXFCPP_EXPORT DXFeed : SharedEntity {
using Unique = std::unique_ptr<DXFeed>;

friend struct DXEndpoint;
friend struct IndexedTxModel;
friend struct TimeSeriesTxModel;
friend struct TimeSeriesTxModelImpl;
friend struct IndexedTxModelImpl;

private:
JavaObjectHandle<DXFeed> handle_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#pragma once

#include "../../internal/Conf.hpp"
#include "dxfeed_graal_cpp_api/symbols/SymbolWrapper.hpp"

DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251)

Expand Down Expand Up @@ -39,6 +40,8 @@ struct SymbolWrapper;
class DXFCPP_EXPORT IndexedEventSubscriptionSymbol {
friend SymbolWrapper;

//struct Impl;

std::unique_ptr<SymbolWrapper> eventSymbol_;
std::unique_ptr<IndexedEventSource> source_;

Expand Down Expand Up @@ -117,11 +120,9 @@ class DXFCPP_EXPORT IndexedEventSubscriptionSymbol {

DXFCPP_END_NAMESPACE

template <> struct DXFCPP_EXPORT std::hash<dxfcpp::IndexedEventSubscriptionSymbol> {
std::size_t
operator()(const dxfcpp::IndexedEventSubscriptionSymbol &indexedEventSubscriptionSymbol) const noexcept {
return std::hash<std::unique_ptr<dxfcpp::SymbolWrapper>>{}(indexedEventSubscriptionSymbol.getEventSymbol()) +
std::hash<dxfcpp::IndexedEventSource>{}(*indexedEventSubscriptionSymbol.getSource()) * 31;
template <> struct std::hash<dxfcpp::IndexedEventSubscriptionSymbol> {
std::size_t operator()(const dxfcpp::IndexedEventSubscriptionSymbol &indexedEventSubscriptionSymbol) const noexcept {
return std::hash<std::string>{}(indexedEventSubscriptionSymbol.toString());
}
};

Expand Down
23 changes: 15 additions & 8 deletions include/dxfeed_graal_cpp_api/entity/SharedEntity.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251)
#include "../internal/Common.hpp"

#include <memory>
#include <vector>
#include <string>
#include <vector>

#include "Entity.hpp"

Expand Down Expand Up @@ -78,19 +78,26 @@ struct DXFCPP_EXPORT SharedEntity : public Entity, std::enable_shared_from_this<

DXFCXX_DISABLE_GCC_WARNINGS_PUSH("-Wvirtual-move-assign")

template <typename T>
struct RequireMakeShared : virtual SharedEntity {
/**
* A helper class needed to construct smart pointers to objects, and does not allow explicit construction of objects.
* @tparam T The object type.
*/
template <typename T> struct RequireMakeShared : virtual SharedEntity {
protected:

struct LockExternalConstructionTag {
explicit LockExternalConstructionTag() = default;
};

public:

template <typename... Args>
static auto createShared(Args&&... args) {
static_assert(std::is_convertible_v<T*, RequireMakeShared*>, "Must derive publicly from RequireMakeShared");
/**
* Creates smart pointer to object.
*
* @tparam Args Types or arguments.
* @param args The arguments.
* @return A new smart pointer to object.
*/
template <typename... Args> static auto createShared(Args &&...args) {
static_assert(std::is_convertible_v<T *, RequireMakeShared *>, "Must derive publicly from RequireMakeShared");

return std::make_shared<T>(LockExternalConstructionTag{}, std::forward<Args>(args)...);
}
Expand Down
71 changes: 68 additions & 3 deletions include/dxfeed_graal_cpp_api/event/EventFlag.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ DXFCPP_BEGIN_NAMESPACE
* It can be retrieved from `eventFlags` with the following piece of code:
*
* ```cpp
* bool txPending = (event-> getEventFlags() & IndexedEvent::TX_PENDING) != 0;
* bool txPending = (event->getEventFlags() & IndexedEvent::TX_PENDING) != 0;
* ```
*
* <p>When `txPending` is `true` it means, that an ongoing transaction update that spans multiple events is
Expand All @@ -56,13 +56,13 @@ DXFCPP_BEGIN_NAMESPACE
* corresponding index has to be removed.
*
* ```cpp
* bool removeEvent = (event-> getEventFlags() & IndexedEvent::REMOVE_EVENT) != 0;
* bool removeEvent = (event->getEventFlags() & IndexedEvent::REMOVE_EVENT) != 0;
* ```
*
* <p> `SB` (bit 2) &mdash; ::SNAPSHOT_BEGIN is used to indicate when the loading of a snapshot starts.
*
* ```cpp
* bool snapshotBegin = (event-> getEventFlags() & IndexedEvent::SNAPSHOT_BEGIN) != 0;
* bool snapshotBegin = (event->getEventFlags() & IndexedEvent::SNAPSHOT_BEGIN) != 0;
* ```
*
* <p> Snapshot load starts on new subscription and the first indexed event that arrives for each non-zero source id
Expand Down Expand Up @@ -316,6 +316,71 @@ class DXFCPP_EXPORT EventFlag final {
friend std::uint32_t operator&(std::uint32_t eventFlag1, const EventFlag &eventFlag2) noexcept {
return dxfcpp::andOp(eventFlag1, eventFlag2.getFlag());
}

/**
* Determines if the given event marks the beginning of a snapshot.
*
* @tparam Event The event's type.
* @param event The event to be checked.
* @return `true` if the event flags indicate the beginning of a snapshot, `false` otherwise.
*/
template <typename Event> static bool isSnapshotBegin(const std::shared_ptr<Event> &event) {
return (event->getEventFlags() & SNAPSHOT_BEGIN) != 0;
}

/**
* Determines if the given event marks the end of a snapshot.
*
* @tparam Event The event's type.
* @param event The event to be checked.
* @return `true` if the event flags indicate the end of a snapshot, `false` otherwise.
*/
template <typename Event> static bool isSnapshotEnd(const std::shared_ptr<Event> &event) {
return (event->getEventFlags() & SNAPSHOT_END) != 0;
}

/**
* Determines if the given event is marked as a snapshot snip.
*
* @tparam Event The event's type.
* @param event The event to be checked.
* @return `true` if the event flags indicate a snapshot snip, `false` otherwise.
*/
template <typename Event> static bool isSnapshotSnip(const std::shared_ptr<Event> &event) {
return (event->getEventFlags() & SNAPSHOT_SNIP) != 0;
}

/**
* Determines if the given event marks the end of a snapshot or a snapshot snip.
* @tparam Event The event's type.
* @param event The event to be checked.
* @return `true` if the event flags indicate the end or snip of a snapshot, `false` otherwise.
*/
template <typename Event> static bool isSnapshotEndOrSnip(const std::shared_ptr<Event> &event) {
return isSnapshotEnd(event) || isSnapshotSnip(event);
}

/**
* Determines if the given event is in a pending state.
*
* @tparam Event The event's type.
* @param event The event to be checked.
* @return `true` if the event flags indicate a pending transaction, `false` otherwise.
*/
template <typename Event> static bool isPending(const std::shared_ptr<Event> &event) {
return (event->getEventFlags() & TX_PENDING) != 0;
}

/**
* Determines if the given event is marked for removal.
*
* @tparam Event The event's type.
* @param event The event to be checked.
* @return `true` if the event flags indicate a remove action, `false` otherwise.
*/
template <typename Event> static bool isRemove(const std::shared_ptr<Event> &event) {
return (event->getEventFlags() & REMOVE_EVENT) != 0;
}
};

DXFCPP_END_NAMESPACE
Expand Down
8 changes: 8 additions & 0 deletions include/dxfeed_graal_cpp_api/internal/JavaObjectHandle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ DXFCXX_DISABLE_MSC_WARNINGS_PUSH(4251)

DXFCPP_BEGIN_NAMESPACE

struct DXFCPP_EXPORT JavaObject {
static std::string toString(void* handle);

static std::size_t hashCode(void* handle);

static bool equals(void* objectHandle1, void* objectHandle2);
};

template <typename T> struct JavaObjectHandle {
#if DXFCPP_DEBUG == 1
static std::string getDebugName() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,72 +25,72 @@ namespace isolated::model::IsolatedIndexedTxModel {

// dxfg_indexed_tx_model_builder_t* dxfg_IndexedTxModel_newBuilder(graal_isolatethread_t* thread, dxfg_event_clazz_t
// eventType);
JavaObjectHandle<IndexedTxModel::Builder> newBuilder(const EventTypeEnum &eventType);
JavaObjectHandle<IndexedTxModelBuilderTag> newBuilder(const EventTypeEnum &eventType);

// dxfg_indexed_event_source_list* dxfg_IndexedTxModel_getSources(graal_isolatethread_t* thread,
// dxfg_indexed_tx_model_t* source);
void *getSources(const JavaObjectHandle<IndexedTxModel> &model);
void *getSources(const JavaObjectHandle<IndexedTxModelTag> &model);

// int32_t dxfg_IndexedTxModel_setSources(graal_isolatethread_t* thread, dxfg_indexed_tx_model_t* source,
// dxfg_indexed_event_source_list* sources);
void setSources(const JavaObjectHandle<IndexedTxModel> &model, void *sources);
void setSources(const JavaObjectHandle<IndexedTxModelTag> &model, void *sources);

// int32_t dxfg_IndexedTxModel_isBatchProcessing(graal_isolatethread_t* thread, dxfg_indexed_tx_model_t* source);
bool isBatchProcessing(const JavaObjectHandle<IndexedTxModel> &model);
bool isBatchProcessing(const JavaObjectHandle<IndexedTxModelTag> &model);

// int32_t dxfg_IndexedTxModel_isSnapshotProcessing(graal_isolatethread_t* thread, dxfg_indexed_tx_model_t* source);
bool isSnapshotProcessing(const JavaObjectHandle<IndexedTxModel> &model);
bool isSnapshotProcessing(const JavaObjectHandle<IndexedTxModelTag> &model);

// int32_t dxfg_IndexedTxModel_attach(graal_isolatethread_t* thread, dxfg_indexed_tx_model_t* source, dxfg_feed_t*
// feed);
void attach(const JavaObjectHandle<IndexedTxModel> &model, const JavaObjectHandle<DXFeed> &feed);
void attach(const JavaObjectHandle<IndexedTxModelTag> &model, const JavaObjectHandle<DXFeed> &feed);

// int32_t dxfg_IndexedTxModel_detach(graal_isolatethread_t* thread, dxfg_indexed_tx_model_t* source, dxfg_feed_t*
// feed);
void detach(const JavaObjectHandle<IndexedTxModel> &model, const JavaObjectHandle<DXFeed> &feed);
void detach(const JavaObjectHandle<IndexedTxModelTag> &model, const JavaObjectHandle<DXFeed> &feed);

// int32_t dxfg_IndexedTxModel_close(graal_isolatethread_t* thread, dxfg_indexed_tx_model_t* source);
void close(const JavaObjectHandle<IndexedTxModel> &model);
void close(const JavaObjectHandle<IndexedTxModelTag> &model);

namespace Builder {

// dxfg_indexed_tx_model_builder_t* dxfg_IndexedTxModel_Builder_withSources(graal_isolatethread_t* thread,
// dxfg_indexed_tx_model_builder_t* source, dxfg_indexed_event_source_list* sources);
JavaObjectHandle<IndexedTxModel::Builder> withSources(const JavaObjectHandle<IndexedTxModel::Builder> &builder,
JavaObjectHandle<IndexedTxModelBuilderTag> withSources(const JavaObjectHandle<IndexedTxModelBuilderTag> &builder,
void *sources);

// dxfg_indexed_tx_model_t* dxfg_IndexedTxModel_Builder_build(graal_isolatethread_t* thread,
// dxfg_indexed_tx_model_builder_t* source);
JavaObjectHandle<IndexedTxModel> build(const JavaObjectHandle<IndexedTxModel::Builder> &builder);
JavaObjectHandle<IndexedTxModelTag> build(const JavaObjectHandle<IndexedTxModelBuilderTag> &builder);

// dxfg_indexed_tx_model_builder_t* dxfg_IndexedTxModel_Builder_withBatchProcessing(graal_isolatethread_t* thread,
// dxfg_indexed_tx_model_builder_t* source, int32_t isBatchProcessing);
JavaObjectHandle<IndexedTxModel::Builder> withBatchProcessing(const JavaObjectHandle<IndexedTxModel::Builder> &builder,
JavaObjectHandle<IndexedTxModelBuilderTag> withBatchProcessing(const JavaObjectHandle<IndexedTxModelBuilderTag> &builder,
bool isBatchProcessing);

// dxfg_indexed_tx_model_builder_t* dxfg_IndexedTxModel_Builder_withSnapshotProcessing(graal_isolatethread_t* thread,
// dxfg_indexed_tx_model_builder_t* source, int32_t isSnapshotProcessing);
JavaObjectHandle<IndexedTxModel::Builder>
withSnapshotProcessing(const JavaObjectHandle<IndexedTxModel::Builder> &builder, bool isSnapshotProcessing);
JavaObjectHandle<IndexedTxModelBuilderTag>
withSnapshotProcessing(const JavaObjectHandle<IndexedTxModelBuilderTag> &builder, bool isSnapshotProcessing);

// dxfg_indexed_tx_model_builder_t* dxfg_IndexedTxModel_Builder_withFeed(graal_isolatethread_t* thread,
// dxfg_indexed_tx_model_builder_t* source, dxfg_feed_t* feed);
JavaObjectHandle<IndexedTxModel::Builder> withFeed(const JavaObjectHandle<IndexedTxModel::Builder> &builder,
JavaObjectHandle<IndexedTxModelBuilderTag> withFeed(const JavaObjectHandle<IndexedTxModelBuilderTag> &builder,
const JavaObjectHandle<DXFeed> &feed);

// dxfg_indexed_tx_model_builder_t* dxfg_IndexedTxModel_Builder_withSymbol(graal_isolatethread_t* thread,
// dxfg_indexed_tx_model_builder_t* source, dxfg_symbol_t* symbol);
JavaObjectHandle<IndexedTxModel::Builder> withSymbol(const JavaObjectHandle<IndexedTxModel::Builder> &builder,
JavaObjectHandle<IndexedTxModelBuilderTag> withSymbol(const JavaObjectHandle<IndexedTxModelBuilderTag> &builder,
const SymbolWrapper &symbol);

// dxfg_indexed_tx_model_builder_t* dxfg_IndexedTxModel_Builder_withListener(graal_isolatethread_t* thread,
// dxfg_indexed_tx_model_builder_t* source, dxfg_tx_model_listener_t* listener);
JavaObjectHandle<IndexedTxModel::Builder> withListener(const JavaObjectHandle<IndexedTxModel::Builder> &builder,
JavaObjectHandle<IndexedTxModelBuilderTag> withListener(const JavaObjectHandle<IndexedTxModelBuilderTag> &builder,
const JavaObjectHandle<TxModelListenerTag> &listener);

// dxfg_indexed_tx_model_builder_t* dxfg_IndexedTxModel_Builder_withExecutor(graal_isolatethread_t* thread,
// dxfg_indexed_tx_model_builder_t* source, dxfg_executor_t* executor);
JavaObjectHandle<IndexedTxModel::Builder> withExecutor(const JavaObjectHandle<IndexedTxModel::Builder> &builder,
JavaObjectHandle<IndexedTxModelBuilderTag> withExecutor(const JavaObjectHandle<IndexedTxModelBuilderTag> &builder,
void *executor);

} // namespace Builder
Expand Down
Loading

0 comments on commit f12b270

Please sign in to comment.