Dtn
Unofficial DTN (IQFeed) client.
Dependencies
- IQFeed client ~> 6.1
IQFeed API support status
Streaming clients
- [x] Quote (Level 1) client
- [x] Level 2 client
- [x] Bar (Derivative) client
- [x] Admin client
Lookup client
- [x] Historical data
- [x] News data
- [x] Symbol Lookup data
- [ ] Chains Lookup data
- [ ] Market Summary Data (new in protocol 6.1)
Installation
Add this line to your application's Gemfile:
gem 'dtn'
And then execute:
$ bundle install
Or install it yourself as:
$ gem install dtn
Usage
Quick start
Dtn::Lookups::Historical::DailyTimeframe.call(
symbol: :aapl,
begin_date: Date.new(2021, 5, 1),
end_date: Date.new(2021, 6, 1)
)
=>
#<Dtn::Messages::Historical::DailyWeeklyMonthly request_id=1, timestamp=Mon, 03 May 2021 18:06:37 +0000, high=134.07, low=131.83, open=132.04, close=132.54, period_volume=75135100, open_interest=0>
#<Dtn::Messages::Historical::DailyWeeklyMonthly request_id=1, timestamp=Tue, 04 May 2021 18:06:37 +0000, high=131.4899, low=126.7, open=131.19, close=127.85, period_volume=137564718, open_interest=0>
#<Dtn::Messages::Historical::DailyWeeklyMonthly request_id=1, timestamp=Wed, 05 May 2021 18:06:37 +0000, high=130.45, low=127.97, open=129.2, close=128.1, period_volume=84000900, open_interest=0>
#<Dtn::Messages::Historical::DailyWeeklyMonthly request_id=1, timestamp=Thu, 06 May 2021 18:06:37 +0000, high=129.75, low=127.13, open=127.89, close=129.74, period_volume=78128334, open_interest=0>
...
# if block provided, then each message will be yielded as it is processed
Dtn::Lookups::News::Headline.call(limit: 10) do |message|
# ...
end
Supported requests
Keep in mind, that at the time of writing DTN, API has limit of 50 historical requests per minute.
TODO: Attach limiter gem after merge https://github.com/Shopify/limiter/pull/17 https://github.com/Shopify/limiter/pull/19 or use own branch of this gem.
News
- config
ruby Dtn::Lookups::News::Config.call
- headline
ruby Dtn::Lookups::News::Headline.call limit: 10, symbols: 'aapl;fb'
- story_count
ruby Dtn::Lookups::News::StoryCount.call symbols: :aapl, date_range: Date.new(2020,1,1)..Date.new(2020,2,1)
- story
ruby Dtn::Lookups::News::Story.call story_id: '22424363689'
NOTES:
- if XML output option selected, the response will return unparsed XML
Historical
- interval_day
ruby Dtn::Lookups::Historical::IntervalDay.call(symbol: :aapl, interval: 3600, max_datapoints: 50, days: 2)
- tick_timeframe
ruby Dtn::Lookups::Historical::TickTimeframe.call( symbol: :aapl, begin_datetime: begin_datetime, end_datetime: end_datetime, max_datapoints: 50 )
- daily_datapoint
ruby Dtn::Lookups::Historical::DailyDatapoint.call(symbol: :aapl, max_datapoints: 50)
- interval_timeframe
ruby Dtn::Lookups::Historical::IntervalTimeframe.call( symbol: :aapl, interval: 15, max_datapoints: 50, begin_datetime: DateTime.new(2020, 5, 1), end_datetime: DateTime.new(2020, 6, 1) )
- tick_datapoint
ruby Dtn::Lookups::Historical::TickDatapoint.call(symbol: :aapl, max_datapoints: 100)
- weekly_datapoint
ruby Dtn::Lookups::Historical::WeeklyDatapoint.call(symbol: :aapl, max_datapoints: 10)
- daily_timeframe
ruby Dtn::Lookups::Historical::DailyTimeframe.call( symbol: :aapl, begin_date: Date.new(2020, 5, 1), end_date: Date.new(2020, 6, 1) )
- interval_datapoint
ruby Dtn::Lookups::Historical::IntervalDatapoint.call(symbol: :aapl, interval: 3600, max_datapoints: 100)
- monthly_datapoint
ruby Dtn::Lookups::Historical::MonthlyDatapoint.call(symbol: :aapl, max_datapoints: 10)
- tick_day
ruby Dtn::Lookups::Historical::TickDay.call(symbol: :aapl, days: 2, max_datapoints: 50)
NOTES:
- Lookups have extra options from their parents classes. They have appropriate defaults and are easy to customize.
Catalogs
For symbol lookup and description API use a few catalogs, which describe each row. They very rarely change and we can treat them as constants. To reduce requests to API they are requested only once. For easy access to them you can use:
Dtn.listed_markets_catalog
Dtn.naic_codes_catalog
Dtn.security_types_catalog
Dtn.sic_codes_catalog
Dtn.trade_conditions_catalog
Symbol lookup
- by_sic
ruby Dtn::Lookups::Symbol::BySic.call(search_line: '42')
- by_naic
ruby Dtn::Lookups::Symbol::ByNaic.call(search_line: '42')
- by_filter
ruby Dtn::Lookups::Symbol::ByFilter.call(field_to_search: "s", search_line: "aap", filter_type: "t", filter_value: "1")
Streaming data
All streaming data is using Observer pattern, so you can connect a few listeners to any client with minimal cost. Below, you will get the examples with simple observers, but there is an Observer for easier development & testing.
Quotes (Level1)
Streaming data is using Observers to deliver the results. Keep in mind, that observers will receive data until you unsubscribe from it or stop the client.
Summary message always come with all the possible fields, while for Update message
it is possible to add a filter with client.request.quote.update_fields list: %w[Bid Ask]
These methods do not allow any historical data access, only real time.
class Observer
# data callbacks are optional and match message class
def level1_summary(message:)
puts
end
def level1_update(message:)
puts
end
# one of system methods callback
def disconnected(message:)
puts
end
end
client = Dtn::Streaming::Clients::Quote.new
client.observers << Observer.new
client.request.quote.watch symbol: :aapl
sleep 10
client.stop
Here you will find all level1 streaming requests with appropriate documentation.
Bars data
Get live data as interval bar data. It allows to look back and fetch historical data and get current (live) data as well, details
class Observer
# this callback will return all historical bars for the symbol
def (message:)
puts
end
# Here you get live updates until the current bar is formed
def (message:)
puts
end
# when the current bar was formed, it will be processed by this callback
def (message:)
puts
end
end
client = Dtn::Streaming::Clients::Bar.new
client.observers << Observer.new
client.request..watch symbol: :aapl
sleep 10
client.stop
Admin
Admin data management. See other commands in here
client.observers << Observer.new
client.request.admin.set_client_stats turned_on: false
Level2
Connection to level2 data. See other commands in here
client.observers << Observer.new
client.request.level2.watch symbol: :aapl
Config
In case you are using DTN client running remotely (no questions asked how you
can do it), you can specify the host with Dtn.host = 'my_host'
setting
Development
After checking out the repo, run bin/setup
to install dependencies. Then, run
bundle exec rake
to run the tests. You can also run bin/console
for an
interactive prompt that will allow you to experiment.
Test specs are using recorded output from DTN client. The recorded file is set
by the RSpec option socket_recorder
, so you can share 1 recording with a few
specs. If the file is missing, then specs will do real request to the api.
socket_recorder
will use the pre-defined Date for the specs from the file
current_day to
minimise recordings rewrites. To bump the date to the yesterday business day
you can use
$ bundle exec rake spec:set_spec_date
To run windows DTN client you can use the docker-compose up
(before execution
pls fill in .env
file with your credentials following the pattern from
.env.example)
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/kvokka/dtn. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.
License
The gem is available as open source under the terms of the MIT License.
Code of Conduct
Everyone interacting in the Dtn project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.