schwab-api-ruby 2.1.0 → 2.2.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -1
- data/README.md +67 -4
- data/lib/schwab/client.rb +18 -0
- data/lib/schwab/error.rb +3 -0
- data/lib/schwab/operations/base_operation.rb +3 -1
- data/lib/schwab/operations/get_account_numbers.rb +11 -0
- data/lib/schwab/operations/get_accounts.rb +106 -0
- data/lib/schwab/operations/get_instrument.rb +4 -0
- data/lib/schwab/operations/get_instrument_by_cusip.rb +11 -0
- data/lib/schwab/operations/get_transactions.rb +44 -0
- data/lib/schwab/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: be363423988093dfb91101597addfe4c045bc1433123b1ca2eec384592f5445f
|
4
|
+
data.tar.gz: 6e344be9f638a121e8198d1dd473f99738d7cd50cbd2e23d4d132c2acffc9551
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d37d7ae1dfb667ba753a29042332416a6b832216ae3516f9e8e2927f3ff3719d4c85d673ab127fd6636cc89859ba8db2994a576a0d5ad25998062e218336bfc4
|
7
|
+
data.tar.gz: 5985f75a67f7f75c118b20f68de6dc839eb8183cfa8f149de27f80d69d7d9801bb7510d0ee175548b329c9953282e7722f2fed737470c2b6cdbd7a672fbd555c
|
data/CHANGELOG.md
CHANGED
@@ -1,8 +1,11 @@
|
|
1
|
+
Version 2.2.0
|
2
|
+
- Add new methods: `get_account_numbers`, `get_accounts`, `get_instrument_by_cusip`, `get_transactions`
|
3
|
+
|
1
4
|
Version 2.1.0
|
2
5
|
- Enable Instrument endpoint with "projection" param so you can query for fundamentals or other data about the ticker
|
3
6
|
|
4
7
|
Version 2.0.0
|
5
|
-
- This is version 2.0.0
|
8
|
+
- This is version 2.0.0 because it's a continuation of the TDAmeritradeAPI gem.
|
6
9
|
|
7
10
|
Version 1.3.0.20210215
|
8
11
|
- Added tracking of token expiration dates to instance vars
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# TD Ameritrade API gem for Ruby
|
1
|
+
# Schwab API (formerly TD Ameritrade API) gem for Ruby
|
2
2
|
|
3
3
|
This is a gem for connecting to the OAuth/JSON-based Schwab API released in 2018. Go to
|
4
4
|
https://beta-developer.schwab.com/ to create your OAuth application login and view the official documentation.
|
@@ -42,11 +42,74 @@ The official API is documented [here](https://developer.tdameritrade.com/apis).
|
|
42
42
|
following functionality. If you would like to expand its functionality, then please submit a pull request.
|
43
43
|
|
44
44
|
- [x] Authentication
|
45
|
-
- [
|
46
|
-
- [
|
45
|
+
- [X] Accounts and Trading
|
46
|
+
- [X] Instruments
|
47
47
|
- [x] Price History
|
48
48
|
- [x] Real-time Quotes
|
49
49
|
|
50
|
+
The following functions correspond to the Schwab Individual Trader API specification found in the online docs:
|
51
|
+
* get_accounts(fields=nil)
|
52
|
+
* get_account_numbers
|
53
|
+
* get_instrument(symbol, projection)
|
54
|
+
* get_instrument_by_cusip(cusip)
|
55
|
+
* get_price_history(symbol, **options)
|
56
|
+
* get_quotes(symbols, **options)
|
57
|
+
* get_transactions(...)
|
58
|
+
|
59
|
+
# Example usage
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
client = Schwab::Client.new(
|
63
|
+
client_id: ENV.fetch('SCHWAB_CLIENT_ID'),
|
64
|
+
secret: ENV.fetch('SCHWAB_SECRET'),
|
65
|
+
redirect_uri: ENV.fetch('SCHWAB_REDIRECT_URI'),
|
66
|
+
access_token: '<access token you received after running the OAuth authentication step>',
|
67
|
+
refresh_token: '<access token you received after running the OAuth authentication step>',
|
68
|
+
access_token_expires_at:,
|
69
|
+
refresh_token_expires_at:
|
70
|
+
)
|
71
|
+
|
72
|
+
symbols = %w[SCHW HOOD MS]
|
73
|
+
result = client.get_quotes(symbols, fields: :quote)
|
74
|
+
#=> {"SCHW" =>
|
75
|
+
# {"assetMainType" => "EQUITY",
|
76
|
+
# "assetSubType" => "COE",
|
77
|
+
# "quoteType" => "NBBO",
|
78
|
+
# "realtime" => true,
|
79
|
+
# "ssid" => 1516105793,
|
80
|
+
# "symbol" => "SCHW",
|
81
|
+
# "quote" =>
|
82
|
+
# {"52WeekHigh" => 93.35,
|
83
|
+
# "52WeekLow" => 61.01,
|
84
|
+
# "askMICId" => "ARCX",
|
85
|
+
# "askPrice" => 92.0,
|
86
|
+
# "askSize" => 1,
|
87
|
+
# "askTime" => 1752276764663,
|
88
|
+
# "bidMICId" => "ARCX",
|
89
|
+
# "bidPrice" => 91.5,
|
90
|
+
# "bidSize" => 1,
|
91
|
+
# "bidTime" => 1752278152374,
|
92
|
+
# "closePrice" => 93.04,
|
93
|
+
# "highPrice" => 92.99,
|
94
|
+
# "lastMICId" => "ARCX",
|
95
|
+
# "lastPrice" => 91.8,
|
96
|
+
# "lastSize" => 5,
|
97
|
+
# "lowPrice" => 91.825,
|
98
|
+
# "mark" => 91.97,
|
99
|
+
# "markChange" => -1.07,
|
100
|
+
# "markPercentChange" => -1.15004299,
|
101
|
+
# "netChange" => -1.24,
|
102
|
+
# "netPercentChange" => -1.3327601,
|
103
|
+
# "openPrice" => 92.53,
|
104
|
+
# "postMarketChange" => -0.17,
|
105
|
+
# "postMarketPercentChange" => -0.18484288,
|
106
|
+
# "quoteTime" => 1752278152374,
|
107
|
+
# "securityStatus" => "Normal",
|
108
|
+
# "totalVolume" => 6815842,
|
109
|
+
# "tradeTime" => 1752277607998}}}
|
110
|
+
```
|
111
|
+
|
112
|
+
|
50
113
|
## Contributions
|
51
114
|
|
52
115
|
If you would like to make a contribution, please submit a pull request to the original branch. Feel free to email me Winston Kotzan
|
@@ -62,4 +125,4 @@ Please open an issue on Github if you have any problems or questions.
|
|
62
125
|
|
63
126
|
## Release Notes
|
64
127
|
|
65
|
-
See CHANGELOG.md
|
128
|
+
See CHANGELOG.md
|
data/lib/schwab/client.rb
CHANGED
@@ -2,9 +2,12 @@ require 'schwab/authentication'
|
|
2
2
|
require 'schwab/client'
|
3
3
|
require 'schwab/error'
|
4
4
|
require 'schwab/version'
|
5
|
+
require 'schwab/operations/get_accounts'
|
6
|
+
require 'schwab/operations/get_account_numbers'
|
5
7
|
require 'schwab/operations/get_instrument'
|
6
8
|
require 'schwab/operations/get_price_history'
|
7
9
|
require 'schwab/operations/get_quotes'
|
10
|
+
require 'schwab/operations/get_transactions'
|
8
11
|
|
9
12
|
module Schwab
|
10
13
|
class Client
|
@@ -21,10 +24,22 @@ module Schwab
|
|
21
24
|
@redirect_uri = args[:redirect_uri] || raise_error('redirect_uri is required!')
|
22
25
|
end
|
23
26
|
|
27
|
+
def get_accounts(fields=nil)
|
28
|
+
Operations::GetAccounts.new(self).call(fields:)
|
29
|
+
end
|
30
|
+
|
31
|
+
def get_account_numbers
|
32
|
+
Operations::GetAccountNumbers.new(self).call
|
33
|
+
end
|
34
|
+
|
24
35
|
def get_instrument(symbol, projection)
|
25
36
|
Operations::GetInstrument.new(self).call(symbol, projection:)
|
26
37
|
end
|
27
38
|
|
39
|
+
def get_instrument_by_cusip(cusip)
|
40
|
+
Operations::GetInstrumentByCusip.new(self).call(cusip)
|
41
|
+
end
|
42
|
+
|
28
43
|
def get_price_history(symbol, **options)
|
29
44
|
Operations::GetPriceHistory.new(self).call(symbol, **options)
|
30
45
|
end
|
@@ -33,5 +48,8 @@ module Schwab
|
|
33
48
|
Operations::GetQuotes.new(self).call(symbols:, **options)
|
34
49
|
end
|
35
50
|
|
51
|
+
def get_transactions(...)
|
52
|
+
Operations::GetTransactions.new(self).call(...)
|
53
|
+
end
|
36
54
|
end
|
37
55
|
end
|
data/lib/schwab/error.rb
CHANGED
@@ -27,6 +27,8 @@ module Schwab
|
|
27
27
|
raise Schwab::RateLimitError.new(response.body)
|
28
28
|
elsif response.code == 401
|
29
29
|
raise Schwab::NotAuthorizedError.new(response.body)
|
30
|
+
elsif response.code == 404
|
31
|
+
raise Schwab::BadRequestError.new(response.body)
|
30
32
|
end
|
31
33
|
|
32
34
|
error_message = response['errors'].to_s
|
@@ -41,7 +43,7 @@ module Schwab
|
|
41
43
|
raise ArgumentError unless response.is_a?(HTTParty::Response)
|
42
44
|
handle_api_error(response) unless response_success?(response)
|
43
45
|
|
44
|
-
response.
|
46
|
+
JSON.parse(response.body)
|
45
47
|
end
|
46
48
|
|
47
49
|
def perform_api_get_request(url: , query: nil)
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'schwab/operations/base_operation'
|
2
|
+
|
3
|
+
module Schwab; module Operations
|
4
|
+
class GetAccounts < BaseOperation
|
5
|
+
|
6
|
+
# Example Response:
|
7
|
+
# [
|
8
|
+
# {
|
9
|
+
# "securitiesAccount": {
|
10
|
+
# "type": "CASH",
|
11
|
+
# "accountNumber": "<account1>",
|
12
|
+
# "roundTrips": 0,
|
13
|
+
# "isDayTrader": false,
|
14
|
+
# "isClosingOnlyRestricted": false,
|
15
|
+
# "pfcbFlag": false,
|
16
|
+
# "positions": [
|
17
|
+
# {
|
18
|
+
# "shortQuantity": 0,
|
19
|
+
# "averagePrice": 13.4,
|
20
|
+
# "currentDayProfitLoss": -31.59,
|
21
|
+
# "currentDayProfitLossPercentage": -5.44,
|
22
|
+
# "longQuantity": 39,
|
23
|
+
# "settledLongQuantity": 39,
|
24
|
+
# "settledShortQuantity": 0,
|
25
|
+
# "instrument": {
|
26
|
+
# "assetType": "EQUITY",
|
27
|
+
# "cusip": "83406F102",
|
28
|
+
# "symbol": "SOFI",
|
29
|
+
# "netChange": -0.8
|
30
|
+
# },
|
31
|
+
# "marketValue": 549.51,
|
32
|
+
# "maintenanceRequirement": 0,
|
33
|
+
# "averageLongPrice": 13.4,
|
34
|
+
# "taxLotAverageLongPrice": 13.4,
|
35
|
+
# "longOpenProfitLoss": 26.91,
|
36
|
+
# "previousSessionLongQuantity": 39,
|
37
|
+
# "currentDayCost": 0
|
38
|
+
# },
|
39
|
+
# ],
|
40
|
+
# "initialBalances": {
|
41
|
+
# "accruedInterest": 0,
|
42
|
+
# "cashAvailableForTrading": 1561.98,
|
43
|
+
# "cashAvailableForWithdrawal": 1561.98,
|
44
|
+
# "cashBalance": 1561.98,
|
45
|
+
# "bondValue": 0,
|
46
|
+
# "cashReceipts": 0,
|
47
|
+
# "liquidationValue": 8566.46,
|
48
|
+
# "longOptionMarketValue": 0,
|
49
|
+
# "longStockValue": 7004.48,
|
50
|
+
# "moneyMarketFund": 0,
|
51
|
+
# "mutualFundValue": 1561.98,
|
52
|
+
# "shortOptionMarketValue": 0,
|
53
|
+
# "shortStockValue": 0,
|
54
|
+
# "isInCall": false,
|
55
|
+
# "unsettledCash": 0,
|
56
|
+
# "cashDebitCallValue": 0,
|
57
|
+
# "pendingDeposits": 0,
|
58
|
+
# "accountValue": 8566.46
|
59
|
+
# },
|
60
|
+
# "currentBalances": {
|
61
|
+
# "accruedInterest": 0,
|
62
|
+
# "cashBalance": 1561.98,
|
63
|
+
# "cashReceipts": 0,
|
64
|
+
# "longOptionMarketValue": 0,
|
65
|
+
# "liquidationValue": 8566.46,
|
66
|
+
# "longMarketValue": 7004.48,
|
67
|
+
# "moneyMarketFund": 0,
|
68
|
+
# "savings": 0,
|
69
|
+
# "shortMarketValue": 0,
|
70
|
+
# "pendingDeposits": 0,
|
71
|
+
# "mutualFundValue": 0,
|
72
|
+
# "bondValue": 0,
|
73
|
+
# "shortOptionMarketValue": 0,
|
74
|
+
# "cashAvailableForTrading": 1561.98,
|
75
|
+
# "cashAvailableForWithdrawal": 1561.98,
|
76
|
+
# "cashCall": 0,
|
77
|
+
# "longNonMarginableMarketValue": 1561.98,
|
78
|
+
# "totalCash": 1561.98,
|
79
|
+
# "cashDebitCallValue": 0,
|
80
|
+
# "unsettledCash": 0
|
81
|
+
# },
|
82
|
+
# "projectedBalances": {
|
83
|
+
# "cashAvailableForTrading": 1561.98,
|
84
|
+
# "cashAvailableForWithdrawal": 1561.98
|
85
|
+
# }
|
86
|
+
# },
|
87
|
+
# "aggregatedBalance": {
|
88
|
+
# "currentLiquidationValue": 8566.46,
|
89
|
+
# "liquidationValue": 8566.46
|
90
|
+
# }
|
91
|
+
# },
|
92
|
+
def call(fields: 'positions')
|
93
|
+
params = {
|
94
|
+
fields:,
|
95
|
+
}
|
96
|
+
|
97
|
+
response = perform_api_get_request(
|
98
|
+
url: 'https://api.schwabapi.com/trader/v1/accounts',
|
99
|
+
query: params,
|
100
|
+
)
|
101
|
+
|
102
|
+
response
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end; end
|
@@ -3,7 +3,11 @@ require 'schwab/operations/base_operation'
|
|
3
3
|
module Schwab; module Operations
|
4
4
|
class GetInstrument < BaseOperation
|
5
5
|
|
6
|
+
PROJECTIONS = %w[symbol-search symbol-regex desc-search desc-regex search fundamental]
|
7
|
+
|
6
8
|
def call(symbols, projection:)
|
9
|
+
raise ArgumentError, "projection must be in #{PROJECTIONS}" unless PROJECTIONS.include?(projection)
|
10
|
+
|
7
11
|
symbol = symbols.is_a?(Array) ? symbols.join(',') : symbols
|
8
12
|
|
9
13
|
params = {
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'schwab/operations/base_operation'
|
2
|
+
|
3
|
+
module Schwab; module Operations
|
4
|
+
class GetInstrumentByCusip < BaseOperation
|
5
|
+
|
6
|
+
def call(cusip)
|
7
|
+
perform_api_get_request(url: "https://api.schwabapi.com/marketdata/v1/instruments/#{cusip}")
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
11
|
+
end; end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'schwab/operations/base_operation'
|
2
|
+
|
3
|
+
module Schwab; module Operations
|
4
|
+
class GetTransactions < BaseOperation
|
5
|
+
|
6
|
+
TYPES = %w[
|
7
|
+
TRADE
|
8
|
+
RECEIVE_AND_DELIVER
|
9
|
+
DIVIDEND_OR_INTEREST
|
10
|
+
ACH_RECEIPT
|
11
|
+
ACH_DISBURSEMENT
|
12
|
+
CASH_RECEIPT
|
13
|
+
CASH_DISBURSEMENT
|
14
|
+
ELECTRONIC_FUND
|
15
|
+
WIRE_OUT
|
16
|
+
WIRE_IN
|
17
|
+
JOURNAL
|
18
|
+
MEMORANDUM
|
19
|
+
MARGIN_CALL
|
20
|
+
MONEY_MARKET
|
21
|
+
SMA_ADJUSTMENT
|
22
|
+
]
|
23
|
+
|
24
|
+
def call(account_number:, start_date:, end_date:, types:, symbol: nil)
|
25
|
+
raise(ArgumentError, "types must be one of #{TYPES}") unless TYPES.include?(types)
|
26
|
+
raise(ArgumentError, "start_date and end_date must be Time") unless [start_date, end_date].all?(Time)
|
27
|
+
|
28
|
+
params = {
|
29
|
+
startDate: start_date.utc.iso8601,
|
30
|
+
endDate: end_date.utc.iso8601,
|
31
|
+
types:,
|
32
|
+
}
|
33
|
+
params.merge!(symbol:) if symbol
|
34
|
+
|
35
|
+
response = perform_api_get_request(
|
36
|
+
url: "https://api.schwabapi.com/trader/v1/accounts/#{account_number}/transactions",
|
37
|
+
query: params,
|
38
|
+
)
|
39
|
+
|
40
|
+
response
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end; end
|
data/lib/schwab/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: schwab-api-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Winston Kotzan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-07-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -114,9 +114,13 @@ files:
|
|
114
114
|
- lib/schwab/client.rb
|
115
115
|
- lib/schwab/error.rb
|
116
116
|
- lib/schwab/operations/base_operation.rb
|
117
|
+
- lib/schwab/operations/get_account_numbers.rb
|
118
|
+
- lib/schwab/operations/get_accounts.rb
|
117
119
|
- lib/schwab/operations/get_instrument.rb
|
120
|
+
- lib/schwab/operations/get_instrument_by_cusip.rb
|
118
121
|
- lib/schwab/operations/get_price_history.rb
|
119
122
|
- lib/schwab/operations/get_quotes.rb
|
123
|
+
- lib/schwab/operations/get_transactions.rb
|
120
124
|
- lib/schwab/operations/support/build_watchlist_items.rb
|
121
125
|
- lib/schwab/util.rb
|
122
126
|
- lib/schwab/version.rb
|