dtn 0.0.0 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +21 -5
- data/.env.example +5 -0
- data/.gitignore +2 -0
- data/.rubocop.yml +7 -0
- data/CHANGELOG.md +5 -1
- data/Gemfile +3 -1
- data/README.md +288 -9
- data/Rakefile +2 -0
- data/docker-compose.yml +34 -0
- data/dtn.gemspec +1 -1
- data/lib/dtn.rb +18 -1
- data/lib/dtn/concerns/id.rb +36 -0
- data/lib/dtn/concerns/validation.rb +71 -0
- data/lib/dtn/helpers/catalog.rb +32 -0
- data/lib/dtn/lookups/catalog/listed_markets.rb +12 -0
- data/lib/dtn/lookups/catalog/naic_codes.rb +12 -0
- data/lib/dtn/lookups/catalog/security_types.rb +12 -0
- data/lib/dtn/lookups/catalog/sic_codes.rb +12 -0
- data/lib/dtn/lookups/catalog/trade_conditions.rb +12 -0
- data/lib/dtn/lookups/historical/base.rb +43 -0
- data/lib/dtn/lookups/historical/daily_datapoint.rb +13 -0
- data/lib/dtn/lookups/historical/daily_timeframe.rb +34 -0
- data/lib/dtn/lookups/historical/datapoint.rb +27 -0
- data/lib/dtn/lookups/historical/interval.rb +14 -0
- data/lib/dtn/lookups/historical/interval_datapoint.rb +31 -0
- data/lib/dtn/lookups/historical/interval_day.rb +32 -0
- data/lib/dtn/lookups/historical/interval_timeframe.rb +37 -0
- data/lib/dtn/lookups/historical/monthly_datapoint.rb +13 -0
- data/lib/dtn/lookups/historical/tick.rb +14 -0
- data/lib/dtn/lookups/historical/tick_datapoint.rb +24 -0
- data/lib/dtn/lookups/historical/tick_day.rb +34 -0
- data/lib/dtn/lookups/historical/tick_timeframe.rb +31 -0
- data/lib/dtn/lookups/historical/weekly_datapoint.rb +13 -0
- data/lib/dtn/lookups/news/base.rb +85 -0
- data/lib/dtn/lookups/news/config.rb +25 -0
- data/lib/dtn/lookups/news/headline.rb +40 -0
- data/lib/dtn/lookups/news/story.rb +40 -0
- data/lib/dtn/lookups/news/story_count.rb +36 -0
- data/lib/dtn/lookups/request.rb +92 -0
- data/lib/dtn/lookups/symbol/base.rb +11 -0
- data/lib/dtn/lookups/symbol/by_filter.rb +58 -0
- data/lib/dtn/lookups/symbol/by_naic.rb +26 -0
- data/lib/dtn/lookups/symbol/by_sic.rb +26 -0
- data/lib/dtn/message.rb +29 -0
- data/lib/dtn/messages/bar/base.rb +30 -0
- data/lib/dtn/messages/bar/current_bar.rb +11 -0
- data/lib/dtn/messages/bar/historical_bar.rb +11 -0
- data/lib/dtn/messages/bar/update_bar.rb +11 -0
- data/lib/dtn/messages/catalog/code.rb +22 -0
- data/lib/dtn/messages/catalog/listed_markets.rb +20 -0
- data/lib/dtn/messages/catalog/naic_codes.rb +10 -0
- data/lib/dtn/messages/catalog/security_types.rb +20 -0
- data/lib/dtn/messages/catalog/sic_codes.rb +10 -0
- data/lib/dtn/messages/catalog/trade_conditions.rb +20 -0
- data/lib/dtn/messages/historical/daily_weekly_monthly.rb +25 -0
- data/lib/dtn/messages/historical/interval.rb +28 -0
- data/lib/dtn/messages/historical/tick.rb +31 -0
- data/lib/dtn/messages/level2/level2_update.rb +38 -0
- data/lib/dtn/messages/level2/market_maker_name.rb +20 -0
- data/lib/dtn/messages/message_with_simple_parser.rb +38 -0
- data/lib/dtn/messages/news/base.rb +34 -0
- data/lib/dtn/messages/news/config.rb +24 -0
- data/lib/dtn/messages/news/headline.rb +25 -0
- data/lib/dtn/messages/news/story.rb +20 -0
- data/lib/dtn/messages/news/story_count.rb +21 -0
- data/lib/dtn/messages/quote/level1.rb +150 -0
- data/lib/dtn/messages/quote/level1_fundamental.rb +17 -0
- data/lib/dtn/messages/quote/level1_news.rb +27 -0
- data/lib/dtn/messages/quote/level1_regional.rb +31 -0
- data/lib/dtn/messages/quote/level1_summary.rb +19 -0
- data/lib/dtn/messages/quote/level1_update.rb +21 -0
- data/lib/dtn/messages/symbol/base.rb +35 -0
- data/lib/dtn/messages/symbol/by_filter.rb +11 -0
- data/lib/dtn/messages/symbol/by_naic.rb +22 -0
- data/lib/dtn/messages/symbol/by_sic.rb +22 -0
- data/lib/dtn/messages/system/client_stats.rb +46 -0
- data/lib/dtn/messages/system/customer_info.rb +30 -0
- data/lib/dtn/messages/system/end_of_message_characters.rb +22 -0
- data/lib/dtn/messages/system/error.rb +20 -0
- data/lib/dtn/messages/system/generic.rb +98 -0
- data/lib/dtn/messages/system/no_data_characters.rb +22 -0
- data/lib/dtn/messages/system/stats.rb +38 -0
- data/lib/dtn/messages/system/symbol_not_found.rb +19 -0
- data/lib/dtn/messages/system/timestamp.rb +16 -0
- data/lib/dtn/messages/unknown.rb +15 -0
- data/lib/dtn/registry.rb +57 -0
- data/lib/dtn/streaming/client.rb +105 -0
- data/lib/dtn/streaming/clients/admin.rb +20 -0
- data/lib/dtn/streaming/clients/bar.rb +49 -0
- data/lib/dtn/streaming/clients/level2.rb +25 -0
- data/lib/dtn/streaming/clients/quote.rb +57 -0
- data/lib/dtn/streaming/messages_recorder_observer.rb +26 -0
- data/lib/dtn/streaming/request.rb +27 -0
- data/lib/dtn/streaming/request_builder.rb +57 -0
- data/lib/dtn/streaming/requests/admin/register_client_app.rb +24 -0
- data/lib/dtn/streaming/requests/admin/remove_client_app.rb +22 -0
- data/lib/dtn/streaming/requests/admin/save_login_info.rb +18 -0
- data/lib/dtn/streaming/requests/admin/set_autoconnect.rb +18 -0
- data/lib/dtn/streaming/requests/admin/set_client_stats.rb +20 -0
- data/lib/dtn/streaming/requests/admin/set_loginid.rb +21 -0
- data/lib/dtn/streaming/requests/admin/set_password.rb +21 -0
- data/lib/dtn/streaming/requests/bar/unwatch.rb +18 -0
- data/lib/dtn/streaming/requests/bar/unwatch_all.rb +16 -0
- data/lib/dtn/streaming/requests/bar/watch.rb +81 -0
- data/lib/dtn/streaming/requests/bar/watches.rb +21 -0
- data/lib/dtn/streaming/requests/level2/connect.rb +16 -0
- data/lib/dtn/streaming/requests/level2/disconnect.rb +16 -0
- data/lib/dtn/streaming/requests/level2/market_maker_by_id.rb +18 -0
- data/lib/dtn/streaming/requests/level2/unwatch.rb +18 -0
- data/lib/dtn/streaming/requests/level2/watch.rb +18 -0
- data/lib/dtn/streaming/requests/quote/all_update_fieldnames.rb +16 -0
- data/lib/dtn/streaming/requests/quote/connect.rb +16 -0
- data/lib/dtn/streaming/requests/quote/current_update_fieldnames.rb +16 -0
- data/lib/dtn/streaming/requests/quote/fundamental_fieldnames.rb +16 -0
- data/lib/dtn/streaming/requests/quote/news_switch.rb +18 -0
- data/lib/dtn/streaming/requests/quote/refresh.rb +29 -0
- data/lib/dtn/streaming/requests/quote/regional_switch.rb +26 -0
- data/lib/dtn/streaming/requests/quote/set_client_name.rb +16 -0
- data/lib/dtn/streaming/requests/quote/set_protocol.rb +16 -0
- data/lib/dtn/streaming/requests/quote/timestamp.rb +21 -0
- data/lib/dtn/streaming/requests/quote/timestamp_switch.rb +18 -0
- data/lib/dtn/streaming/requests/quote/trades.rb +21 -0
- data/lib/dtn/streaming/requests/quote/unwatch.rb +22 -0
- data/lib/dtn/streaming/requests/quote/unwatch_all.rb +16 -0
- data/lib/dtn/streaming/requests/quote/update_fields.rb +40 -0
- data/lib/dtn/streaming/requests/quote/watch.rb +22 -0
- data/lib/dtn/streaming/requests/quote/watches.rb +21 -0
- data/lib/dtn/version.rb +1 -1
- data/lib/ext/business_day.rb +15 -0
- data/lib/tasks/spec_date.rake +13 -0
- metadata +126 -6
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dtn
|
4
|
+
module Streaming
|
5
|
+
# Request abstraction
|
6
|
+
class Request
|
7
|
+
def initialize(client:)
|
8
|
+
@client = client
|
9
|
+
end
|
10
|
+
|
11
|
+
# Initialize the request to api, should be used in children classes only
|
12
|
+
#
|
13
|
+
# @returns nil
|
14
|
+
def call(*)
|
15
|
+
raise NotImplementedError
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def socket
|
21
|
+
client.socket
|
22
|
+
end
|
23
|
+
|
24
|
+
attr_reader :client
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dtn
|
4
|
+
module Streaming
|
5
|
+
# Request builder abstraction
|
6
|
+
class RequestBuilder
|
7
|
+
# Proxy class between builder and request
|
8
|
+
class Proxy
|
9
|
+
def initialize(client:, requests_module:)
|
10
|
+
@client = client
|
11
|
+
@requests_module = requests_module
|
12
|
+
end
|
13
|
+
|
14
|
+
def method_missing(method_name, *args, **opts, &blk)
|
15
|
+
req = requests_module.const_get(method_name.to_s.camelize).new(client: client)
|
16
|
+
req.call(*args, **opts, &blk)
|
17
|
+
rescue NameError
|
18
|
+
super
|
19
|
+
end
|
20
|
+
|
21
|
+
def respond_to_missing?(method_name, include_private = false)
|
22
|
+
requests_module.const_get(method_name.to_s.camelize).is_a? Module
|
23
|
+
rescue NameError
|
24
|
+
super
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
attr_reader :client, :requests_module
|
30
|
+
end
|
31
|
+
|
32
|
+
def initialize(client:)
|
33
|
+
@client = client
|
34
|
+
end
|
35
|
+
|
36
|
+
def method_missing(method_name, *_args, **_opts, &_blk)
|
37
|
+
Proxy.new(client: client, requests_module: _requests_module(method_name))
|
38
|
+
rescue NameError
|
39
|
+
super
|
40
|
+
end
|
41
|
+
|
42
|
+
def respond_to_missing?(method_name, include_private = false)
|
43
|
+
_requests_module(method_name).is_a? Module
|
44
|
+
rescue NameError
|
45
|
+
super
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
attr_reader :client
|
51
|
+
|
52
|
+
def _requests_module(method_name)
|
53
|
+
"Dtn::Streaming::Requests::#{method_name.to_s.camelize}".constantize
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dtn
|
4
|
+
module Streaming
|
5
|
+
module Requests
|
6
|
+
module Admin
|
7
|
+
# Register your application with IQFeed.
|
8
|
+
#
|
9
|
+
# :param product: Developer/Product token from DTN.
|
10
|
+
#
|
11
|
+
# IQFeed requires all developers to get a developer/app token from
|
12
|
+
# them before you develop using IQFeed. You can register you developer
|
13
|
+
# token either using the command line used to start IQFeed or here.
|
14
|
+
# IQFeed will not connect to DTN servers or send you any data without
|
15
|
+
# a developer token.
|
16
|
+
class RegisterClientApp < Request
|
17
|
+
def call(product:)
|
18
|
+
socket.puts "S,REGISTER CLIENT APP,#{product}\r\n"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dtn
|
4
|
+
module Streaming
|
5
|
+
module Requests
|
6
|
+
module Admin
|
7
|
+
# Unregister your application with IQFeed.
|
8
|
+
#
|
9
|
+
# :param product: Developer/Product token from DTN.
|
10
|
+
#
|
11
|
+
# Unregister your developer token. Apps from other developers may still
|
12
|
+
# be talking to IQFeed. This tells IQFeed that any further calls are
|
13
|
+
# from them and not you.
|
14
|
+
class RemoveClientApp < Request
|
15
|
+
def call(product:)
|
16
|
+
socket.puts "S,REMOVE CLIENT APP,#{product}\r\n"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dtn
|
4
|
+
module Streaming
|
5
|
+
module Requests
|
6
|
+
module Admin
|
7
|
+
# Tells IQFeed to save the login info
|
8
|
+
#
|
9
|
+
# :param turned_on: True means save info, False means don't
|
10
|
+
class SaveLoginInfo < Request
|
11
|
+
def call(turned_on: true, **)
|
12
|
+
socket.puts "S,SET SAVE LOGIN INFO,#{turned_on ? "On" : "Off"}\r\n"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dtn
|
4
|
+
module Streaming
|
5
|
+
module Requests
|
6
|
+
module Admin
|
7
|
+
# Tells IQFeed to autoconnect to DTN servers on startup or not
|
8
|
+
#
|
9
|
+
# :param turned_on: True means autoconnect, False means don't
|
10
|
+
class SetAutoconnect < Request
|
11
|
+
def call(turned_on: true, **)
|
12
|
+
socket.puts "S,SET AUTOCONNECT,#{turned_on ? "On" : "Off"}\r\n"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dtn
|
4
|
+
module Streaming
|
5
|
+
module Requests
|
6
|
+
module Admin
|
7
|
+
# Request client statistics from IQFeed.
|
8
|
+
#
|
9
|
+
# Call this is you want IQFeed to send you a message every second about
|
10
|
+
# the status of every connection. Lets you know things like number of
|
11
|
+
# subscriptions and if the connection is buffering.
|
12
|
+
class SetClientStats < Request
|
13
|
+
def call(turned_on: true, **)
|
14
|
+
socket.puts "S,CLIENTSTATS #{turned_on ? "ON" : "OFF"}\r\n"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dtn
|
4
|
+
module Streaming
|
5
|
+
module Requests
|
6
|
+
module Admin
|
7
|
+
# Set the user login.
|
8
|
+
#
|
9
|
+
# :param login: IQFeed subscriber's login
|
10
|
+
#
|
11
|
+
# The user of the app must have a subscription to IQFeed. Pass the user's
|
12
|
+
# login either here or in cmd line options when IQFeed is started.
|
13
|
+
class SetLoginid < Request
|
14
|
+
def call(loginid:)
|
15
|
+
socket.puts "S,SET LOGINID,#{loginid}\r\n"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dtn
|
4
|
+
module Streaming
|
5
|
+
module Requests
|
6
|
+
module Admin
|
7
|
+
# Set the user password.
|
8
|
+
#
|
9
|
+
# :param password: IQFeed subscriber's pwd
|
10
|
+
#
|
11
|
+
# The user of the app must have a subscription to IQFeed. Pass the user's
|
12
|
+
# password either here or in cmd line options when IQFeed is started.
|
13
|
+
class SetPassword < Request
|
14
|
+
def call(password:)
|
15
|
+
socket.puts "S,SET PASSWORD,#{password}\r\n"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dtn
|
4
|
+
module Streaming
|
5
|
+
module Requests
|
6
|
+
module Bar
|
7
|
+
# Stop watching a symbol.
|
8
|
+
#
|
9
|
+
# :param symbol: A valid symbol for a security or derivative.
|
10
|
+
class Unwatch < Request
|
11
|
+
def call(symbol:)
|
12
|
+
socket.puts "BR,#{symbol.upcase}\r\n"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dtn
|
4
|
+
module Streaming
|
5
|
+
module Requests
|
6
|
+
module Bar
|
7
|
+
# Request live interval (bar) data.
|
8
|
+
#
|
9
|
+
# :param symbol: Symbol for which you are requesting data.
|
10
|
+
# :param interval: Interval length in interval_type units (can be fractal)
|
11
|
+
# :param interval_type: 's' = secs, 'v' = volume, 't' = ticks
|
12
|
+
# :param begin_filter_time: Earliest time of day for which you want data
|
13
|
+
# :param end_filter_time: Latest time of day for which you want data
|
14
|
+
# :param update_interval: Update the current bar every update secs.
|
15
|
+
# :param begin_datetime: Get back-fill bars starting at begin_datetime
|
16
|
+
# :param lookback_days: Get lookback_days of backfill data
|
17
|
+
# :param lookback_bars: Get lookback_bars of backfill data
|
18
|
+
#
|
19
|
+
# Only one of begin_datetime, lookback_days or lookback_bars should be set.
|
20
|
+
#
|
21
|
+
# Requests live interval data. You can also request some backfill data.
|
22
|
+
# When you call this function:
|
23
|
+
# 1) Client will return HistoricalBar messages with bars
|
24
|
+
# that go back either a) upto begin_datetime, b) upto lookback_days or
|
25
|
+
# c) upto lookback_bars.
|
26
|
+
# 2) The callback on observer update_bar is called on every update
|
27
|
+
# to data for the current live bar.
|
28
|
+
# 3) The callback current_bar is called every time we cross an
|
29
|
+
# interval boundary with data for the now complete bar.
|
30
|
+
class Watch < Request
|
31
|
+
TEMPLATE =
|
32
|
+
"BW,%<symbol>s,%<interval>d,%<begin_datetime>s,%<lookback_days>s," \
|
33
|
+
"%<lookback_bars>s,%<begin_filter_time>s,%<end_filter_time>s,%<id>s," \
|
34
|
+
"%<interval_type>s,'',%<update_interval>d\r\n"
|
35
|
+
|
36
|
+
include Dtn::Concerns::Validation
|
37
|
+
include Dtn::Concerns::Id
|
38
|
+
|
39
|
+
DEFAULT_BEGIN_FILTER_TIME = "093000"
|
40
|
+
DEFAULT_END_FILTER_TIME = "160000"
|
41
|
+
|
42
|
+
LOOKBACK_OPTIONS = %i[begin_datetime lookback_days lookback_bars].freeze
|
43
|
+
|
44
|
+
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
45
|
+
def call(symbol:, interval: 60, update_interval: 5, **options)
|
46
|
+
options.merge!({
|
47
|
+
symbol: symbol.to_s.upcase,
|
48
|
+
interval: validate_int(interval),
|
49
|
+
begin_filter_time: options[:begin_filter_time] || DEFAULT_BEGIN_FILTER_TIME,
|
50
|
+
end_filter_time: options[:end_filter_time] || DEFAULT_END_FILTER_TIME,
|
51
|
+
interval_type: validate_interval_type(options[:interval_type]),
|
52
|
+
update_interval: validate_int(update_interval),
|
53
|
+
id: id,
|
54
|
+
begin_datetime: options[:begin_datetime],
|
55
|
+
lookback_days: options[:lookback_days],
|
56
|
+
lookback_bars: options[:lookback_bars]
|
57
|
+
}).tap { |o| validate_lookback_options(**o) }
|
58
|
+
|
59
|
+
socket.print format(TEMPLATE, options)
|
60
|
+
end
|
61
|
+
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def validate_lookback_options(**value)
|
66
|
+
v = value.slice(*LOOKBACK_OPTIONS)
|
67
|
+
|
68
|
+
return if [
|
69
|
+
[false, false, false],
|
70
|
+
[true, false, false],
|
71
|
+
[false, true, false],
|
72
|
+
[false, false, true]
|
73
|
+
].include?(v.values.map(&:present?))
|
74
|
+
|
75
|
+
raise ValidationError, "Only one of '#{LOOKBACK_OPTIONS.join(", ")}' should be entered, but got #{v}"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dtn
|
4
|
+
module Streaming
|
5
|
+
module Requests
|
6
|
+
module Bar
|
7
|
+
# Request a current watches message.
|
8
|
+
#
|
9
|
+
# IQFeed.exe will send you a list of all securities currently watched
|
10
|
+
#
|
11
|
+
# process_watched_symbols is called in each listener when the list of
|
12
|
+
# current watches message is received.
|
13
|
+
class Watches < Request
|
14
|
+
def call
|
15
|
+
socket.puts "S,REQUEST WATCHES\r\n"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dtn
|
4
|
+
module Streaming
|
5
|
+
module Requests
|
6
|
+
module Level2
|
7
|
+
# Get MarketMakerById
|
8
|
+
#
|
9
|
+
# :param mmid: A valid MMID.
|
10
|
+
class MarketMakerById < Request
|
11
|
+
def call(mmid:)
|
12
|
+
socket.puts "m#{mmid.upcase}\r\n"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Dtn
|
4
|
+
module Streaming
|
5
|
+
module Requests
|
6
|
+
module Level2
|
7
|
+
# Stop watching a symbol.
|
8
|
+
#
|
9
|
+
# :param symbol: A valid symbol for a security or derivative.
|
10
|
+
class Unwatch < Request
|
11
|
+
def call(symbol:)
|
12
|
+
socket.puts "r#{symbol.upcase}\r\n"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|