bberg 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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