ig_markets 0.31 → 0.32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +17 -4
  3. data/lib/ig_markets/account.rb +2 -2
  4. data/lib/ig_markets/activity.rb +12 -12
  5. data/lib/ig_markets/application.rb +1 -1
  6. data/lib/ig_markets/cli/commands/activities_command.rb +4 -3
  7. data/lib/ig_markets/cli/commands/orders_command.rb +6 -6
  8. data/lib/ig_markets/cli/commands/performance_command.rb +4 -3
  9. data/lib/ig_markets/cli/commands/positions_command.rb +13 -11
  10. data/lib/ig_markets/cli/commands/prices_command.rb +4 -4
  11. data/lib/ig_markets/cli/commands/sprints_command.rb +2 -2
  12. data/lib/ig_markets/cli/commands/transactions_command.rb +4 -3
  13. data/lib/ig_markets/cli/main.rb +12 -10
  14. data/lib/ig_markets/cli/tables/accounts_table.rb +6 -4
  15. data/lib/ig_markets/cli/tables/activities_table.rb +1 -1
  16. data/lib/ig_markets/cli/tables/historical_price_result_snapshots_table.rb +1 -1
  17. data/lib/ig_markets/cli/tables/market_overviews_table.rb +1 -1
  18. data/lib/ig_markets/client_account_summary.rb +8 -8
  19. data/lib/ig_markets/deal_confirmation.rb +25 -25
  20. data/lib/ig_markets/dealing_platform/account_methods.rb +2 -2
  21. data/lib/ig_markets/dealing_platform/position_methods.rb +13 -6
  22. data/lib/ig_markets/dealing_platform/sprint_market_position_methods.rb +3 -3
  23. data/lib/ig_markets/dealing_platform/streaming_methods.rb +10 -10
  24. data/lib/ig_markets/dealing_platform/working_order_methods.rb +6 -6
  25. data/lib/ig_markets/instrument.rb +7 -7
  26. data/lib/ig_markets/limited_risk_premium.rb +1 -1
  27. data/lib/ig_markets/market.rb +9 -9
  28. data/lib/ig_markets/market_overview.rb +1 -1
  29. data/lib/ig_markets/model.rb +16 -2
  30. data/lib/ig_markets/model/typecasters.rb +1 -1
  31. data/lib/ig_markets/position.rb +6 -6
  32. data/lib/ig_markets/sprint_market_position.rb +1 -1
  33. data/lib/ig_markets/streaming/account_state.rb +1 -1
  34. data/lib/ig_markets/streaming/consolidated_chart_data_update.rb +1 -1
  35. data/lib/ig_markets/streaming/market_update.rb +2 -2
  36. data/lib/ig_markets/streaming/position_update.rb +4 -4
  37. data/lib/ig_markets/streaming/working_order_update.rb +6 -6
  38. data/lib/ig_markets/transaction.rb +5 -5
  39. data/lib/ig_markets/version.rb +1 -1
  40. data/lib/ig_markets/working_order.rb +5 -5
  41. metadata +5 -19
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d43d7d776df76a8ac237f866ea55d5006e1f87c5
4
- data.tar.gz: d4ec2f9f14cb68aeb9b2942bc5e4c5a54f6d59f8
3
+ metadata.gz: 33c3ae06269ac129ea8042da743d2638e9d103a7
4
+ data.tar.gz: 5dc8bdd1bc5f32b58b845f6bec1040eeb2c21e92
5
5
  SHA512:
6
- metadata.gz: 7ebcba64fce12c9f276811d0df4e6588d484de43c5673cfbf7afd8c448f9d6cd94bf396847890d188e5cd2d53326652783e5ef19f24f210e0e2ae08901377c8b
7
- data.tar.gz: 5f3a03a7c45f0d973303fb37284b67ab5ba14e83a73917f540a4054b271b4812227a8afa826c11586fee6378d81c1be933bd8e450e8d74b5c874300e532d41bc
6
+ metadata.gz: 91d9892ccc49bdf29b5143c8ddb7f3e80d8aa7da64e89fb340da98b2fdbc8425c03178f87202a71efe8ec544319961d9c49acf7d6af73b1a86837bcd5caeaf5e
7
+ data.tar.gz: bbb4cdf0f2472244ad059372276520f043d521667218189b2d670f7de5ca6d54efe332224ee920737e1edc07ab5f71b6b3ef9bc7926921b0dbe028e9b6132be3
data/CHANGELOG.md CHANGED
@@ -1,12 +1,25 @@
1
1
  # IG Markets Changelog
2
2
 
3
+ ### 0.32 — May 27, 2017
4
+
5
+ - The `force_open` option now defaults to true for working orders, and is automatically set to true when creating a
6
+ position that specifies a limit distance, limit level, stop distance, or stop level
7
+ - Added `--to` option to the `ig_markets activities`, `ig_markets transactions`, and `ig_markets performance`
8
+ commands
9
+ - All timestamps provided to the `ig_markets activities`, `ig_markets transactions`, and `ig_markets performance`
10
+ commands must now specify an explicit time zone
11
+ - Support the `unavailable` state on `IGMarkets::Streaming::MarketUpdate#market_state`
12
+ - Fix exception in the `ig_markets performance` command when no performance data is found
13
+ - Fixed `IGMarkets::AccountMethods#activities` and `IGMarkets::AccountMethods#transactions` sometimes returning
14
+ duplicate entries
15
+
3
16
  ### 0.31 — March 26, 2017
4
17
 
5
- - Added `IGMarkets::Streaming::PositionUpdate#currency` attribute.
6
- - Added proper detection of an invalid deal ID passed to `ig_markets orders update`.
18
+ - Added `IGMarkets::Streaming::PositionUpdate#currency` attribute
19
+ - Added proper detection of an invalid deal ID passed to `ig_markets orders update`
7
20
  - Limited the update rate of `ig_markets stream` to 2Hz to avoid flickering caused by large numbers of simultaneous
8
- updates.
9
- - Fixed errors caused by a missing millisecond component on certain timestamps.
21
+ updates
22
+ - Fixed errors caused by a missing millisecond component on certain timestamps
10
23
 
11
24
  ### 0.30 — March 10, 2017
12
25
 
@@ -12,13 +12,13 @@ module IGMarkets
12
12
  attribute :account_alias
13
13
  attribute :account_id
14
14
  attribute :account_name
15
- attribute :account_type, Symbol, allowed_values: [:cfd, :physical, :spreadbet]
15
+ attribute :account_type, Symbol, allowed_values: %i[cfd physical spreadbet]
16
16
  attribute :balance, Balance
17
17
  attribute :can_transfer_from, Boolean
18
18
  attribute :can_transfer_to, Boolean
19
19
  attribute :currency, String, regex: Regex::CURRENCY
20
20
  attribute :preferred, Boolean
21
- attribute :status, Symbol, allowed_values: [:disabled, :enabled, :suspended_from_dealing]
21
+ attribute :status, Symbol, allowed_values: %i[disabled enabled suspended_from_dealing]
22
22
 
23
23
  # Reloads this account's attributes by re-querying the IG Markets API.
24
24
  def reload
@@ -6,20 +6,20 @@ module IGMarkets
6
6
  class Details < Model
7
7
  # Contains details on the actions that were performed by an activity. Returned by {#actions}.
8
8
  class Action < Model
9
- attribute :action_type, Symbol, allowed_values: [:limit_order_amended, :limit_order_deleted,
10
- :limit_order_filled, :limit_order_opened, :limit_order_rolled,
11
- :position_closed, :position_deleted, :position_opened,
12
- :position_partially_closed, :position_rolled,
13
- :stop_limit_amended, :stop_order_amended, :stop_order_deleted,
14
- :stop_order_filled, :stop_order_opened, :stop_order_rolled,
15
- :unknown, :working_order_deleted]
9
+ attribute :action_type, Symbol, allowed_values: %i[limit_order_amended limit_order_deleted
10
+ limit_order_filled limit_order_opened limit_order_rolled
11
+ position_closed position_deleted position_opened
12
+ position_partially_closed position_rolled
13
+ stop_limit_amended stop_order_amended stop_order_deleted
14
+ stop_order_filled stop_order_opened stop_order_rolled
15
+ unknown working_order_deleted]
16
16
  attribute :affected_deal_id
17
17
  end
18
18
 
19
19
  attribute :actions, Action
20
20
  attribute :currency
21
21
  attribute :deal_reference
22
- attribute :direction, Symbol, allowed_values: [:buy, :sell]
22
+ attribute :direction, Symbol, allowed_values: %i[buy sell]
23
23
  attribute :good_till_date
24
24
  attribute :guaranteed_stop, Boolean
25
25
  attribute :level, Float
@@ -33,14 +33,14 @@ module IGMarkets
33
33
  attribute :trailing_stop_distance, Integer
34
34
  end
35
35
 
36
- attribute :channel, Symbol, allowed_values: [:dealer, :mobile, :public_fix_api, :public_web_api, :system, :web]
36
+ attribute :channel, Symbol, allowed_values: %i[dealer mobile public_fix_api public_web_api system web]
37
37
  attribute :date, Time, format: '%FT%T'
38
38
  attribute :deal_id
39
39
  attribute :description
40
40
  attribute :details, Details
41
41
  attribute :epic, String, regex: Regex::EPIC
42
- attribute :period, Time, nil_if: %w(- DFB), format: ['%FT%T', '%d-%b-%y', '%b-%y']
43
- attribute :status, Symbol, allowed_values: [:accepted, :rejected, :unknown]
44
- attribute :type, Symbol, allowed_values: [:edit_stop_and_limit, :position, :system, :working_order]
42
+ attribute :period, Time, nil_if: %w[- DFB], format: ['%FT%T', '%d-%b-%y', '%b-%y']
43
+ attribute :status, Symbol, allowed_values: %i[accepted rejected unknown]
44
+ attribute :type, Symbol, allowed_values: %i[edit_stop_and_limit position system working_order]
45
45
  end
46
46
  end
@@ -15,7 +15,7 @@ module IGMarkets
15
15
  attribute :id
16
16
  attribute :name
17
17
  attribute :restricted_to_self, Boolean
18
- attribute :status, Symbol, allowed_values: [:disabled, :enabled, :revoked]
18
+ attribute :status, Symbol, allowed_values: %i[disabled enabled revoked]
19
19
  attribute :terms_accepted_date, Time, format: '%Q'
20
20
  attribute :tier
21
21
  end
@@ -4,10 +4,11 @@ module IGMarkets
4
4
  class Main
5
5
  desc 'activities', 'Prints account activities'
6
6
 
7
- option :days, type: :numeric, required: true, desc: 'The number of days to print account activities for'
8
- option :from, desc: 'The date and time to print account activities from, format: yyyy-mm-ddThh:mm:ss'
7
+ option :days, type: :numeric, desc: 'The number of days to print account activities for'
8
+ option :from, desc: 'The date and time to print account activities from, format: yyyy-mm-ddThh:mm:ss(+|-)zz:zz'
9
+ option :to, desc: 'The end date and time to print account transactions for, format: yyyy-mm-ddThh:mm:ss(+|-)zz:zz'
9
10
  option :epic, desc: 'Regex for filtering activities based on their EPIC'
10
- option :sort_by, enum: %w(channel date epic type), default: 'date', desc: 'The attribute to sort activities by'
11
+ option :sort_by, enum: %w[channel date epic type], default: 'date', desc: 'The attribute to sort activities by'
11
12
 
12
13
  def activities
13
14
  self.class.begin_session(options) do |dealing_platform|
@@ -20,10 +20,10 @@ module IGMarkets
20
20
 
21
21
  option :currency_code, required: true, desc: "The 3 character currency code, must be one of the instrument's " \
22
22
  'currencies'
23
- option :direction, enum: %w(buy sell), required: true, desc: 'The trade direction'
23
+ option :direction, enum: %w[buy sell], required: true, desc: 'The trade direction'
24
24
  option :epic, required: true, desc: 'The EPIC of the market to trade'
25
25
  option :expiry, desc: 'The expiry date of the instrument (if applicable), format: yyyy-mm-dd'
26
- option :force_open, type: :boolean, default: false, desc: 'Whether a force open is required'
26
+ option :force_open, type: :boolean, default: true, desc: 'Whether a force open is required'
27
27
  option :good_till_date, desc: 'The date that the order will live till, format: yyyy-mm-ddThh:mm(+|-)zz:zz'
28
28
  option :guaranteed_stop, type: :boolean, default: false, desc: 'Whether a guaranteed stop is required'
29
29
  option :level, type: :numeric, required: true, desc: 'The level at which the order will be triggered'
@@ -32,7 +32,7 @@ module IGMarkets
32
32
  option :size, type: :numeric, required: true, desc: 'The size of the order'
33
33
  option :stop_distance, type: :numeric, desc: 'The distance away in pips to place the stop'
34
34
  option :stop_level, type: :numeric, desc: 'The level at which to place the stop'
35
- option :type, enum: %w(limit stop), required: true, desc: 'The order type'
35
+ option :type, enum: %w[limit stop], required: true, desc: 'The order type'
36
36
 
37
37
  def create
38
38
  Main.begin_session(options) do |dealing_platform|
@@ -50,7 +50,7 @@ module IGMarkets
50
50
  option :limit_level, type: :numeric, desc: 'The level at which to place the limit'
51
51
  option :stop_distance, desc: 'The distance away in pips to place the stop'
52
52
  option :stop_level, type: :numeric, desc: 'The level at which to place the stop'
53
- option :type, enum: %w(limit stop), desc: 'The order type'
53
+ option :type, enum: %w[limit stop], desc: 'The order type'
54
54
 
55
55
  def update(deal_id)
56
56
  Main.begin_session(options) do |dealing_platform|
@@ -92,8 +92,8 @@ module IGMarkets
92
92
 
93
93
  private
94
94
 
95
- ATTRIBUTES = [:currency_code, :direction, :epic, :expiry, :force_open, :good_till_date, :guaranteed_stop, :level,
96
- :limit_distance, :limit_level, :size, :stop_distance, :stop_level, :type].freeze
95
+ ATTRIBUTES = %i[currency_code direction epic expiry force_open good_till_date guaranteed_stop level
96
+ limit_distance limit_level size stop_distance stop_level type].freeze
97
97
 
98
98
  def working_order_attributes
99
99
  attributes = Main.filter_options options, ATTRIBUTES
@@ -4,8 +4,9 @@ module IGMarkets
4
4
  class Main
5
5
  desc 'performance', 'Prints a summary of trading performance over a period'
6
6
 
7
- option :days, type: :numeric, required: true, desc: 'The number of days to print performance for'
8
- option :from, desc: 'The date and time to show performance from, format: yyyy-mm-ddThh:mm:ss'
7
+ option :days, type: :numeric, desc: 'The number of days to print performance for'
8
+ option :from, desc: 'The date and time to show performance from, format: yyyy-mm-ddThh:mm:ss(+|-)zz:zz'
9
+ option :to, desc: 'The end date and time to show transactions for, format: yyyy-mm-ddThh:mm:ss(+|-)zz:zz'
9
10
 
10
11
  def performance
11
12
  self.class.begin_session(options) do |dealing_platform|
@@ -16,7 +17,7 @@ module IGMarkets
16
17
 
17
18
  puts table
18
19
 
19
- print_summary performances
20
+ print_summary performances if performances.any?
20
21
  end
21
22
  end
22
23
 
@@ -26,22 +26,24 @@ module IGMarkets
26
26
 
27
27
  option :currency_code, required: true, desc: "The 3 character currency code, must be one of the instrument's " \
28
28
  'currencies'
29
- option :direction, required: true, enum: %w(buy sell), desc: 'The trade direction'
29
+ option :direction, required: true, enum: %w[buy sell], desc: 'The trade direction'
30
30
  option :epic, required: true, desc: 'The EPIC of the market to trade'
31
31
  option :expiry, desc: 'The expiry date of the instrument (if applicable), format: yyyy-mm-dd'
32
- option :force_open, type: :boolean, default: false, desc: 'Whether a force open is required'
32
+ option :force_open, type: :boolean, desc: 'Whether a force open is required, defaults to true if ' \
33
+ '--limit-distance, --limit-level, --stop-distance or --stop-level ' \
34
+ 'are specified'
33
35
  option :guaranteed_stop, type: :boolean, default: false, desc: 'Whether a guaranteed stop is required'
34
36
  option :level, type: :numeric, desc: "Required if and only if --order-type is 'limit' or 'quote'"
35
37
  option :limit_distance, type: :numeric, desc: 'The distance away in pips to place the limit, if set then ' \
36
38
  '--limit-level must not be used'
37
39
  option :limit_level, type: :numeric, desc: 'The limit level, if set then --limit-distance must not be used'
38
- option :order_type, enum: %w(limit market quote), default: 'market', desc: 'The order type'
40
+ option :order_type, enum: %w[limit market quote], default: 'market', desc: 'The order type'
39
41
  option :quote_id, desc: 'The Lightstreamer quote ID, required when using --order-type=quote'
40
42
  option :size, type: :numeric, required: true, desc: 'The size of the position'
41
43
  option :stop_distance, type: :numeric, desc: 'The distance away in pips to place the stop, if set then ' \
42
44
  '--stop-level must not be used'
43
45
  option :stop_level, type: :numeric, desc: 'The stop level, if set then --stop-distance must not be used'
44
- option :time_in_force, enum: %w(execute-and-eliminate fill-or-kill), desc: 'The order fill strategy'
46
+ option :time_in_force, enum: %w[execute-and-eliminate fill-or-kill], desc: 'The order fill strategy'
45
47
  option :trailing_stop, type: :boolean, desc: 'Whether to use a trailing stop, defaults to false'
46
48
  option :trailing_stop_increment, type: :numeric, desc: 'The increment step in pips for the trailing stop, ' \
47
49
  'required when --trailing-stop is specified'
@@ -71,11 +73,11 @@ module IGMarkets
71
73
  desc 'close DEAL-ID', 'Closes or partially closes a position'
72
74
 
73
75
  option :level, type: :numeric, desc: "Required if and only if --order-type is 'limit' or 'quote'"
74
- option :order_type, enum: %w(limit market quote), default: 'market', desc: 'The order type'
76
+ option :order_type, enum: %w[limit market quote], default: 'market', desc: 'The order type'
75
77
  option :quote_id, desc: 'The Lightstreamer quote ID, required when using --order-type=quote'
76
78
  option :size, type: :numeric, desc: 'The size of the position to close, if not specified then the entire ' \
77
79
  'position will be closed'
78
- option :time_in_force, enum: %w(execute-and-eliminate fill-or-kill), desc: 'The order fill strategy'
80
+ option :time_in_force, enum: %w[execute-and-eliminate fill-or-kill], desc: 'The order fill strategy'
79
81
 
80
82
  def close(deal_id)
81
83
  with_position(deal_id) do |position|
@@ -85,8 +87,8 @@ module IGMarkets
85
87
 
86
88
  desc 'close-all', 'Closes all open positions'
87
89
 
88
- option :order_type, enum: %w(limit market quote), default: 'market', desc: 'The order type'
89
- option :time_in_force, enum: %w(execute-and-eliminate fill-or-kill), desc: 'The order fill strategy'
90
+ option :order_type, enum: %w[limit market quote], default: 'market', desc: 'The order type'
91
+ option :time_in_force, enum: %w[execute-and-eliminate fill-or-kill], desc: 'The order fill strategy'
90
92
 
91
93
  def close_all
92
94
  Main.begin_session(options) do |dealing_platform|
@@ -100,9 +102,9 @@ module IGMarkets
100
102
 
101
103
  private
102
104
 
103
- ATTRIBUTES = [:currency_code, :direction, :epic, :expiry, :force_open, :guaranteed_stop, :level, :limit_distance,
104
- :limit_level, :order_type, :quote_id, :size, :stop_distance, :stop_level, :time_in_force,
105
- :trailing_stop, :trailing_stop_increment].freeze
105
+ ATTRIBUTES = %i[currency_code direction epic expiry force_open guaranteed_stop level limit_distance
106
+ limit_level order_type quote_id size stop_distance stop_level time_in_force
107
+ trailing_stop trailing_stop_increment].freeze
106
108
 
107
109
  def position_attributes
108
110
  attributes = Main.filter_options options, ATTRIBUTES
@@ -5,8 +5,8 @@ module IGMarkets
5
5
  desc 'prices', 'Prints historical prices for a market'
6
6
 
7
7
  option :epic, required: true, desc: 'The EPIC of the market to print historical prices for'
8
- option :resolution, enum: %w(second minute minute-2 minute-3 minute-5 minute-10 minute-15 minute-30 hour hour-2
9
- hour-3 hour-4 day week month), required: true, desc: 'The price resolution'
8
+ option :resolution, enum: %w[second minute minute-2 minute-3 minute-5 minute-10 minute-15 minute-30 hour hour-2
9
+ hour-3 hour-4 day week month], required: true, desc: 'The price resolution'
10
10
  option :number, type: :numeric, desc: 'The number of historical prices to return, if this is specified then ' \
11
11
  '--from and --to are ignored, otherwise they are required'
12
12
  option :from, desc: 'The start of the period to return prices for, required unless --number is specified, ' \
@@ -55,9 +55,9 @@ END
55
55
  end
56
56
 
57
57
  def historical_price_result_from_date_range(market)
58
- filtered_options = self.class.filter_options options, [:from, :to]
58
+ filtered_options = self.class.filter_options options, %i[from to]
59
59
 
60
- [:from, :to].each do |attribute|
60
+ %i[from to].each do |attribute|
61
61
  self.class.parse_date_time filtered_options, attribute, Time, '%FT%T%z', 'yyyy-mm-ddThh:mm:ss(+|-)zz:zz'
62
62
  end
63
63
 
@@ -20,9 +20,9 @@ module IGMarkets
20
20
 
21
21
  desc 'create', 'Creates a new sprint market position'
22
22
 
23
- option :direction, enum: %w(buy sell), required: true, desc: 'The trade direction'
23
+ option :direction, enum: %w[buy sell], required: true, desc: 'The trade direction'
24
24
  option :epic, required: true, desc: 'The EPIC of the market to trade'
25
- option :expiry_period, enum: %w(1 2 5 20 60), required: true, desc: 'The expiry period in seconds'
25
+ option :expiry_period, enum: %w[1 2 5 20 60], required: true, desc: 'The expiry period in seconds'
26
26
  option :size, required: true, desc: 'The position size'
27
27
 
28
28
  def create
@@ -4,11 +4,12 @@ module IGMarkets
4
4
  class Main
5
5
  desc 'transactions', 'Prints account transactions'
6
6
 
7
- option :days, type: :numeric, required: true, desc: 'The number of days to print account transactions for'
8
- option :from, desc: 'The date and time to print account transactions from, format: yyyy-mm-ddThh:mm:ss'
7
+ option :days, type: :numeric, desc: 'The number of days to print account transactions for'
8
+ option :from, desc: 'The date and time to print account transactions from, format: yyyy-mm-ddThh:mm:ss(+|-)zz:zz'
9
+ option :to, desc: 'The end date and time to print account transactions for, format: yyyy-mm-ddThh:mm:ss(+|-)zz:zz'
9
10
  option :instrument, desc: 'Regex for filtering transactions based on their instrument'
10
11
  option :interest, type: :boolean, default: true, desc: 'Whether to show interest deposits and withdrawals'
11
- option :sort_by, enum: %w(date instrument profit-loss type), default: 'date', desc: 'The attribute to sort ' \
12
+ option :sort_by, enum: %w[date instrument profit-loss type], default: 'date', desc: 'The attribute to sort ' \
12
13
  'transactions by'
13
14
 
14
15
  def transactions
@@ -27,21 +27,23 @@ module IGMarkets
27
27
 
28
28
  private
29
29
 
30
- # Turns the `:days` and `:from` options into a hash with `:from` and `:to` keys that can be passed to
31
- # {AccountMethods#activities} and {AccountMethods#transactions}.
30
+ # Turns the `:days` or `:from` options into a hash that can be passed to {AccountMethods#activities} and
31
+ # {AccountMethods#transactions}.
32
32
  def history_options
33
- days_in_seconds = options[:days] * 24 * 60 * 60
34
-
35
33
  if options[:from]
36
- from = Time.strptime options[:from], '%FT%T'
37
- to = from + days_in_seconds
38
-
39
- { from: from, to: to }
34
+ {
35
+ from: history_options_parse_time(options[:from]),
36
+ to: history_options_parse_time(options[:to])
37
+ }
40
38
  else
41
- { from: Time.now - days_in_seconds }
39
+ { from: Time.now.utc - options[:days] * 86_400 }
42
40
  end
43
41
  end
44
42
 
43
+ def history_options_parse_time(input)
44
+ input && Time.strptime(input, '%FT%T%z')
45
+ end
46
+
45
47
  class << self
46
48
  # This is the initial entry point for the execution of the command-line client. It is responsible for reading
47
49
  # any config files, implementing the --version/-v options, and then invoking the main application.
@@ -97,7 +99,7 @@ module IGMarkets
97
99
  end
98
100
 
99
101
  # Parses and validates a `Date` or `Time` option received as a command-line argument. Raises `ArgumentError` if
100
- # it is been specified in an invalid format.
102
+ # it has been specified in an invalid format.
101
103
  #
102
104
  # @param [Hash] attributes The attributes hash.
103
105
  # @param [Symbol] attribute The name of the date or time attribute to parse and validate.
@@ -22,10 +22,12 @@ module IGMarkets
22
22
  status = { disabled: 'Disabled', enabled: 'Enabled',
23
23
  suspended_from_dealing: 'Suspended' }.fetch account.status
24
24
 
25
- [account.account_name, account.account_id, type, account.currency, status, account.preferred] +
26
- [:available, :balance, :deposit, :profit_loss].map do |attribute|
27
- Format.currency account.balance.send(attribute), account.currency
28
- end
25
+ currency_values = %i[available balance deposit profit_loss].map do |attribute|
26
+ Format.currency account.balance.send(attribute), account.currency
27
+ end
28
+
29
+ [account.account_name, account.account_id, type, account.currency, status,
30
+ account.preferred] + currency_values
29
31
  end
30
32
 
31
33
  def cell_color(value, _model, _row_index, column_index)
@@ -10,7 +10,7 @@ module IGMarkets
10
10
  end
11
11
 
12
12
  def headings
13
- %w(Date Channel Type Status EPIC Market Size Level Limit Stop Result)
13
+ %w[Date Channel Type Status EPIC Market Size Level Limit Stop Result]
14
14
  end
15
15
 
16
16
  def right_aligned_columns
@@ -6,7 +6,7 @@ module IGMarkets
6
6
  private
7
7
 
8
8
  def headings
9
- %w(Date Open Close Low High)
9
+ %w[Date Open Close Low High]
10
10
  end
11
11
 
12
12
  def right_aligned_columns
@@ -34,7 +34,7 @@ module IGMarkets
34
34
  end
35
35
 
36
36
  def levels(market_overview)
37
- [:bid, :offer, :high, :low, :net_change, :percentage_change].map do |attribute|
37
+ %i[bid offer high low net_change percentage_change].map do |attribute|
38
38
  Format.level market_overview.send(attribute)
39
39
  end
40
40
  end
@@ -5,7 +5,7 @@ module IGMarkets
5
5
  class FormDetails < Model
6
6
  attribute :form_dismissable, Boolean
7
7
  attribute :form_title
8
- attribute :form_type, Symbol, allowed_values: [:bca, :kyc]
8
+ attribute :form_type, Symbol, allowed_values: %i[bca kyc]
9
9
  attribute :form_url
10
10
  end
11
11
 
@@ -13,17 +13,17 @@ module IGMarkets
13
13
  class AccountDetails < Model
14
14
  attribute :account_id
15
15
  attribute :account_name
16
- attribute :account_type, Symbol, allowed_values: [:cfd, :physical, :spreadbet]
16
+ attribute :account_type, Symbol, allowed_values: %i[cfd physical spreadbet]
17
17
  attribute :preferred, Boolean
18
18
  end
19
19
 
20
20
  attribute :account_info, Account::Balance
21
- attribute :account_type, Symbol, allowed_values: [:cfd, :physical, :spreadbet]
21
+ attribute :account_type, Symbol, allowed_values: %i[cfd physical spreadbet]
22
22
  attribute :accounts, AccountDetails
23
- attribute :authentication_status, Symbol, allowed_values: [:authenticated, :authenticated_missing_credentials,
24
- :change_environment, :disabled_preferred_account,
25
- :missing_preferred_account,
26
- :rejected_invalid_client_version]
23
+ attribute :authentication_status, Symbol, allowed_values: %i[authenticated authenticated_missing_credentials
24
+ change_environment disabled_preferred_account
25
+ missing_preferred_account
26
+ rejected_invalid_client_version]
27
27
  attribute :client_id
28
28
  attribute :currency_iso_code, String, regex: Regex::CURRENCY
29
29
  attribute :currency_symbol
@@ -35,7 +35,7 @@ module IGMarkets
35
35
  attribute :has_active_live_accounts, Boolean
36
36
  attribute :ig_company
37
37
  attribute :lightstreamer_endpoint
38
- attribute :rerouting_environment, Symbol, allowed_values: [:demo, :live, :test, :uat]
38
+ attribute :rerouting_environment, Symbol, allowed_values: %i[demo live test uat]
39
39
  attribute :timezone_offset, Float
40
40
  attribute :trailing_stops_enabled, Boolean
41
41
  end
@@ -4,7 +4,7 @@ module IGMarkets
4
4
  # Contains details on a specific deal that was affected by a dealing event. Returned by {#affected_deals}.
5
5
  class AffectedDeal < Model
6
6
  attribute :deal_id
7
- attribute :status, Symbol, allowed_values: [:amended, :deleted, :fully_closed, :opened, :partially_closed]
7
+ attribute :status, Symbol, allowed_values: %i[amended deleted fully_closed opened partially_closed]
8
8
  end
9
9
 
10
10
  attribute :account_id
@@ -13,38 +13,38 @@ module IGMarkets
13
13
  attribute :date, Time, format: ['%FT%T.%L', '%FT%T']
14
14
  attribute :deal_id
15
15
  attribute :deal_reference
16
- attribute :deal_status, Symbol, allowed_values: [:accepted, :fund_account, :rejected]
17
- attribute :direction, Symbol, allowed_values: [:buy, :sell]
16
+ attribute :deal_status, Symbol, allowed_values: %i[accepted fund_account rejected]
17
+ attribute :direction, Symbol, allowed_values: %i[buy sell]
18
18
  attribute :epic, String, regex: Regex::EPIC
19
- attribute :expiry, Date, nil_if: %w(- DFB), format: ['%d-%b-%y', '%b-%y']
19
+ attribute :expiry, Date, nil_if: %w[- DFB], format: ['%d-%b-%y', '%b-%y']
20
20
  attribute :guaranteed_stop, Boolean
21
21
  attribute :level, Float
22
22
  attribute :limit_distance, Integer
23
23
  attribute :limit_level, Float
24
24
  attribute :profit, Float
25
25
  attribute :profit_currency, String, regex: Regex::CURRENCY
26
- attribute :reason, Symbol, allowed_values: [:account_not_enabled_to_trading, :attached_order_level_error,
27
- :attached_order_trailing_stop_error, :cannot_change_stop_type,
28
- :cannot_remove_stop, :closing_only_trades_accepted_on_this_market,
29
- :conflicting_order, :contact_support_instrument_error, :cr_spacing,
30
- :duplicate_order_error, :exchange_manual_override,
31
- :finance_repeat_dealing, :force_open_on_same_market_different_currency,
32
- :general_error, :good_till_date_in_the_past, :instrument_not_found,
33
- :insufficient_funds, :level_tolerance_error, :manual_order_timeout,
34
- :market_closed, :market_closed_with_edits, :market_closing,
35
- :market_not_borrowable, :market_offline, :market_phone_only,
36
- :market_rolled, :market_unavailable_to_client, :max_auto_size_exceeded,
37
- :minimum_order_size_error, :move_away_only_limit, :move_away_only_stop,
38
- :move_away_only_trigger_level, :opposing_direction_orders_not_allowed,
39
- :opposing_positions_not_allowed, :order_locked, :order_not_found,
40
- :over_normal_market_size, :partially_closed_position_not_deleted,
41
- :position_not_available_to_close, :position_not_found,
42
- :reject_spreadbet_order_on_cfd_account, :size_increment,
43
- :sprint_market_expiry_after_market_close, :stop_or_limit_not_allowed,
44
- :stop_required_error, :strike_level_tolerance, :success,
45
- :trailing_stop_not_allowed, :unknown, :wrong_side_of_market]
26
+ attribute :reason, Symbol, allowed_values: %i[account_not_enabled_to_trading attached_order_level_error
27
+ attached_order_trailing_stop_error cannot_change_stop_type
28
+ cannot_remove_stop closing_only_trades_accepted_on_this_market
29
+ conflicting_order contact_support_instrument_error cr_spacing
30
+ duplicate_order_error exchange_manual_override
31
+ finance_repeat_dealing force_open_on_same_market_different_currency
32
+ general_error good_till_date_in_the_past instrument_not_found
33
+ insufficient_funds level_tolerance_error manual_order_timeout
34
+ market_closed market_closed_with_edits market_closing
35
+ market_not_borrowable market_offline market_phone_only
36
+ market_rolled market_unavailable_to_client max_auto_size_exceeded
37
+ minimum_order_size_error move_away_only_limit move_away_only_stop
38
+ move_away_only_trigger_level opposing_direction_orders_not_allowed
39
+ opposing_positions_not_allowed order_locked order_not_found
40
+ over_normal_market_size partially_closed_position_not_deleted
41
+ position_not_available_to_close position_not_found
42
+ reject_spreadbet_order_on_cfd_account size_increment
43
+ sprint_market_expiry_after_market_close stop_or_limit_not_allowed
44
+ stop_required_error strike_level_tolerance success
45
+ trailing_stop_not_allowed unknown wrong_side_of_market]
46
46
  attribute :size, Float
47
- attribute :status, Symbol, allowed_values: [:amended, :closed, :deleted, :open, :partially_closed]
47
+ attribute :status, Symbol, allowed_values: %i[amended closed deleted open partially_closed]
48
48
  attribute :stop_distance, Integer
49
49
  attribute :stop_level, Float
50
50
  attribute :trailing_stop, Boolean
@@ -45,7 +45,7 @@ module IGMarkets
45
45
  def transactions(options)
46
46
  options[:type] ||= :all
47
47
 
48
- unless [:all, :all_deal, :deposit, :withdrawal].include? options[:type]
48
+ unless %i[all all_deal deposit withdrawal].include? options[:type]
49
49
  raise ArgumentError, "invalid transaction type: #{options[:type]}"
50
50
  end
51
51
 
@@ -85,7 +85,7 @@ module IGMarkets
85
85
  options[:url_parameters][:to] = request_result.last.send(options[:date_attribute]).utc.strftime('%FT%T')
86
86
  end
87
87
 
88
- models.uniq
88
+ models.uniq(&:to_h)
89
89
  end
90
90
 
91
91
  # Parses and formats options shared by {#activities} and {#transactions} into a set of URL parameters.
@@ -80,7 +80,7 @@ module IGMarkets
80
80
  # Internal model used by {#create}
81
81
  class PositionCreateAttributes < Model
82
82
  attribute :currency_code, String, regex: Regex::CURRENCY
83
- attribute :direction, Symbol, allowed_values: [:buy, :sell]
83
+ attribute :direction, Symbol, allowed_values: %i[buy sell]
84
84
  attribute :epic, String, regex: Regex::EPIC
85
85
  attribute :expiry, Date, format: '%d-%b-%y'
86
86
  attribute :force_open, Boolean
@@ -88,12 +88,12 @@ module IGMarkets
88
88
  attribute :level, Float
89
89
  attribute :limit_distance, Integer
90
90
  attribute :limit_level, Float
91
- attribute :order_type, Symbol, allowed_values: [:limit, :market, :quote]
91
+ attribute :order_type, Symbol, allowed_values: %i[limit market quote]
92
92
  attribute :quote_id
93
93
  attribute :size, Float
94
94
  attribute :stop_distance, Integer
95
95
  attribute :stop_level, Float
96
- attribute :time_in_force, Symbol, allowed_values: [:execute_and_eliminate, :fill_or_kill]
96
+ attribute :time_in_force, Symbol, allowed_values: %i[execute_and_eliminate fill_or_kill]
97
97
  attribute :trailing_stop, Boolean
98
98
  attribute :trailing_stop_increment, Integer
99
99
 
@@ -106,12 +106,19 @@ module IGMarkets
106
106
  private
107
107
 
108
108
  def set_defaults
109
- self.force_open = false if force_open.nil?
109
+ set_default_force_open
110
+
110
111
  self.guaranteed_stop = false if guaranteed_stop.nil?
111
112
  self.order_type ||= :market
112
113
  self.time_in_force = :execute_and_eliminate if order_type == :market
113
114
  end
114
115
 
116
+ def set_default_force_open
117
+ self.force_open = false if force_open.nil?
118
+ self.force_open = true if attributes[:limit_distance] || attributes[:limit_level] ||
119
+ attributes[:stop_distance] || attributes[:stop_level]
120
+ end
121
+
115
122
  # Runs a series of validations on this model's attributes to check whether it is ready to be sent to the IG
116
123
  # Markets API.
117
124
  def validate
@@ -124,8 +131,8 @@ module IGMarkets
124
131
 
125
132
  # Checks that all required attributes for position creation are present.
126
133
  def validate_required_attributes
127
- required = [:currency_code, :direction, :epic, :force_open, :guaranteed_stop, :order_type, :size,
128
- :time_in_force]
134
+ required = %i[currency_code direction epic force_open guaranteed_stop order_type size
135
+ time_in_force]
129
136
 
130
137
  required.each do |attribute|
131
138
  raise ArgumentError, "#{attribute} attribute must be set" if attributes[attribute].nil?
@@ -49,10 +49,10 @@ module IGMarkets
49
49
 
50
50
  # Internal model used by {#create}
51
51
  class SprintMarketPositionCreateAttributes < Model
52
- attribute :direction, Symbol, allowed_values: [:buy, :sell]
52
+ attribute :direction, Symbol, allowed_values: %i[buy sell]
53
53
  attribute :epic, String, regex: Regex::EPIC
54
- attribute :expiry_period, Symbol, allowed_values: [:one_minute, :two_minutes, :five_minutes, :twenty_minutes,
55
- :sixty_minutes]
54
+ attribute :expiry_period, Symbol, allowed_values: %i[one_minute two_minutes five_minutes twenty_minutes
55
+ sixty_minutes]
56
56
  attribute :size, Float
57
57
  end
58
58
 
@@ -49,8 +49,8 @@ module IGMarkets
49
49
  accounts ||= @dealing_platform.client_account_summary.accounts
50
50
 
51
51
  items = Array(accounts).map { |account| "ACCOUNT:#{account.account_id}" }
52
- fields = [:available_cash, :available_to_deal, :deposit, :equity, :equity_used, :funds, :margin, :margin_lr,
53
- :margin_nlr, :pnl, :pnl_lr, :pnl_nlr]
52
+ fields = %i[available_cash available_to_deal deposit equity equity_used funds margin margin_lr
53
+ margin_nlr pnl pnl_lr pnl_nlr]
54
54
 
55
55
  build_subscription items: items, fields: fields, mode: :merge
56
56
  end
@@ -64,8 +64,8 @@ module IGMarkets
64
64
  # @return [Streaming::Subscription]
65
65
  def build_markets_subscription(epics)
66
66
  items = Array(epics).map { |epic| "MARKET:#{epic}" }
67
- fields = [:bid, :change, :change_pct, :high, :low, :market_delay, :market_state, :mid_open, :odds, :offer,
68
- :strike_price, :update_time]
67
+ fields = %i[bid change change_pct high low market_delay market_state mid_open odds offer
68
+ strike_price update_time]
69
69
 
70
70
  build_subscription items: items, fields: fields, mode: :merge
71
71
  end
@@ -82,7 +82,7 @@ module IGMarkets
82
82
  accounts ||= @dealing_platform.client_account_summary.accounts
83
83
 
84
84
  items = Array(accounts).map { |account| "TRADE:#{account.account_id}" }
85
- fields = [:confirms, :opu, :wou]
85
+ fields = %i[confirms opu wou]
86
86
 
87
87
  build_subscription items: items, fields: fields, mode: :distinct
88
88
  end
@@ -96,8 +96,8 @@ module IGMarkets
96
96
  # @return [Streaming::Subscription]
97
97
  def build_chart_ticks_subscription(epics)
98
98
  items = Array(epics).map { |epic| "CHART:#{epic}:TICK" }
99
- fields = [:bid, :day_high, :day_low, :day_net_chg_mid, :day_open_mid, :day_perc_chg_mid, :ltp, :ltv, :ofr, :ttv,
100
- :utm]
99
+ fields = %i[bid day_high day_low day_net_chg_mid day_open_mid day_perc_chg_mid ltp ltv ofr ttv
100
+ utm]
101
101
 
102
102
  build_subscription items: items, fields: fields, mode: :distinct
103
103
  end
@@ -114,9 +114,9 @@ module IGMarkets
114
114
  scale = { one_second: 'SECOND', one_minute: '1MINUTE', five_minutes: '5MINUTE', one_hour: 'HOUR' }.fetch scale
115
115
  items = ["CHART:#{epic}:#{scale}"]
116
116
 
117
- fields = [:bid_close, :bid_high, :bid_low, :bid_open, :cons_end, :cons_tick_count, :day_high, :day_low,
118
- :day_net_chg_mid, :day_open_mid, :day_perc_chg_mid, :ltp_close, :ltp_high, :ltp_low, :ltp_open, :ltv,
119
- :ofr_close, :ofr_high, :ofr_low, :ofr_open, :ttv, :utm]
117
+ fields = %i[bid_close bid_high bid_low bid_open cons_end cons_tick_count day_high day_low
118
+ day_net_chg_mid day_open_mid day_perc_chg_mid ltp_close ltp_high ltp_low ltp_open ltv
119
+ ofr_close ofr_high ofr_low ofr_open ttv utm]
120
120
 
121
121
  build_subscription items: items, fields: fields, mode: :merge
122
122
  end
@@ -39,7 +39,7 @@ module IGMarkets
39
39
  # @option attributes [:buy, :sell] :direction Order direction. Required.
40
40
  # @option attributes [String] :epic The EPIC of the instrument for the order. Required.
41
41
  # @option attributes [Date] :expiry The expiry date of the instrument (if applicable). Optional.
42
- # @option attributes [Boolean] :force_open Whether a force open is required. Defaults to `false`.
42
+ # @option attributes [Boolean] :force_open Whether a force open is required. Defaults to `true`.
43
43
  # @option attributes [Time] :good_till_date The date that the working order will live till. If not specified then
44
44
  # the working order will remain until it is cancelled.
45
45
  # @option attributes [Boolean] :guaranteed_stop Whether a guaranteed stop is required. Defaults to `false`.
@@ -72,7 +72,7 @@ module IGMarkets
72
72
  # Internal model used by {#create}.
73
73
  class WorkingOrderCreateAttributes < Model
74
74
  attribute :currency_code, String, regex: Regex::CURRENCY
75
- attribute :direction, Symbol, allowed_values: [:buy, :sell]
75
+ attribute :direction, Symbol, allowed_values: %i[buy sell]
76
76
  attribute :epic, String, regex: Regex::EPIC
77
77
  attribute :expiry, Date, format: '%d-%b-%y'
78
78
  attribute :force_open, Boolean
@@ -84,8 +84,8 @@ module IGMarkets
84
84
  attribute :size, Float
85
85
  attribute :stop_distance, Integer
86
86
  attribute :stop_level, Float
87
- attribute :time_in_force, Symbol, allowed_values: [:good_till_cancelled, :good_till_date]
88
- attribute :type, Symbol, allowed_values: [:limit, :stop]
87
+ attribute :time_in_force, Symbol, allowed_values: %i[good_till_cancelled good_till_date]
88
+ attribute :type, Symbol, allowed_values: %i[limit stop]
89
89
 
90
90
  def initialize(attributes)
91
91
  super
@@ -96,7 +96,7 @@ module IGMarkets
96
96
  private
97
97
 
98
98
  def set_defaults
99
- self.force_open = false if force_open.nil?
99
+ self.force_open = true if force_open.nil?
100
100
  self.guaranteed_stop = false if guaranteed_stop.nil?
101
101
  self.time_in_force = good_till_date ? :good_till_date : :good_till_cancelled
102
102
  end
@@ -104,7 +104,7 @@ module IGMarkets
104
104
  # Runs a series of validations on this model's attributes to check whether it is ready to be sent to the IG
105
105
  # Markets API.
106
106
  def validate
107
- required = [:currency_code, :direction, :epic, :guaranteed_stop, :level, :size, :time_in_force, :type]
107
+ required = %i[currency_code direction epic guaranteed_stop level size time_in_force type]
108
108
  required.each do |attribute|
109
109
  raise ArgumentError, "#{attribute} attribute must be set" if send(attribute).nil?
110
110
  end
@@ -62,14 +62,14 @@ module IGMarkets
62
62
  attribute :country
63
63
  attribute :currencies, Currency
64
64
  attribute :epic, String, regex: Regex::EPIC
65
- attribute :expiry, Date, nil_if: %w(- DFB), format: ['%d-%b-%y', '%b-%y']
65
+ attribute :expiry, Date, nil_if: %w[- DFB], format: ['%d-%b-%y', '%b-%y']
66
66
  attribute :expiry_details, ExpiryDetails
67
67
  attribute :force_open_allowed, Boolean
68
68
  attribute :limited_risk_premium, LimitedRiskPremium
69
69
  attribute :lot_size, Float
70
70
  attribute :margin_deposit_bands, MarginDepositBand
71
71
  attribute :margin_factor, Float
72
- attribute :margin_factor_unit, Symbol, allowed_values: [:percentage, :points]
72
+ attribute :margin_factor_unit, Symbol, allowed_values: %i[percentage points]
73
73
  attribute :market_id
74
74
  attribute :name
75
75
  attribute :news_code
@@ -82,11 +82,11 @@ module IGMarkets
82
82
  attribute :sprint_markets_minimum_expiry_time, Float
83
83
  attribute :stops_limits_allowed, Boolean
84
84
  attribute :streaming_prices_available, Boolean
85
- attribute :type, Symbol, allowed_values: [:binary, :bungee_capped, :bungee_commodities, :bungee_currencies,
86
- :bungee_indices, :commodities, :currencies, :indices, :opt_commodities,
87
- :opt_currencies, :opt_indices, :opt_rates, :opt_shares, :rates, :sectors,
88
- :shares, :sprint_market, :test_market, :unknown]
89
- attribute :unit, Symbol, allowed_values: [:amount, :contracts, :shares]
85
+ attribute :type, Symbol, allowed_values: %i[binary bungee_capped bungee_commodities bungee_currencies
86
+ bungee_indices commodities currencies indices opt_commodities
87
+ opt_currencies opt_indices opt_rates opt_shares rates sectors
88
+ shares sprint_market test_market unknown]
89
+ attribute :unit, Symbol, allowed_values: %i[amount contracts shares]
90
90
  attribute :value_of_one_pip
91
91
  end
92
92
  end
@@ -2,7 +2,7 @@ module IGMarkets
2
2
  # Contains details on a limited risk premium. Returned by {Instrument#limited_risk_premium},
3
3
  # {Position#limited_risk_premium} and {WorkingOrder#limited_risk_premium}.
4
4
  class LimitedRiskPremium < Model
5
- attribute :unit, Symbol, allowed_values: [:percentage, :points]
5
+ attribute :unit, Symbol, allowed_values: %i[percentage points]
6
6
  attribute :value, Float
7
7
  end
8
8
  end
@@ -7,18 +7,18 @@ module IGMarkets
7
7
  class DealingRules < Model
8
8
  # Contains specfics for a single dealing rule.
9
9
  class RuleDetails < Model
10
- attribute :unit, Symbol, allowed_values: [:percentage, :points]
10
+ attribute :unit, Symbol, allowed_values: %i[percentage points]
11
11
  attribute :value, Float
12
12
  end
13
13
 
14
- attribute :market_order_preference, Symbol, allowed_values: [:available_default_off, :available_default_on,
15
- :not_available]
14
+ attribute :market_order_preference, Symbol, allowed_values: %i[available_default_off available_default_on
15
+ not_available]
16
16
  attribute :max_stop_or_limit_distance, RuleDetails
17
17
  attribute :min_controlled_risk_stop_distance, RuleDetails
18
18
  attribute :min_deal_size, RuleDetails
19
19
  attribute :min_normal_stop_or_limit_distance, RuleDetails
20
20
  attribute :min_step_distance, RuleDetails
21
- attribute :trailing_stops_preference, Symbol, allowed_values: [:available, :not_available]
21
+ attribute :trailing_stops_preference, Symbol, allowed_values: %i[available not_available]
22
22
  end
23
23
 
24
24
  # Contains details on a snapshot of a market. Returned by {#snapshot}.
@@ -30,8 +30,8 @@ module IGMarkets
30
30
  attribute :delay_time, Float
31
31
  attribute :high, Float
32
32
  attribute :low, Float
33
- attribute :market_status, Symbol, allowed_values: [:closed, :edits_only, :offline, :on_auction,
34
- :on_auction_no_edits, :suspended, :tradeable]
33
+ attribute :market_status, Symbol, allowed_values: %i[closed edits_only offline on_auction
34
+ on_auction_no_edits suspended tradeable]
35
35
  attribute :net_change, Float
36
36
  attribute :offer, Float
37
37
  attribute :percentage_change, Float
@@ -75,12 +75,12 @@ module IGMarkets
75
75
 
76
76
  # Validates the options passed to {#historical_prices}.
77
77
  def validate_historical_prices_options(options)
78
- resolutions = [:second, :minute, :minute_2, :minute_3, :minute_5, :minute_10, :minute_15, :minute_30, :hour,
79
- :hour_2, :hour_3, :hour_4, :day, :week, :month]
78
+ resolutions = %i[second minute minute_2 minute_3 minute_5 minute_10 minute_15 minute_30 hour
79
+ hour_2 hour_3 hour_4 day week month]
80
80
 
81
81
  raise ArgumentError, 'resolution is invalid' unless resolutions.include? options[:resolution]
82
82
 
83
- return if options.keys == [:resolution, :from, :to] || options.keys == [:resolution, :number]
83
+ return if options.keys == %i[resolution from to] || options.keys == %i[resolution number]
84
84
 
85
85
  raise ArgumentError, 'options must specify either :number or :from and :to'
86
86
  end
@@ -5,7 +5,7 @@ module IGMarkets
5
5
  attribute :delay_time, Float
6
6
  attribute :epic, String, regex: Regex::EPIC
7
7
  attribute :exchange_id
8
- attribute :expiry, String, nil_if: %w(- DFB)
8
+ attribute :expiry, String, nil_if: %w[- DFB]
9
9
  attribute :high, Float
10
10
  attribute :instrument_name
11
11
  attribute :instrument_type, Symbol, allowed_values: Instrument.allowed_values(:type)
@@ -35,11 +35,25 @@ module IGMarkets
35
35
 
36
36
  # Compares this model to another, the attributes and class must match for them to be considered equal.
37
37
  #
38
- # @param [#class, #attributes] other The other model to compare to.
38
+ # @param [Model] other The other model to compare to.
39
39
  #
40
40
  # @return [Boolean]
41
41
  def ==(other)
42
- self.class == other.class && attributes == other.attributes
42
+ self.class == other.class && to_h == other.to_h
43
+ end
44
+
45
+ # Converts this model into a nested hash of attributes. This is simlar to just calling {#attributes}, but in this
46
+ # case any attributes that are instances of {Model} will also be transformed into a hash in the return value.
47
+ #
48
+ # @return [Hash]
49
+ def to_h
50
+ attributes.each_with_object({}) do |(key, value), hash|
51
+ hash[key] = if value.is_a? Model
52
+ value.to_h
53
+ else
54
+ value
55
+ end
56
+ end
43
57
  end
44
58
 
45
59
  # Returns a human-readable string containing this model's type and all its current attribute values.
@@ -20,7 +20,7 @@ module IGMarkets
20
20
 
21
21
  def typecaster_boolean(value, _options, name)
22
22
  return value if [nil, true, false].include? value
23
- return value == '1' if %w(0 1).include? value
23
+ return value == '1' if %w[0 1].include? value
24
24
 
25
25
  raise ArgumentError, "#{self}##{name}: invalid boolean value: #{value}"
26
26
  end
@@ -8,7 +8,7 @@ module IGMarkets
8
8
  attribute :currency, String, regex: Regex::CURRENCY
9
9
  attribute :deal_id
10
10
  attribute :deal_reference
11
- attribute :direction, Symbol, allowed_values: [:buy, :sell]
11
+ attribute :direction, Symbol, allowed_values: %i[buy sell]
12
12
  attribute :level, Float
13
13
  attribute :limit_level, Float
14
14
  attribute :limited_risk_premium, LimitedRiskPremium
@@ -134,7 +134,7 @@ module IGMarkets
134
134
  raise ArgumentError, 'set quote_id if and only if order_type is :quote'
135
135
  end
136
136
 
137
- return unless [:limit, :quote].include?(attributes[:order_type]) == attributes[:level].nil?
137
+ return unless %i[limit quote].include?(attributes[:order_type]) == attributes[:level].nil?
138
138
 
139
139
  raise ArgumentError, 'set level if and only if order_type is :limit or :quote'
140
140
  end
@@ -142,17 +142,17 @@ module IGMarkets
142
142
  # Internal model used by {#close}.
143
143
  class PositionCloseAttributes < Model
144
144
  attribute :deal_id
145
- attribute :direction, Symbol, allowed_values: [:buy, :sell]
145
+ attribute :direction, Symbol, allowed_values: %i[buy sell]
146
146
  attribute :level, Float
147
- attribute :order_type, Symbol, allowed_values: [:limit, :market, :quote]
147
+ attribute :order_type, Symbol, allowed_values: %i[limit market quote]
148
148
  attribute :quote_id
149
149
  attribute :size, Float
150
- attribute :time_in_force, Symbol, allowed_values: [:execute_and_eliminate, :fill_or_kill]
150
+ attribute :time_in_force, Symbol, allowed_values: %i[execute_and_eliminate fill_or_kill]
151
151
 
152
152
  # Runs a series of validations on this model's attributes to check whether it is ready to be sent to the IG
153
153
  # Markets API.
154
154
  def validate
155
- [:deal_id, :direction, :order_type, :size, :time_in_force].each do |attribute|
155
+ %i[deal_id direction order_type size time_in_force].each do |attribute|
156
156
  raise ArgumentError, "#{attribute} attribute must be set" if attributes[attribute].nil?
157
157
  end
158
158
 
@@ -5,7 +5,7 @@ module IGMarkets
5
5
  attribute :currency, String, regex: Regex::CURRENCY
6
6
  attribute :deal_id
7
7
  attribute :description
8
- attribute :direction, Symbol, allowed_values: [:buy, :sell]
8
+ attribute :direction, Symbol, allowed_values: %i[buy sell]
9
9
  attribute :epic, String, regex: Regex::EPIC
10
10
  attribute :expiry_time, Time, format: '%FT%T'
11
11
  attribute :instrument_name
@@ -174,7 +174,7 @@ module IGMarkets
174
174
  working_order.currency_code = working_order_update.currency
175
175
  working_order.order_level = working_order_update.level
176
176
 
177
- %i(good_till_date limit_distance order_type stop_distance time_in_force).each do |attribute|
177
+ %i[good_till_date limit_distance order_type stop_distance time_in_force].each do |attribute|
178
178
  working_order.send "#{attribute}=", working_order_update.send(attribute)
179
179
  end
180
180
  end
@@ -24,7 +24,7 @@ module IGMarkets
24
24
  attribute :ofr_high, Float
25
25
  attribute :ofr_low, Float
26
26
  attribute :ofr_open, Float
27
- attribute :scale, Symbol, allowed_values: [:one_second, :one_minute, :five_minutes, :one_hour]
27
+ attribute :scale, Symbol, allowed_values: %i[one_second one_minute five_minutes one_hour]
28
28
  attribute :ttv, Float
29
29
  attribute :utm, Time, format: '%Q'
30
30
  end
@@ -9,8 +9,8 @@ module IGMarkets
9
9
  attribute :high, Float
10
10
  attribute :low, Float
11
11
  attribute :market_delay, Boolean
12
- attribute :market_state, Symbol, allowed_values: [:closed, :offline, :tradeable, :edit, :auction,
13
- :auction_no_edit, :suspended]
12
+ attribute :market_state, Symbol, allowed_values: %i[closed offline tradeable edit auction
13
+ auction_no_edit suspended unavailable]
14
14
  attribute :mid_open, Float
15
15
  attribute :odds, Float
16
16
  attribute :offer, Float
@@ -8,15 +8,15 @@ module IGMarkets
8
8
  attribute :deal_id
9
9
  attribute :deal_id_origin
10
10
  attribute :deal_reference
11
- attribute :deal_status, Symbol, allowed_values: [:accepted, :rejected]
12
- attribute :direction, Symbol, allowed_values: [:buy, :sell]
11
+ attribute :deal_status, Symbol, allowed_values: %i[accepted rejected]
12
+ attribute :direction, Symbol, allowed_values: %i[buy sell]
13
13
  attribute :epic, String, regex: Regex::EPIC
14
- attribute :expiry, Date, nil_if: %w(- DFB), format: ['%d-%b-%y', '%b-%y']
14
+ attribute :expiry, Date, nil_if: %w[- DFB], format: ['%d-%b-%y', '%b-%y']
15
15
  attribute :guaranteed_stop, Boolean
16
16
  attribute :level, Float
17
17
  attribute :limit_level, Float
18
18
  attribute :size, Float
19
- attribute :status, Symbol, allowed_values: [:deleted, :open, :updated]
19
+ attribute :status, Symbol, allowed_values: %i[deleted open updated]
20
20
  attribute :stop_level, Float
21
21
  attribute :timestamp, Time, format: ['%FT%T.%L', '%FT%T']
22
22
  end
@@ -8,19 +8,19 @@ module IGMarkets
8
8
  attribute :currency, String, regex: Regex::CURRENCY
9
9
  attribute :deal_id
10
10
  attribute :deal_reference
11
- attribute :deal_status, Symbol, allowed_values: [:accepted, :rejected]
12
- attribute :direction, Symbol, allowed_values: [:buy, :sell]
11
+ attribute :deal_status, Symbol, allowed_values: %i[accepted rejected]
12
+ attribute :direction, Symbol, allowed_values: %i[buy sell]
13
13
  attribute :epic, String, regex: Regex::EPIC
14
- attribute :expiry, Date, nil_if: %w(- DFB), format: ['%d-%b-%y', '%b-%y']
14
+ attribute :expiry, Date, nil_if: %w[- DFB], format: ['%d-%b-%y', '%b-%y']
15
15
  attribute :good_till_date, Time, format: '%FT%T'
16
16
  attribute :guaranteed_stop, Boolean
17
17
  attribute :level, Float
18
18
  attribute :limit_distance, Integer
19
- attribute :order_type, Symbol, allowed_values: [:limit, :stop]
19
+ attribute :order_type, Symbol, allowed_values: %i[limit stop]
20
20
  attribute :size, Float
21
- attribute :status, Symbol, allowed_values: [:deleted, :open, :updated]
21
+ attribute :status, Symbol, allowed_values: %i[deleted open updated]
22
22
  attribute :stop_distance, Integer
23
- attribute :time_in_force, Symbol, allowed_values: [:good_till_cancelled, :good_till_date]
23
+ attribute :time_in_force, Symbol, allowed_values: %i[good_till_cancelled good_till_date]
24
24
  attribute :timestamp, Time, format: ['%FT%T.%L', '%FT%T']
25
25
  end
26
26
  end
@@ -3,17 +3,17 @@ module IGMarkets
3
3
  # {DealingPlatform::AccountMethods#transactions}.
4
4
  class Transaction < Model
5
5
  attribute :cash_transaction, Boolean
6
- attribute :close_level, String, nil_if: %w(- 0)
6
+ attribute :close_level, String, nil_if: %w[- 0]
7
7
  attribute :currency
8
8
  attribute :date_utc, Time, format: '%FT%T'
9
9
  attribute :instrument_name
10
10
  attribute :open_date_utc, Time, format: '%FT%T'
11
- attribute :open_level, String, nil_if: %w(- 0)
12
- attribute :period, Time, nil_if: %w(- DFB), format: ['%FT%T', '%d-%b-%y', '%b-%y']
11
+ attribute :open_level, String, nil_if: %w[- 0]
12
+ attribute :period, Time, nil_if: %w[- DFB], format: ['%FT%T', '%d-%b-%y', '%b-%y']
13
13
  attribute :profit_and_loss
14
14
  attribute :reference
15
15
  attribute :size, String, nil_if: '-'
16
- attribute :transaction_type, Symbol, allowed_values: [:chart, :deal, :depo, :dividend, :exchange, :trade, :with]
16
+ attribute :transaction_type, Symbol, allowed_values: %i[chart deal depo dividend exchange trade with]
17
17
 
18
18
  deprecated_attribute :date
19
19
 
@@ -23,7 +23,7 @@ module IGMarkets
23
23
  #
24
24
  # @return [Boolean]
25
25
  def interest?
26
- [:depo, :with].include?(transaction_type) && !(instrument_name.downcase =~ /(^|[^a-z])interest([^a-z]|$)/).nil?
26
+ %i[depo with].include?(transaction_type) && !(instrument_name.downcase =~ /(^|[^a-z])interest([^a-z]|$)/).nil?
27
27
  end
28
28
 
29
29
  # Returns this transaction's {#profit_and_loss} as a `Float`, denominated in this transaction's {#currency}.
@@ -1,4 +1,4 @@
1
1
  module IGMarkets
2
2
  # The version of this gem.
3
- VERSION = '0.31'.freeze
3
+ VERSION = '0.32'.freeze
4
4
  end
@@ -5,7 +5,7 @@ module IGMarkets
5
5
  attribute :created_date_utc, Time, format: '%FT%T'
6
6
  attribute :currency_code, String, regex: Regex::CURRENCY
7
7
  attribute :deal_id
8
- attribute :direction, Symbol, allowed_values: [:buy, :sell]
8
+ attribute :direction, Symbol, allowed_values: %i[buy sell]
9
9
  attribute :dma, Boolean
10
10
  attribute :epic, String, regex: Regex::EPIC
11
11
  attribute :good_till_date, Time, format: '%Y/%m/%d %R'
@@ -14,9 +14,9 @@ module IGMarkets
14
14
  attribute :limited_risk_premium, LimitedRiskPremium
15
15
  attribute :order_level, Float
16
16
  attribute :order_size, Float
17
- attribute :order_type, Symbol, allowed_values: [:limit, :stop]
17
+ attribute :order_type, Symbol, allowed_values: %i[limit stop]
18
18
  attribute :stop_distance, Integer
19
- attribute :time_in_force, Symbol, allowed_values: [:good_till_cancelled, :good_till_date]
19
+ attribute :time_in_force, Symbol, allowed_values: %i[good_till_cancelled good_till_date]
20
20
 
21
21
  attribute :market, MarketOverview
22
22
 
@@ -70,8 +70,8 @@ module IGMarkets
70
70
  attribute :limit_level, Float
71
71
  attribute :stop_distance, Integer
72
72
  attribute :stop_level, Float
73
- attribute :time_in_force, Symbol, allowed_values: [:good_till_cancelled, :good_till_date]
74
- attribute :type, Symbol, allowed_values: [:limit, :stop]
73
+ attribute :time_in_force, Symbol, allowed_values: %i[good_till_cancelled good_till_date]
74
+ attribute :type, Symbol, allowed_values: %i[limit stop]
75
75
 
76
76
  def initialize(existing_attributes, new_attributes)
77
77
  existing_attributes.delete :limit_distance if new_attributes.key? :limit_level
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.31'
4
+ version: '0.32'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Viney
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-03-26 00:00:00.000000000 Z
11
+ date: 2017-05-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize
@@ -66,20 +66,6 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: 0.10.4
69
- - !ruby/object:Gem::Dependency
70
- name: rainbow
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: 2.1.0
76
- type: :runtime
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: 2.1.0
83
69
  - !ruby/object:Gem::Dependency
84
70
  name: terminal-table
85
71
  requirement: !ruby/object:Gem::Requirement
@@ -198,14 +184,14 @@ dependencies:
198
184
  requirements:
199
185
  - - "~>"
200
186
  - !ruby/object:Gem::Version
201
- version: '0.47'
187
+ version: '0.48'
202
188
  type: :development
203
189
  prerelease: false
204
190
  version_requirements: !ruby/object:Gem::Requirement
205
191
  requirements:
206
192
  - - "~>"
207
193
  - !ruby/object:Gem::Version
208
- version: '0.47'
194
+ version: '0.48'
209
195
  - !ruby/object:Gem::Dependency
210
196
  name: rubocop-rspec
211
197
  requirement: !ruby/object:Gem::Requirement
@@ -361,7 +347,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
361
347
  version: '0'
362
348
  requirements: []
363
349
  rubyforge_project:
364
- rubygems_version: 2.5.2
350
+ rubygems_version: 2.6.11
365
351
  signing_key:
366
352
  specification_version: 4
367
353
  summary: Library and command-line client for accessing the IG Markets dealing platform.