scottrade 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -4,6 +4,7 @@ Very basic gem for accessing Scottrade account information including balances an
4
4
 
5
5
  **This software comes with no warranty and you use it at your own risk.**
6
6
 
7
+ [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/nolanbrown/scottrade)
7
8
 
8
9
  ## Installation
9
10
 
@@ -12,14 +12,14 @@ rescue StandardError => e
12
12
  exit 1
13
13
  end
14
14
 
15
- begin
15
+ #begin
16
16
  scottrade.brokerage.update_accounts
17
17
  scottrade.brokerage.update_positions
18
18
 
19
- rescue StandardError => e
20
- puts e
21
- exit 1
22
- end
19
+ # rescue StandardError => e
20
+ # puts e
21
+ # exit 1
22
+ # end
23
23
 
24
24
  puts scottrade.brokerage.account_balance
25
25
  ##
@@ -1,9 +1,11 @@
1
1
  require 'money'
2
2
  require_relative 'account'
3
3
  require_relative 'position'
4
+ require_relative 'helpers'
4
5
 
5
6
  module Scottrade
6
7
  class Brokerage
8
+ include Scottrade::Helpers
7
9
 
8
10
  attr_reader :total_value, :total_cash_balance, :yesterday_total_cash_balance, :available_free_cash_blanace, :account_balance
9
11
  attr_reader :total_market_value_with_options, :total_market_value_without_options, :yesterday_total_market_value
@@ -12,96 +14,94 @@ module Scottrade
12
14
  attr_reader :accounts, :positions
13
15
  attr_reader :current_market_value, :todays_percent_change, :todays_value_change
14
16
 
17
+ KEYS_TO_VARIABLES = {
18
+ # accounts data keys
19
+ "TotalAccountValue" => { :key => :total_value, :is_money => true },
20
+ "TotalMoneyBalance" => { :key => :total_cash_balance, :is_money => true },
21
+ "YesterdayTotalMoneyBalance" => { :key => :yesterday_total_cash_balance, :is_money => true },
22
+ "AvailableFreeCash" => { :key => :available_free_cash_blanace, :is_money => true },
23
+ "TotalMarketValueWithOptions" => { :key => :total_market_value_with_options, :is_money => true },
24
+ "TotalMarketValueNoOptions" => { :key => :total_market_value_without_options, :is_money => true },
25
+ "YesterdayTotalMarketValue" => { :key => :yesterday_total_market_value, :is_money => true },
26
+ "TotalSettledFunds" => { :key => :total_settled_funds, :is_money => true },
27
+ "TotalUnsettledSells" => { :key => :total_unsettled_sells, :is_money => true },
28
+ "FundsAvailableToBuyNonMarginables" => { :key => :funds_available_to_buy_non_marginables, :is_money => true },
29
+ "FundsAvailableToBuyMarginables" => { :key => :funds_available_to_buy_marginables, :is_money => true },
30
+ "FundsAvailableToBuyOptions" => { :key => :funds_available_to_buy_options, :is_money => true },
31
+ "FundsAvailableToBuyMutualFunds" => { :key => :funds_available_to_buy_mutual_funds, :is_money => true },
32
+ "FundsAvailableForWithdraw" => { :key => :funds_available_for_withdraw, :is_money => true },
33
+ "TodaysChangeApproxLiquidationValNoOptions" => { :key => :approximate_liquidation_value, :is_money => true },
34
+ "BrokerageAccountBalance" => { :key => :account_balance, :is_money => true },
35
+ # positions data keys
36
+ "totalMktValue" => { :key => :current_market_value, :is_money => false },
37
+ "totalPctChange" => { :key => :todays_percent_change, :is_money => false },
38
+ "toalPriceChange" => { :key => :todays_value_change, :is_money => false },
39
+ }
40
+
41
+
15
42
  def initialize(session)
16
43
  @session = session
17
44
  end
18
45
 
19
- # def positions
20
- #
21
- # end
22
- # def accounts
23
- # end
24
-
25
46
  def update_accounts
26
- params = {}
27
- params["channel"] = "rc"
28
- params["appID"] = "Scottrade"
29
- params["rcid"] = "iPhone"
30
- params["cacheid"] = ""
31
- params["platform"] = "iPhone"
32
- params["appver"] = "1.1.4"
33
- params["useCachedData"] = "false"
47
+ params = request_parameters("GetFrontEndMoneyBalances")
34
48
 
35
- params["serviceID"] = "GetFrontEndMoneyBalances"
36
-
37
- response = @session.post(params)
38
- parsed_response = JSON.parse(response.body)
39
- if parsed_response["error"] == "false"
40
- @total_value = Money.parse parsed_response["TotalAccountValue"]
41
- @total_cash_balance = Money.parse parsed_response["TotalMoneyBalance"]
42
- @yesterday_total_cash_balance = Money.parse parsed_response["YesterdayTotalMoneyBalance"]
43
- @available_free_cash_blanace = Money.parse parsed_response["AvailableFreeCash"]
44
- @total_market_value_with_options = Money.parse parsed_response["TotalMarketValueWithOptions"]
45
- @total_market_value_without_options = Money.parse parsed_response["TotalMarketValueNoOptions"]
46
- @yesterday_total_market_value = Money.parse parsed_response["YesterdayTotalMarketValue"]
47
- @total_settled_funds = Money.parse parsed_response["TotalSettledFunds"]
48
- @total_unsettled_sells = Money.parse parsed_response["TotalUnsettledSells"]
49
- @funds_available_to_buy_non_marginables = Money.parse parsed_response["FundsAvailableToBuyNonMarginables"]
50
- @funds_available_to_buy_marginables = Money.parse parsed_response["FundsAvailableToBuyMarginables"]
51
- @funds_available_to_buy_options = Money.parse parsed_response["FundsAvailableToBuyOptions"]
52
- @funds_available_to_buy_mutual_funds = Money.parse parsed_response["FundsAvailableToBuyMutualFunds"]
53
- @funds_available_for_withdraw = Money.parse parsed_response["FundsAvailableForWithdraw"]
54
- @approximate_liquidation_value = Money.parse parsed_response["TodaysChangeApproxLiquidationValNoOptions"]
55
- @account_balance = Money.parse parsed_response["BrokerageAccountBalance"]
56
-
57
- @accounts = []
58
- unparsed_accounts = parsed_response["AccTypeBalances"]
59
- unparsed_accounts.each{|acct|
60
- @accounts.push Account.new(acct)
61
- }
62
-
63
- elsif parsed_response["msg"]
64
- raise RequestError, parsed_response["msg"]
65
- else
66
- raise RequestError
67
- end
49
+ response = session_post(params)
50
+ set_variables_from_response(response)
51
+
52
+ @accounts = []
53
+ unparsed_accounts = response["AccTypeBalances"]
54
+ unparsed_accounts.each{|acct|
55
+ @accounts.push Account.new(acct)
56
+ }
57
+
68
58
  end
69
59
 
70
60
  def update_positions
71
- params = {}
72
- params["channel"] = "rc"
73
- params["appID"] = "Scottrade"
74
- params["rcid"] = "iPhone"
75
- params["cacheid"] = ""
76
- params["platform"] = "iPhone"
77
- params["appver"] = "1.1.4"
78
-
79
- params["useCachedData"] = "false"
61
+ params = request_parameters("GetPositions_v2")
80
62
  params["startRow"] = "0"
81
63
  params["noOfRows"] = "1000"
82
64
  params["returnRealTimeMktValue"] = "true"
83
65
 
84
66
  params["serviceID"] = "GetPositions_v2"
85
-
67
+
68
+ response = session_post(params)
69
+
70
+ set_variables_from_response(response)
71
+
72
+ @positions = []
73
+ all_positions = response["Positions"]
74
+ all_positions.each{|pos|
75
+ @positions.push Position.new(pos)
76
+ }
77
+ end
78
+
79
+ private
80
+ def session_post(params)
86
81
  response = @session.post(params)
87
82
  parsed_response = JSON.parse(response.body)
88
83
  if parsed_response["error"] == "false"
89
-
90
- @current_market_value = parsed_response["totalMktValue"]
91
- @todays_percent_change = parsed_response["totalPctChange"]
92
- @todays_value_change = parsed_response["toalPriceChange"]
93
-
94
- @positions = []
95
- all_positions = parsed_response["Positions"]
96
- all_positions.each{|pos|
97
- @positions.push Position.new(pos)
98
- }
99
-
84
+ return parsed_response
100
85
  elsif parsed_response["msg"]
101
86
  raise RequestError, parsed_response["msg"]
102
87
  else
103
88
  raise RequestError
104
89
  end
105
90
  end
91
+
92
+ def set_variables_from_response(response)
93
+ response.each{|key,value|
94
+ settings = KEYS_TO_VARIABLES[key]
95
+ if settings
96
+ if settings[:is_money]
97
+ begin
98
+ value = Money.parse value
99
+ rescue
100
+ end
101
+ end
102
+ instance_variable_set("@#{settings[:key].to_s}", value)
103
+ end
104
+ }
105
+ end
106
106
  end
107
107
  end
@@ -0,0 +1,17 @@
1
+
2
+ module Scottrade
3
+ module Helpers
4
+ def request_parameters(serviceID)
5
+ params = {}
6
+ params["channel"] = "rc"
7
+ params["appID"] = "Scottrade"
8
+ params["rcid"] = "iPhone"
9
+ params["cacheid"] = ""
10
+ params["platform"] = "iPhone"
11
+ params["appver"] = "1.1.4"
12
+ params["useCachedData"] = "false"
13
+ params["serviceID"] = serviceID
14
+ params
15
+ end
16
+ end
17
+ end
@@ -4,19 +4,31 @@ module Scottrade
4
4
  attr_reader :symbol, :display_symbol, :quantity, :previous_market_close_value, :account_type, :cusip, :security_description
5
5
  attr_reader :security_class, :previous_close_price, :realTimePrice, :real_time_price, :real_time_market_value, :price_change
6
6
 
7
- def initialize(details)
7
+ def initialize(details)
8
8
  @symbol = details["symbol"]
9
9
  @display_symbol = details["displaySymbol"]
10
10
  @quantity = details["quantity"]
11
- @previous_market_close_value = Money.parse(details["prevCloseMktValue"])
12
11
  @account_type = details["accType"]
13
12
  @cusip = details["cusip"]
14
13
  @security_description = details["securityDescription"]
15
14
  @security_class = details["SecurityClass"]
16
15
  @previous_close_price = details["previousClosePrice"]
17
16
  @real_time_price = details["realTimePrice"]
18
- @real_time_market_value = Money.parse(details["RealTimeMktValue"])
19
- @price_change = Money.parse(details["priceChange"])
17
+ begin
18
+ @price_change = Money.parse details["priceChange"].split("\n")[0]
19
+ rescue
20
+ @price_change = Money.parse("$0.00")
21
+ end
22
+ begin
23
+ @previous_market_close_value = Money.parse(details["prevCloseMktValue"])
24
+ rescue
25
+ @previous_market_close_value = Money.parse("$0.00")
26
+ end
27
+ begin
28
+ @real_time_market_value = Money.parse(details["RealTimeMktValue"])
29
+ rescue
30
+ @previous_market_close_value = Money.parse("$0.00")
31
+ end
20
32
  end
21
33
  end
22
34
  end
@@ -2,9 +2,11 @@ require 'json'
2
2
 
3
3
  require_relative 'base'
4
4
  require_relative 'error'
5
+ require_relative 'helpers'
5
6
 
6
7
  module Scottrade
7
8
  class Session < Base
9
+ include Scottrade::Helpers
8
10
 
9
11
  attr_reader :encrypted_id, :mask_id
10
12
 
@@ -17,46 +19,45 @@ module Scottrade
17
19
  return (@cookies != nil)
18
20
  end
19
21
  def authenticate
20
- params = {}
21
- params["appID"] = "Scottrade"
22
+ params = request_parameters("VerifyLogin")
22
23
  params["appName"] = "ScottradeMobileApplication"
23
- params["rcid"] = "iPhone"
24
- params["osName"] = "iPhone"
25
- params["platform"] = "iPhone"
26
- params["cacheid"] = ""
27
- params["osVer"] = "6"
28
- params["appver"] = "1.1.4"
29
24
  params["appVer"] = "1.1.4"
30
25
  params["isRemAcc"] = "true"
31
26
  params["page"] = "LogIn"
32
- params["serviceID"] = "VerifyLogin"
33
- params["channel"] = "rc"
34
27
  params["langId"] = "English"
35
28
 
36
29
  params["acc"] = @account
37
30
  params["pwd"] = @password
38
31
  params["isEncrypted"] = "false"
39
32
 
40
- response = post(params, nil)
33
+ response = authentication_post(params)
41
34
  all_cookies = response.get_fields('set-cookie') # only cookies are set on valid credentials
42
35
  parsed_response = JSON.parse(response.body)
36
+
37
+ @cookies = []
38
+ all_cookies.each { | cookie |
39
+ @cookies.push(cookie.split('; ')[0])
40
+ }
41
+ @encrypted_dd = parsed_response["encryptedId"]
42
+ @mask_id = parsed_response["maskId"]
43
+
44
+ return self
45
+ end
46
+
47
+ private
48
+ def authentication_post(params)
49
+ response = post(params)
50
+ parsed_response = JSON.parse(response.body)
43
51
  if parsed_response["error"] == "false" and !parsed_response.has_key?("errmsg")
44
- cookies = []
45
- all_cookies.each { | cookie |
46
- cookies.push(cookie.split('; ')[0])
47
- }
48
- @cookies = cookies
49
- @encrypted_dd = parsed_response["encryptedId"]
50
- @mask_id = parsed_response["maskId"]
51
-
52
- return self
52
+ return response
53
53
  elsif parsed_response["msg"]
54
54
  raise AuthenticationError, parsed_response["msg"]
55
55
  elsif parsed_response["errmsg"]
56
56
  raise AuthenticationError, parsed_response["errmsg"]
57
57
  else
58
58
  raise AuthenticationError
59
- end
59
+ end
60
60
  end
61
+
61
62
  end
62
63
  end
@@ -1,3 +1,3 @@
1
1
  module Scottrade
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -1,20 +1,16 @@
1
1
  require 'test/unit'
2
2
  require 'rack/test'
3
- require '../../lib/scottrade'
3
+ require_relative '../../lib/scottrade'
4
+ require_relative 'helpers'
4
5
 
5
6
  class AuthenticationTest < Test::Unit::TestCase
6
7
  include Rack::Test::Methods
7
-
8
+ include ScottradeUnitTestHelpers
9
+
8
10
  def test_positive_authentication
9
- scottrade = Scottrade::Scottrade.new(ENV["SCOTTRADE_ACCOUNT"],ENV["SCOTTRADE_PASSWORD"])
10
- assert_nothing_raised Scottrade::AuthenticationError do
11
- scottrade.authenticate
12
- end
11
+ authenticate(ENV["SCOTTRADE_ACCOUNT"],ENV["SCOTTRADE_PASSWORD"])
13
12
  end
14
13
  def test_negative_authentication
15
- scottrade = Scottrade::Scottrade.new("555555555","password")
16
- assert_raise Scottrade::AuthenticationError do
17
- scottrade.authenticate
18
- end
14
+ authenticate("555555555","password")
19
15
  end
20
16
  end
@@ -1,25 +1,24 @@
1
1
  require 'test/unit'
2
2
  require 'rack/test'
3
- require '../../lib/scottrade'
3
+ require_relative 'helpers'
4
+ require_relative '../../lib/scottrade'
5
+
4
6
  class AuthenticationTest < Test::Unit::TestCase
5
7
  include Rack::Test::Methods
6
-
8
+ include ScottradeUnitTestHelpers
7
9
  def test_brokerage_balances
8
- scottrade = Scottrade::Scottrade.new(ENV["SCOTTRADE_ACCOUNT"],ENV["SCOTTRADE_PASSWORD"])
9
- assert_nothing_raised Scottrade::AuthenticationError do
10
- scottrade.authenticate
11
- end
10
+ authenticate(ENV["SCOTTRADE_ACCOUNT"],ENV["SCOTTRADE_PASSWORD"])
11
+
12
12
  assert_nothing_raised Scottrade::RequestError do
13
13
  scottrade.brokerage.update_accounts
14
14
  end
15
15
  end
16
16
  def test_brokerage_positions
17
- scottrade = Scottrade::Scottrade.new(ENV["SCOTTRADE_ACCOUNT"],ENV["SCOTTRADE_PASSWORD"])
18
- assert_nothing_raised Scottrade::AuthenticationError do
19
- scottrade.authenticate
20
- end
17
+ authenticate(ENV["SCOTTRADE_ACCOUNT"],ENV["SCOTTRADE_PASSWORD"])
18
+
21
19
  assert_nothing_raised Scottrade::RequestError do
22
20
  scottrade.brokerage.update_positions
23
21
  end
24
22
  end
23
+
25
24
  end
@@ -0,0 +1,8 @@
1
+ module ScottradeUnitTestHelpers
2
+ def authenticate(username, password)
3
+ scottrade = Scottrade::Scottrade.new(username, password)
4
+ assert_nothing_raised Scottrade::AuthenticationError do
5
+ scottrade.authenticate
6
+ end
7
+ end
8
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scottrade
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-10 00:00:00.000000000 Z
12
+ date: 2013-01-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: money
@@ -45,6 +45,7 @@ files:
45
45
  - lib/scottrade/base.rb
46
46
  - lib/scottrade/brokerage.rb
47
47
  - lib/scottrade/error.rb
48
+ - lib/scottrade/helpers.rb
48
49
  - lib/scottrade/position.rb
49
50
  - lib/scottrade/quote.rb
50
51
  - lib/scottrade/session.rb
@@ -52,6 +53,7 @@ files:
52
53
  - scottrade.gemspec
53
54
  - tests/unit/auth.rb
54
55
  - tests/unit/brokerage.rb
56
+ - tests/unit/helpers.rb
55
57
  homepage: https://github.com/nolanbrown/scottrade
56
58
  licenses: []
57
59
  post_install_message: