robinhood-ruby 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.DS_Store +0 -0
- data/.coveralls.yml +1 -0
- data/.github/robinhood-ruby.png +0 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +15 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +11 -0
- data/Guardfile +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +520 -0
- data/Rakefile +8 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/example/.DS_Store +0 -0
- data/example/robinhood-sample/.DS_Store +0 -0
- data/example/robinhood-sample/.env.example +2 -0
- data/example/robinhood-sample/.gitignore +19 -0
- data/example/robinhood-sample/Gemfile +16 -0
- data/example/robinhood-sample/Gemfile.lock +164 -0
- data/example/robinhood-sample/README.MD +7 -0
- data/example/robinhood-sample/Rakefile +6 -0
- data/example/robinhood-sample/app/assets/images/.keep +0 -0
- data/example/robinhood-sample/app/assets/javascripts/application.js +16 -0
- data/example/robinhood-sample/app/assets/stylesheets/application.css +15 -0
- data/example/robinhood-sample/app/controllers/application_controller.rb +5 -0
- data/example/robinhood-sample/app/controllers/concerns/.keep +0 -0
- data/example/robinhood-sample/app/helpers/application_helper.rb +2 -0
- data/example/robinhood-sample/app/mailers/.keep +0 -0
- data/example/robinhood-sample/app/models/.keep +0 -0
- data/example/robinhood-sample/app/models/concerns/.keep +0 -0
- data/example/robinhood-sample/app/views/layouts/application.html.erb +14 -0
- data/example/robinhood-sample/bin/bundle +3 -0
- data/example/robinhood-sample/bin/rails +9 -0
- data/example/robinhood-sample/bin/rake +9 -0
- data/example/robinhood-sample/bin/setup +29 -0
- data/example/robinhood-sample/bin/spring +16 -0
- data/example/robinhood-sample/config.ru +4 -0
- data/example/robinhood-sample/config/.DS_Store +0 -0
- data/example/robinhood-sample/config/application.rb +26 -0
- data/example/robinhood-sample/config/boot.rb +3 -0
- data/example/robinhood-sample/config/database.yml +25 -0
- data/example/robinhood-sample/config/environment.rb +5 -0
- data/example/robinhood-sample/config/environments/development.rb +41 -0
- data/example/robinhood-sample/config/environments/production.rb +79 -0
- data/example/robinhood-sample/config/environments/test.rb +42 -0
- data/example/robinhood-sample/config/initializers/.DS_Store +0 -0
- data/example/robinhood-sample/config/initializers/assets.rb +11 -0
- data/example/robinhood-sample/config/initializers/backtrace_silencers.rb +7 -0
- data/example/robinhood-sample/config/initializers/cookies_serializer.rb +3 -0
- data/example/robinhood-sample/config/initializers/filter_parameter_logging.rb +4 -0
- data/example/robinhood-sample/config/initializers/inflections.rb +16 -0
- data/example/robinhood-sample/config/initializers/mime_types.rb +4 -0
- data/example/robinhood-sample/config/initializers/robinhood.rb +1 -0
- data/example/robinhood-sample/config/initializers/session_store.rb +3 -0
- data/example/robinhood-sample/config/initializers/wrap_parameters.rb +14 -0
- data/example/robinhood-sample/config/locales/en.yml +23 -0
- data/example/robinhood-sample/config/routes.rb +56 -0
- data/example/robinhood-sample/config/secrets.yml +22 -0
- data/example/robinhood-sample/db/seeds.rb +7 -0
- data/example/robinhood-sample/lib/.DS_Store +0 -0
- data/example/robinhood-sample/lib/assets/.keep +0 -0
- data/example/robinhood-sample/lib/tasks/.keep +0 -0
- data/example/robinhood-sample/log/.keep +0 -0
- data/example/robinhood-sample/public/404.html +67 -0
- data/example/robinhood-sample/public/422.html +67 -0
- data/example/robinhood-sample/public/500.html +66 -0
- data/example/robinhood-sample/public/favicon.ico +0 -0
- data/example/robinhood-sample/public/robots.txt +5 -0
- data/example/robinhood-sample/test/controllers/.keep +0 -0
- data/example/robinhood-sample/test/fixtures/.keep +0 -0
- data/example/robinhood-sample/test/helpers/.keep +0 -0
- data/example/robinhood-sample/test/integration/.keep +0 -0
- data/example/robinhood-sample/test/mailers/.keep +0 -0
- data/example/robinhood-sample/test/models/.keep +0 -0
- data/example/robinhood-sample/test/test_helper.rb +10 -0
- data/example/robinhood-sample/vendor/assets/javascripts/.keep +0 -0
- data/example/robinhood-sample/vendor/assets/stylesheets/.keep +0 -0
- data/lib/.DS_Store +0 -0
- data/lib/robinhood-ruby.rb +37 -0
- data/lib/robinhood-ruby/.DS_Store +0 -0
- data/lib/robinhood-ruby/rest/.DS_Store +0 -0
- data/lib/robinhood-ruby/rest/api.rb +184 -0
- data/lib/robinhood-ruby/rest/client.rb +120 -0
- data/lib/robinhood-ruby/util.rb +4 -0
- data/lib/robinhood-ruby/util/.DS_Store +0 -0
- data/lib/robinhood-ruby/util/configuration.rb +7 -0
- data/lib/robinhood-ruby/util/request.rb +51 -0
- data/lib/robinhood-ruby/version.rb +3 -0
- data/robinhood-ruby-0.3.2.gem +0 -0
- data/robinhood-ruby.gemspec +52 -0
- metadata +346 -0
@@ -0,0 +1,67 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>The change you wanted was rejected (422)</title>
|
5
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
6
|
+
<style>
|
7
|
+
body {
|
8
|
+
background-color: #EFEFEF;
|
9
|
+
color: #2E2F30;
|
10
|
+
text-align: center;
|
11
|
+
font-family: arial, sans-serif;
|
12
|
+
margin: 0;
|
13
|
+
}
|
14
|
+
|
15
|
+
div.dialog {
|
16
|
+
width: 95%;
|
17
|
+
max-width: 33em;
|
18
|
+
margin: 4em auto 0;
|
19
|
+
}
|
20
|
+
|
21
|
+
div.dialog > div {
|
22
|
+
border: 1px solid #CCC;
|
23
|
+
border-right-color: #999;
|
24
|
+
border-left-color: #999;
|
25
|
+
border-bottom-color: #BBB;
|
26
|
+
border-top: #B00100 solid 4px;
|
27
|
+
border-top-left-radius: 9px;
|
28
|
+
border-top-right-radius: 9px;
|
29
|
+
background-color: white;
|
30
|
+
padding: 7px 12% 0;
|
31
|
+
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
32
|
+
}
|
33
|
+
|
34
|
+
h1 {
|
35
|
+
font-size: 100%;
|
36
|
+
color: #730E15;
|
37
|
+
line-height: 1.5em;
|
38
|
+
}
|
39
|
+
|
40
|
+
div.dialog > p {
|
41
|
+
margin: 0 0 1em;
|
42
|
+
padding: 1em;
|
43
|
+
background-color: #F7F7F7;
|
44
|
+
border: 1px solid #CCC;
|
45
|
+
border-right-color: #999;
|
46
|
+
border-left-color: #999;
|
47
|
+
border-bottom-color: #999;
|
48
|
+
border-bottom-left-radius: 4px;
|
49
|
+
border-bottom-right-radius: 4px;
|
50
|
+
border-top-color: #DADADA;
|
51
|
+
color: #666;
|
52
|
+
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
53
|
+
}
|
54
|
+
</style>
|
55
|
+
</head>
|
56
|
+
|
57
|
+
<body>
|
58
|
+
<!-- This file lives in public/422.html -->
|
59
|
+
<div class="dialog">
|
60
|
+
<div>
|
61
|
+
<h1>The change you wanted was rejected.</h1>
|
62
|
+
<p>Maybe you tried to change something you didn't have access to.</p>
|
63
|
+
</div>
|
64
|
+
<p>If you are the application owner check the logs for more information.</p>
|
65
|
+
</div>
|
66
|
+
</body>
|
67
|
+
</html>
|
@@ -0,0 +1,66 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>We're sorry, but something went wrong (500)</title>
|
5
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
6
|
+
<style>
|
7
|
+
body {
|
8
|
+
background-color: #EFEFEF;
|
9
|
+
color: #2E2F30;
|
10
|
+
text-align: center;
|
11
|
+
font-family: arial, sans-serif;
|
12
|
+
margin: 0;
|
13
|
+
}
|
14
|
+
|
15
|
+
div.dialog {
|
16
|
+
width: 95%;
|
17
|
+
max-width: 33em;
|
18
|
+
margin: 4em auto 0;
|
19
|
+
}
|
20
|
+
|
21
|
+
div.dialog > div {
|
22
|
+
border: 1px solid #CCC;
|
23
|
+
border-right-color: #999;
|
24
|
+
border-left-color: #999;
|
25
|
+
border-bottom-color: #BBB;
|
26
|
+
border-top: #B00100 solid 4px;
|
27
|
+
border-top-left-radius: 9px;
|
28
|
+
border-top-right-radius: 9px;
|
29
|
+
background-color: white;
|
30
|
+
padding: 7px 12% 0;
|
31
|
+
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
32
|
+
}
|
33
|
+
|
34
|
+
h1 {
|
35
|
+
font-size: 100%;
|
36
|
+
color: #730E15;
|
37
|
+
line-height: 1.5em;
|
38
|
+
}
|
39
|
+
|
40
|
+
div.dialog > p {
|
41
|
+
margin: 0 0 1em;
|
42
|
+
padding: 1em;
|
43
|
+
background-color: #F7F7F7;
|
44
|
+
border: 1px solid #CCC;
|
45
|
+
border-right-color: #999;
|
46
|
+
border-left-color: #999;
|
47
|
+
border-bottom-color: #999;
|
48
|
+
border-bottom-left-radius: 4px;
|
49
|
+
border-bottom-right-radius: 4px;
|
50
|
+
border-top-color: #DADADA;
|
51
|
+
color: #666;
|
52
|
+
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
53
|
+
}
|
54
|
+
</style>
|
55
|
+
</head>
|
56
|
+
|
57
|
+
<body>
|
58
|
+
<!-- This file lives in public/500.html -->
|
59
|
+
<div class="dialog">
|
60
|
+
<div>
|
61
|
+
<h1>We're sorry, but something went wrong.</h1>
|
62
|
+
</div>
|
63
|
+
<p>If you are the application owner check the logs for more information.</p>
|
64
|
+
</div>
|
65
|
+
</body>
|
66
|
+
</html>
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,10 @@
|
|
1
|
+
ENV['RAILS_ENV'] ||= 'test'
|
2
|
+
require File.expand_path('../../config/environment', __FILE__)
|
3
|
+
require 'rails/test_help'
|
4
|
+
|
5
|
+
class ActiveSupport::TestCase
|
6
|
+
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
|
7
|
+
fixtures :all
|
8
|
+
|
9
|
+
# Add more helper methods to be used by all tests here...
|
10
|
+
end
|
File without changes
|
File without changes
|
data/lib/.DS_Store
ADDED
Binary file
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'net/https'
|
3
|
+
require 'builder'
|
4
|
+
require 'multi_json'
|
5
|
+
require 'cgi'
|
6
|
+
require 'openssl'
|
7
|
+
require 'base64'
|
8
|
+
require 'forwardable'
|
9
|
+
require 'singleton'
|
10
|
+
|
11
|
+
require 'robinhood-ruby/version' unless defined?(Robinhood::VERSION)
|
12
|
+
require 'robinhood-ruby'
|
13
|
+
require 'robinhood-ruby/util'
|
14
|
+
require 'robinhood-ruby/util/configuration'
|
15
|
+
require 'robinhood-ruby/util/request'
|
16
|
+
require 'robinhood-ruby/rest/api'
|
17
|
+
require 'robinhood-ruby/rest/client'
|
18
|
+
|
19
|
+
module Robinhood
|
20
|
+
extend SingleForwardable
|
21
|
+
|
22
|
+
def_delegators :configuration, :username, :password
|
23
|
+
|
24
|
+
##
|
25
|
+
# Pre-configure with account SID and auth token so that you don't need to
|
26
|
+
# pass them to various initializers each time.
|
27
|
+
def self.configure(&block)
|
28
|
+
yield configuration
|
29
|
+
end
|
30
|
+
|
31
|
+
##
|
32
|
+
# Returns an existing or instantiates a new configuration object.
|
33
|
+
def self.configuration
|
34
|
+
@configuration ||= Util::Configuration.new
|
35
|
+
end
|
36
|
+
private_class_method :configuration
|
37
|
+
end
|
Binary file
|
Binary file
|
@@ -0,0 +1,184 @@
|
|
1
|
+
module Robinhood
|
2
|
+
module REST
|
3
|
+
class API
|
4
|
+
def account
|
5
|
+
url = URI(@api_url + @endpoints[:accounts])
|
6
|
+
response = http_request(url)
|
7
|
+
puts response.read_body
|
8
|
+
JSON.parse(response.read_body)
|
9
|
+
end
|
10
|
+
|
11
|
+
def investment_profile
|
12
|
+
url = URI(@api_url + @endpoints[:investment_profile])
|
13
|
+
response = http_request(url)
|
14
|
+
puts response.read_body
|
15
|
+
JSON.parse(response.read_body)
|
16
|
+
end
|
17
|
+
|
18
|
+
def fundamentals(ticker)
|
19
|
+
url = URI(@api_url + @endpoints[:fundamentals] + "?symbols=" + ticker.to_s)
|
20
|
+
response = http_request(url)
|
21
|
+
puts response.read_body
|
22
|
+
JSON.parse(response.read_body)
|
23
|
+
end
|
24
|
+
|
25
|
+
def instruments(symbol)
|
26
|
+
url = URI(@api_url + @endpoints[:instruments] + "?query=" + symbol.to_s)
|
27
|
+
response = http_request(url)
|
28
|
+
puts response.read_body
|
29
|
+
JSON.parse(response.read_body)
|
30
|
+
end
|
31
|
+
|
32
|
+
def quote_data(symbol)
|
33
|
+
symbol = symbol.is_a?(Array) ? symbol.join(',') : symbol;
|
34
|
+
url = URI(@api_url + @endpoints[:quotes] + "?symbols=" + symbol.to_s)
|
35
|
+
response = http_request(url)
|
36
|
+
puts response.read_body
|
37
|
+
JSON.parse(response.read_body)
|
38
|
+
end
|
39
|
+
|
40
|
+
def user
|
41
|
+
url = URI(@api_url + @endpoints[:user])
|
42
|
+
response = http_request(url)
|
43
|
+
puts response.read_body
|
44
|
+
JSON.parse(response.read_body)
|
45
|
+
end
|
46
|
+
|
47
|
+
def dividends
|
48
|
+
url = URI(@api_url + @endpoints[:dividends])
|
49
|
+
response = http_request(url)
|
50
|
+
puts response.read_body
|
51
|
+
JSON.parse(response.read_body)
|
52
|
+
end
|
53
|
+
|
54
|
+
def orders
|
55
|
+
url = URI(@api_url + @endpoints[:orders])
|
56
|
+
response = http_request(url)
|
57
|
+
puts response.read_body
|
58
|
+
JSON.parse(response.read_body)
|
59
|
+
end
|
60
|
+
|
61
|
+
# def cancel_order(order)
|
62
|
+
# if(order.cancel){
|
63
|
+
# return _request.post({
|
64
|
+
# uri: _apiUrl + order.cancel
|
65
|
+
# }, callback);
|
66
|
+
# }else{
|
67
|
+
# callback({message: order.state=="cancelled" ? "Order already cancelled." : "Order cannot be cancelled.", order: order }, null, null);
|
68
|
+
# };
|
69
|
+
# }
|
70
|
+
|
71
|
+
def place_order(options)
|
72
|
+
url = URI(@api_url + @endpoints[:orders])
|
73
|
+
http = Net::HTTP.new(url.host, url.port)
|
74
|
+
http.use_ssl = true
|
75
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
76
|
+
|
77
|
+
form = {
|
78
|
+
account: _private.account,
|
79
|
+
instrument: options.instrument.url,
|
80
|
+
price: options.bid_price,
|
81
|
+
stop_price: options.stop_price,
|
82
|
+
quantity: options.quantity,
|
83
|
+
side: options.transaction,
|
84
|
+
symbol: options.instrument.symbol.toUpperCase(),
|
85
|
+
time_in_force: options.time || 'gfd',
|
86
|
+
trigger: options.trigger || 'immediate',
|
87
|
+
type: options.type || 'market'
|
88
|
+
}
|
89
|
+
|
90
|
+
request = Net::HTTP::Post.new(url)
|
91
|
+
request["accept"] = '*/*'
|
92
|
+
request["accept-encoding"] = 'gzip, deflate'
|
93
|
+
request["accept-language"] = 'en;q=1, fr;q=0.9, de;q=0.8, ja;q=0.7, nl;q=0.6, it;q=0.5'
|
94
|
+
request["content-type"] = 'multipart/form-data; boundary=---011000010111000001101001'
|
95
|
+
request["x-robinhood-api-version"] = '1.0.0'
|
96
|
+
request["connection"] = 'keep-alive'
|
97
|
+
request["user-agent"] = 'Robinhood/823 (iPhone; iOS 7.1.2; Scale/2.00)'
|
98
|
+
request["authorization"] = 'Token ' + @private[:auth_token]
|
99
|
+
request["cache-control"] = 'no-cache'
|
100
|
+
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"account\"\r\n\r\n"+form[:account]+"\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"instrument\"\r\n\r\n"+form[:instrument]+"\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"price\"\r\n\r\n"+form[:price]+"\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"stop_price\"\r\n\r\n"+form[:stop_price]+"\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"quantity\"\r\n\r\n"+form[:quantity]+"\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"side\"\r\n\r\n"+form[:side]+"\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"symbol\"\r\n\r\n"+form[:symbol]+"\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"time_in_force\"\r\n\r\n"+form[:time_in_force]+"\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"trigger\"\r\n\r\n"+form[:trigger]+"\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"type\"\r\n\r\n"+form[:type]+"\r\n-----011000010111000001101001--"
|
101
|
+
|
102
|
+
response = http.request(request)
|
103
|
+
puts response.read_body
|
104
|
+
JSON.parse(response.read_body)
|
105
|
+
end
|
106
|
+
|
107
|
+
def place_buy_order(options)
|
108
|
+
options[:transaction] = 'buy'
|
109
|
+
place_order(options)
|
110
|
+
end
|
111
|
+
|
112
|
+
def place_sell_order(options)
|
113
|
+
options[:transaction] = 'sell'
|
114
|
+
place_order(options)
|
115
|
+
end
|
116
|
+
|
117
|
+
def positions
|
118
|
+
url = URI(@api_url + @endpoints[:positions])
|
119
|
+
response = http_request(url)
|
120
|
+
puts response.read_body
|
121
|
+
JSON.parse(response.read_body)
|
122
|
+
end
|
123
|
+
|
124
|
+
def news(symbol)
|
125
|
+
url = URI(@api_url + @endpoints[:news] + symbol.to_s + "/")
|
126
|
+
response = http_request(url)
|
127
|
+
puts response.read_body
|
128
|
+
JSON.parse(response.read_body)
|
129
|
+
end
|
130
|
+
|
131
|
+
def markets
|
132
|
+
url = URI(@api_url + @endpoints[:markets])
|
133
|
+
response = http_request(url)
|
134
|
+
puts response.read_body
|
135
|
+
JSON.parse(response.read_body)
|
136
|
+
end
|
137
|
+
|
138
|
+
def sp500_up
|
139
|
+
url = URI(@api_url + @endpoints[:sp500_up])
|
140
|
+
response = http_request(url)
|
141
|
+
puts response.read_body
|
142
|
+
JSON.parse(response.read_body)
|
143
|
+
end
|
144
|
+
|
145
|
+
def sp500_down
|
146
|
+
url = URI(@api_url + @endpoints[:sp500_down])
|
147
|
+
response = http_request(url)
|
148
|
+
puts response.read_body
|
149
|
+
JSON.parse(response.read_body)
|
150
|
+
end
|
151
|
+
|
152
|
+
# def create_watch_list(name, callback)
|
153
|
+
# return _request.post({
|
154
|
+
# uri: @api_url + @endpoints.watchlists,
|
155
|
+
# form: {
|
156
|
+
# name: name
|
157
|
+
# }
|
158
|
+
# }, callback);
|
159
|
+
# end
|
160
|
+
|
161
|
+
def watchlists
|
162
|
+
url = URI(@api_url + @endpoints[:watchlists])
|
163
|
+
response = http_request(url)
|
164
|
+
puts response.read_body
|
165
|
+
JSON.parse(response.read_body)
|
166
|
+
end
|
167
|
+
|
168
|
+
def splits(instrument)
|
169
|
+
url = URI(@api_url + @endpoints[:instruments] + "/splits/" + instrument.to_s)
|
170
|
+
response = http_request(url)
|
171
|
+
puts response.read_body
|
172
|
+
JSON.parse(response.read_body)
|
173
|
+
end
|
174
|
+
|
175
|
+
def historicals(symbol, intv, span)
|
176
|
+
url = URI(@api_url + @endpoints[:quotes] + "historicals/" + symbol + "?interval" + intv.to_s + "&span=" + span)
|
177
|
+
response = http_request(url)
|
178
|
+
puts response.read_body
|
179
|
+
JSON.parse(response.read_body)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
end
|
184
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
module Robinhood
|
2
|
+
module REST
|
3
|
+
class Client < API
|
4
|
+
attr_accessor :token, :api_url, :options, :endpoints, :private
|
5
|
+
|
6
|
+
def initialize(*args)
|
7
|
+
@options = args.last.is_a?(Hash) ? args.pop : {}
|
8
|
+
|
9
|
+
@options[:username] = args[0] || Robinhood.username
|
10
|
+
@options[:password] = args[1] || Robinhood.password
|
11
|
+
@options[:username] = (args.size > 2 && args[2].is_a?(String) ? args[2] : args[0]) || Robinhood.username
|
12
|
+
|
13
|
+
if @options[:username].nil? || @options[:password].nil?
|
14
|
+
raise ArgumentError, 'Account username and password are required'
|
15
|
+
end
|
16
|
+
|
17
|
+
configuration
|
18
|
+
setup
|
19
|
+
end
|
20
|
+
|
21
|
+
def inspect # :nodoc:
|
22
|
+
"<Robinhood::REST::Client @username=#{@options[:username]}>"
|
23
|
+
end
|
24
|
+
|
25
|
+
##
|
26
|
+
# Delegate account methods from the client. This saves having to call
|
27
|
+
# <tt>client.account</tt> every time for resources on the default
|
28
|
+
# account.
|
29
|
+
def method_missing(method_name, *args, &block)
|
30
|
+
if account.respond_to?(method_name)
|
31
|
+
account.send(method_name, *args, &block)
|
32
|
+
else
|
33
|
+
super
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def respond_to?(method_name, include_private=false)
|
38
|
+
if account.respond_to?(method_name, include_private)
|
39
|
+
true
|
40
|
+
else
|
41
|
+
super
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def configuration()
|
46
|
+
@api_url = 'https://api.robinhood.com/';
|
47
|
+
|
48
|
+
@endpoints = {
|
49
|
+
"login": 'api-token-auth/',
|
50
|
+
"investment_profile": 'user/investment_profile/',
|
51
|
+
"accounts": 'accounts/',
|
52
|
+
"ach_iav_auth": 'ach/iav/auth/',
|
53
|
+
"ach_relationships": 'ach/relationships/',
|
54
|
+
"ach_transfers": 'ach/transfers/',
|
55
|
+
"ach_deposit_schedules": "ach/deposit_schedules/",
|
56
|
+
"applications": 'applications/',
|
57
|
+
"dividends": 'dividends/',
|
58
|
+
"edocuments": 'documents/',
|
59
|
+
"instruments": 'instruments/',
|
60
|
+
"margin_upgrade": 'margin/upgrades/',
|
61
|
+
"markets": 'markets/',
|
62
|
+
"notifications": 'notifications/',
|
63
|
+
"notifications_devices": "notifications/devices/",
|
64
|
+
"orders": 'orders/',
|
65
|
+
"cancel_order": 'orders/', #API expects https://api.robinhood.com/orders/{{orderId}}/cancel/
|
66
|
+
"password_reset": 'password_reset/request/',
|
67
|
+
"quotes": 'quotes/',
|
68
|
+
"document_requests": 'upload/document_requests/',
|
69
|
+
"user": 'user/',
|
70
|
+
|
71
|
+
"user_additional_info": "user/additional_info/",
|
72
|
+
"user_basic_info": "user/basic_info/",
|
73
|
+
"user_employment": "user/employment/",
|
74
|
+
"user_investment_profile": "user/investment_profile/",
|
75
|
+
|
76
|
+
"watchlists": 'watchlists/',
|
77
|
+
"positions": 'positions/',
|
78
|
+
"fundamentals": 'fundamentals/',
|
79
|
+
"sp500_up": 'midlands/movers/sp500/?direction=up',
|
80
|
+
"sp500_down": 'midlands/movers/sp500/?direction=down',
|
81
|
+
"news": 'midlands/news/'
|
82
|
+
}
|
83
|
+
|
84
|
+
@is_init = false
|
85
|
+
|
86
|
+
@private = {
|
87
|
+
"session": {},
|
88
|
+
"account": nil,
|
89
|
+
"username": nil,
|
90
|
+
"password": nil,
|
91
|
+
"headers": nil,
|
92
|
+
"auth_token": nil
|
93
|
+
}
|
94
|
+
|
95
|
+
@api = {}
|
96
|
+
end
|
97
|
+
|
98
|
+
def setup
|
99
|
+
@private[:username] = @options[:username];
|
100
|
+
@private[:password] = @options[:password];
|
101
|
+
|
102
|
+
if @private[:auth_token].nil?
|
103
|
+
login
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def http_request(url)
|
108
|
+
request = Util::Request.new(@private)
|
109
|
+
request.http_request(url)
|
110
|
+
end
|
111
|
+
|
112
|
+
def login
|
113
|
+
url = URI(@api_url + "api-token-auth/")
|
114
|
+
response = http_request(url)
|
115
|
+
@private[:auth_token] = JSON.parse(response.read_body)["token"]
|
116
|
+
@private[:account] = account["results"][0]["url"]
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|