em-nordnet 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use --create ruby-1.9.3@em-nordnet
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in em-nordnet.gemspec
4
+ gemspec
@@ -0,0 +1,65 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ em-nordnet (0.0.1)
5
+ em-http-request
6
+ em-synchrony
7
+ eventmachine
8
+ faraday_middleware-multi_json
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ addressable (2.3.2)
14
+ columnize (0.3.6)
15
+ cookiejar (0.3.0)
16
+ crack (0.3.1)
17
+ debugger (1.2.0)
18
+ columnize (>= 0.3.1)
19
+ debugger-linecache (~> 1.1.1)
20
+ debugger-ruby_core_source (~> 1.1.3)
21
+ debugger-linecache (1.1.2)
22
+ debugger-ruby_core_source (>= 1.1.1)
23
+ debugger-ruby_core_source (1.1.3)
24
+ diff-lcs (1.1.3)
25
+ em-http-request (1.0.3)
26
+ addressable (>= 2.2.3)
27
+ cookiejar
28
+ em-socksify
29
+ eventmachine (>= 1.0.0.beta.4)
30
+ http_parser.rb (>= 0.5.3)
31
+ em-socksify (0.2.1)
32
+ eventmachine (>= 1.0.0.beta.4)
33
+ em-synchrony (1.0.2)
34
+ eventmachine (>= 1.0.0.beta.1)
35
+ eventmachine (1.0.0.rc.4)
36
+ faraday (0.8.4)
37
+ multipart-post (~> 1.1)
38
+ faraday_middleware (0.8.8)
39
+ faraday (>= 0.7.4, < 0.9)
40
+ faraday_middleware-multi_json (0.0.3)
41
+ faraday_middleware
42
+ multi_json
43
+ http_parser.rb (0.5.3)
44
+ multi_json (1.3.6)
45
+ multipart-post (1.1.5)
46
+ rspec (2.11.0)
47
+ rspec-core (~> 2.11.0)
48
+ rspec-expectations (~> 2.11.0)
49
+ rspec-mocks (~> 2.11.0)
50
+ rspec-core (2.11.1)
51
+ rspec-expectations (2.11.3)
52
+ diff-lcs (~> 1.1.3)
53
+ rspec-mocks (2.11.2)
54
+ webmock (1.8.9)
55
+ addressable (>= 2.2.7)
56
+ crack (>= 0.1.7)
57
+
58
+ PLATFORMS
59
+ ruby
60
+
61
+ DEPENDENCIES
62
+ debugger
63
+ em-nordnet!
64
+ rspec
65
+ webmock
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Dennis Rogenius
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,66 @@
1
+ # Em::Nordnet
2
+
3
+ Eventmachine driven wrapper for the Nordnet REST and Feed API. Comes
4
+ with a golith plugin for connecting to the feed sockets.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'em-nordnet'
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install em-nordnet
19
+
20
+
21
+
22
+ ## Usage
23
+
24
+ ### Configuration
25
+
26
+ After installing the gem you can configure it with your own credentials
27
+
28
+ ```
29
+ Em::Nordnet.configure do |config|
30
+ config.url = 'https://api.test.nordnet.se'
31
+ config.user = 'john'
32
+ config.password = 'doe'
33
+ config.service = 'NEXTAPI'
34
+ config.pem = <<-CERT
35
+ -----BEGIN PUBLIC KEY-----
36
+ MIIBIjANBgkq...
37
+ -----END PUBLIC KEY-----
38
+ CERT
39
+ end
40
+ ```
41
+
42
+ The configuration may be accessed by ``Em::Nordnet.config``
43
+
44
+ ### Models
45
+
46
+ Em::Nordnet comes with a few models to make actions more Object-oriented
47
+
48
+ ```
49
+ Em::Nordnet::Instrument
50
+ Em::Nordnet::Account
51
+ Em::Nordnet::Order
52
+ ```
53
+
54
+ ### REST API
55
+
56
+ ### Private Feed
57
+
58
+ ### Public Feed
59
+
60
+ ## Contributing
61
+
62
+ 1. Fork it
63
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
64
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
65
+ 4. Push to the branch (`git push origin my-new-feature`)
66
+ 5. Create new Pull Request
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/em-nordnet/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Dennis Rogenius"]
6
+ gem.email = ["denro03@gmail.com"]
7
+ gem.description = %q{REST API and Socket Wrapper for Nordnet using Eventmachine}
8
+ gem.summary = %q{Nordnet API wrapper using EventMachine}
9
+ gem.homepage = "https://github.com/denro/em-nordnet"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "em-nordnet"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Em::Nordnet::VERSION
17
+
18
+ gem.required_ruby_version = '>= 1.9.3'
19
+
20
+ gem.add_dependency 'eventmachine'
21
+ gem.add_dependency 'em-http-request'
22
+ gem.add_dependency 'em-synchrony'
23
+ gem.add_dependency 'faraday_middleware-multi_json'
24
+
25
+ gem.add_development_dependency 'debugger'
26
+ gem.add_development_dependency 'rspec'
27
+ gem.add_development_dependency 'webmock'
28
+ end
@@ -0,0 +1,46 @@
1
+ autoload :Base64, 'base64'
2
+ autoload :OpenSSL, 'openssl'
3
+
4
+ require 'rubygems'
5
+ require 'em-synchrony'
6
+ require 'faraday_middleware-multi_json'
7
+
8
+ module Em
9
+ module Nordnet
10
+ class << self
11
+ def configure &block
12
+ yield(config) if block_given?
13
+ end
14
+
15
+ def config
16
+ @@config ||= Nordnet::Config.new
17
+ end
18
+
19
+ def api
20
+ @@api ||= Nordnet::Api.new
21
+ end
22
+ end
23
+
24
+ autoload :VERSION, 'em-nordnet/version'
25
+
26
+ autoload :Config, 'em-nordnet/config'
27
+ autoload :Api, 'em-nordnet/api'
28
+
29
+ autoload :Account, 'em-nordnet/account'
30
+ autoload :Order, 'em-nordnet/order'
31
+ autoload :Instrument, 'em-nordnet/instrument'
32
+
33
+ module Feed
34
+ autoload :DSL, 'em-nordnet/feed/dsl'
35
+ autoload :Public, 'em-nordnet/feed/public'
36
+ autoload :Private, 'em-nordnet/feed/private'
37
+ autoload :Connection, 'em-nordnet/feed/connection'
38
+ end
39
+
40
+ module Goliath
41
+ autoload :FeedPlugin, 'em-nordnet/goliath/feed_plugin'
42
+ autoload :PublicFeed, 'em-nordnet/goliath/public_feed'
43
+ autoload :PrivateFeed, 'em-nordnet/goliath/private_feed'
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,27 @@
1
+ module Em
2
+ module Nordnet
3
+ class Account
4
+ attr_accessor :id, :alias, :default
5
+
6
+ class << self
7
+ def all
8
+ @accounts ||= Nordnet.api.accounts.map { |attrs| new attrs }
9
+ end
10
+
11
+ def default
12
+ all.select(&:default).first
13
+ end
14
+ end
15
+
16
+ def initialize attributes={}
17
+ self.id = attributes[:id]
18
+ self.alias = attributes[:alias]
19
+ self.default = attributes[:default]
20
+ end
21
+
22
+ def orders
23
+ Order.all id
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,234 @@
1
+ module Em
2
+ module Nordnet
3
+ class Api
4
+ class AuthorizationFailureError < StandardError; end
5
+ class SessionExpiredError < StandardError; end
6
+ class InstrumentNotFoundError < StandardError; end
7
+ class InternalServerError < StandardError; end
8
+
9
+ attr_reader :credentials, :session,
10
+ :public_feed, :private_feed,
11
+ :expires_in, :last_usage_at
12
+
13
+ def initialize
14
+ @credentials = Nordnet.config.credentials
15
+ login
16
+ end
17
+
18
+ def login
19
+ login_path = path 'login'
20
+
21
+ res = perform! do |conn|
22
+ conn.post login_path do |req|
23
+ req.params = {service: Nordnet.config.service, auth: credentials}
24
+ end
25
+ end
26
+
27
+ if res
28
+ @session = res[:session_key]
29
+ @expires_in = res[:expires_in]
30
+ @public_feed = res[:public_feed]
31
+ @private_feed = res[:private_feed]
32
+ end
33
+
34
+ res
35
+ end
36
+
37
+ def touch
38
+ touch_path = path "login/#{session}"
39
+ perform { |conn| conn.put touch_path }
40
+ end
41
+
42
+ def realtime_access
43
+ realtime_path = path 'realtime_access'
44
+ perform { |conn| conn.get realtime_path }
45
+ end
46
+
47
+ def news_sources
48
+ news_sources_path = path 'news_sources'
49
+ perform { |conn| conn.get news_sources_path }
50
+ end
51
+
52
+ def news_items params = {}
53
+ news_items_path = path 'news_items'
54
+ perform { |conn| conn.get news_items_path, params }
55
+ end
56
+
57
+ def news_item news_item_id
58
+ news_item_path = path "news_items/#{news_item_id}"
59
+ perform { |conn| conn.get news_item_path }
60
+ end
61
+
62
+ def accounts
63
+ accounts_path = path 'accounts'
64
+ perform { |conn| conn.get accounts_path }
65
+ end
66
+
67
+ def account account_id
68
+ account_path = path "accounts/#{account_id}"
69
+ perform { |conn| conn.get account_path }
70
+ end
71
+
72
+ def ledgers account_id
73
+ ledgers_path = path "accounts/#{account_id}/ledgers"
74
+ perform { |conn| conn.get ledgers_path }
75
+ end
76
+
77
+ def positions account_id
78
+ positions_path = path "accounts/#{account_id}/positions"
79
+ perform { |conn| conn.get positions_path }
80
+ end
81
+
82
+ def orders account_id
83
+ orders_path = path "accounts/#{account_id}/orders"
84
+ perform { |conn| conn.get orders_path }
85
+ end
86
+
87
+ def trades account_id
88
+ trades_path = path "accounts/#{account_id}/trades"
89
+ perform { |conn| conn.get trades_path }
90
+ end
91
+
92
+ def instrument_search params = {}
93
+ instruments_path = path 'instruments'
94
+ perform { |conn| conn.get instruments_path, params }
95
+ end
96
+
97
+ def instrument_lookup params = {}
98
+ instruments_path = path 'instruments'
99
+ perform { |conn| conn.get instruments_path, params }
100
+ end
101
+
102
+ def multiple_instrument_lookup list
103
+ instruments_path = path 'instruments'
104
+ perform { |conn| conn.get instruments_path, list: list}
105
+ end
106
+
107
+ def chart_data params = {}
108
+ chart_data_path = path 'chart_data'
109
+ perform { |conn| conn.get chart_data_path, params }
110
+ end
111
+
112
+ def lists
113
+ lists_path = path 'lists'
114
+ perform { |conn| conn.get lists_path }
115
+ end
116
+
117
+ def list_items list_id
118
+ list_items_path = path "lists/#{list_id}"
119
+ perform { |conn| conn.get list_items_path }
120
+ end
121
+
122
+ def markets
123
+ markets_path = path 'markets'
124
+ perform { |conn| conn.get markets_path }
125
+ end
126
+
127
+ def trading_days market_id
128
+ trading_days_path = path "markets/#{market_id}/trading_days"
129
+ perform { |conn| conn.get trading_days_path }
130
+ end
131
+
132
+ def indices
133
+ indices_path = path 'indices'
134
+ perform { |conn| conn.get indices_path }
135
+ end
136
+
137
+ def ticksizes instrument_id
138
+ ticksize_path = path "ticksizes/#{instrument_id}"
139
+ perform { |conn| conn.get ticksize_path }
140
+ end
141
+
142
+ def countries derivative_type
143
+ countries_path = path "derivatives/#{derivative_type}"
144
+ perform { |conn| conn.get countries_path }
145
+ end
146
+
147
+ def underlyings derivative_type, country
148
+ underlyings_path = path "derivatives/#{derivative_type}/underlyings/#{country}"
149
+ perform { |conn| conn.get underlyings_path }
150
+ end
151
+
152
+ def derivatives derivative_type, params = {}
153
+ derivatives_path = path "derivatives/#{derivative_type}/derivatives"
154
+ perform { |conn| conn.get derivatives_path, params }
155
+ end
156
+
157
+ def related_markets params = {}
158
+ related_markets_path = path "related_markets"
159
+ perform { |conn| conn.get related_markets_path, params }
160
+ end
161
+
162
+ def create_order account_id, params = {}
163
+ orders_path = path "accounts/#{account_id}/orders"
164
+ perform { |conn| conn.post(orders_path) { |req| req.params = params } }
165
+ end
166
+
167
+ def modify_order account_id, order_id, params = {}
168
+ modify_order_path = path "accounts/#{account_id}/orders/#{order_id}"
169
+ perform { |conn| conn.put(modify_order_path) { |req| req.params = params } }
170
+ end
171
+
172
+ def destroy_order account_id, order_id
173
+ order_path = path "accounts/#{account_id}/orders/#{order_id}"
174
+ perform { |conn| conn.delete(order_path) }
175
+ end
176
+
177
+ private
178
+
179
+ def perform &block
180
+ verify_session
181
+ perform! &block
182
+ end
183
+
184
+ def perform! &block
185
+ yield(connection).body.tap do |result|
186
+ parse_error result
187
+ @last_usage_at = Time.now
188
+ end
189
+ end
190
+
191
+ def verify_session
192
+ login if session.nil? || session_expired?
193
+ end
194
+
195
+ def session_expired?
196
+ if last_usage_at then Time.now > expires_at else false end
197
+ end
198
+
199
+ def expires_at
200
+ last_usage_at + expires_in
201
+ end
202
+
203
+ def parse_error result
204
+ return unless result.is_a?(Hash)
205
+
206
+ case error = result[:error]
207
+ when /decrypt authorization/
208
+ raise AuthorizationFailureError.new error
209
+ when /Session expired/ then
210
+ raise SessionExpiredError.new error
211
+ when /Instrument not found/
212
+ raise InstrumentNotFoundError.new error
213
+ when /Internal Server Error/
214
+ raise InternalServerError.new error
215
+ end
216
+ end
217
+
218
+ def connection
219
+ Faraday.new url: Nordnet.config.url do |conn|
220
+ conn.adapter :em_synchrony
221
+ conn.request :url_encoded
222
+ conn.response :multi_json, symbolize_keys: true
223
+
224
+ conn.headers['Content-Type'] = 'application/json'
225
+ conn.basic_auth session, session if session
226
+ end
227
+ end
228
+
229
+ def path endpoint
230
+ "/%s/%s/%s" % ['next', '1', endpoint]
231
+ end
232
+ end
233
+ end
234
+ end