alpaca-trade-api 0.3.0 → 0.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7b11b95c51e70df9f8dede233caff85b1f6ba320ef48223f352fb9aad667a7be
4
- data.tar.gz: 34ec4d4d1d1a7e30cdae40bfcff47a672f604776b3165ec5b58ec837d5b37eed
3
+ metadata.gz: dd1c174ba5c6598f9887738ad9cc14250e1dfb90e20c7566bccdf7f1e293c130
4
+ data.tar.gz: 7855a473230181b698498c453bde427e82abb4c6d425828b461a24bb2b42ae1b
5
5
  SHA512:
6
- metadata.gz: 6c6e449816b441014290897abb54fec95c555f8a2d505ae7ca2e61bd11b234660fd72ea1705bd3b6c16d2aff2b55de6d2a349269dcf08bd39c5b7a0e39f251ad
7
- data.tar.gz: 6237db054e3a43eb502be7676d6d13addc1f8d20dd52977297ee454081791360b7e987be4b6bfca5c5b86b4c0cc1e0edaf0acc7922350fbbca283a24ab14787d
6
+ metadata.gz: bb7a080c7f81b837d0d330b2f5df96a5fe437a5be4223513cca9ba6156fbb127da56aaeed7e130c8565381264f9687def53afa6e61a395368052c942a4c94210
7
+ data.tar.gz: d95a17099844cb82780b00f00e570362247f5739092029b8696b97b9222aba758ba1e4b499094a615b8adc88acad0f1df2aa7b8f0302d8749c75745031cf4d54
data/CHANGELOG.md CHANGED
@@ -4,6 +4,27 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.7.0] - 2021-02-27
8
+ ### Added
9
+ - Support for `faraday` 1.x.
10
+
11
+ ## [0.6.0] - 2020-05-26
12
+ ### Added
13
+ - Implemented Client#account_activities. Thanks @travishooper.
14
+
15
+ ## [0.5.0] - 2020-05-25
16
+ ### Added
17
+ - Implemented Client#last_trade. Thanks @nathanworden.
18
+
19
+ ## [0.4.1] - 2020-04-25
20
+ ### Fixed
21
+ - Added explicit `BigDecimal` require.
22
+
23
+ ## [0.4.0] - 2020-02-16
24
+ ### Added
25
+ - Supporting [Bracket Orders](https://docs.alpaca.markets/trading-on-alpaca/orders/#bracket-orders)
26
+ - Validating time frame in Client#bars
27
+
7
28
  ## [0.3.0] - 2019-09-19
8
29
  ### Added
9
30
  - Implemented new endpoints:
data/Gemfile.lock CHANGED
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- alpaca-trade-api (0.3.0)
5
- faraday (~> 0.15)
4
+ alpaca-trade-api (0.7.0)
5
+ faraday (>= 0.15, < 2.0)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
@@ -14,13 +14,16 @@ GEM
14
14
  safe_yaml (~> 1.0.0)
15
15
  diff-lcs (1.3)
16
16
  docile (1.3.2)
17
- faraday (0.15.4)
17
+ faraday (1.3.0)
18
+ faraday-net_http (~> 1.0)
18
19
  multipart-post (>= 1.2, < 3)
20
+ ruby2_keywords
21
+ faraday-net_http (1.0.1)
19
22
  hashdiff (0.4.0)
20
23
  json (2.2.0)
21
24
  multipart-post (2.1.1)
22
25
  public_suffix (3.1.1)
23
- rake (10.5.0)
26
+ rake (13.0.1)
24
27
  rb-readline (0.5.5)
25
28
  rspec (3.8.0)
26
29
  rspec-core (~> 3.8.0)
@@ -35,6 +38,7 @@ GEM
35
38
  diff-lcs (>= 1.2.0, < 2.0)
36
39
  rspec-support (~> 3.8.0)
37
40
  rspec-support (3.8.2)
41
+ ruby2_keywords (0.0.4)
38
42
  safe_yaml (1.0.5)
39
43
  simplecov (0.16.1)
40
44
  docile (~> 1.1)
@@ -54,7 +58,7 @@ DEPENDENCIES
54
58
  alpaca-trade-api!
55
59
  bundler (~> 2.0)
56
60
  byebug
57
- rake (~> 10.0)
61
+ rake (~> 13.0)
58
62
  rb-readline
59
63
  rspec (~> 3.0)
60
64
  simplecov (~> 0.16)
@@ -62,4 +66,4 @@ DEPENDENCIES
62
66
  webmock (~> 3.0)
63
67
 
64
68
  BUNDLED WITH
65
- 2.0.2
69
+ 2.1.4
data/README.md CHANGED
@@ -26,23 +26,55 @@ By default, the library is configured to use the Paper Trading host - `https://p
26
26
 
27
27
  ```ruby
28
28
  Alpaca::Trade::Api.configure do |config|
29
- config.endpoint = 'https://api.alapca.markets'
29
+ config.endpoint = 'https://api.alpaca.markets'
30
30
  config.key_id = 'A_KEY_ID'
31
31
  config.key_secret = 'A_S3CRET'
32
32
  end
33
33
  ```
34
34
 
35
- ### Account
36
35
 
37
- TODO: Write usage instructions here
36
+ ### Example
38
37
 
39
- ### Asset
38
+ Here's an example on how to use the library to read details of an account's orders in paper trading.
40
39
 
41
- TODO: Write usage instructions here
40
+ ```ruby
41
+ require 'alpaca/trade/api'
42
42
 
43
- ### Trading
43
+ Alpaca::Trade::Api.configure do |config|
44
+ config.endpoint = 'https://paper-api.alpaca.markets'
45
+ config.key_id = 'xxxxxxxx'
46
+ config.key_secret = 'xxxxx'
47
+ end
48
+
49
+ client = Alpaca::Trade::Api::Client.new
50
+ puts client.orders.last.inspect
51
+ ```
44
52
 
45
- TODO: Write usage instructions here
53
+ ### Supported endpoints
54
+
55
+ Here's a table with all currently supported endpoints in this library:
56
+
57
+ | Object | Action | Method |
58
+ |-----------------------------------------------------------------------------------------------|----------------------------------------|-------------------------------------------|
59
+ | [Account](https://docs.alpaca.markets/api-documentation/api-v2/account/) | [GET] Get the account | Client#account |
60
+ | [Account Activities](https://docs.alpaca.markets/api-documentation/api-v2/account-activities) | [GET] Get a list of account activities | Client#account_activities(activity_type:) |
61
+ | [Orders](https://docs.alpaca.markets/api-documentation/api-v2/orders/) | [GET] Get a list of orders | Client#orders |
62
+ | | [POST] Request a new order | Client#new_order |
63
+ | | [GET] Get an order | Client#order(id:) |
64
+ | | [GET] Get an order by client order id | Client#order(id:) |
65
+ | | [PATCH] Replace an order | Client#replace_order |
66
+ | | [DELETE] Cancel all orders | Client#cancel_orders |
67
+ | | [DELETE] Cancel an order | Client#cancel_order(id:) |
68
+ | [Positions](https://docs.alpaca.markets/api-documentation/api-v2/positions/) | [GET] Get open positions | Client#positions |
69
+ | | [GET] Get an open position | Client#position(symbol:) |
70
+ | | [DELETE] Close all positions | Client#close_positions |
71
+ | | [DELETE] Close a position | Client#close_position(symbol:) |
72
+ | [Assets](https://docs.alpaca.markets/api-documentation/api-v2/assets/) | [GET] Get assets | Client#assets |
73
+ | | [GET] Get assets/:id | Client#asset(symbol:) |
74
+ | | [GET] Get an asset | Client#asset(symbol:) |
75
+ | [Calendar](https://docs.alpaca.markets/api-documentation/api-v2/calendar/) | [GET] Get the calendar | Client#calendar(start_date:, end_date:) |
76
+ | [Clock](https://docs.alpaca.markets/api-documentation/api-v2/clock/) | [GET] Get the clock | Client#clock |
77
+ | [Bars](https://docs.alpaca.markets/api-documentation/api-v2/market-data/bars/) | [GET] Get a list of bars | Client#bars(timeframe, symbols, limit:) |
46
78
 
47
79
  ## Development
48
80
 
@@ -39,11 +39,11 @@ Gem::Specification.new do |spec|
39
39
  spec.add_development_dependency "bundler", "~> 2.0"
40
40
  spec.add_development_dependency "byebug"
41
41
  spec.add_development_dependency 'rb-readline'
42
- spec.add_development_dependency "rake", "~> 10.0"
42
+ spec.add_development_dependency "rake", "~> 13.0"
43
43
  spec.add_development_dependency "rspec", "~> 3.0"
44
44
  spec.add_development_dependency "simplecov", "~> 0.16"
45
45
  spec.add_development_dependency "vcr", "~> 5.0"
46
46
  spec.add_development_dependency "webmock", "~> 3.0"
47
47
 
48
- spec.add_dependency 'faraday', "~> 0.15"
48
+ spec.add_dependency 'faraday', ">= 0.15", "< 2.0"
49
49
  end
@@ -8,12 +8,16 @@ require 'alpaca/trade/api/asset'
8
8
  require 'alpaca/trade/api/bar'
9
9
  require 'alpaca/trade/api/calendar'
10
10
  require 'alpaca/trade/api/clock'
11
+ require 'alpaca/trade/api/last_trade'
12
+ require 'alpaca/trade/api/non_trade_activity'
11
13
  require 'alpaca/trade/api/order'
12
14
  require 'alpaca/trade/api/position'
15
+ require 'alpaca/trade/api/trade_activity'
13
16
 
14
17
  require 'alpaca/trade/api/client'
15
18
  require 'alpaca/trade/api/errors'
16
19
 
20
+ require 'bigdecimal/util'
17
21
  require 'json'
18
22
 
19
23
  module Alpaca
@@ -9,6 +9,8 @@ module Alpaca
9
9
  class Client
10
10
  attr_reader :data_endpoint, :endpoint, :key_id, :key_secret
11
11
 
12
+ TIMEFRAMES = ['minute', '1Min', '5Min', '15Min', 'day', '1D']
13
+
12
14
  def initialize(endpoint: Alpaca::Trade::Api.configuration.endpoint,
13
15
  key_id: Alpaca::Trade::Api.configuration.key_id,
14
16
  key_secret: Alpaca::Trade::Api.configuration.key_secret)
@@ -23,6 +25,14 @@ module Alpaca
23
25
  Account.new(JSON.parse(response.body))
24
26
  end
25
27
 
28
+ def account_activities(activity_type:)
29
+ response = get_request(endpoint, "/v2/account/activities/#{activity_type}")
30
+ raise InvalidActivityType, JSON.parse(response.body)['message'] if response.status == 422
31
+ json = JSON.parse(response.body)
32
+ activity_class = (TradeActivity::ATTRIBUTES - json.first.to_h.keys).none? ? TradeActivity : NonTradeActivity
33
+ json.map { |item| activity_class.new(item) }
34
+ end
35
+
26
36
  def asset(symbol:)
27
37
  response = get_request(endpoint, "v2/assets/#{symbol}")
28
38
  Asset.new(JSON.parse(response.body))
@@ -35,6 +45,7 @@ module Alpaca
35
45
  end
36
46
 
37
47
  def bars(timeframe, symbols, limit: 100)
48
+ validate_timeframe(timeframe)
38
49
  response = get_request(data_endpoint, "v1/bars/#{timeframe}", symbols: symbols.join(','), limit: limit)
39
50
  json = JSON.parse(response.body)
40
51
  json.keys.each_with_object({}) do |symbol, hash|
@@ -43,6 +54,7 @@ module Alpaca
43
54
  end
44
55
 
45
56
  def calendar(start_date: Date.today, end_date: (Date.today + 30))
57
+ # FIX, use start_date.strftime('%F')
46
58
  params = { "start" => start_date.iso8601, "end" => end_date.iso8601 }
47
59
  response = get_request(endpoint, "v2/calendar", params)
48
60
  json = JSON.parse(response.body)
@@ -93,8 +105,16 @@ module Alpaca
93
105
  end
94
106
  end
95
107
 
108
+ def last_trade(symbol:)
109
+ response = get_request(data_endpoint, "v1/last/stocks/#{symbol}")
110
+ raise InvalidRequest, JSON.parse(response.body)['message'] if response.status == 404
111
+
112
+ LastTrade.new(JSON.parse(response.body))
113
+ end
114
+
96
115
  def new_order(symbol:, qty:, side:, type:, time_in_force:, limit_price: nil,
97
- stop_price: nil, extended_hours: false, client_order_id: nil)
116
+ stop_price: nil, extended_hours: false, client_order_id: nil, order_class: nil,
117
+ take_profit: nil, stop_loss: nil)
98
118
 
99
119
  params = {
100
120
  symbol: symbol,
@@ -103,7 +123,10 @@ module Alpaca
103
123
  type: type,
104
124
  time_in_force: time_in_force,
105
125
  limit_price: limit_price,
126
+ order_class: order_class,
106
127
  stop_price: stop_price,
128
+ take_profit: take_profit,
129
+ stop_loss: stop_loss,
107
130
  extended_hours: extended_hours,
108
131
  client_order_id: client_order_id
109
132
  }
@@ -219,6 +242,12 @@ module Alpaca
219
242
  raise InternalServerError, JSON.parse(response.body)['message']
220
243
  end
221
244
  end
245
+
246
+ def validate_timeframe(timeframe)
247
+ unless TIMEFRAMES.include?(timeframe)
248
+ raise ArgumentError, "Invalid timeframe: #{timeframe}. Valid arguments are: #{TIMEFRAMES}"
249
+ end
250
+ end
222
251
  end
223
252
  end
224
253
  end
@@ -6,6 +6,7 @@ module Alpaca
6
6
  class Error < StandardError; end
7
7
  class InsufficientFunds < Error; end
8
8
  class InternalServerError < Error; end
9
+ class InvalidActivityType < Error; end
9
10
  class InvalidOrderId < Error; end
10
11
  class InvalidRequest < Error; end
11
12
  class MissingParameters < Error; end
@@ -0,0 +1,15 @@
1
+ module Alpaca
2
+ module Trade
3
+ module Api
4
+ class LastTrade
5
+ attr_reader :status, :symbol, :last
6
+
7
+ def initialize(json)
8
+ @status = json['status']
9
+ @symbol = json['symbol']
10
+ @last = json['last']
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Alpaca
4
+ module Trade
5
+ module Api
6
+ class NonTradeActivity
7
+ attr_reader :id, :activity_type, :date, :net_ammount, :symbol, :qty, :per_share_amount
8
+
9
+ def initialize(json)
10
+ @id = json['id']
11
+ @activity_type = json['activity_type']
12
+ @date = json['date']
13
+ @net_ammount = json['net_ammount']
14
+ @symbol = json['symbol']
15
+ @qty = json['qty']
16
+ @per_share_amount = json['per_share_amount']
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -4,34 +4,41 @@ module Alpaca
4
4
  module Trade
5
5
  module Api
6
6
  class Order
7
- attr_reader :id, :client_order_id, :created_at, :updated_at, :submitted_at,
8
- :filled_at, :expired_at, :canceled_at, :failed_at, :asset_id, :symbol,
9
- :asset_class, :qty, :filled_qty, :type, :side, :time_in_force, :limit_price,
10
- :stop_price, :filled_avg_price, :status, :extended_hours
7
+ attr_reader :id, :asset_class, :asset_id, :canceled_at, :client_order_id,
8
+ :created_at, :expired_at, :extended_hours, :failed_at, :filled_at, :filled_avg_price,
9
+ :filled_qty, :legs, :limit_price, :order_class, :qty, :replaced_at, :replaced_by,
10
+ :replaces, :side, :status, :stop_price, :submitted_at, :symbol, :time_in_force,
11
+ :type, :updated_at
11
12
 
12
13
  def initialize(json)
13
14
  @id = json['id']
15
+
16
+ @asset_class = json['asset_class']
17
+ @asset_id = json['asset_id']
18
+ @canceled_at = json['canceled_at']
14
19
  @client_order_id = json['client_order_id']
15
20
  @created_at = json['created_at']
16
- @updated_at = json['updated_at']
17
- @submitted_at = json['submitted_at']
18
- @filled_at = json['filled_at']
19
21
  @expired_at = json['expired_at']
20
- @canceled_at = json['canceled_at']
22
+ @extended_hours = json['extended_hours']
21
23
  @failed_at = json['failed_at']
22
- @asset_id = json['asset_id']
23
- @symbol = json['symbol']
24
- @asset_class = json['asset_class']
25
- @qty = json['qty']
24
+ @filled_at = json['filled_at']
25
+ @filled_avg_price = json['filled_avg_price']
26
26
  @filled_qty = json['filled_qty']
27
- @type = json['type']
28
- @side = json['side']
29
- @time_in_force = json['time_in_force']
27
+ @legs = (json['legs'] || []).map {|leg| Order.new(leg)}
30
28
  @limit_price = json['limit_price']
31
- @stop_price = json['stop_price']
32
- @filled_avg_price = json['filled_avg_price']
29
+ @order_class = json['order_class']
30
+ @qty = json['qty']
31
+ @replaced_at = json['replaced_at']
32
+ @replaced_by = json['replaced_by']
33
+ @replaces = json['replaces']
34
+ @side = json['side']
33
35
  @status = json['status']
34
- @extended_hours = json['extended_hours']
36
+ @stop_price = json['stop_price']
37
+ @submitted_at = json['submitted_at']
38
+ @symbol = json['symbol']
39
+ @time_in_force = json['time_in_force']
40
+ @type = json['type']
41
+ @updated_at = json['updated_at']
35
42
  end
36
43
  end
37
44
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Alpaca
4
+ module Trade
5
+ module Api
6
+ class TradeActivity
7
+ ATTRIBUTES = %w(id activity_type transaction_time type price qty side
8
+ symbol leaves_qty order_id cum_qty)
9
+
10
+ attr_reader :id, :activity_type, :transaction_time, :type, :price, :qty,
11
+ :side, :symbol, :leaves_qty, :order_id, :cum_qty
12
+
13
+ def initialize(json)
14
+ @id = json['id']
15
+ @activity_type = json['activity_type']
16
+ @transaction_time = json['transaction_time']
17
+ @type = json['type']
18
+ @price = json['price']
19
+ @qty = json['qty']
20
+ @side = json['side']
21
+ @symbol = json['symbol']
22
+ @leaves_qty = json['leaves_qty']
23
+ @order_id = json['order_id']
24
+ @cum_qty = json['cum_qty']
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -3,7 +3,7 @@
3
3
  module Alpaca
4
4
  module Trade
5
5
  module Api
6
- VERSION = '0.3.0'
6
+ VERSION = '0.7.0'
7
7
  end
8
8
  end
9
9
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: alpaca-trade-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cloves Carneiro Jr
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-09-20 00:00:00.000000000 Z
11
+ date: 2021-02-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '10.0'
61
+ version: '13.0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '10.0'
68
+ version: '13.0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -126,16 +126,22 @@ dependencies:
126
126
  name: faraday
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - "~>"
129
+ - - ">="
130
130
  - !ruby/object:Gem::Version
131
131
  version: '0.15'
132
+ - - "<"
133
+ - !ruby/object:Gem::Version
134
+ version: '2.0'
132
135
  type: :runtime
133
136
  prerelease: false
134
137
  version_requirements: !ruby/object:Gem::Requirement
135
138
  requirements:
136
- - - "~>"
139
+ - - ">="
137
140
  - !ruby/object:Gem::Version
138
141
  version: '0.15'
142
+ - - "<"
143
+ - !ruby/object:Gem::Version
144
+ version: '2.0'
139
145
  description: Alpaca API lets you build and trade with real-time market data for free.
140
146
  email:
141
147
  - ccarneiroj@gmail.com
@@ -165,8 +171,11 @@ files:
165
171
  - lib/alpaca/trade/api/clock.rb
166
172
  - lib/alpaca/trade/api/configuration.rb
167
173
  - lib/alpaca/trade/api/errors.rb
174
+ - lib/alpaca/trade/api/last_trade.rb
175
+ - lib/alpaca/trade/api/non_trade_activity.rb
168
176
  - lib/alpaca/trade/api/order.rb
169
177
  - lib/alpaca/trade/api/position.rb
178
+ - lib/alpaca/trade/api/trade_activity.rb
170
179
  - lib/alpaca/trade/api/version.rb
171
180
  homepage: https://github.com/ccjr/alpaca-trade-api
172
181
  licenses: