scottrade 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/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: