alpaca-trade-api 0.3.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
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: