-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathProgram.cs
356 lines (298 loc) · 14.9 KB
/
Program.cs
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
#region License
/*
Copyright (c) 2010-2023 Devexperts LLC
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#endregion
using System;
using System.Globalization;
using com.dxfeed.api;
using com.dxfeed.api.candle;
using com.dxfeed.api.connection;
using com.dxfeed.api.data;
using com.dxfeed.api.events;
using com.dxfeed.api.extras;
using com.dxfeed.native;
namespace dxf_client
{
internal class InputParam<T>
{
private T value;
private InputParam()
{
IsSet = false;
}
public InputParam(T defaultValue) : this()
{
value = defaultValue;
}
public bool IsSet { get; private set; }
public T Value
{
get { return value; }
set
{
this.value = value;
IsSet = true;
}
}
}
internal class Program
{
private const int DefaultRecordsPrintLimit = 7;
private const int HostIndex = 0;
private const int EventIndex = 1;
private const int SymbolIndex = 2;
private static bool TryParseDateTimeParam(string stringParam, InputParam<DateTime?> param)
{
DateTime dateTimeValue;
if (!DateTime.TryParse(stringParam, out dateTimeValue)) return false;
param.Value = dateTimeValue;
return true;
}
private static bool TryParseSnapshotParam(string stringParam, InputParam<bool> param)
{
if (!stringParam.ToLower().Equals("snapshot")) return false;
param.Value = true;
return true;
}
private static void TryParseSourcesParam(string stringParam, InputParam<string[]> param)
{
param.Value = stringParam.Split(',');
}
private static bool TryParseRecordsPrintLimitParam(string paramTagString, string paramString,
InputParam<int> param)
{
if (!paramTagString.Equals("-l")) return false;
int newRecordsPrintLimit;
if (!int.TryParse(paramString, out newRecordsPrintLimit)) return false;
param.Value = newRecordsPrintLimit;
return true;
}
private static bool TryParseEventSubscriptionFlagParam(string tag, string paramTagString, string paramString,
InputParam<EventSubscriptionFlag> param)
{
if (!paramTagString.Equals(tag)) return false;
if (paramString.Equals("ticker", StringComparison.InvariantCultureIgnoreCase))
param.Value = EventSubscriptionFlag.ForceTicker;
else if (paramString.Equals("stream", StringComparison.InvariantCultureIgnoreCase))
param.Value = EventSubscriptionFlag.ForceStream;
else if (paramString.Equals("history", StringComparison.InvariantCultureIgnoreCase))
param.Value = EventSubscriptionFlag.ForceHistory;
else
return false;
return true;
}
private static bool TryParseTaggedStringParam(string tag, string paramTagString, string paramString,
InputParam<string> param)
{
if (!paramTagString.Equals(tag)) return false;
param.Value = paramString;
return true;
}
private static void Main(string[] args)
{
if (args.Length < 3 || (args.Length > 0 && args[0].Equals("-h")))
{
Console.WriteLine(
"Usage: dxf_client <host:port>|<path> <event> <symbol> [<date>] [<source>] [snapshot] [-l <records_print_limit>] [-T <token>] [-s <subscr_data>] [-p] [-b] [-q]\n" +
"where\n" +
" host:port - The address of dxfeed server (demo.dxfeed.com:7300)\n" +
" path - The path to file with candle data (non zipped Candle Web Service output) or `tape` file\n" +
" event - Any of the {Profile,Order,Quote,Trade,TimeAndSale,Summary,\n" +
" TradeETH,SpreadOrder,Candle,Greeks,TheoPrice,Underlying,Series,\n" +
" Configuration}\n" +
" symbol - a) IBM, MSFT, ... ; * - all symbols\n" +
" b) if it is Candle event you can specify candle symbol\n" +
" attribute by string, for example: XBT/USD{=d}\n" +
" date - The date of time series event in the format YYYY-MM-DD (optional)\n" +
" source - Used only for Order or MarketMaker subscription:\n" +
" a) OPTIONAL source for order events is any combination of:\n" +
" NTV,ntv,NFX,ESPD,XNFI,ICE,ISE,DEA,DEX,BYX,BZX,BATE,CHIX,CEUX,\n" +
" BXTR,IST,BI20,ABE,FAIR,GLBX,glbx,ERIS,XEUR,xeur,CFE,C2OX,SMFE," +
" smfe,iex,MEMX,memx;\n" +
" b) source for Order snapshot can be one of following: " +
" NTV,ntv,NFX,ESPD,XNFI,ICE,ISE,DEA,DEX,BYX,BZX,BATE,CHIX,CEUX,\n" +
" BXTR,IST,BI20,ABE,FAIR,GLBX,glbx,ERIS,XEUR,xeur,CFE,C2OX,SMFE," +
" smfe,iex,MEMX,memx;\n" +
" c) source for MarketMaker snapshot, can be AGGREGATE_ASK\n" +
" or AGGREGATE_BID\n" +
" snapshot - Use keyword 'snapshot' for create snapshot subscription,\n" +
" otherwise leave empty\n" +
$" -l <records_print_limit> - The number of displayed records (0 - unlimited, default: {DefaultRecordsPrintLimit})\n" +
" -T <token> - The authorization token\n\n" +
" -s <subscr_data> - The subscription data: ticker|TICKER, stream|STREAM, history|HISTORY\n" +
" -p - Enables the data transfer logging\n" +
" -b - Enables the server's heartbeat logging to console\n" +
" -q - Quiet mode (do not print events and snapshots)\n\n" +
"examples:\n" +
" events: dxf_client demo.dxfeed.com:7300 Quote,Trade MSFT.TEST,IBM.TEST\n" +
" events: dxf_client demo.dxfeed.com:7300 Quote,Trade MSFT.TEST,IBM.TEST -s stream\n" +
" order: dxf_client demo.dxfeed.com:7300 Order MSFT.TEST,IBM.TEST NTV,IST\n" +
" candle: dxf_client demo.dxfeed.com:7300 Candle XBT/USD{=d} 2016-10-10\n" +
" underlying: dxf_client demo.dxfeed.com:7300 Underlying AAPL\n" +
" series: dxf_client demo.dxfeed.com:7300 Series AAPL\n" +
" order snapshot: dxf_client demo.dxfeed.com:7300 Order AAPL NTV snapshot\n" +
" order snapshot: dxf_client demo.dxfeed.com:7300 Order AAPL NTV snapshot -l 0\n" +
" market maker snapshot: dxf_client demo.dxfeed.com:7300 Order AAPL AGGREGATE_BID snapshot\n" +
" market maker snapshot: dxf_client demo.dxfeed.com:7300 Order AAPL AGGREGATE_BID snapshot -l 3\n" +
" candle snapshot: dxf_client demo.dxfeed.com:7300 Candle XBT/USD{=d} 2016-10-10 snapshot\n" +
" candle snapshot: dxf_client demo.dxfeed.com:7300 Candle XBT/USD{=d} 2016-10-10 snapshot -l 10\n" +
" candle snapshot: dxf_client demo.dxfeed.com:7300 Candle XBT/USD{=d,pl=0.5} 2016-10-10 snapshot -l 10\n" +
" tape file: dxf_client ./tape_file Order,TimeAndSale AAPL\n" +
" candle data: dxf_client ./candledata.bin Candle AIV{=d}\n"
);
return;
}
var address = args[HostIndex];
EventType events;
if (!Enum.TryParse(args[EventIndex], true, out events))
{
Console.WriteLine($"Unsupported event type: {args[EventIndex]}");
return;
}
var symbols = args[SymbolIndex];
var sources = new InputParam<string[]>(new string[] { });
var isSnapshot = new InputParam<bool>(false);
var dateTime = new InputParam<DateTime?>(null);
var recordsPrintLimit = new InputParam<int>(DefaultRecordsPrintLimit);
var token = new InputParam<string>(null);
var subscriptionData = new InputParam<EventSubscriptionFlag>(EventSubscriptionFlag.Default);
var logDataTransferFlag = false;
var logServerHeartbeatsFlag = false;
var quiteMode = false;
for (var i = SymbolIndex + 1; i < args.Length; i++)
{
if (!dateTime.IsSet && TryParseDateTimeParam(args[i], dateTime))
continue;
if (!isSnapshot.IsSet && TryParseSnapshotParam(args[i], isSnapshot))
continue;
if (!recordsPrintLimit.IsSet && i < args.Length - 1 &&
TryParseRecordsPrintLimitParam(args[i], args[i + 1], recordsPrintLimit))
{
i++;
continue;
}
if (!token.IsSet && i < args.Length - 1 &&
TryParseTaggedStringParam("-T", args[i], args[i + 1], token))
{
i++;
continue;
}
if (!subscriptionData.IsSet && i < args.Length - 1 &&
TryParseEventSubscriptionFlagParam("-s", args[i], args[i + 1], subscriptionData))
{
i++;
continue;
}
if (logDataTransferFlag == false && args[i].Equals("-p"))
{
logDataTransferFlag = true;
continue;
}
if (logServerHeartbeatsFlag == false && args[i].Equals("-b"))
{
logServerHeartbeatsFlag = true;
continue;
}
if (quiteMode == false && args[i].Equals("-q"))
{
quiteMode = true;
continue;
}
if (!sources.IsSet)
TryParseSourcesParam(args[i], sources);
}
var snapshotString = isSnapshot.Value ? " snapshot" : string.Empty;
var timeSeriesString = dateTime.IsSet && !isSnapshot.Value ? " time-series" : string.Empty;
Console.WriteLine(
$"Connecting to {address} for [{events}{snapshotString}]{timeSeriesString} on [{symbols}] ...");
//NativeTools.LoadConfigFromString("network.heartbeatPeriod = 11\n");
NativeTools.LoadConfigFromString("logger.level = \"debug\"\n");
NativeTools.InitializeLogging("dxf_client.log", true, true, logDataTransferFlag);
var eventPrinter = quiteMode ? (IEventPrinter) new DummyEventPrinter() : new EventPrinter();
using (var con = token.IsSet
? new NativeConnection(address, token.Value, DisconnectHandler, ConnectionStatusChangeHandler)
: new NativeConnection(address, DisconnectHandler, ConnectionStatusChangeHandler))
{
if (logServerHeartbeatsFlag)
{
con.SetOnServerHeartbeatHandler((connection, time, lagMark, rtt) =>
{
Console.Error.WriteLine(
$"##### Server time (UTC) = {time}, Server lag = {lagMark} us, RTT = {rtt} us #####");
});
}
IDxSubscription s = null;
try
{
if (dateTime.IsSet && (events & (EventType.Order | EventType.SpreadOrder)) != 0)
{
Console.Error.WriteLine(
"Date and event type Order or SpreadOrder cannot be used for subscription");
}
if (isSnapshot.Value)
{
s = con.CreateSnapshotSubscription(events, dateTime.Value,
quiteMode
? (ISnapshotPrinter) new DummySnapshotPrinter()
: new SnapshotPrinter(recordsPrintLimit.Value));
}
else if (dateTime.IsSet)
s = subscriptionData.IsSet
? con.CreateSubscription(events, dateTime.Value, subscriptionData.Value, eventPrinter)
: con.CreateSubscription(events, dateTime.Value, eventPrinter);
else
s = subscriptionData.IsSet
? con.CreateSubscription(events, subscriptionData.Value, eventPrinter)
: con.CreateSubscription(events, eventPrinter);
if (events.HasFlag(EventType.Order) && sources.Value.Length > 0)
s.SetSource(sources.Value);
if (events == EventType.Candle)
{
var candleSymbol = CandleSymbol.ValueOf(symbols);
s.AddSymbol(candleSymbol);
}
else
{
s.AddSymbols(symbols.Split(','));
}
Console.WriteLine("Press enter to stop");
Console.ReadLine();
}
catch (DxException dxException)
{
Console.WriteLine($"Native exception occurred: {dxException.Message}");
}
catch (Exception exc)
{
Console.WriteLine($"Exception occurred: {exc.Message}");
}
finally
{
s?.Dispose();
}
}
}
private static void ConnectionStatusChangeHandler(IDxConnection connection, ConnectionStatus oldStatus,
ConnectionStatus newStatus)
{
switch (newStatus)
{
case ConnectionStatus.Connected:
Console.WriteLine("Connected to {0}", connection.ConnectedAddress);
break;
case ConnectionStatus.Authorized:
Console.WriteLine("Authorized");
break;
default:
return;
}
}
private static void DisconnectHandler(IDxConnection con)
{
Console.WriteLine("Disconnected");
}
}
}