-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathmain.cpp
More file actions
148 lines (126 loc) · 7.57 KB
/
main.cpp
File metadata and controls
148 lines (126 loc) · 7.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// Copyright (c) 2025 Devexperts LLC.
// SPDX-License-Identifier: MPL-2.0
#include <dxfeed_graal_cpp_api/api.hpp>
#include <iostream>
/**
* This sample demonstrates a way to subscribe to the big world of symbols with dxFeed API, so that the events are
* updated and cached in memory of this process and then take snapshots of those events from memory whenever
* they are needed. This example repeatedly reads the symbol name from the console and prints a snapshot of its last
* quote, trade, summary, and profile events.
*/
int main() {
using namespace dxfcpp;
using namespace std::literals;
try {
/*
* Permanent subscription to the world is performed with a special property named "dxfeed.qd.subscribe.ticker".
* Its value consists of a comma-separated list of records, followed by a space, followed by a comma-separated
* list of symbols. Record names for composite (NBBO) events are the same as the corresponding event classes
* in API. The string below defines subscription for quote, trade, summary, and profile composite events:
*/
const auto records = "Quote,Trade,Summary,Profile";
/*
* Records for regional-exchange events are derived by appending "&" (ampersand) and a single-digit
* exchange code. Regexp-like syntax can be used instead of listing them all. For example, the commented
* line below and to the mix a subscription on regional quotes from all potential exchange codes A-Z
*/
// auto records = "Quote,Trade,Summary,Profile,Quote&[A-Z]";
/*
* There is an important trade-off between resource consumption and speed of access to the last events.
* The whole world of stocks and options from all the exchanges is very large and will consume gigabytes
* of memory to cache. Moreover, this cache has to be constantly kept uptodate, which consumes a lot of
* networks and CPU.
*
* A particular application's use cases have to be studied to figure out what is an option for this particular
* application. If some events are known to be rarely needed and a small delay while access to them can be
* tolerated, then it is not worth configuring a permanent subscription for them. The code in this
* sample works using `DXFeed::getLastEventPromise()` method that will request an event from the upstream data provider
* if it is not present in the local in-memory cache.
*/
/*
* There are multiple ways to specify a list of symbols. It is typically taken from an IPF file, and its
* specification consists of a URL to the file which has to contain ".ipf" to be recognized.
* The string below defines subscription for all symbols that are available on the demo feed.
*/
const auto symbols = "https://dxfeed.s3.amazonaws.com/masterdata/ipf/demo/mux-demo.ipf.zip";
// Disable QD logging.
// Logging::init();
/*
* Permanent subscription property "dxfeed.qd.subscribe.ticker" can be directly placed into the
* "dxfeed.system.properties" file, and no custom DXEndpoint instance will be needed. Here it is explicitly
* specified using a DXFeedEndpoint::Builder class. Note that we don't use `DXEndpoint::connect()` method.
* It is assumed by this sample that the ` dxfeed.address ` property is specified in "dxfeed.system.properties" and
* connection is automatically established to that address.
* Alternatively, "dxfeed.address" can also be specified in the builder.
*/
const auto endpoint =
DXEndpoint::newBuilder()->withProperty("dxfeed.qd.subscribe.ticker", records + " "s + symbols)->build();
/*
* The actual client code does not need a reference to DXEndpoint, which only contains lifecycle
* methods like "connect" and "close". The client code needs a reference to DXFeed.
*/
const auto feed = endpoint->getFeed();
/*
* Print a short help.
*/
std::cout << "Type symbols to get their quote, trade, summary, and profile event snapshots\n";
while (true) {
/*
* User of this sample application can type symbols in the console. Symbol like "IBM" corresponds
* to the stock. Symbol like "IBM&N" corresponds to the information from a specific exchange.
* See the dxFeed Symbol guide at http://www.dxfeed.com/downloads/documentation/dxFeed_Symbol_Guide.pdf
*/
std::string symbol;
std::getline(std::cin, symbol);
if (symbol.empty() || symbol == "exit" || symbol == "quit" || symbol == "q") {
return 0;
}
/*
* The first step is to extract promises for all events that we are interested in. This way we
* can get an event even if we have not previously subscribed for it.
*/
const auto quotePromise = feed->getLastEventPromise<Quote>(symbol);
const auto tradePromise = feed->getLastEventPromise<Trade>(symbol);
const auto summaryPromise = feed->getLastEventPromise<Summary>(symbol);
/*
* All promises are put into a list for convenience.
*/
std::vector<std::shared_ptr<Promise<std::shared_ptr<EventType>>>> promises{};
promises.push_back(quotePromise->sharedAs<EventType>());
promises.push_back(tradePromise->sharedAs<EventType>());
promises.push_back(summaryPromise->sharedAs<EventType>());
/*
* Profile events are composite-only. They are not available for regional symbols like
* "IBM&N" and the attempt to retrieve never completes (will time out), so we don't even try.
*/
if (!MarketEventSymbols::hasExchangeCode(symbol)) {
const auto profilePromise = feed->getLastEventPromise<Profile>(symbol);
promises.push_back(profilePromise->sharedAs<EventType>(true));
}
/*
* If the events are available in the in-memory cache, then the promises will be completed immediately.
* Otherwise, a request to the upstream data provider is sent. Below we combine promises using
* Promises utility class from DXFeed API to wait for at most 1 second for all the
* promises to complete. The last event promise never completes exceptionally, and we don't
* have to especially process a case of timeout, so "awaitWithoutException" is used to continue
* normal execution even on timeout. This sample prints a special message in the case of timeout.
*/
if (!Promises::allOf(promises)->awaitWithoutException(1s)) {
std::cout << "Request timed out\n";
}
/*
* The combination above is used only to ensure a common wait of 1 second. Promises to individual events
* are completed independently, and the corresponding events can be accessed even if some events were not
* available for any reason and the wait above had timed out. This sample just prints all results.
* "<null>" is printed when the event is not available.
*/
for (const auto &promise : promises) {
const auto event = promise->getResult();
std::cout << (!event ? String::NUL : event->toString()) << std::endl;
}
}
} catch (const RuntimeException &e) {
std::cerr << e << '\n';
return 1;
}
}