dtn 0.0.0 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (132) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +21 -5
  3. data/.env.example +5 -0
  4. data/.gitignore +2 -0
  5. data/.rubocop.yml +7 -0
  6. data/CHANGELOG.md +5 -1
  7. data/Gemfile +3 -1
  8. data/README.md +288 -9
  9. data/Rakefile +2 -0
  10. data/docker-compose.yml +34 -0
  11. data/dtn.gemspec +1 -1
  12. data/lib/dtn.rb +18 -1
  13. data/lib/dtn/concerns/id.rb +36 -0
  14. data/lib/dtn/concerns/validation.rb +71 -0
  15. data/lib/dtn/helpers/catalog.rb +32 -0
  16. data/lib/dtn/lookups/catalog/listed_markets.rb +12 -0
  17. data/lib/dtn/lookups/catalog/naic_codes.rb +12 -0
  18. data/lib/dtn/lookups/catalog/security_types.rb +12 -0
  19. data/lib/dtn/lookups/catalog/sic_codes.rb +12 -0
  20. data/lib/dtn/lookups/catalog/trade_conditions.rb +12 -0
  21. data/lib/dtn/lookups/historical/base.rb +43 -0
  22. data/lib/dtn/lookups/historical/daily_datapoint.rb +13 -0
  23. data/lib/dtn/lookups/historical/daily_timeframe.rb +34 -0
  24. data/lib/dtn/lookups/historical/datapoint.rb +27 -0
  25. data/lib/dtn/lookups/historical/interval.rb +14 -0
  26. data/lib/dtn/lookups/historical/interval_datapoint.rb +31 -0
  27. data/lib/dtn/lookups/historical/interval_day.rb +32 -0
  28. data/lib/dtn/lookups/historical/interval_timeframe.rb +37 -0
  29. data/lib/dtn/lookups/historical/monthly_datapoint.rb +13 -0
  30. data/lib/dtn/lookups/historical/tick.rb +14 -0
  31. data/lib/dtn/lookups/historical/tick_datapoint.rb +24 -0
  32. data/lib/dtn/lookups/historical/tick_day.rb +34 -0
  33. data/lib/dtn/lookups/historical/tick_timeframe.rb +31 -0
  34. data/lib/dtn/lookups/historical/weekly_datapoint.rb +13 -0
  35. data/lib/dtn/lookups/news/base.rb +85 -0
  36. data/lib/dtn/lookups/news/config.rb +25 -0
  37. data/lib/dtn/lookups/news/headline.rb +40 -0
  38. data/lib/dtn/lookups/news/story.rb +40 -0
  39. data/lib/dtn/lookups/news/story_count.rb +36 -0
  40. data/lib/dtn/lookups/request.rb +92 -0
  41. data/lib/dtn/lookups/symbol/base.rb +11 -0
  42. data/lib/dtn/lookups/symbol/by_filter.rb +58 -0
  43. data/lib/dtn/lookups/symbol/by_naic.rb +26 -0
  44. data/lib/dtn/lookups/symbol/by_sic.rb +26 -0
  45. data/lib/dtn/message.rb +29 -0
  46. data/lib/dtn/messages/bar/base.rb +30 -0
  47. data/lib/dtn/messages/bar/current_bar.rb +11 -0
  48. data/lib/dtn/messages/bar/historical_bar.rb +11 -0
  49. data/lib/dtn/messages/bar/update_bar.rb +11 -0
  50. data/lib/dtn/messages/catalog/code.rb +22 -0
  51. data/lib/dtn/messages/catalog/listed_markets.rb +20 -0
  52. data/lib/dtn/messages/catalog/naic_codes.rb +10 -0
  53. data/lib/dtn/messages/catalog/security_types.rb +20 -0
  54. data/lib/dtn/messages/catalog/sic_codes.rb +10 -0
  55. data/lib/dtn/messages/catalog/trade_conditions.rb +20 -0
  56. data/lib/dtn/messages/historical/daily_weekly_monthly.rb +25 -0
  57. data/lib/dtn/messages/historical/interval.rb +28 -0
  58. data/lib/dtn/messages/historical/tick.rb +31 -0
  59. data/lib/dtn/messages/level2/level2_update.rb +38 -0
  60. data/lib/dtn/messages/level2/market_maker_name.rb +20 -0
  61. data/lib/dtn/messages/message_with_simple_parser.rb +38 -0
  62. data/lib/dtn/messages/news/base.rb +34 -0
  63. data/lib/dtn/messages/news/config.rb +24 -0
  64. data/lib/dtn/messages/news/headline.rb +25 -0
  65. data/lib/dtn/messages/news/story.rb +20 -0
  66. data/lib/dtn/messages/news/story_count.rb +21 -0
  67. data/lib/dtn/messages/quote/level1.rb +150 -0
  68. data/lib/dtn/messages/quote/level1_fundamental.rb +17 -0
  69. data/lib/dtn/messages/quote/level1_news.rb +27 -0
  70. data/lib/dtn/messages/quote/level1_regional.rb +31 -0
  71. data/lib/dtn/messages/quote/level1_summary.rb +19 -0
  72. data/lib/dtn/messages/quote/level1_update.rb +21 -0
  73. data/lib/dtn/messages/symbol/base.rb +35 -0
  74. data/lib/dtn/messages/symbol/by_filter.rb +11 -0
  75. data/lib/dtn/messages/symbol/by_naic.rb +22 -0
  76. data/lib/dtn/messages/symbol/by_sic.rb +22 -0
  77. data/lib/dtn/messages/system/client_stats.rb +46 -0
  78. data/lib/dtn/messages/system/customer_info.rb +30 -0
  79. data/lib/dtn/messages/system/end_of_message_characters.rb +22 -0
  80. data/lib/dtn/messages/system/error.rb +20 -0
  81. data/lib/dtn/messages/system/generic.rb +98 -0
  82. data/lib/dtn/messages/system/no_data_characters.rb +22 -0
  83. data/lib/dtn/messages/system/stats.rb +38 -0
  84. data/lib/dtn/messages/system/symbol_not_found.rb +19 -0
  85. data/lib/dtn/messages/system/timestamp.rb +16 -0
  86. data/lib/dtn/messages/unknown.rb +15 -0
  87. data/lib/dtn/registry.rb +57 -0
  88. data/lib/dtn/streaming/client.rb +105 -0
  89. data/lib/dtn/streaming/clients/admin.rb +20 -0
  90. data/lib/dtn/streaming/clients/bar.rb +49 -0
  91. data/lib/dtn/streaming/clients/level2.rb +25 -0
  92. data/lib/dtn/streaming/clients/quote.rb +57 -0
  93. data/lib/dtn/streaming/messages_recorder_observer.rb +26 -0
  94. data/lib/dtn/streaming/request.rb +27 -0
  95. data/lib/dtn/streaming/request_builder.rb +57 -0
  96. data/lib/dtn/streaming/requests/admin/register_client_app.rb +24 -0
  97. data/lib/dtn/streaming/requests/admin/remove_client_app.rb +22 -0
  98. data/lib/dtn/streaming/requests/admin/save_login_info.rb +18 -0
  99. data/lib/dtn/streaming/requests/admin/set_autoconnect.rb +18 -0
  100. data/lib/dtn/streaming/requests/admin/set_client_stats.rb +20 -0
  101. data/lib/dtn/streaming/requests/admin/set_loginid.rb +21 -0
  102. data/lib/dtn/streaming/requests/admin/set_password.rb +21 -0
  103. data/lib/dtn/streaming/requests/bar/unwatch.rb +18 -0
  104. data/lib/dtn/streaming/requests/bar/unwatch_all.rb +16 -0
  105. data/lib/dtn/streaming/requests/bar/watch.rb +81 -0
  106. data/lib/dtn/streaming/requests/bar/watches.rb +21 -0
  107. data/lib/dtn/streaming/requests/level2/connect.rb +16 -0
  108. data/lib/dtn/streaming/requests/level2/disconnect.rb +16 -0
  109. data/lib/dtn/streaming/requests/level2/market_maker_by_id.rb +18 -0
  110. data/lib/dtn/streaming/requests/level2/unwatch.rb +18 -0
  111. data/lib/dtn/streaming/requests/level2/watch.rb +18 -0
  112. data/lib/dtn/streaming/requests/quote/all_update_fieldnames.rb +16 -0
  113. data/lib/dtn/streaming/requests/quote/connect.rb +16 -0
  114. data/lib/dtn/streaming/requests/quote/current_update_fieldnames.rb +16 -0
  115. data/lib/dtn/streaming/requests/quote/fundamental_fieldnames.rb +16 -0
  116. data/lib/dtn/streaming/requests/quote/news_switch.rb +18 -0
  117. data/lib/dtn/streaming/requests/quote/refresh.rb +29 -0
  118. data/lib/dtn/streaming/requests/quote/regional_switch.rb +26 -0
  119. data/lib/dtn/streaming/requests/quote/set_client_name.rb +16 -0
  120. data/lib/dtn/streaming/requests/quote/set_protocol.rb +16 -0
  121. data/lib/dtn/streaming/requests/quote/timestamp.rb +21 -0
  122. data/lib/dtn/streaming/requests/quote/timestamp_switch.rb +18 -0
  123. data/lib/dtn/streaming/requests/quote/trades.rb +21 -0
  124. data/lib/dtn/streaming/requests/quote/unwatch.rb +22 -0
  125. data/lib/dtn/streaming/requests/quote/unwatch_all.rb +16 -0
  126. data/lib/dtn/streaming/requests/quote/update_fields.rb +40 -0
  127. data/lib/dtn/streaming/requests/quote/watch.rb +22 -0
  128. data/lib/dtn/streaming/requests/quote/watches.rb +21 -0
  129. data/lib/dtn/version.rb +1 -1
  130. data/lib/ext/business_day.rb +15 -0
  131. data/lib/tasks/spec_date.rake +13 -0
  132. metadata +126 -6
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dtn
4
+ module Lookups
5
+ module Historical
6
+ # Interval datapoint requests
7
+ class IntervalDay < Interval
8
+ TEMPLATE =
9
+ "HID,%<symbol>s,%<interval>d,%<days>d,%<max_datapoints>d,%<begin_filter_time>s,"\
10
+ "%<end_filter_time>s,%<data_direction>d,%<id>d,%<datapoints_per_send>d,%<interval_type>s"
11
+
12
+ # HID - Retrieves [Days] days of interval data for the specified [Symbol].
13
+ #
14
+ # Example message
15
+ #
16
+ # HID,[Symbol],[Interval],[Days],[MaxDatapoints],[BeginFilterTime],[EndFilterTime],
17
+ # [DataDirection],[RequestID],[DatapointsPerSend],[IntervalType]<CR><LF>
18
+ def call(symbol:, interval:, days:, **options)
19
+ self.combined_options = defaults(**options).merge(
20
+ {
21
+ symbol: validate_symbol(symbol),
22
+ days: validate_short_int(days),
23
+ interval: validate_int(interval),
24
+ interval_type: validate_interval_type(options[:interval_type])
25
+ }
26
+ )
27
+ super
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dtn
4
+ module Lookups
5
+ module Historical
6
+ # Interval timeframe requests
7
+ class IntervalTimeframe < Interval
8
+ TEMPLATE =
9
+ "HIT,%<symbol>s,%<interval>d,%<begin_datetime>s,%<end_datetime>s,%<max_datapoints>d,"\
10
+ "%<begin_filter_time>s,%<end_filter_time>s,%<data_direction>d,%<id>d,"\
11
+ "%<datapoints_per_send>d,%<interval_type>s"
12
+
13
+ # HIT - Retrieves interval data between [BeginDate BeginTime] and [EndDate EndTime] for the
14
+ # specified [Symbol].
15
+ #
16
+ # Example message
17
+ #
18
+ # HIT,[Symbol],[Interval],[BeginDate BeginTime],[EndDate EndTime],[MaxDatapoints],\
19
+ # [BeginFilterTime],[EndFilterTime],[DataDirection],[RequestID],[DatapointsPerSend],\
20
+ # [IntervalType]<CR><LF>
21
+
22
+ def call(symbol:, interval:, begin_datetime:, end_datetime:, **options)
23
+ self.combined_options = defaults(**options).merge(
24
+ {
25
+ symbol: validate_symbol(symbol),
26
+ interval: validate_int(interval),
27
+ interval_type: validate_interval_type(options[:interval_type]),
28
+ begin_datetime: validate_datetime(begin_datetime),
29
+ end_datetime: validate_datetime(end_datetime)
30
+ }
31
+ )
32
+ super
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dtn
4
+ module Lookups
5
+ module Historical
6
+ # Weekly datapoint requests
7
+ class MonthlyDatapoint < Datapoint
8
+ TEMPLATE =
9
+ "HMX,%<symbol>s,%<max_datapoints>d,%<data_direction>d,%<id>d,%<datapoints_per_send>d"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dtn
4
+ module Lookups
5
+ module Historical
6
+ # Tick requests
7
+ class Tick < Base
8
+ def expected_messages_class
9
+ Messages::Historical::Tick
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dtn
4
+ module Lookups
5
+ module Historical
6
+ # Tick datapoint requests
7
+ class TickDatapoint < Tick
8
+ TEMPLATE =
9
+ "HTX,%<symbol>s,%<max_datapoints>d,%<data_direction>d,%<id>d,%<datapoints_per_send>d"
10
+
11
+ # Retrieves up to [MaxDatapoints] number of ticks for the specified [Symbol].
12
+ #
13
+ # Example message
14
+ #
15
+ # HTX,[Symbol],[MaxDatapoints],[DataDirection],[RequestID],[DatapointsPerSend]<CR><LF>
16
+ def call(symbol:, **options)
17
+ self.combined_options = defaults(**options).merge(symbol: validate_symbol(symbol))
18
+
19
+ super
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dtn
4
+ module Lookups
5
+ module Historical
6
+ # Tick days requests
7
+ class TickDay < Tick
8
+ TEMPLATE =
9
+ "HTD,%<symbol>s,%<days>s,%<max_datapoints>d,%<begin_filter_time>s,%<end_filter_time>s," \
10
+ "%<data_direction>d,%<id>d,%<datapoints_per_send>d"
11
+
12
+ # Retrieves ticks for the previous [Days] days for the specified [Symbol].
13
+ #
14
+ # NOTE: Unfortunately I constantly get an empty response with this and
15
+ # more information about this data point needed.
16
+ #
17
+ # Example message
18
+ #
19
+ # HTD,[Symbol],[Days],[MaxDatapoints],[BeginFilterTime],[EndFilterTime],[DataDirection],\
20
+ # [RequestID],[DatapointsPerSend]<CR><LF>
21
+ #
22
+ # @returns Integer id
23
+ def call(symbol:, days:, **options)
24
+ self.combined_options = defaults(**options).merge({
25
+ symbol: validate_symbol(symbol),
26
+ days: validate_short_int(days)
27
+ })
28
+
29
+ super
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dtn
4
+ module Lookups
5
+ module Historical
6
+ # Tick timeframe requests
7
+ class TickTimeframe < Tick
8
+ TEMPLATE =
9
+ "HTT,%<symbol>s,%<begin_datetime>s,%<end_datetime>s,%<max_datapoints>d," \
10
+ "%<begin_filter_time>s,%<end_filter_time>s,%<data_direction>d,%<id>d," \
11
+ "%<datapoints_per_send>d"
12
+
13
+ # Retrieves tick data between [BeginDate BeginTime] and [EndDate EndTime] for the specified [Symbol].
14
+ #
15
+ # Example message
16
+ #
17
+ # HTT,[Symbol],[BeginDate BeginTime],[EndDate EndTime],[MaxDatapoints],[BeginFilterTime],\
18
+ # [EndFilterTime],[DataDirection],[RequestID],[DatapointsPerSend]<CR><LF>
19
+ def call(symbol:, begin_datetime:, end_datetime:, **options)
20
+ self.combined_options = defaults(**options).merge({
21
+ symbol: validate_symbol(symbol),
22
+ begin_datetime: validate_datetime(begin_datetime),
23
+ end_datetime: validate_datetime(end_datetime)
24
+ })
25
+
26
+ super
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dtn
4
+ module Lookups
5
+ module Historical
6
+ # Weekly datapoint requests
7
+ class WeeklyDatapoint < Datapoint
8
+ TEMPLATE =
9
+ "HWX,%<symbol>s,%<max_datapoints>d,%<data_direction>d,%<id>d,%<datapoints_per_send>d"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dtn
4
+ module Lookups
5
+ module News
6
+ # User news requests
7
+ class Base < Request
8
+ DEFAULT_NEWS_FORMAT_TYPE = "t"
9
+
10
+ include Dtn::Concerns::Validation
11
+
12
+ private
13
+
14
+ def validate_format_type(value)
15
+ it = value.to_s.downcase[0]
16
+ return it if [nil, "x", "t"].include?(it)
17
+
18
+ raise ValidationError, "Got #{value}, but interval_type can be only 't' for text or 'x' for XML"
19
+ end
20
+
21
+ def validate_list(value)
22
+ return value.join(";") if value.is_a? Array
23
+
24
+ value
25
+ end
26
+
27
+ # Date range validator.
28
+ # Consume Date, Range or String as a values (or any combination of them as the args,
29
+ # Array including)
30
+ # Returns Dtn valid String
31
+ class DateRangeValidator
32
+ include Dtn::Concerns::Validation
33
+
34
+ def initialize(*values)
35
+ @values = values.flatten
36
+ end
37
+
38
+ def call
39
+ return "" if empty_values?
40
+
41
+ check_each_value.join(":")
42
+ end
43
+
44
+ private
45
+
46
+ attr_reader :values
47
+
48
+ def empty_values?
49
+ values.all?(&:blank?)
50
+ end
51
+
52
+ def check_each_value
53
+ values.inject([]) do |acc, value|
54
+ case value
55
+ when Date then acc.push(check_date(value))
56
+ when Range then acc.push(check_range(value))
57
+ else acc + check(value)
58
+ end
59
+ end
60
+ end
61
+
62
+ def check_date(value)
63
+ validate_date(value)
64
+ end
65
+
66
+ def check_range(value)
67
+ "#{validate_date(value.begin)}-#{validate_date(value.end)}"
68
+ end
69
+
70
+ def check(value)
71
+ value.split(":").map do |pair|
72
+ raise(ValidationError, "Wrong dates range group in '#{pair}'") unless pair =~ /^\d{8}(-\d{8})?$/
73
+
74
+ pair.to_s.split("-").map { |d| validate_date(d) }.join("-")
75
+ end
76
+ end
77
+ end
78
+
79
+ def validate_date_ranges(*values)
80
+ DateRangeValidator.new(*values).call
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dtn
4
+ module Lookups
5
+ module News
6
+ # News config
7
+ class Config < Base
8
+ TEMPLATE = "NCG,%<format_type>s,%<id>d"
9
+
10
+ # Returns the News configuration which tells you what news sources
11
+ # you are subscribed to.
12
+ #
13
+ # Example messages
14
+ #
15
+ # NCG,[XML/Text],[RequestID]<CR><LF>
16
+ def call(format_type: DEFAULT_NEWS_FORMAT_TYPE)
17
+ self.combined_options = defaults.merge(
18
+ format_type: validate_format_type(format_type)
19
+ )
20
+ super
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dtn
4
+ module Lookups
5
+ module News
6
+ # News headlines
7
+ class Headline < Base
8
+ TEMPLATE = "NHL,%<sources>s,%<symbols>s,%<format_type>s,%<limit>d,%<date_range>s,%<id>d"
9
+
10
+ DEFAULT_NEWS_HEADLINES_LIMIT = 1000
11
+
12
+ # Returns all current news headlines.
13
+ #
14
+ # @params sources Array of Strings or ';' separated String,
15
+ # Filter news sources to query. Default all sources.
16
+ # @params symbols Array of Strings or ';' separated String,
17
+ # Filter symbols you want news for. Default all symbols.
18
+ # @params date_range String or Date
19
+ # Filter News only for dates. Default no date filter
20
+ # @params limit Integer
21
+ # Limit fetching stories, Default 1000
22
+ #
23
+ # Example messages
24
+ #
25
+ # NHL,[Sources],[Symbols],[XML/Text],[Limit],[Date],[RequestID]
26
+ def call(date_range: "", symbols: [], sources: [], format_type: DEFAULT_NEWS_FORMAT_TYPE,
27
+ limit: DEFAULT_NEWS_HEADLINES_LIMIT)
28
+ self.combined_options = defaults.merge(
29
+ format_type: validate_format_type(format_type),
30
+ symbols: validate_list(symbols),
31
+ sources: validate_list(sources),
32
+ date_range: validate_date_ranges(date_range),
33
+ limit: limit
34
+ )
35
+ super
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dtn
4
+ module Lookups
5
+ module News
6
+ # News story
7
+ class Story < Base
8
+ NEWS_FORMAT_TYPES = %w[x t e].freeze
9
+
10
+ TEMPLATE = "NSY,%<story_id>s,%<format_type>s,%<deliver_to>s,%<id>d"
11
+
12
+ # Returns all current news story.
13
+ #
14
+ # Note: email support was not implemented
15
+ #
16
+ # Example messages
17
+ #
18
+ # NSY,[ID],[XML/Text/Email],[DeliverTo],[RequestID]<CR><LF>
19
+ def call(story_id:, deliver_to: nil, format_type: DEFAULT_NEWS_FORMAT_TYPE)
20
+ self.combined_options = defaults.merge(
21
+ format_type: validate_format_type(format_type),
22
+ deliver_to: deliver_to,
23
+ story_id: story_id
24
+ )
25
+ super
26
+ end
27
+
28
+ private
29
+
30
+ def validate_format_type(value)
31
+ it = value.to_s.downcase[0]
32
+ return it if [nil, "x", "t", "e"].include?(it)
33
+
34
+ raise ValidationError,
35
+ "Got #{value}, but interval_type can be only 't' for text, 'e' for email or 'x' for XML"
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Dtn
4
+ module Lookups
5
+ module News
6
+ # News story count
7
+ class StoryCount < Base
8
+ TEMPLATE = "NSC,%<symbols>s,%<format_type>s,%<sources>s,%<date_range>s,%<id>d"
9
+
10
+ DEFAULT_NEWS_HEADLINES_LIMIT = 1000
11
+
12
+ # Returns all current news headlines.
13
+ #
14
+ # @params sources Array of Strings or ';' separated String,
15
+ # Filter news sources to query. Default all sources.
16
+ # @params symbols Array of Strings or ';' separated String,
17
+ # Filter symbols you want news for. Default all symbols.
18
+ # @params date_range String or Date
19
+ # Filter News only for dates. Default no date filter
20
+ #
21
+ # Example messages
22
+ #
23
+ # NSC,[Symbols],[XML/Text],[Sources],[DateRange],[RequestID]<CR>
24
+ def call(date_range: "", symbols: [], sources: [], format_type: DEFAULT_NEWS_FORMAT_TYPE)
25
+ self.combined_options = defaults.merge(
26
+ format_type: validate_format_type(format_type),
27
+ symbols: validate_list(symbols),
28
+ sources: validate_list(sources),
29
+ date_range: validate_date_ranges(date_range)
30
+ )
31
+ super
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end