ig_markets 0.5 → 0.6

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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +18 -8
  3. data/README.md +40 -10
  4. data/lib/ig_markets.rb +3 -1
  5. data/lib/ig_markets/cli/commands/activities_command.rb +9 -7
  6. data/lib/ig_markets/cli/commands/orders_command.rb +8 -11
  7. data/lib/ig_markets/cli/commands/positions_command.rb +9 -7
  8. data/lib/ig_markets/cli/commands/prices_command.rb +66 -0
  9. data/lib/ig_markets/cli/commands/search_command.rb +19 -2
  10. data/lib/ig_markets/cli/commands/sprints_command.rb +2 -2
  11. data/lib/ig_markets/cli/config_file.rb +1 -1
  12. data/lib/ig_markets/cli/main.rb +25 -16
  13. data/lib/ig_markets/cli/tables/accounts_table.rb +10 -0
  14. data/lib/ig_markets/cli/tables/historical_price_result_snapshots_table.rb +25 -0
  15. data/lib/ig_markets/cli/tables/table.rb +2 -2
  16. data/lib/ig_markets/client_sentiment.rb +3 -1
  17. data/lib/ig_markets/dealing_platform.rb +49 -14
  18. data/lib/ig_markets/dealing_platform/account_methods.rb +13 -5
  19. data/lib/ig_markets/dealing_platform/client_sentiment_methods.rb +2 -4
  20. data/lib/ig_markets/dealing_platform/market_methods.rb +14 -6
  21. data/lib/ig_markets/dealing_platform/position_methods.rb +7 -7
  22. data/lib/ig_markets/dealing_platform/sprint_market_position_methods.rb +16 -2
  23. data/lib/ig_markets/dealing_platform/watchlist_methods.rb +4 -2
  24. data/lib/ig_markets/dealing_platform/working_order_methods.rb +2 -4
  25. data/lib/ig_markets/format.rb +10 -0
  26. data/lib/ig_markets/historical_price_result.rb +1 -1
  27. data/lib/ig_markets/instrument.rb +10 -10
  28. data/lib/ig_markets/market.rb +3 -3
  29. data/lib/ig_markets/model.rb +17 -25
  30. data/lib/ig_markets/model/typecasters.rb +20 -13
  31. data/lib/ig_markets/payload_formatter.rb +1 -1
  32. data/lib/ig_markets/position.rb +1 -1
  33. data/lib/ig_markets/session.rb +8 -8
  34. data/lib/ig_markets/sprint_market_position.rb +2 -2
  35. data/lib/ig_markets/transaction.rb +1 -1
  36. data/lib/ig_markets/version.rb +1 -1
  37. data/lib/ig_markets/watchlist.rb +6 -4
  38. data/lib/ig_markets/working_order.rb +2 -2
  39. metadata +4 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ef481344a1515b0031301c4e70e17ce843f7f111
4
- data.tar.gz: f2282b07a67e0dfba0fa8e7a8936d630777663e0
3
+ metadata.gz: 589e81bb5e11e735c8dacf82cac67d784d5d705f
4
+ data.tar.gz: 2a84abcae5a0844574fdbc25cbeff2fd831624e3
5
5
  SHA512:
6
- metadata.gz: d3816a297817a2d1da84402f1a20689e2b2f271ae7bc1c76a623f19b45320674f7ca94ec39b703bbb3553f2eb364b6d08f10f3cdc1db0c615b4887859253dc28
7
- data.tar.gz: 27b911f529724f105c3d443b41fc878f78c45815f6b9b1ce94569a6e88c17d85de48e34ed087e38307f638c05af61d90c9101b50a2db9056eb76d9c939ed2aaa
6
+ metadata.gz: f2706333bf110e2b169df6769d602bda5dae0d7e14cb98b92bb73785d81f169b35286855b72367f7182b5d41994514053768d95e1991028ee39c4a7733b3f4fb
7
+ data.tar.gz: d7c015c2573702b1ac5c1be4ec83f9c5d7e4212ded0be95d80fbe15f6542d580fed02e7fa1e5cfa5fb921227e4cd6ab74b3aaa47da6a3a093776f1949b8f0d6e
data/CHANGELOG.md CHANGED
@@ -1,12 +1,22 @@
1
1
  # IG Markets Changelog
2
2
 
3
- ### 0.6 - Unreleased
3
+ ### 0.6 April 27, 2016
4
4
 
5
- -
5
+ - Added `ig_markets prices` command to print historical market prices
6
+ - Added `IGMarkets::DealingPlatform#account_time_zone` to handle the `Time` attributes that come back from the IG
7
+ Markets API not in UTC and without a specified time zone
8
+ - Added `--account-time-zone` option to the command-line client, defaults to UTC
9
+ - Times reported by the command-line client are now in the local time zone instead of UTC
10
+ - Added `--type` option to `ig_markets search` to only show instruments of specific type(s)
11
+ - Use a default currency of `USD` for `ig_markets orders create` and `ig_markets positions create`
12
+ - Improved command-line client help output for several commands
13
+ - Added `IGMarkets::DealingPlatform::SprintMarketPositionMethods#[]`
14
+ - Fixed `IGMarkets::DealingPlatform::PositionMethods#[]` raising on an unknown deal ID
15
+ - Fixed `IGMarkets::Market#prices_in_date_range`
6
16
 
7
- ### 0.5 - April 23, 2016
17
+ ### 0.5 April 23, 2016
8
18
 
9
- - Ouptut from the command-line client is now formatted using ASCII tables and contains a lot more detail
19
+ - Output from the command-line client is now formatted using ASCII tables and contains a lot more detail
10
20
  - Added `--aggregate` option to `ig_markets positions list` to aggregate together positions with the same EPIC
11
21
  - Added `--instrument` option to `ig_markets transactions` to filter by instrument name
12
22
  - Added `--no-interest` option to `ig_markets transactions` to exclude interest transactions
@@ -18,7 +28,7 @@
18
28
  - Added `IGMarkets::Position#close_level`
19
29
  - Removed `IGMarkets::Position#formatted_size` and `IGMarkets::Transaction#formatted_transaction_type`
20
30
 
21
- ### 0.4 - April 18, 2016
31
+ ### 0.4 April 18, 2016
22
32
 
23
33
  - Added `create`, `update` and `delete` subcommands to `ig_markets orders`
24
34
  - Added `create`, `update` and `close` subcommands to `ig_markets positions`
@@ -34,11 +44,11 @@
34
44
  - Fixed errors working with a working order's `#good_till_date` attribute
35
45
  - Automatically reauthenticate if the client security token has expired
36
46
 
37
- ### 0.3 - April 14, 2016
47
+ ### 0.3 April 14, 2016
38
48
 
39
49
  - Added `--version` and `-v` options to the command-line client
40
50
 
41
- ### 0.2 - April 14, 2016
51
+ ### 0.2 April 14, 2016
42
52
 
43
53
  - Added `ig_markets` command-line client
44
54
  - `IGMarkets::Model` now has separate `Date` and `Time` attribute types, and a new `:time_zone` option is used for
@@ -50,6 +60,6 @@
50
60
  - Added `#expired?` and `#seconds_till_expiry` to `IGMarkets::SprintMarketPosition`
51
61
  - Fixed `IGMarkets::RequestFailedError#message`
52
62
 
53
- ### 0.1 - April 8, 2016
63
+ ### 0.1 April 8, 2016
54
64
 
55
65
  - Initial release
data/README.md CHANGED
@@ -41,7 +41,7 @@ $ gem install ig_markets
41
41
  The general form for invoking the command-line client is:
42
42
 
43
43
  ```
44
- $ ig_markets COMMAND [SUBCOMMAND] --username=USERNAME --password=PASSWORD --api-key=API-KEY [--demo] [...]
44
+ $ ig_markets COMMAND [SUBCOMMAND] --username USERNAME --password PASSWORD --api-key API-KEY [--demo] [...]
45
45
  ```
46
46
 
47
47
  #### Config File
@@ -53,9 +53,9 @@ details with every invocation.
53
53
  To do this create a config file at `"./.ig_markets"` or `"~/.ig_markets"` with the following contents:
54
54
 
55
55
  ```shell
56
- --username=USERNAME
57
- --password=PASSWORD
58
- --api-key=API-KEY
56
+ --username USERNAME
57
+ --password PASSWORD
58
+ --api-key API-KEY
59
59
  --demo # Include only if this is a demo account
60
60
  ```
61
61
 
@@ -67,7 +67,7 @@ Use `ig_markets help` to get details on the options accepted by the commands and
67
67
  commands and their subcommands is:
68
68
 
69
69
  - `ig_markets account`
70
- - `ig_markets activities --days=N [--start-date=YYYY-MM-DD]`
70
+ - `ig_markets activities --days N [--start-date YYYY-MM-DD]`
71
71
  - `ig_markets confirmation DEAL-REFERENCE`
72
72
  - `ig_markets help [COMMAND]`
73
73
  - `ig_markets orders [list]`
@@ -78,11 +78,12 @@ commands and their subcommands is:
78
78
  - `ig_markets positions create ...`
79
79
  - `ig_markets positions update DEAL-ID ...`
80
80
  - `ig_markets positions close DEAL-ID [...]`
81
- - `ig_markets search QUERY`
81
+ - `ig_markets prices --epic EPIC --resolution RESOLUTION [...]`
82
+ - `ig_markets search QUERY [--type TYPE]`
82
83
  - `ig_markets sentiment MARKET`
83
84
  - `ig_markets sprints [list]`
84
85
  - `ig_markets sprints create ...`
85
- - `ig_markets transactions --days=N [--start-date=YYYY-MM-DD] [--instrument=INSTRUMENT] [--no-interest]`
86
+ - `ig_markets transactions --days N [--start-date YYYY-MM-DD] [--instrument INSTRUMENT] [--no-interest]`
86
87
  - `ig_markets watchlists [list]`
87
88
  - `ig_markets watchlists create NAME [EPIC EPIC ...]`
88
89
  - `ig_markets watchlists add-markets WATCHLIST-ID [EPIC EPIC ...]`
@@ -96,13 +97,16 @@ commands and their subcommands is:
96
97
  ig_markets account
97
98
 
98
99
  # Print EUR/USD transactions from the last week, excluding interest transactions
99
- ig_markets transactions --days=7 --instrument EUR/USD --no-interest
100
+ ig_markets transactions --days 7 --instrument EUR/USD --no-interest
101
+
102
+ # Search for EURUSD currency markets
103
+ ig_markets search EURUSD --type currencies
100
104
 
101
105
  # Print current positions in aggregate
102
106
  ig_markets positions --aggregate
103
107
 
104
108
  # Create a EURUSD long position of size 2
105
- ig_markets positions create --currency-code USD --direction buy --epic CS.D.EURUSD.CFD.IP --size 2
109
+ ig_markets positions create --direction buy --epic CS.D.EURUSD.CFD.IP --size 2
106
110
 
107
111
  # Change the limit and stop levels for an existing position
108
112
  ig_markets positions update DEAL-ID --limit-level 1.15 --stop-level 1.10
@@ -117,7 +121,28 @@ ig_markets positions close DEAL-ID --size 1
117
121
  ig_markets sprints create --direction sell --epic FM.D.EURUSD24.EURUSD24.IP --expiry-period 20 --size 100
118
122
 
119
123
  # Create a working order to buy 1 unit of EURUSD at the level 1.1
120
- ig_markets orders create --currency-code USD --direction buy --epic CS.D.EURUSD.CFD.IP --level 1.1 --size 1 --type limit
124
+ ig_markets orders create --direction buy --epic CS.D.EURUSD.CFD.IP --level 1.1 --size 1 --type limit
125
+
126
+ # Print daily prices for EURUSD from the last two weeks
127
+ ig_markets prices --epic CS.D.EURUSD.CFD.IP --resolution day --number 14
128
+ ```
129
+
130
+ #### Account Time Zone
131
+
132
+ Some timestamps returned by the IG Markets API are in an unspecified time zone, which can result in some times
133
+ displayed by the command-line client being incorrect. By default the unknown time zone is assumed to be UTC, but if this
134
+ is incorrect then use the `--account-time-zone` argument to specify the actual time zone these times are in.
135
+
136
+ For example, an IG Markets Australia account requires `--account-time-zone +1000`.
137
+
138
+ The `--account-time-zone` argument should be put into an `.ig_markets` config file to avoid specifying it on every
139
+ invocation.
140
+
141
+ To check that the account time zone is correct run the following command and verify that the date and time reported for
142
+ the price is the current date/time in your local time zone.
143
+
144
+ ```
145
+ ig_markets prices --epic CS.D.EURUSD.CFD.IP --resolution minute --number 1
121
146
  ```
122
147
 
123
148
  ## Usage — Library
@@ -137,6 +162,10 @@ ig = IGMarkets::DealingPlatform.new
137
162
  ig.sign_in 'username', 'password', 'api_key', :demo
138
163
  ig.sign_out
139
164
 
165
+ # Set the time zone for the account, this is applied to time attributes returned from the IG Markets API that are not
166
+ # in a known time zone such as UTC
167
+ ig.account_time_zone = '+0000'
168
+
140
169
  # Account
141
170
  ig.account.all
142
171
  ig.account.recent_activities 365
@@ -157,6 +186,7 @@ ig.positions['deal_id'].close
157
186
 
158
187
  # Sprint market positions
159
188
  ig.sprint_market_positions.all
189
+ ig.sprint_market_positions['deal_id']
160
190
  ig.sprint_market_positions.create direction: :buy, epic: 'FM.D.EURUSD24.EURUSD24.IP',
161
191
  expiry_period: :twenty_minutes, size: 100
162
192
 
data/lib/ig_markets.rb CHANGED
@@ -52,6 +52,7 @@ require 'ig_markets/cli/config_file'
52
52
  require 'ig_markets/cli/commands/account_command'
53
53
  require 'ig_markets/cli/commands/activities_command'
54
54
  require 'ig_markets/cli/commands/confirmation_command'
55
+ require 'ig_markets/cli/commands/prices_command'
55
56
  require 'ig_markets/cli/commands/search_command'
56
57
  require 'ig_markets/cli/commands/sentiment_command'
57
58
  require 'ig_markets/cli/commands/transactions_command'
@@ -59,11 +60,12 @@ require 'ig_markets/cli/tables/table'
59
60
  require 'ig_markets/cli/tables/accounts_table'
60
61
  require 'ig_markets/cli/tables/activities_table'
61
62
  require 'ig_markets/cli/tables/client_sentiments_table'
63
+ require 'ig_markets/cli/tables/historical_price_result_snapshots_table'
62
64
  require 'ig_markets/cli/tables/market_overviews_table'
63
- require 'ig_markets/cli/tables/working_orders_table'
64
65
  require 'ig_markets/cli/tables/positions_table'
65
66
  require 'ig_markets/cli/tables/sprint_market_positions_table'
66
67
  require 'ig_markets/cli/tables/transactions_table'
68
+ require 'ig_markets/cli/tables/working_orders_table'
67
69
 
68
70
  # This module contains all the code for the IG Markets gem. See `README.md` and the {DealingPlatform} class to get
69
71
  # started with using this gem.
@@ -23,14 +23,16 @@ module IGMarkets
23
23
  days = options[:days]
24
24
  start_date = options[:start_date]
25
25
 
26
- if start_date
27
- start_date = Date.strptime start_date, '%F'
28
- end_date = start_date + days.to_i
26
+ send_args = if start_date
27
+ start_date = Date.strptime start_date, '%F'
28
+ end_date = start_date + days.to_i
29
29
 
30
- Main.dealing_platform.account.send "#{type}_in_date_range", start_date, end_date
31
- else
32
- Main.dealing_platform.account.send "recent_#{type}", days
33
- end
30
+ ["#{type}_in_date_range", start_date, end_date]
31
+ else
32
+ ["recent_#{type}", days]
33
+ end
34
+
35
+ Main.dealing_platform.account.send(*send_args)
34
36
  end
35
37
  end
36
38
  end
@@ -18,21 +18,19 @@ module IGMarkets
18
18
 
19
19
  desc 'create', 'Creates a new working order'
20
20
 
21
- option :currency_code, required: true, desc: 'The 3 character currency code, must be one of the instrument\'s ' \
21
+ option :currency_code, default: 'USD', desc: 'The 3 character currency code, must be one of the instrument\'s ' \
22
22
  'currencies'
23
- option :direction, required: true, desc: 'The trade direction, must be \'buy\' or \'sell\''
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, default: false'
27
- option :good_till_date, desc: 'The date that the order will live till, if not specified then the order will ' \
28
- 'remain until it is deleted, format: yyyy-mm-ddThh:mm(+|-)zz:zz'
29
- option :guaranteed_stop, type: :boolean, default: false, desc: 'Whether a guaranteed stop is required, ' \
30
- 'default: false'
26
+ option :force_open, type: :boolean, default: false, desc: 'Whether a force open is required'
27
+ option :good_till_date, desc: 'The date that the order will live till, format: yyyy-mm-ddThh:mm(+|-)zz:zz'
28
+ option :guaranteed_stop, type: :boolean, default: false, desc: 'Whether a guaranteed stop is required'
31
29
  option :level, type: :numeric, required: true, desc: 'The level at which the order will be triggered'
32
30
  option :limit_distance, type: :numeric, desc: 'The distance away in pips to place the limit'
33
31
  option :size, type: :numeric, required: true, desc: 'The size of the order'
34
32
  option :stop_distance, type: :numeric, desc: 'The distance away in pips to place the stop'
35
- option :type, required: true, desc: 'The order type, either \'limit\' or \'stop\''
33
+ option :type, enum: %w(limit stop), required: true, desc: 'The order type'
36
34
 
37
35
  def create
38
36
  Main.begin_session(options) do |dealing_platform|
@@ -44,12 +42,11 @@ module IGMarkets
44
42
 
45
43
  desc 'update DEAL-ID', 'Updates an existing working order'
46
44
 
47
- option :good_till_date, desc: 'The date that the order will live till, if not specified then the order will ' \
48
- 'remain until it is deleted, format: yyyy-mm-ddThh:mm(+|-)zz:zz'
45
+ option :good_till_date, desc: 'The date that the order will live till, format: yyyy-mm-ddThh:mm(+|-)zz:zz'
49
46
  option :level, type: :numeric, desc: 'The level at which the order will be triggered'
50
47
  option :limit_distance, desc: 'The distance away in pips to place the limit'
51
48
  option :stop_distance, desc: 'The distance away in pips to place the stop'
52
- option :type, desc: 'The order type, either \'limit\' or \'stop\''
49
+ option :type, enum: %w(limit stop), desc: 'The order type'
53
50
 
54
51
  def update(deal_id)
55
52
  Main.begin_session(options) do |dealing_platform|
@@ -24,9 +24,9 @@ module IGMarkets
24
24
 
25
25
  desc 'create', 'Creates a new position'
26
26
 
27
- option :currency_code, required: true, desc: 'The 3 character currency code, must be one of the instrument\'s ' \
27
+ option :currency_code, default: 'USD', desc: 'The 3 character currency code, must be one of the instrument\'s ' \
28
28
  'currencies'
29
- option :direction, required: true, desc: 'The trade direction, must be \'buy\' or \'sell\''
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
32
  option :force_open, type: :boolean, default: false, desc: 'Whether a force open is required'
@@ -35,13 +35,13 @@ module IGMarkets
35
35
  option :limit_distance, type: :numeric, desc: 'The distance away in pips to place the limit, if set then ' \
36
36
  '--limit-level must not be used'
37
37
  option :limit_level, type: :numeric, desc: 'The limit level, if set then --limit-distance must not be used'
38
- option :order_type, default: 'market', desc: 'The order type, must be \'limit\', \'market\' or \'quote\''
38
+ option :order_type, enum: %w(limit market quote), default: 'market', desc: 'The order type'
39
39
  option :quote_id, desc: 'The Lightstreamer quote ID, required when using --order-type=quote'
40
40
  option :size, type: :numeric, required: true, desc: 'The size of the position'
41
41
  option :stop_distance, type: :numeric, desc: 'The distance away in pips to place the stop, if set then ' \
42
42
  '--stop-level must not be used'
43
43
  option :stop_level, type: :numeric, desc: 'The stop level, if set then --stop-distance must not be used'
44
- option :time_in_force, desc: 'The order fill strategy, either \'execute_and_eliminate\' or \'fill_or_kill\''
44
+ option :time_in_force, enum: %w(execute-and-eliminate fill-or-kill), desc: 'The order fill strategy'
45
45
  option :trailing_stop, type: :boolean, desc: 'Whether to use a trailing stop, defaults to false'
46
46
  option :trailing_stop_increment, type: :numeric, desc: 'The increment step in pips for the trailing stop, ' \
47
47
  'required when --trailing-stop is specified'
@@ -71,11 +71,11 @@ module IGMarkets
71
71
  desc 'close DEAL-ID', 'Closes or partially closes a position'
72
72
 
73
73
  option :level, type: :numeric, desc: 'Required if and only if --order-type is \'limit\' or \'quote\''
74
- option :order_type, default: 'market', desc: 'The order type, must be \'limit\', \'market\' or \'quote\''
74
+ option :order_type, enum: %w(limit market quote), default: 'market', desc: 'The order type'
75
75
  option :quote_id, desc: 'The Lightstreamer quote ID, required when using --order-type=quote'
76
76
  option :size, type: :numeric, desc: 'The size of the position to close, if not specified then the entire ' \
77
77
  'position will be closed'
78
- option :time_in_force, desc: 'The order fill strategy, either \'execute_and_eliminate\' or \'fill_or_kill\''
78
+ option :time_in_force, enum: %w(execute-and-eliminate fill-or-kill), desc: 'The order fill strategy'
79
79
 
80
80
  def close(deal_id)
81
81
  with_position(deal_id) do |position|
@@ -92,6 +92,8 @@ module IGMarkets
92
92
  def position_attributes
93
93
  attributes = Main.filter_options options, ATTRIBUTES
94
94
 
95
+ attributes[:time_in_force] = attributes[:time_in_force].tr('-', '_').to_sym if attributes.key? :time_in_force
96
+
95
97
  Main.parse_date_time attributes, :expiry, Date, '%F', 'yyyy-mm-dd'
96
98
 
97
99
  attributes
@@ -111,7 +113,7 @@ module IGMarkets
111
113
 
112
114
  def print_position_totals(positions)
113
115
  currency_totals = positions.group_by(&:currency).map do |currency, subset|
114
- total = subset.map(&:profit_loss).reduce(:+)
116
+ total = subset.map(&:profit_loss).reduce :+
115
117
 
116
118
  Format.currency(total, currency).colorize(total < 0 ? :red : :green)
117
119
  end
@@ -0,0 +1,66 @@
1
+ module IGMarkets
2
+ module CLI
3
+ # Implements the `ig_markets prices` command.
4
+ class Main
5
+ desc 'prices', 'Prints historical prices for a market'
6
+
7
+ option :epic, required: true, desc: 'The EPIC of the market to print historical prices for'
8
+ option :resolution, enum: %w(minute minute-2 minute-3 minute-5 minute-10 minute-15 minute-30 hour hour-2 hour-3
9
+ hour-4 day week month), required: true, desc: 'The price resolution'
10
+ option :number, type: :numeric, desc: 'The number of historical prices to return, if this is specified then ' \
11
+ '--start-date and --end-date are ignored, otherwise they are required'
12
+ option :start_date, desc: 'The start of the period to return prices for, required unless --number is specified' \
13
+ ', format: yyyy-mm-ddThh:mm(+|-)zz:zz'
14
+ option :end_date, desc: 'The end of the period to return prices for, required unless --number is specified' \
15
+ ', format: yyyy-mm-ddThh:mm(+|-)zz:zz'
16
+
17
+ def prices
18
+ self.class.begin_session(options) do |dealing_platform|
19
+ result = historical_price_result dealing_platform
20
+
21
+ table = HistoricalPriceResultSnapshotsTable.new result.prices, title: "Prices for #{options[:epic]}"
22
+
23
+ puts <<-END
24
+ #{table}
25
+
26
+ Allowance: #{result.allowance.total_allowance}
27
+ Remaining: #{result.allowance.remaining_allowance}
28
+ END
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def resolution
35
+ options[:resolution].to_s.tr('-', '_').to_sym
36
+ end
37
+
38
+ def historical_price_result(dealing_platform)
39
+ market = dealing_platform.markets[options[:epic]]
40
+
41
+ raise ArgumentError, 'invalid epic' unless market
42
+
43
+ if options[:number]
44
+ historical_price_result_from_number market
45
+ elsif options[:start_date] && options[:end_date]
46
+ historical_price_result_from_date_range market
47
+ else
48
+ raise ArgumentError, 'specify --number or both --start-date and --end-date'
49
+ end
50
+ end
51
+
52
+ def historical_price_result_from_number(market)
53
+ market.recent_prices resolution, options[:number]
54
+ end
55
+
56
+ def historical_price_result_from_date_range(market)
57
+ filtered = self.class.filter_options options, [:start_date, :end_date]
58
+
59
+ self.class.parse_date_time filtered, :start_date, Time, '%FT%R%z', 'yyyy-mm-ddThh:mm(+|-)zz:zz'
60
+ self.class.parse_date_time filtered, :end_date, Time, '%FT%R%z', 'yyyy-mm-ddThh:mm(+|-)zz:zz'
61
+
62
+ market.prices_in_date_range resolution, filtered[:start_date], filtered[:end_date]
63
+ end
64
+ end
65
+ end
66
+ end
@@ -2,17 +2,34 @@ module IGMarkets
2
2
  module CLI
3
3
  # Implements the `ig_markets search` command.
4
4
  class Main < Thor
5
- desc 'search QUERY', 'Searches markets based on the specified query string'
5
+ desc 'search QUERY', 'Searches for markets using the specified query'
6
+
7
+ option :type, type: :array, enum: Instrument.allowed_values(:type).map(&:to_s),
8
+ desc: 'Only match markets of the specified types'
6
9
 
7
10
  def search(query)
8
11
  self.class.begin_session(options) do |dealing_platform|
9
- market_overviews = dealing_platform.markets.search query
12
+ market_overviews = gather_market_overviews dealing_platform, query
10
13
 
11
14
  table = MarketOverviewsTable.new market_overviews
12
15
 
13
16
  puts table
14
17
  end
15
18
  end
19
+
20
+ private
21
+
22
+ def gather_market_overviews(dealing_platform, query)
23
+ market_overviews = dealing_platform.markets.search(query)
24
+
25
+ if options[:type]
26
+ market_overviews = market_overviews.select do |market_overview|
27
+ options[:type].include? market_overview.instrument_type.to_s
28
+ end
29
+ end
30
+
31
+ market_overviews
32
+ end
16
33
  end
17
34
  end
18
35
  end
@@ -20,9 +20,9 @@ module IGMarkets
20
20
 
21
21
  desc 'create', 'Creates a new sprint market position'
22
22
 
23
- option :direction, required: true, desc: 'The trade direction, must be \'buy\' or \'sell\')'
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, required: true, desc: 'The expiry period in seconds, must be 1, 2, 5, 20 or 60'
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