ig_markets 0.13 → 0.14

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
  SHA1:
3
- metadata.gz: d08c5bda8c3b5efc6a42dff92de064a76e42fa24
4
- data.tar.gz: defcb9eaeb04b87f3772911e66b849a22ab091e2
3
+ metadata.gz: 4a9c0f861710bf880c830d2826c3e4ece9c2ef35
4
+ data.tar.gz: 4c2f4dbd5d336489e2a343ac0015ff34c0910e2b
5
5
  SHA512:
6
- metadata.gz: 80efc7ada830d2c5758c0c58dd5f2e666c0c4f315bd196e1de8c25423b8a901be0ac4cac40ddc6f189ca8bedf3d48001caa925b149fa7afb62340f3e32e41a6b
7
- data.tar.gz: 4eace6c040b07b374f878c9a621a8e090781758b345da829a841f0b8868c406b3f15b6e27f8166627fae33efebed7a4282e4b0367afce45492477c2e965fd861
6
+ metadata.gz: fa7dc0e4c01816d95e5b6dfec934c3a52e66b9b82ed27f5b777c19a89fa7bda5915b8f9bdba02ae6a3b8b42c251622ffa91c2c1a41e6c032ca4ae7300b611ca8
7
+ data.tar.gz: 9ca3b4fe730001d4ed3d8900ec5483e3a10e386e9b772f4057e0696b9c3f8019889318faf6abda047735046dade967bcaf537a1a157b95e90e5eb751928feb23
data/CHANGELOG.md CHANGED
@@ -1,6 +1,12 @@
1
1
  # IG Markets Changelog
2
2
 
3
- ### 0.13Unreleased
3
+ ### 0.14July 2, 2016
4
+
5
+ - Added `delete-all` subcommand to `ig_markets orders`
6
+ - Added a `#reload` method that reloads a model's attributes in-place to `IGMarkets::Account`,
7
+ `IGMarkets::ClientSentiment`, `IGMarkets::Market`, `IGMarkets::Position` and `IGMarkets::WorkingOrder`
8
+
9
+ ### 0.13 — June 22, 2016
4
10
 
5
11
  - Added `ig_markets performance` command that summarizes an account's dealing performance over a specified period
6
12
  - Added `ig_markets markets` command which prints the current state of all the passed EPICs
data/README.md CHANGED
@@ -76,6 +76,7 @@ commands and their subcommands is:
76
76
  - `ig_markets orders create ...`
77
77
  - `ig_markets orders update DEAL-ID ...`
78
78
  - `ig_markets orders delete DEAL-ID`
79
+ - `ig_markets orders delete-all`
79
80
  - `ig_markets performance --days N [...]`
80
81
  - `ig_markets positions [list] [...]`
81
82
  - `ig_markets positions create ...`
@@ -173,45 +174,48 @@ ig.deal_confirmation 'deal_reference'
173
174
  # Positions
174
175
  ig.positions.all
175
176
  ig.positions.create currency_code: 'USD', direction: :buy, epic: 'CS.D.EURUSD.CFD.IP', size: 2
176
- ig.positions['deal_id']
177
- ig.positions['deal_id'].profit_loss
178
- ig.positions['deal_id'].update limit_level: 1.2, stop_level: 1.1
179
- ig.positions['deal_id'].close
177
+ position = ig.positions['deal_id']
178
+ position.profit_loss
179
+ position.update limit_level: 1.2, stop_level: 1.1
180
+ position.reload
181
+ position.close
180
182
 
181
183
  # Sprint market positions
182
184
  ig.sprint_market_positions.all
183
- ig.sprint_market_positions['deal_id']
184
185
  ig.sprint_market_positions.create direction: :buy, epic: 'FM.D.EURUSD24.EURUSD24.IP',
185
186
  expiry_period: :twenty_minutes, size: 100
187
+ sprint_market_position = ig.sprint_market_positions['deal_id']
186
188
 
187
189
  # Working orders
188
190
  ig.working_orders.all
189
191
  ig.working_orders.create currency_code: 'USD', direction: :buy, epic: 'CS.D.EURUSD.CFD.IP',
190
192
  level: 0.99, size: 1, type: :limit
191
- ig.working_orders['deal_id']
192
- ig.working_orders['deal_id'].update level: 1.25, limit_distance: 50, stop_distance: 50
193
- ig.working_orders['deal_id'].delete
193
+ working_order = ig.working_orders['deal_id']
194
+ working_order.update level: 1.25, limit_distance: 50, stop_distance: 50
195
+ working_order.reload
196
+ working_order.delete
194
197
 
195
198
  # Markets
196
199
  ig.markets.hierarchy
197
200
  ig.markets.search 'EURUSD'
198
201
  ig.markets.find 'CS.D.EURUSD.CFD.IP', 'IX.D.DOW.IFD.IP'
199
- ig.markets['CS.D.EURUSD.CFD.IP'].historical_prices resolution: :hour, number: 48
200
- ig.markets['CS.D.EURUSD.CFD.IP'].historical_prices resolution: :second, from: Time.now - 120,
201
- to: Time.now - 60
202
+ market = ig.markets['CS.D.EURUSD.CFD.IP']
203
+ market.historical_prices resolution: :hour, number: 48
204
+ market.historical_prices resolution: :second, from: Time.now - 120, to: Time.now - 60
202
205
 
203
206
  # Watchlists
204
207
  ig.watchlists.all
205
208
  ig.watchlists.create 'New Watchlist', 'CS.D.EURUSD.CFD.IP', 'UA.D.AAPL.CASH.IP'
206
- ig.watchlists['watchlist_id']
207
- ig.watchlists['watchlist_id'].markets
208
- ig.watchlists['watchlist_id'].add_market 'CS.D.EURUSD.CFD.IP'
209
- ig.watchlists['watchlist_id'].remove_market 'CS.D.EURUSD.CFD.IP'
210
- ig.watchlists['watchlist_id'].delete
209
+ watchlist = ig.watchlists['watchlist_id']
210
+ watchlist.markets
211
+ watchlist.add_market 'CS.D.EURUSD.CFD.IP'
212
+ watchlist.remove_market 'CS.D.EURUSD.CFD.IP'
213
+ watchlist.delete
211
214
 
212
215
  # Client sentiment
213
- ig.client_sentiment['EURUSD']
214
- ig.client_sentiment['EURUSD'].related_sentiments
216
+ client_sentiment = ig.client_sentiment['EURUSD']
217
+ client_sentiment.related_sentiments
218
+ client_sentiment.reload
215
219
 
216
220
  # Miscellaneous
217
221
  ig.applications
data/lib/ig_markets.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'base64'
2
2
  require 'colorize'
3
3
  require 'date'
4
+ require 'json'
4
5
  require 'pry'
5
6
  require 'rest-client'
6
7
  require 'terminal-table'
@@ -19,5 +19,10 @@ module IGMarkets
19
19
  attribute :currency, String, regex: Regex::CURRENCY
20
20
  attribute :preferred, Boolean
21
21
  attribute :status, Symbol, allowed_values: [:disabled, :enabled, :suspended_from_dealing]
22
+
23
+ # Reloads this account's attributes by re-querying the IG Markets API.
24
+ def reload
25
+ self.attributes = @dealing_platform.account.all.detect { |a| a.account_id == account_id }.attributes
26
+ end
22
27
  end
23
28
  end
@@ -8,7 +8,7 @@ module IGMarkets
8
8
  class Action < Model
9
9
  attribute :action_type, Symbol, allowed_values: [:limit_order_amended, :limit_order_deleted,
10
10
  :limit_order_filled, :limit_order_opened, :limit_order_rolled,
11
- :position_closed, :position_deleted, :position_opended,
11
+ :position_closed, :position_deleted, :position_opened,
12
12
  :position_partially_closed, :position_rolled,
13
13
  :stop_limit_amended, :stop_order_amended, :stop_order_deleted,
14
14
  :stop_order_filled, :stop_order_opened, :stop_order_rolled,
@@ -74,6 +74,18 @@ module IGMarkets
74
74
  end
75
75
  end
76
76
 
77
+ desc 'delete-all', 'Deletes all working orders'
78
+
79
+ def delete_all
80
+ Main.begin_session(options) do |dealing_platform|
81
+ dealing_platform.working_orders.all.each do |working_order|
82
+ deal_reference = working_order.delete
83
+
84
+ Main.report_deal_confirmation deal_reference
85
+ end
86
+ end
87
+ end
88
+
77
89
  private
78
90
 
79
91
  ATTRIBUTES = [:currency_code, :direction, :epic, :expiry, :force_open, :good_till_date, :guaranteed_stop, :level,
@@ -66,11 +66,13 @@ module IGMarkets
66
66
  end
67
67
 
68
68
  def table_title(watchlist)
69
- title = "#{watchlist.name} (id: #{watchlist.id}"
70
- title << ', editable' if watchlist.editable
71
- title << ', deleteable' if watchlist.deleteable
72
- title << ', default' if watchlist.default_system_watchlist
73
- title << ')'
69
+ details = ["id: #{watchlist.id}"]
70
+
71
+ details << :default if watchlist.default_system_watchlist
72
+ details << :editable if watchlist.editable
73
+ details << :deleteable if watchlist.deleteable
74
+
75
+ "#{watchlist.name} (#{details.join ', '})"
74
76
  end
75
77
  end
76
78
  end
@@ -27,9 +27,6 @@ module IGMarkets
27
27
  types = details.actions.map(&:action_type).uniq
28
28
  types.delete :unknown
29
29
 
30
- # Fix a typo in one of the values
31
- types.map! { |v| v == :position_opended ? :position_opened : v }
32
-
33
30
  types.map { |v| format_cell_value v }.join ', '
34
31
  end
35
32
  end
@@ -6,6 +6,11 @@ module IGMarkets
6
6
  attribute :market_id
7
7
  attribute :short_position_percentage, Float
8
8
 
9
+ # Reloads this client sentiment's attributes by re-querying the IG Markets API.
10
+ def reload
11
+ self.attributes = @dealing_platform.client_sentiment[market_id].attributes
12
+ end
13
+
9
14
  # Returns client sentiments for markets that are related to this one.
10
15
  #
11
16
  # @return [Array<ClientSentiment>]
@@ -69,10 +69,8 @@ module IGMarkets
69
69
  # the position creation.
70
70
  def create(attributes)
71
71
  model = PositionCreateAttributes.new attributes
72
- model.validate
73
72
 
74
- payload = PayloadFormatter.format model
75
- payload[:expiry] ||= '-'
73
+ payload = PayloadFormatter.format model, expiry: '-'
76
74
 
77
75
  @dealing_platform.session.post('positions/otc', payload, API_V2).fetch(:deal_reference)
78
76
  end
@@ -101,8 +99,17 @@ module IGMarkets
101
99
 
102
100
  def initialize(attributes = {})
103
101
  super
104
-
105
102
  set_defaults
103
+ validate
104
+ end
105
+
106
+ private
107
+
108
+ def set_defaults
109
+ self.force_open = false if force_open.nil?
110
+ self.guaranteed_stop = false if guaranteed_stop.nil?
111
+ self.order_type ||= :market
112
+ self.time_in_force = :execute_and_eliminate if order_type == :market
106
113
  end
107
114
 
108
115
  # Runs a series of validations on this model's attributes to check whether it is ready to be sent to the IG
@@ -115,15 +122,6 @@ module IGMarkets
115
122
  validate_guaranteed_stop_constraints
116
123
  end
117
124
 
118
- private
119
-
120
- def set_defaults
121
- self.force_open = false if force_open.nil?
122
- self.guaranteed_stop = false if guaranteed_stop.nil?
123
- self.order_type ||= :market
124
- self.time_in_force = :execute_and_eliminate if order_type == :market
125
- end
126
-
127
125
  # Checks that all required attributes for position creation are present.
128
126
  def validate_required_attributes
129
127
  required = [:currency_code, :direction, :epic, :force_open, :guaranteed_stop, :order_type, :size,
@@ -63,11 +63,8 @@ module IGMarkets
63
63
  # the working order creation.
64
64
  def create(attributes)
65
65
  model = WorkingOrderCreateAttributes.new attributes
66
- model.validate
67
66
 
68
- payload = PayloadFormatter.format model
69
-
70
- payload[:expiry] ||= '-'
67
+ payload = PayloadFormatter.format model, expiry: '-'
71
68
 
72
69
  @dealing_platform.session.post('workingorders/otc', payload, API_V2).fetch :deal_reference
73
70
  end
@@ -92,8 +89,16 @@ module IGMarkets
92
89
 
93
90
  def initialize(attributes)
94
91
  super
95
-
96
92
  set_defaults
93
+ validate
94
+ end
95
+
96
+ private
97
+
98
+ def set_defaults
99
+ self.force_open = false if force_open.nil?
100
+ self.guaranteed_stop = false if guaranteed_stop.nil?
101
+ self.time_in_force = good_till_date ? :good_till_date : :good_till_cancelled
97
102
  end
98
103
 
99
104
  # Runs a series of validations on this model's attributes to check whether it is ready to be sent to the IG
@@ -110,14 +115,6 @@ module IGMarkets
110
115
 
111
116
  raise ArgumentError, 'Do not specify both stop_distance and stop_level options' if stop_distance && stop_level
112
117
  end
113
-
114
- private
115
-
116
- def set_defaults
117
- self.force_open = false if force_open.nil?
118
- self.guaranteed_stop = false if guaranteed_stop.nil?
119
- self.time_in_force = good_till_date ? :good_till_date : :good_till_cancelled
120
- end
121
118
  end
122
119
 
123
120
  private_constant :WorkingOrderCreateAttributes
@@ -43,6 +43,11 @@ module IGMarkets
43
43
  attribute :instrument, Instrument
44
44
  attribute :snapshot, Snapshot
45
45
 
46
+ # Reloads this market's attributes by re-querying the IG Markets API.
47
+ def reload
48
+ self.attributes = @dealing_platform.markets[instrument.epic].attributes
49
+ end
50
+
46
51
  # Returns historical prices for this market at a given resolution, either the most recent prices by specifying the
47
52
  # `:number` option, or those from a date range by specifying the `:from` and `:to` options.
48
53
  #
@@ -51,6 +51,15 @@ module IGMarkets
51
51
  "#<#{self.class.name} #{formatted_attributes.join ', '}>"
52
52
  end
53
53
 
54
+ # Mass assigns the passed attributes to this model.
55
+ #
56
+ # @param [Hash] new_attributes The attributes to assign on this model.
57
+ def attributes=(new_attributes)
58
+ new_attributes.each do |name, value|
59
+ send "#{name}=", value
60
+ end
61
+ end
62
+
54
63
  private
55
64
 
56
65
  # Returns the {#inspect} string for the given value.
@@ -9,10 +9,11 @@ module IGMarkets
9
9
  # available `:format` option.
10
10
  #
11
11
  # @param [Model] model The model instance to convert attributes for.
12
+ # @param [Hash] defaults The default attribute values to return, can be overridden by values set on `model`.
12
13
  #
13
14
  # @return [Hash] The resulting attributes hash.
14
- def format(model)
15
- model.class.defined_attributes.each_with_object({}) do |(name, options), formatted|
15
+ def format(model, defaults = {})
16
+ model.class.defined_attributes.each_with_object(defaults.dup) do |(name, options), formatted|
16
17
  value = model.send name
17
18
 
18
19
  next if value.nil?
@@ -59,6 +59,11 @@ module IGMarkets
59
59
  price_delta * size * contract_size
60
60
  end
61
61
 
62
+ # Reloads this position's attributes by re-querying the IG Markets API.
63
+ def reload
64
+ self.attributes = @dealing_platform.positions[deal_id].attributes
65
+ end
66
+
62
67
  # Closes this position. If called with no options then this position will be fully closed at current market prices,
63
68
  # partial closes and greater control over the close conditions can be achieved by using the relevant options.
64
69
  #
@@ -1,4 +1,4 @@
1
1
  module IGMarkets
2
2
  # The version of this gem.
3
- VERSION = '0.13'.freeze
3
+ VERSION = '0.14'.freeze
4
4
  end
@@ -21,6 +21,11 @@ module IGMarkets
21
21
 
22
22
  deprecated_attribute :created_date, :good_till_date_iso
23
23
 
24
+ # Reloads this working order's attributes by re-querying the IG Markets API.
25
+ def reload
26
+ self.attributes = @dealing_platform.working_orders[deal_id].attributes
27
+ end
28
+
24
29
  # Deletes this working order.
25
30
  #
26
31
  # @return [String] The deal reference of the deletion operation. Use {DealingPlatform#deal_confirmation} to check
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ig_markets
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.13'
4
+ version: '0.14'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Viney
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-22 00:00:00.000000000 Z
11
+ date: 2016-07-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize
@@ -16,56 +16,56 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.7'
19
+ version: '0.8'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '0.7'
26
+ version: '0.8'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: pry
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0.10'
33
+ version: 0.10.3
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0.10'
40
+ version: 0.10.3
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rest-client
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '1.8'
47
+ version: '2.0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '1.8'
54
+ version: '2.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: terminal-table
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '1.5'
61
+ version: '1.6'
62
62
  type: :runtime
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: '1.5'
68
+ version: '1.6'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: thor
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -80,20 +80,34 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0.19'
83
+ - !ruby/object:Gem::Dependency
84
+ name: activesupport
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '5.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '5.0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: codeclimate-test-reporter
85
99
  requirement: !ruby/object:Gem::Requirement
86
100
  requirements:
87
101
  - - "~>"
88
102
  - !ruby/object:Gem::Version
89
- version: '0.5'
103
+ version: '0.6'
90
104
  type: :development
91
105
  prerelease: false
92
106
  version_requirements: !ruby/object:Gem::Requirement
93
107
  requirements:
94
108
  - - "~>"
95
109
  - !ruby/object:Gem::Version
96
- version: '0.5'
110
+ version: '0.6'
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: factory_girl
99
113
  requirement: !ruby/object:Gem::Requirement
@@ -142,42 +156,42 @@ dependencies:
142
156
  requirements:
143
157
  - - "~>"
144
158
  - !ruby/object:Gem::Version
145
- version: '3.4'
159
+ version: '3.5'
146
160
  type: :development
147
161
  prerelease: false
148
162
  version_requirements: !ruby/object:Gem::Requirement
149
163
  requirements:
150
164
  - - "~>"
151
165
  - !ruby/object:Gem::Version
152
- version: '3.4'
166
+ version: '3.5'
153
167
  - !ruby/object:Gem::Dependency
154
168
  name: rspec-mocks
155
169
  requirement: !ruby/object:Gem::Requirement
156
170
  requirements:
157
171
  - - "~>"
158
172
  - !ruby/object:Gem::Version
159
- version: '3.4'
173
+ version: '3.5'
160
174
  type: :development
161
175
  prerelease: false
162
176
  version_requirements: !ruby/object:Gem::Requirement
163
177
  requirements:
164
178
  - - "~>"
165
179
  - !ruby/object:Gem::Version
166
- version: '3.4'
180
+ version: '3.5'
167
181
  - !ruby/object:Gem::Dependency
168
182
  name: rubocop
169
183
  requirement: !ruby/object:Gem::Requirement
170
184
  requirements:
171
185
  - - "~>"
172
186
  - !ruby/object:Gem::Version
173
- version: '0.40'
187
+ version: '0.41'
174
188
  type: :development
175
189
  prerelease: false
176
190
  version_requirements: !ruby/object:Gem::Requirement
177
191
  requirements:
178
192
  - - "~>"
179
193
  - !ruby/object:Gem::Version
180
- version: '0.40'
194
+ version: '0.41'
181
195
  - !ruby/object:Gem::Dependency
182
196
  name: yard
183
197
  requirement: !ruby/object:Gem::Requirement