bberg 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --markup markdown --title "bberg Documentation" --protected lib/**/*.rb README.md LICENSE.TXT
data/ChangeLog.md ADDED
@@ -0,0 +1,3 @@
1
+ ### 0.1.0 / 2011-03-10
2
+
3
+ * Initial release:
data/Gemfile ADDED
@@ -0,0 +1,29 @@
1
+ source :rubygems
2
+
3
+ #gemspec
4
+
5
+ gem 'activesupport'
6
+ gem 'i18n'
7
+ gem 'tzinfo'
8
+ gem 'rake', '~> 0.8.7'
9
+
10
+ group :development do
11
+ gem 'ore-core', '~> 0.1.0'
12
+ gem 'rspec', '~> 2.5.0'
13
+ case RUBY_PLATFORM
14
+ when 'java'
15
+ gem 'maruku'
16
+ else
17
+ gem 'bluecloth', '>= 2.0.0'
18
+ end
19
+ gem 'yard', '~> 0.6.0'
20
+ gem 'guard', '~> 0.3.0'
21
+ gem 'guard-rspec', '~> 0.2.0'
22
+ gem 'ci_reporter', '~> 1.6.4'
23
+ gem 'rcov', '~> 0.9.9'
24
+ gem 'flog', '~> 2.5.0'
25
+ gem 'yardstick'
26
+ # install separately so that we can do a bundle install --deployment --without development
27
+ # when packaging to .exe
28
+ #gem 'rawr', :git => 'https://github.com/sundbp/rawr.git'
29
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,64 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activesupport (3.0.3)
5
+ builder (3.0.0)
6
+ ci_reporter (1.6.4)
7
+ builder (>= 2.1.2)
8
+ configuration (1.2.0)
9
+ diff-lcs (1.1.2)
10
+ flog (2.5.0)
11
+ ruby_parser (~> 2.0)
12
+ sexp_processor (~> 3.0)
13
+ guard (0.3.0)
14
+ open_gem (~> 1.4.2)
15
+ thor (~> 0.14.6)
16
+ guard-rspec (0.2.0)
17
+ guard (>= 0.2.2)
18
+ i18n (0.5.0)
19
+ launchy (0.3.7)
20
+ configuration (>= 0.0.5)
21
+ rake (>= 0.8.1)
22
+ maruku (0.6.0)
23
+ syntax (>= 1.0.0)
24
+ open_gem (1.4.2)
25
+ launchy (~> 0.3.5)
26
+ ore-core (0.1.0)
27
+ rake (0.8.7)
28
+ rcov (0.9.9-java)
29
+ rspec (2.5.0)
30
+ rspec-core (~> 2.5.0)
31
+ rspec-expectations (~> 2.5.0)
32
+ rspec-mocks (~> 2.5.0)
33
+ rspec-core (2.5.1)
34
+ rspec-expectations (2.5.0)
35
+ diff-lcs (~> 1.1.2)
36
+ rspec-mocks (2.5.0)
37
+ ruby_parser (2.0.5)
38
+ sexp_processor (~> 3.0)
39
+ sexp_processor (3.0.5)
40
+ syntax (1.0.0)
41
+ thor (0.14.6)
42
+ tzinfo (0.3.23)
43
+ yard (0.6.4)
44
+ yardstick (0.2.0)
45
+ yard (~> 0.6.1)
46
+
47
+ PLATFORMS
48
+ java
49
+
50
+ DEPENDENCIES
51
+ activesupport
52
+ ci_reporter (~> 1.6.4)
53
+ flog (~> 2.5.0)
54
+ guard (~> 0.3.0)
55
+ guard-rspec (~> 0.2.0)
56
+ i18n
57
+ maruku
58
+ ore-core (~> 0.1.0)
59
+ rake (~> 0.8.7)
60
+ rcov (~> 0.9.9)
61
+ rspec (~> 2.5.0)
62
+ tzinfo
63
+ yard (~> 0.6.0)
64
+ yardstick
data/Guardfile ADDED
@@ -0,0 +1,6 @@
1
+ # rspec
2
+ guard 'rspec' do
3
+ watch(%r{^spec/.+_spec\.rb})
4
+ watch(%r{^lib/(.+)\.rb}) { |m| p "spec/#{m[1]}_spec.rb"; "spec/#{m[1]}_spec.rb" }
5
+ watch('spec/spec_helper.rb') { "spec" }
6
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 pts
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,51 @@
1
+ # bberg
2
+
3
+ * [Homepage](http://rubygems.org/gems/bberg)
4
+ * [Github](http://github.com/sundbp/bberg/)
5
+ * [Issue tracker](http://github.com/sundbp/bberg/issues)
6
+
7
+ ## Description
8
+
9
+ A library to use the Bloomberg Java API from jruby
10
+
11
+ ## Features
12
+
13
+ So far the following requests can be made:
14
+
15
+ * HistoricalDataRequest
16
+ * ReferenceDataRequest
17
+
18
+ We'll be working on adding all the requests supported by the Java API, including "subscriptions".
19
+
20
+ Feel free to pitch in :)
21
+
22
+ ## Examples
23
+
24
+ TODO: add examples. For now look at the specs for a couple of examples
25
+
26
+ ## Requirements
27
+
28
+ * The Bloomberg Java API jar
29
+
30
+ ## Install
31
+
32
+ $ gem install bberg
33
+
34
+ The gem comes with a drb server to make it simpler to use the API from several processes on
35
+ the same machine (multiple machines not allowed by the Java API copyright, same applies here):
36
+
37
+ $ bberg_drb_server
38
+
39
+ To create a stand alone executable do the following (after checking out the git repo):
40
+
41
+ $ bundle install
42
+ $ bundle install --deployment --without development
43
+ $ rake bberg:create_exe
44
+
45
+ This creates a folder with a .exe in ../bberg-package/windows/
46
+
47
+ ## Copyright
48
+
49
+ Copyright (c) 2010 pts
50
+
51
+ See {file:LICENSE.txt} for details.
data/Rakefile ADDED
@@ -0,0 +1,88 @@
1
+ require 'rubygems'
2
+ require 'fileutils'
3
+
4
+ begin
5
+ require 'rawr'
6
+ rescue LoadError
7
+ # just silently ignore it, for development we don't have rawr available
8
+ nil
9
+ end
10
+
11
+ begin
12
+ require 'bundler'
13
+ rescue LoadError => e
14
+ STDERR.puts e.message
15
+ STDERR.puts "Run `gem install bundler` to install Bundler."
16
+ STDERR.puts "But we'll continue ahead in case you're trying to bundle a .exe file.."
17
+ end
18
+
19
+ begin
20
+ Bundler.setup(:development) if defined?(Bundler)
21
+ rescue Bundler::BundlerError => e
22
+ STDERR.puts e.message
23
+ STDERR.puts "Run `bundle install` to install missing gems."
24
+ exit e.status_code
25
+ end
26
+
27
+ require 'rake'
28
+
29
+ begin
30
+ require 'rspec/core/rake_task'
31
+ RSpec::Core::RakeTask.new
32
+
33
+ require 'yard'
34
+ YARD::Rake::YardocTask.new
35
+
36
+ require 'yardstick/rake/measurement'
37
+ Yardstick::Rake::Measurement.new(:yardstick_measure) do |measurement|
38
+ measurement.output = 'measurement/report.txt'
39
+ end
40
+
41
+ require 'yardstick/rake/verify'
42
+ Yardstick::Rake::Verify.new do |verify|
43
+ verify.threshold = 80
44
+ end
45
+
46
+ rescue LoadError => e
47
+ STDERR.puts e.message
48
+ STDERR.puts "But we'll continue ahead in case you're trying to create a .exe file.."
49
+ end
50
+
51
+ task :default => :spec
52
+ namespace :bberg do
53
+ desc "create a .exe file for the bberg drb server"
54
+ task :create_exe => [:clean_for_exe, :download_jruby_jar, "rawr:bundle:exe"]
55
+
56
+ desc "clean up files in order to create a clean .exe"
57
+ task :clean_for_exe do
58
+ FileUtils.rm_rf('pkg')
59
+ end
60
+
61
+ desc "download jruby-complete.jar"
62
+ task :download_jruby_jar do
63
+ jar_file = File.join('vendor', 'java', 'jruby-complete-1.5.6.jar')
64
+ if File.exists? jar_file
65
+ puts "Already have a copy of jruby-complete.jar."
66
+ else
67
+ require 'net/http'
68
+ require 'uri'
69
+ http_proxy = ENV['http_proxy']
70
+ http_proxy ||= ENV['HTTP_PROXY']
71
+ http_object = if http_proxy
72
+ uri = URI.parse(http_proxy)
73
+ proxy_user, proxy_pass = uri.userinfo.split(/:/) if uri.userinfo
74
+ Net::HTTP::Proxy(uri.host, uri.port, proxy_user, proxy_pass)
75
+ else
76
+ Net::HTTP
77
+ end
78
+ http_object.start('jruby.org.s3.amazonaws.com') do |http|
79
+ puts "Downloading jruby-complete.jar.."
80
+ #response = http.get('/downloads/1.6.0.RC3/jruby-complete-1.6.0.RC3.jar')
81
+ response = http.get('/downloads/1.5.6/jruby-complete-1.5.6.jar')
82
+ FileUtils.mkdir_p(File.join('vendor', 'java'))
83
+ open(jar_file, "wb") do |file|
84
+ file.write(response.body)
85
+ end
86
+ end
87
  end
88
+ end
89
+ end
data/bberg.gemspec ADDED
@@ -0,0 +1,10 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ begin
4
+ Ore::Specification.new do |gemspec|
5
+ # custom logic here
6
+ end
7
+ rescue NameError
8
+ STDERR.puts "The 'bberg.gemspec' file requires Ore."
9
+ STDERR.puts "Run `gem install ore-core` to install Ore."
10
+ end
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'bberg/drb_server'
@@ -0,0 +1,91 @@
1
+ configuration do |c|
2
+ # The name for your resulting application file (e.g., if the project_name is 'foo' then you'll get foo.jar, foo.exe, etc.)
3
+ # default value: "bberg"
4
+ #
5
+ c.project_name = "bberg_drb_server"
6
+
7
+ # Undocumented option 'output_dir'
8
+ # default value: "package"
9
+ #
10
+ c.output_dir = "../bberg-package"
11
+
12
+ c.executable_type = "console"
13
+
14
+ # The main ruby file to invoke, minus the .rb extension
15
+ # default value: "main"
16
+ #
17
+ c.main_ruby_file = "lib/bberg/drb_server_rawr_launcher"
18
+
19
+ # The fully-qualified name of the main Java file used to initiate the application.
20
+ # default value: "org.rubyforge.rawr.Main"
21
+ #
22
+ #c.main_java_file = "org.rubyforge.rawr.Main"
23
+
24
+ # A list of directories where source files reside
25
+ # default value: ["src"]
26
+ #
27
+ c.source_dirs = ['.']
28
+
29
+ # A list of regexps of files to exclude
30
+ # default value: []
31
+ #
32
+ c.source_exclude_filter = [/jruby-complete-.*.jar/]
33
+
34
+ # Whether Ruby source files should be compiled into .class files
35
+ # default value: true
36
+ #
37
+ c.compile_ruby_files = false
38
+
39
+ # A list of individual Java library files to include.
40
+ # default value: []
41
+ #
42
+ #c.java_lib_files = []
43
+
44
+ # A list of directories for rawr to include . All files in the given directories get bundled up.
45
+ # default value: ["lib/java"]
46
+ #
47
+ c.java_lib_dirs = ["vendor/java"]
48
+
49
+ # Undocumented option 'files_to_copy'
50
+ # default value: []
51
+ #
52
+ #c.files_to_copy = []
53
+
54
+ # Undocumented option 'target_jvm_version'
55
+ # default value: 1.6
56
+ #
57
+ #c.target_jvm_version = 1.6
58
+
59
+ # Undocumented option 'jvm_arguments'
60
+ # default value: ""
61
+ #
62
+ #c.jvm_arguments = ""
63
+
64
+ # Undocumented option 'java_library_path'
65
+ # default value: ""
66
+ #
67
+ #c.java_library_path = ""
68
+
69
+ # Undocumented option 'extra_user_jars'
70
+ # default value: {}
71
+ #
72
+ #c.extra_user_jars[:data] = { :directory => 'data/images/png',
73
+ # :location_in_jar => 'images',
74
+ # :exclude => /*.bak$/ }
75
+
76
+ # Undocumented option 'mac_do_not_generate_plist'
77
+ # default value: nil
78
+ #
79
+ #c.mac_do_not_generate_plist = nil
80
+
81
+ # Undocumented option 'mac_icon_path'
82
+ # default value: nil
83
+ #
84
+ #c.mac_icon_path = nil
85
+
86
+ # Undocumented option 'windows_icon_path'
87
+ # default value: nil
88
+ #
89
+ #c.windows_icon_path = nil
90
+
91
+ end
data/gemspec.yml ADDED
@@ -0,0 +1,12 @@
1
+ name: bberg
2
+ summary: "Bloomberg API wrapper for ruby"
3
+ description: "Makes the Bloomberg Java API available from jruby - in ruby friendly manner."
4
+ license: MIT
5
+ authors: Patrik Sundberg
6
+ email: patrik.sundberg@gmail.com
7
+ homepage: http://rubygems.org/gems/bberg
8
+ has_yard: true
9
+
10
+ development_dependencies:
11
+ bundler: ~> 1.0.0
12
+ yard: ~> 0.6.0
data/lib/bberg.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'active_support/time'
2
+
3
+ require 'bberg/version'
4
+ require 'bberg/bberg_wrapper'
5
+ require 'bberg/bberg_exception'
6
+ require 'bberg/client'
@@ -0,0 +1,5 @@
1
+ module Bberg
2
+ # Exception class that is thrown from inside the bberg gem
3
+ class BbergException < StandardError
4
+ end
5
+ end
@@ -0,0 +1,32 @@
1
+ require 'java'
2
+
3
+ module Bberg
4
+
5
+ # path to where the bloomberg java API jar can be found.
6
+ #
7
+ # either uses the path in the env variable BBERG_JAVA_HOME
8
+ # or defaults to 'C:/blp/API/APIv3/JavaAPI/v3.3.3.3/lib'
9
+ # @return [String] path to jar
10
+ def self.jar_path
11
+ # load either from BBERG_JAVA_HOME or the default location
12
+ base_path = ENV['BBERG_JAVA_HOME'].nil? ? 'C:/blp/API/APIv3/JavaAPI/v3.3.3.3/lib' : ENV['BBERG_JAVA_HOME']
13
+ File.join(base_path, 'blpapi3.jar')
14
+ end
15
+
16
+ # Module to hold references to the native java API classes in a ruby friendly way.
17
+ module Native
18
+ require Bberg.jar_path
19
+ import com.bloomberglp.blpapi.CorrelationID
20
+ import com.bloomberglp.blpapi.Datetime
21
+ import com.bloomberglp.blpapi.Element
22
+ import com.bloomberglp.blpapi.Event
23
+ import com.bloomberglp.blpapi.Message
24
+ import com.bloomberglp.blpapi.MessageIterator
25
+ import com.bloomberglp.blpapi.Request
26
+ import com.bloomberglp.blpapi.Service
27
+ import com.bloomberglp.blpapi.Session
28
+ import com.bloomberglp.blpapi.SessionOptions
29
+ import com.bloomberglp.blpapi.Schema
30
+ end
31
+
32
+ end
@@ -0,0 +1,64 @@
1
+ require 'date'
2
+
3
+ require 'bberg/requests'
4
+
5
+ module Bberg
6
+
7
+ # Main class for making synchronous bberg data requests.
8
+ class Client
9
+
10
+ # Create a new instance of Client
11
+ # @param [String] host host running bberg we want to connect to
12
+ # @param [Fixnum] port port to connect to
13
+ def initialize(host = "localhost", port = 8194)
14
+ @session_options = Bberg::Native::SessionOptions.new
15
+ @session_options.setServerHost("localhost")
16
+ @session_options.setServerPort(8194)
17
+ end
18
+
19
+ # Perform a historical data request.
20
+ # @param [#each|String] identifiers a list of identifiers for this request
21
+ # @param [Time] start_time start of historical range
22
+ # @param [Time] end_time end of historical range
23
+ # @param [Hash] options_arg specification of what fields or other parameters to use for the request.
24
+ # @return [Hash] result in Hash format.
25
+ def historical_data_request(identifiers, start_time, end_time, options = {})
26
+ request = Bberg::Requests::HistoricalDataRequest.new(@session_options, identifiers, start_time, end_time, options)
27
+ request.perform_request
28
+ end
29
+
30
+ # Perform a reference data request.
31
+ # @param [#each|String] identifiers a list of identifiers for this request
32
+ # @param [Hash] options_arg specification of what fields or other parameters to use for the request.
33
+ # @return [Hash] result in Hash format.
34
+ def reference_data_request(identifiers, options)
35
+ request = Bberg::Requests::ReferenceDataRequest.new(@session_options, identifiers, options)
36
+ request.perform_request
37
+ end
38
+
39
+ # Convencience method to perform a reference data request for holiday calendar data.
40
+ # @param [String] currency which settlement currency to use for calendar.
41
+ # @param [String] calendar name of calendar.
42
+ # @param [Date|Time] start_date when to start calendar from.
43
+ # @param [Date|Time] end_date when to end calendar.
44
+ # @return [Array] an array of Dates.
45
+ def get_holidays_for_calendar(currency, calendar, start_date, end_date)
46
+ overrides = Hash[
47
+ "CALENDAR_START_DATE", start_date,
48
+ "CALENDAR_END_DATE", end_date
49
+ ]
50
+ overrides["SETTLEMENT_CALENDAR_CODE"] = calendar unless calendar.nil?
51
+ options = Hash[ :fields => ["CALENDAR_HOLIDAYS"]]
52
+ options[:overrides] = overrides
53
+
54
+ response = self.reference_data_request(currency, options)
55
+ result = response[currency]["CALENDAR_HOLIDAYS"].map {|o| o["Holiday Date"]}
56
+ result
57
+ end
58
+
59
+ ################## PRIVATE #######################
60
+
61
+ private
62
+
63
+ end
64
+ end
@@ -0,0 +1,17 @@
1
+ require 'drb'
2
+ require 'socket'
3
+
4
+ require 'bberg'
5
+
6
+ hostname = Socket.gethostbyname(Socket.gethostname).first
7
+ port = ARGV.size == 1 ? ARGV.shift : 9000
8
+
9
+ uri = "druby://#{hostname}:#{port}"
10
+
11
+ puts "Starting server using URI = '#{uri}'"
12
+
13
+ DRb.start_service uri, Bberg::Client.new
14
+
15
+ puts "Ready to accept requests!"
16
+
17
+ DRb.thread.join
@@ -0,0 +1,15 @@
1
+ # find the base of the current jar file
2
+ base = __FILE__.split('!').first + '!'
3
+
4
+ # first setup LOAD_PATH
5
+
6
+ # add our gem's lib dir
7
+ $LOAD_PATH << File.join(base, 'lib')
8
+
9
+ # look through all bundled gems
10
+ Dir[File.join(base, 'vendor/bundle') + '/**/lib'].each do |dir|
11
+ $LOAD_PATH << dir
12
+ end
13
+
14
+ # then launch server
15
+ require 'bberg/drb_server'
@@ -0,0 +1,3 @@
1
+ require 'bberg/requests/refdata_request_base'
2
+ require 'bberg/requests/historical_data_request'
3
+ require 'bberg/requests/reference_data_request'
@@ -0,0 +1,109 @@
1
+ require 'bberg/bberg_exception'
2
+ require 'bberg/requests/refdata_request_base'
3
+
4
+ module Bberg
5
+ module Requests
6
+
7
+ # A class for preforming historical data requets.
8
+ class HistoricalDataRequest < RefdataRequestBase
9
+
10
+ DEFAULT_OPTIONS = Hash[
11
+ :fields => ["PX_SETTLE"],
12
+ :frequency => "DAILY"
13
+ ]
14
+
15
+ # Create new instance.
16
+ # @param [Bberg::Native::SessionOptions] session_options to specify how to connect session.
17
+ # @param [#each|String] identifiers a list of identifiers for this request
18
+ # @param [Time] start_time start of historical range
19
+ # @param [Time] end_time end of historical range
20
+ # @param [Hash] options_arg specification of what fields or other parameters to use for the request.
21
+ def initialize(session_options, identifiers, start_time, end_time, options_arg = {})
22
+ @session_options = session_options
23
+
24
+ @identifiers = unless identifiers.respond_to? 'each'
25
+ [identifiers]
26
+ else
27
+ identifiers
28
+ end
29
+
30
+ @start_time = start_time
31
+ @end_time = end_time
32
+
33
+ @options = DEFAULT_OPTIONS.merge(options_arg)
34
+ end
35
+
36
+ # Create a historical data request.
37
+ def create_request
38
+ request = @svc.createRequest("HistoricalDataRequest")
39
+ request.set("startDate", @start_time.strftime("%Y%m%d"))
40
+ request.set("endDate", @end_time.strftime("%Y%m%d"))
41
+ request.set("periodicitySelection", @options[:frequency])
42
+ request.set("returnEids", false)
43
+ @identifiers.each {|identifier| request.append("securities", identifier) }
44
+ @options[:fields].each {|f| request.append("fields", f) }
45
+ @request = request
46
+ end
47
+
48
+ # Parse event for HistoricalDataResponse.
49
+ # @return [Hash] event parsed into a Hash format.
50
+ def parse_response(event)
51
+ iter = event.messageIterator()
52
+ result = Hash.new
53
+
54
+ while iter.hasNext()
55
+
56
+ message = iter.next()
57
+ raise Bberg::BbergException.new("Got a response with incorrect correlation id!") if message.correlationID != @req_id
58
+ msg_type = message.messageType().toString()
59
+ raise Bberg::BbergException.new("Expected message of type HistoricalDataResponse but got #{msg_type}") if msg_type != "HistoricalDataResponse"
60
+
61
+ field_data = message.getElement("securityData").getElement("fieldData")
62
+ security_name = message.getElement("securityData").getElementAsString("security")
63
+
64
+ result[security_name] ||= []
65
+
66
+ (0..(field_data.numValues - 1)).each do |field_num|
67
+ field_values = get_field_values(field_data, field_num)
68
+ result[security_name] << field_values
69
+ end
70
+ end
71
+ result
72
+ end
73
+
74
+ ##################### PRIVATE ############################
75
+
76
+ private
77
+
78
+ def get_field_values(field_data, field_num)
79
+ element = field_data.getValueAsElement(field_num)
80
+ timestamp = convert_to_rb_time(element.getElementAsDatetime("date"))
81
+ values = Hash.new
82
+ values["date"] = timestamp
83
+
84
+ @options[:fields].each do |field|
85
+ raise Bberg::BbergException.new("Can't find required field #{field} in response") unless element.hasElement(field)
86
+ field_element = element.getElement(field)
87
+
88
+ data_type = element.getElement(field).datatype()
89
+
90
+ values[field] = case data_type.intValue()
91
+ when Bberg::Native::Schema::Datatype::Constants::INT32
92
+ element.getElementAsInt32(field).to_i
93
+ when Bberg::Native::Schema::Datatype::Constants::INT64
94
+ element.getElementAsInt64(field).to_i
95
+ when Bberg::Native::Schema::Datatype::Constants::FLOAT32
96
+ element.getElementAsFloat32(field).to_f
97
+ when Bberg::Native::Schema::Datatype::Constants::FLOAT64
98
+ element.getElementAsFloat64(field).to_f
99
+ else
100
+ raise Bberg::BbergException.new("Unsupported data type in response: #{data_type.to_s}")
101
+ end
102
+ end
103
+ values
104
+ end
105
+
106
+ end
107
+
108
+ end
109
+ end
@@ -0,0 +1,179 @@
1
+ require 'bberg/bberg_exception'
2
+
3
+ module Bberg
4
+
5
+ # Module containing classes for the various bberg requests that can be made
6
+ module Requests
7
+
8
+ # Base class for reference data requests.
9
+ # Child classes implements particular requests, using features of this base class.
10
+ class RefdataRequestBase
11
+
12
+ # raises exception, do not instantiate base class - only use child classes.
13
+ def initialize
14
+ raise Bberg::BbergException.new("Do not instantiate base class!")
15
+ end
16
+
17
+ # Perform a synchronous reference data request.
18
+ # Calls (#create_request) to create the request object to send.
19
+ # Blocks while waiting for the response.
20
+ # @return [Hash] A parsed response in the form of a Hash.
21
+ def perform_request
22
+ @session, @svc, @req_id = create_ref_data_service()
23
+
24
+ create_request
25
+
26
+ @session.sendRequest(@request, @req_id)
27
+
28
+ response = retrieve_response
29
+
30
+ @session.stop()
31
+ @session = nil
32
+
33
+ response
34
+ end
35
+
36
+ # Create the reference data request to send to server.
37
+ # To be implemented by specialized child classes.
38
+ # Implementation on base class raises exception.
39
+ def create_request
40
+ raise Bberg::BbergException.new("Not implemented on base class!")
41
+ end
42
+
43
+ # Retrieve response for this request.
44
+ # Will retrieve events from the request's session until an event of type REPONSE is found.
45
+ # For each event (partial or not) it will callse (#parse_response) and merge the hash
46
+ # returned into a cummulitative result.
47
+ #
48
+ # Note: if you set the $DEBUG flag the unparsed event will be printed on STDOUT.
49
+ # @return [Hash] A parsed response in the form of a Hash.
50
+ def retrieve_response
51
+ done = false
52
+ result = Hash.new
53
+ until done
54
+ event = @session.nextEvent()
55
+ case event.eventType().intValue()
56
+ when Bberg::Native::Event::EventType::Constants::RESPONSE
57
+ print_response_event(event) if $DEBUG
58
+ event_result = parse_response(event)
59
+ result = hash_merge_concat(result, event_result)
60
+ done = true
61
+ when Bberg::Native::Event::EventType::Constants::PARTIAL_RESPONSE
62
+ print_response_event(event) if $DEBUG
63
+ event_result = parse_response(event)
64
+ result = hash_merge_concat(result, event_result)
65
+ else
66
+ print_other_event(event) if $DEBUG
67
+ end
68
+ end
69
+ result
70
+ end
71
+
72
+ # Parse response from server.
73
+ # Ideally this should convert the java response into a ruby friendly format.
74
+ # To be implemented by specialized child classes.
75
+ # Implementation on base class raises exception.
76
+ # @return [Hash] the information in the result parsed to Hash format.
77
+ def parse_response(event)
78
+ raise Bberg::BbergException.new("Not implemented in base class!")
79
+ end
80
+
81
+ ##################### PROTECTED ############################
82
+
83
+ protected
84
+
85
+ # Create a reference data service.
86
+ # This both creates and starts a session, and opens a refdata service.
87
+ # @return [Bberg::Native::Session, Object, Fixnum] session, service and request ID.
88
+ def create_ref_data_service
89
+ session = Bberg::Native::Session.new(@session_options)
90
+ raise Bberg::BbergException.new("Could not start session!") unless session.start()
91
+ raise Bberg::BbergException.new("Could not open service!") unless session.openService("//blp/refdata")
92
+ request_id = get_correlation_id()
93
+ ref_data_service = session.getService("//blp/refdata")
94
+ [session, ref_data_service, request_id]
95
+ end
96
+
97
+ # Get correlation ID.
98
+ #
99
+ # NOTE: this needs to be updated so we have increasing unique IDs here.
100
+ # @return [Fixnum] correlation ID.
101
+ def get_correlation_id
102
+ # TODO: we need a mutex protected instance variable of increasing ID's to pass in here
103
+ Bberg::Native::CorrelationID.new(1)
104
+ end
105
+
106
+ # Utility method to merge and concatenate two Hashes.
107
+ #
108
+ # This is useful for creating a cummulitative Hash result when reply consists of several events.
109
+ # @param [Hash] existing_hash what we have so far
110
+ # @param [Hash] new_hash partial result to add
111
+ # @return [Hash] merged and concatenated result
112
+ def hash_merge_concat(existing_hash, new_hash)
113
+ new_hash.each do |key, value|
114
+ if existing_hash.has_key? key
115
+ existing_hash[key] = existing_hash[key].concat(value)
116
+ else
117
+ existing_hash[key] = value
118
+ end
119
+ end
120
+ existing_hash
121
+ end
122
+
123
+ # Utility method to convert a ruby values to their bberg format.
124
+ #
125
+ # So far only time like types are affected.
126
+ def convert_value_to_bberg(value)
127
+ if value.is_a? Date or value.is_a? DateTime or value.is_a? Time
128
+ value.strftime("%Y%m%d")
129
+ else
130
+ value
131
+ end
132
+ end
133
+
134
+ # Convert a Java::ComBloomberglpBlpapi::Datetime to a ruby Time
135
+ # @return [Time] value as Time
136
+ def convert_to_rb_time(dt)
137
+ hour = dt.hour == 24 ? 0 : dt.hour
138
+ Time.local(dt.year, dt.month, dt.dayOfMonth, hour, dt.minute, dt.second, dt.milliSecond)
139
+ end
140
+
141
+ # Convert a Java::ComBloomberglpBlpapi::Datetime to a ruby Date
142
+ # @return [Date] value as Date
143
+ def convert_to_rb_date(d)
144
+ Date.new(d.year, d.month, d.dayOfMonth)
145
+ end
146
+
147
+ ##################### PRIVATE ############################
148
+
149
+ private
150
+
151
+ def print_response_event(event)
152
+ iter = event.messageIterator()
153
+ while iter.hasNext()
154
+ message = iter.next()
155
+ puts "correlationID=" + message.correlationID().to_s
156
+ puts "messageType =" + message.messageType().toString()
157
+ puts message.toString()
158
+ end
159
+ end
160
+
161
+ def print_other_event(event)
162
+ puts "EventType=" + event.eventType().toString()
163
+ iter = event.messageIterator()
164
+ while iter.hasNext()
165
+ message = iter.next()
166
+ puts "correlationID=" + message.correlationID().to_s
167
+ puts "messageType =" + message.messageType().toString()
168
+ puts message.toString()
169
+ if Bberg::Native::Event::EventType::Constants::SESSION_STATUS == event.eventType().intValue() and
170
+ "SessionStopped" == message.messageType().toString()
171
+ puts "Terminating: " + message.messageType()
172
+ exit
173
+ end
174
+ end
175
+ end
176
+
177
+ end
178
+ end
179
+ end
@@ -0,0 +1,134 @@
1
+ require 'date'
2
+ require 'bberg/bberg_exception'
3
+ require 'bberg/requests/refdata_request_base'
4
+
5
+ module Bberg
6
+ module Requests
7
+
8
+ # A class for preforming reference data requets.
9
+ class ReferenceDataRequest < RefdataRequestBase
10
+
11
+ DEFAULT_OPTIONS = Hash[
12
+ :fields => ["PX_SETTLE"],
13
+ :useUTCTime => true,
14
+ :returnEids => false
15
+ ]
16
+
17
+ # Create new instance.
18
+ # @param [Bberg::Native::SessionOptions] session_options to specify how to connect session.
19
+ # @param [#each|String] identifiers a list of identifiers for this request
20
+ # @param [Hash] options_arg specification of what fields or other parameters to use for the request.
21
+ def initialize(session_options, identifiers, options_arg = {})
22
+ @session_options = session_options
23
+
24
+ @identifiers = unless identifiers.respond_to? 'each'
25
+ [identifiers]
26
+ else
27
+ identifiers
28
+ end
29
+
30
+ @options = DEFAULT_OPTIONS.merge(options_arg)
31
+ end
32
+
33
+ # Create a reference data request.
34
+ def create_request
35
+ request = @svc.createRequest("ReferenceDataRequest")
36
+
37
+ @identifiers.each {|identifier| request.append("securities", identifier) }
38
+
39
+ @options.each do |key, value|
40
+ next if key == :fields or key == :overrides
41
+ request.set(key.to_s, convert_value_to_bberg(value))
42
+ end
43
+
44
+ @options[:fields].each {|f| request.append("fields", f) }
45
+
46
+ overrides = request.getElement("overrides")
47
+ @options[:overrides].each do |field_id, value|
48
+ new_override = overrides.appendElement()
49
+ new_override.setElement("fieldId", field_id.to_s)
50
+ new_override.setElement("value", convert_value_to_bberg(value))
51
+ end
52
+ @request = request
53
+ end
54
+
55
+ # Parse event for ReferenceDataResponse.
56
+ # @return [Hash] event parsed into a Hash format.
57
+ def parse_response(event)
58
+ iter = event.messageIterator()
59
+ result = Hash.new
60
+
61
+ while iter.hasNext()
62
+
63
+ message = iter.next()
64
+ raise Bberg::BbergException.new("Got a response with incorrect correlation id!") if message.correlationID != @req_id
65
+ msg_type = message.messageType().toString()
66
+ raise Bberg::BbergException.new("Expected message of type ReferenceDataResponse but got #{msg_type}") if msg_type != "ReferenceDataResponse"
67
+
68
+ security_data_array = message.getElement("securityData")
69
+ (0..(security_data_array.numValues - 1)).each do |sec_num|
70
+ security_data = security_data_array.getValueAsElement(sec_num)
71
+ security_name = security_data.getElementAsString("security")
72
+ field_data = security_data.getElement("fieldData")
73
+
74
+ result[security_name] ||= Hash.new
75
+
76
+ (0..(field_data.numElements - 1)).each do |field_num|
77
+ field_element = field_data.getElement(field_num)
78
+ values = if field_element.isArray
79
+ process_array_type(field_element)
80
+ else
81
+ get_element_values(field_data, field_num)
82
+ end
83
+ result[security_name][field_element.name.toString] = values
84
+ end
85
+ end
86
+ end
87
+ result
88
+ end
89
+
90
+ ##################### PRIVATE ############################
91
+
92
+ private
93
+
94
+ def process_array_type(element)
95
+ result = []
96
+ (0..(element.numValues - 1)).each do |num|
97
+ sub_element = element.getValueAsElement(num)
98
+ values = if sub_element.isArray
99
+ process_array_type(sub_element)
100
+ else
101
+ get_element_values(sub_element)
102
+ end
103
+ result << values
104
+ end
105
+ result
106
+ end
107
+
108
+ def get_element_values(sub_element)
109
+ values = Hash.new
110
+ iter = sub_element.elementIterator()
111
+ while iter.hasNext()
112
+ e = iter.next()
113
+ values[e.name.toString] = case e.datatype.intValue()
114
+ when Bberg::Native::Schema::Datatype::Constants::INT32
115
+ e.getValueAsInt32().to_i
116
+ when Bberg::Native::Schema::Datatype::Constants::INT64
117
+ e.getValueAsInt64().to_i
118
+ when Bberg::Native::Schema::Datatype::Constants::FLOAT32
119
+ e.getValueAsFloat32().to_f
120
+ when Bberg::Native::Schema::Datatype::Constants::FLOAT64
121
+ e.getValueAsFloat64().to_f
122
+ when Bberg::Native::Schema::Datatype::Constants::DATE
123
+ convert_to_rb_date(e.getValueAsDate())
124
+ else
125
+ raise Bberg::BbergException.new("Unsupported data type in response: #{e.datatype.to_s}")
126
+ end
127
+ end
128
+ values
129
+ end
130
+
131
+ end
132
+
133
+ end
134
+ end
@@ -0,0 +1,4 @@
1
+ module Bberg
2
+ # bberg gem version
3
+ VERSION = "0.1.0"
4
+ end
@@ -0,0 +1,99 @@
1
+ require 'spec_helper'
2
+ require 'bberg'
3
+
4
+ describe Bberg::Client do
5
+ before(:each) do
6
+ @client = Bberg::Client.new
7
+ end
8
+
9
+ it "should handle historical data request for one security" do
10
+ securities = ["CLF1 Comdty"]
11
+ start_time = Date.new(2010,12,1)
12
+ end_time = Date.new(2010,12,3)
13
+ data = @client.historical_data_request(securities, start_time, end_time)
14
+ data.has_key?(securities.first).should be_true
15
+ data[securities.first].size.should == 3
16
+ data[securities.first][0]["date"].should == Date.new(2010,12,1).to_time
17
+ data[securities.first][0]["PX_SETTLE"].should == 86.75
18
+ data[securities.first][1]["date"].should == Date.new(2010,12,2).to_time
19
+ data[securities.first][1]["PX_SETTLE"].should == 88.00
20
+ data[securities.first][2]["date"].should == Date.new(2010,12,3).to_time
21
+ data[securities.first][2]["PX_SETTLE"].should == 89.19
22
+ end
23
+
24
+ it "should handle historical data request with one security not given as array" do
25
+ security = "CLF1 Comdty"
26
+ start_time = Date.new(2010,12,1)
27
+ end_time = Date.new(2010,12,3)
28
+ data = @client.historical_data_request(security, start_time, end_time)
29
+ data.has_key?(security).should be_true
30
+ data[security].size.should == 3
31
+ end
32
+
33
+ it "should handle historical data request for multiple securities" do
34
+ securities = ["CLF1 Comdty", "CLG1 Comdty"]
35
+ start_time = Date.new(2010,12,1)
36
+ end_time = Date.new(2010,12,3)
37
+ data = @client.historical_data_request(securities, start_time, end_time)
38
+
39
+ data.has_key?(securities.first).should be_true
40
+ data.has_key?(securities.last).should be_true
41
+
42
+ data[securities.first].size.should == 3
43
+ data[securities.first][0]["date"].should == Date.new(2010,12,1).to_time
44
+ data[securities.first][0]["PX_SETTLE"].should == 86.75
45
+ data[securities.first][1]["date"].should == Date.new(2010,12,2).to_time
46
+ data[securities.first][1]["PX_SETTLE"].should == 88.00
47
+ data[securities.first][2]["date"].should == Date.new(2010,12,3).to_time
48
+ data[securities.first][2]["PX_SETTLE"].should == 89.19
49
+
50
+ data[securities.last].size.should == 3
51
+ data[securities.last][0]["date"].should == Date.new(2010,12,1).to_time
52
+ data[securities.last][0]["PX_SETTLE"].should == 87.25
53
+ data[securities.last][1]["date"].should == Date.new(2010,12,2).to_time
54
+ data[securities.last][1]["PX_SETTLE"].should == 88.42
55
+ data[securities.last][2]["date"].should == Date.new(2010,12,3).to_time
56
+ data[securities.last][2]["PX_SETTLE"].should == 89.59
57
+ end
58
+
59
+ it "should handle historical data request for multiple fields" do
60
+ security = "CLF1 Comdty"
61
+ start_time = Date.new(2010,12,1)
62
+ end_time = Date.new(2010,12,3)
63
+ data = @client.historical_data_request(security, start_time, end_time, :fields => ["PX_OPEN", "PX_HIGH"])
64
+ data.has_key?(security).should be_true
65
+ data[security].size.should == 3
66
+
67
+ data[security][0]["date"].should == Date.new(2010,12,1).to_time
68
+ data[security][0]["PX_OPEN"].should == 83.66
69
+ data[security][0]["PX_HIGH"].should == 86.95
70
+ data[security][1]["date"].should == Date.new(2010,12,2).to_time
71
+ data[security][1]["PX_OPEN"].should == 86.80
72
+ data[security][1]["PX_HIGH"].should == 88.13
73
+ data[security][2]["date"].should == Date.new(2010,12,3).to_time
74
+ data[security][2]["PX_OPEN"].should == 87.94
75
+ data[security][2]["PX_HIGH"].should == 89.49
76
+ end
77
+
78
+ it "should get holiday calendar reference data correctly (tests overrides)" do
79
+ start_date = Date.new(2010, 1, 1)
80
+ end_date = Date.new(2010, 12, 31)
81
+ holidays = @client.get_holidays_for_calendar("USD Curncy", "NM", start_date, end_date)
82
+
83
+ known_holidays = [
84
+ Date.new(2010,1,1),
85
+ Date.new(2010,1,18),
86
+ Date.new(2010,2,15),
87
+ Date.new(2010,4,2),
88
+ Date.new(2010,5,31),
89
+ Date.new(2010,7,5),
90
+ Date.new(2010,9,6),
91
+ Date.new(2010,11,25),
92
+ Date.new(2010,12,24),
93
+ ]
94
+
95
+ holidays.size.should == known_holidays.size
96
+ holidays.each_with_index {|d,i| d.should == known_holidays[i] }
97
+ end
98
+
99
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+ require 'bberg'
3
+
4
+ describe Bberg do
5
+ it "should have a VERSION constant" do
6
+ Bberg.const_get('VERSION').should_not be_empty
7
+ end
8
+ end
@@ -0,0 +1,4 @@
1
+ require 'rspec'
2
+ require 'bberg/version'
3
+
4
+ include Bberg
@@ -0,0 +1,67 @@
1
+ package org.rubyforge.rawr;
2
+
3
+ import java.io.BufferedReader;
4
+ import java.io.InputStreamReader;
5
+ import java.io.InputStream;
6
+ import java.io.IOException;
7
+ import java.net.URL;
8
+
9
+
10
+ import java.util.ArrayList;
11
+ import org.jruby.Ruby;
12
+ import org.jruby.RubyInstanceConfig;
13
+ import org.jruby.javasupport.JavaEmbedUtils;
14
+
15
+ public class Main
16
+ {
17
+ public static void main(String[] args) throws Exception
18
+ {
19
+ RubyInstanceConfig config = new RubyInstanceConfig();
20
+ config.setArgv(args);
21
+ Ruby runtime = JavaEmbedUtils.initialize(new ArrayList(0), config);
22
+ String mainRubyFile = "main";
23
+
24
+ ArrayList<String> config_data = new ArrayList<String>();
25
+ try{
26
+ java.io.InputStream ins = Main.class.getClassLoader().getResourceAsStream("run_configuration");
27
+ if (ins == null ) {
28
+ System.err.println("Did not find configuration file 'run_configuration', using defaults.");
29
+ } else {
30
+ config_data = getConfigFileContents(ins);
31
+ }
32
+ }
33
+ catch(IOException ioe)
34
+ {
35
+ System.err.println("Error loading run configuration file 'run_configuration', using defaults: " + ioe);
36
+ }
37
+ catch(java.lang.NullPointerException npe)
38
+ {
39
+ System.err.println("Error loading run configuration file 'run_configuration', using defaults: " + npe );
40
+ }
41
+
42
+ for(String line : config_data) {
43
+ String[] parts = line.split(":");
44
+ if("main_ruby_file".equals(parts[0].replaceAll(" ", ""))) {
45
+ mainRubyFile = parts[1].replaceAll(" ", "");
46
+ }
47
+ }
48
+
49
+ runtime.evalScriptlet("require '" + mainRubyFile + "'");
50
+ }
51
+
52
+ public static URL getResource(String path) {
53
+ return Main.class.getClassLoader().getResource(path);
54
+ }
55
+
56
+ private static ArrayList<String> getConfigFileContents(InputStream input) throws IOException, java.lang.NullPointerException {
57
+ BufferedReader reader = new BufferedReader(new InputStreamReader(input));
58
+ String line;
59
+ ArrayList<String> contents = new ArrayList<String>();
60
+
61
+ while ((line = reader.readLine()) != null) {
62
+ contents.add(line);
63
+ }
64
+ reader.close();
65
+ return(contents);
66
+ }
67
+ }
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bberg
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.0
6
+ platform: ruby
7
+ authors:
8
+ - Patrik Sundberg
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-03-14 00:00:00 +00:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: bundler
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ~>
23
+ - !ruby/object:Gem::Version
24
+ version: 1.0.0
25
+ type: :development
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: yard
29
+ prerelease: false
30
+ requirement: &id002 !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ~>
34
+ - !ruby/object:Gem::Version
35
+ version: 0.6.0
36
+ type: :development
37
+ version_requirements: *id002
38
+ description: Makes the Bloomberg Java API available from jruby - in ruby friendly manner.
39
+ email:
40
+ - patrik.sundberg@gmail.com
41
+ executables: []
42
+
43
+ extensions: []
44
+
45
+ extra_rdoc_files:
46
+ - README.md
47
+ files:
48
+ - .yardopts
49
+ - ChangeLog.md
50
+ - Gemfile
51
+ - Gemfile.lock
52
+ - Guardfile
53
+ - LICENSE.txt
54
+ - README.md
55
+ - Rakefile
56
+ - bberg.gemspec
57
+ - bin/bberg_drb_server
58
+ - build_configuration.rb
59
+ - gemspec.yml
60
+ - lib/bberg.rb
61
+ - lib/bberg/bberg_exception.rb
62
+ - lib/bberg/bberg_wrapper.rb
63
+ - lib/bberg/client.rb
64
+ - lib/bberg/drb_server.rb
65
+ - lib/bberg/drb_server_rawr_launcher.rb
66
+ - lib/bberg/requests.rb
67
+ - lib/bberg/requests/historical_data_request.rb
68
+ - lib/bberg/requests/refdata_request_base.rb
69
+ - lib/bberg/requests/reference_data_request.rb
70
+ - lib/bberg/version.rb
71
+ - spec/bberg/client_spec.rb
72
+ - spec/bberg_spec.rb
73
+ - spec/spec_helper.rb
74
+ - src/org/rubyforge/rawr/Main.java
75
+ has_rdoc: yard
76
+ homepage: http://rubygems.org/gems/bberg
77
+ licenses:
78
+ - MIT
79
+ post_install_message:
80
+ rdoc_options: []
81
+
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: "0"
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: 1.3.6
96
+ requirements: []
97
+
98
+ rubyforge_project: bberg
99
+ rubygems_version: 1.6.2
100
+ signing_key:
101
+ specification_version: 3
102
+ summary: Bloomberg API wrapper for ruby
103
+ test_files:
104
+ - spec/bberg_spec.rb
105
+ - spec/bberg/client_spec.rb