ig_markets 0.11 → 0.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -1
- data/README.md +10 -7
- data/lib/ig_markets/activity.rb +37 -13
- data/lib/ig_markets/cli/commands/activities_command.rb +1 -14
- data/lib/ig_markets/cli/commands/orders_command.rb +6 -2
- data/lib/ig_markets/cli/commands/positions_command.rb +1 -1
- data/lib/ig_markets/cli/commands/transactions_command.rb +1 -1
- data/lib/ig_markets/cli/main.rb +32 -2
- data/lib/ig_markets/cli/tables/activities_table.rb +12 -4
- data/lib/ig_markets/cli/tables/market_overviews_table.rb +2 -2
- data/lib/ig_markets/cli/tables/positions_table.rb +7 -1
- data/lib/ig_markets/client_account_summary.rb +4 -3
- data/lib/ig_markets/deal_confirmation.rb +22 -14
- data/lib/ig_markets/dealing_platform/account_methods.rb +13 -9
- data/lib/ig_markets/dealing_platform/sprint_market_position_methods.rb +2 -2
- data/lib/ig_markets/dealing_platform/working_order_methods.rb +42 -21
- data/lib/ig_markets/dealing_platform.rb +2 -0
- data/lib/ig_markets/instrument.rb +4 -4
- data/lib/ig_markets/market.rb +4 -4
- data/lib/ig_markets/model/typecasters.rb +18 -10
- data/lib/ig_markets/model.rb +20 -3
- data/lib/ig_markets/payload_formatter.rb +4 -4
- data/lib/ig_markets/position.rb +2 -2
- data/lib/ig_markets/transaction.rb +1 -1
- data/lib/ig_markets/version.rb +1 -1
- data/lib/ig_markets/working_order.rb +29 -6
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7e50f2a597b16e6d091f0eff038350ec67847f60
|
4
|
+
data.tar.gz: 769b2056a2a1db136b05947fccbe42127ff54809
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 091827f393098b7b5b19df4686832ce96dd630038aee32ab15af550bfbdae5c4236bb238993198c9caae96273d02b83d8f34dd8d287dc4456b068e974969a3f0
|
7
|
+
data.tar.gz: 4ee120e6a912fdeef9ee98752c15559800ee3b406f168d1bb68524ee213b42a92afb7638dcf1675747bab6e6ed634f2a7030a41cb009b2235ff9ef5f090d17ad
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,18 @@
|
|
1
1
|
# IG Markets Changelog
|
2
2
|
|
3
|
+
### 0.12 - June 21, 2016
|
4
|
+
|
5
|
+
- Unrecognized attributes returned by the IG Markets API now trigger a warning rather than causing an error, this makes
|
6
|
+
the library able to handle new return values being added to existing APIs
|
7
|
+
- Upgraded to version 3 of the activities API, which significantly changes the structure of `IGMarkets::Activity`
|
8
|
+
- Accept "`DFB`" (daily funded bet) on instrument periods, it is silently converted to `nil`
|
9
|
+
- Correctly handle instrument periods that are formatted as `MMM-YY`
|
10
|
+
- Stops and limits can now be specified as levels rather than distances when creating and updating working orders
|
11
|
+
- Report profit/loss information when printing deal confirmations
|
12
|
+
- Renamed `--print-requests` option to `--verbose`
|
13
|
+
- The `--currency-code` option to `ig_markets positions create` and `ig_markets orders create` no longer defaults to
|
14
|
+
`USD` and must be specified explicitly
|
15
|
+
|
3
16
|
### 0.11 — May 23, 2016
|
4
17
|
|
5
18
|
- `IGMarkets::DealingPlatform::AccountMethods#activities` and `IGMarkets::DealingPlatform::AccountMethods#transactions`
|
@@ -7,7 +20,7 @@
|
|
7
20
|
of results returned by a single request at 500
|
8
21
|
- `IGMarkets::DealingPlatform::AccountMethods#activities` and `IGMarkets::DealingPlatform::AccountMethods#transactions`
|
9
22
|
no longer take a `:days` option, and their `:to` option defaults to today's date if it is omitted
|
10
|
-
- Accept "`DFB`" (
|
23
|
+
- Accept "`DFB`" (daily funded bet) on instrument expiries, it is silently converted to `nil`
|
11
24
|
- Instrument high and low is now shown in the `ig_markets positions list` command
|
12
25
|
|
13
26
|
### 0.10 — May 10, 2016
|
data/README.md
CHANGED
@@ -108,7 +108,7 @@ ig_markets search EURUSD --type currencies
|
|
108
108
|
ig_markets positions --aggregate
|
109
109
|
|
110
110
|
# Create a EURUSD long position of size 2
|
111
|
-
ig_markets positions create --direction buy --epic CS.D.EURUSD.CFD.IP --size 2
|
111
|
+
ig_markets positions create --direction buy --epic CS.D.EURUSD.CFD.IP --size 2 --currency-code USD
|
112
112
|
|
113
113
|
# Change the limit and stop levels for an existing position
|
114
114
|
ig_markets positions update DEAL-ID --limit-level 1.15 --stop-level 1.10
|
@@ -120,16 +120,18 @@ ig_markets positions close DEAL-ID
|
|
120
120
|
ig_markets positions close DEAL-ID --size 1
|
121
121
|
|
122
122
|
# Create a EURUSD sprint market short position of size 100 that expires in 20 minutes
|
123
|
-
ig_markets sprints create --direction sell --epic FM.D.EURUSD24.EURUSD24.IP --expiry-period 20
|
123
|
+
ig_markets sprints create --direction sell --epic FM.D.EURUSD24.EURUSD24.IP --expiry-period 20
|
124
|
+
--size 100
|
124
125
|
|
125
126
|
# Create a working order to buy 1 unit of EURUSD at the level 1.1
|
126
127
|
ig_markets orders create --direction buy --epic CS.D.EURUSD.CFD.IP --level 1.1 --size 1 --type limit
|
128
|
+
--currency-code USD
|
127
129
|
|
128
130
|
# Print daily prices for EURUSD from the last two weeks
|
129
131
|
ig_markets prices --epic CS.D.EURUSD.CFD.IP --resolution day --number 14
|
130
132
|
|
131
|
-
# Log in and
|
132
|
-
ig_markets console --
|
133
|
+
# Log in and open a Ruby console which can be used to query the IG API, printing all REST requests
|
134
|
+
ig_markets console --verbose
|
133
135
|
```
|
134
136
|
|
135
137
|
## Usage — Library
|
@@ -176,8 +178,8 @@ ig.sprint_market_positions.create direction: :buy, epic: 'FM.D.EURUSD24.EURUSD24
|
|
176
178
|
|
177
179
|
# Working orders
|
178
180
|
ig.working_orders.all
|
179
|
-
ig.working_orders.create currency_code: 'USD', direction: :buy, epic: 'CS.D.EURUSD.CFD.IP',
|
180
|
-
size: 1, type: :limit
|
181
|
+
ig.working_orders.create currency_code: 'USD', direction: :buy, epic: 'CS.D.EURUSD.CFD.IP',
|
182
|
+
level: 0.99, size: 1, type: :limit
|
181
183
|
ig.working_orders['deal_id']
|
182
184
|
ig.working_orders['deal_id'].update level: 1.25, limit_distance: 50, stop_distance: 50
|
183
185
|
ig.working_orders['deal_id'].delete
|
@@ -187,7 +189,8 @@ ig.markets.hierarchy
|
|
187
189
|
ig.markets.search 'EURUSD'
|
188
190
|
ig.markets['CS.D.EURUSD.CFD.IP']
|
189
191
|
ig.markets['CS.D.EURUSD.CFD.IP'].historical_prices resolution: :hour, number: 48
|
190
|
-
ig.markets['CS.D.EURUSD.CFD.IP'].historical_prices resolution: :second, from: Time.now - 120,
|
192
|
+
ig.markets['CS.D.EURUSD.CFD.IP'].historical_prices resolution: :second, from: Time.now - 120,
|
193
|
+
to: Time.now - 60
|
191
194
|
|
192
195
|
# Watchlists
|
193
196
|
ig.watchlists.all
|
data/lib/ig_markets/activity.rb
CHANGED
@@ -2,21 +2,45 @@ module IGMarkets
|
|
2
2
|
# Contains details on a single activity that occurred on an IG Markets account. Returned by
|
3
3
|
# {DealingPlatform::AccountMethods#activities}.
|
4
4
|
class Activity < Model
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
# Contains additional details on an activity. Returned by {#details}.
|
6
|
+
class Details < Model
|
7
|
+
# Contains details on the actions that were performed by an activity. Returned by {#actions}.
|
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_opended,
|
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
|
+
attribute :affected_deal_id
|
17
|
+
end
|
18
|
+
|
19
|
+
attribute :actions, Action
|
20
|
+
attribute :currency
|
21
|
+
attribute :deal_reference
|
22
|
+
attribute :direction, Symbol, allowed_values: [:buy, :sell]
|
23
|
+
attribute :good_till_date
|
24
|
+
attribute :guaranteed_stop, Boolean
|
25
|
+
attribute :level, Float, nil_if: 0
|
26
|
+
attribute :limit_distance, Fixnum
|
27
|
+
attribute :limit_level, Float, nil_if: 0
|
28
|
+
attribute :market_name
|
29
|
+
attribute :size
|
30
|
+
attribute :stop_distance, Fixnum
|
31
|
+
attribute :stop_level, Float, nil_if: 0
|
32
|
+
attribute :trailing_step, Float, nil_if: 0
|
33
|
+
attribute :trailing_stop_distance, Fixnum
|
34
|
+
end
|
35
|
+
|
36
|
+
attribute :channel, Symbol, allowed_values: [:dealer, :mobile, :public_fix_api, :public_web_api, :system, :web]
|
10
37
|
attribute :date, Time, format: '%FT%T'
|
11
38
|
attribute :deal_id
|
39
|
+
attribute :description
|
40
|
+
attribute :details, Details
|
12
41
|
attribute :epic, String, regex: Regex::EPIC
|
13
|
-
attribute :
|
14
|
-
attribute :
|
15
|
-
attribute :
|
16
|
-
attribute :period, String, nil_if: '-'
|
17
|
-
attribute :result
|
18
|
-
attribute :size
|
19
|
-
attribute :stop, String, nil_if: '-'
|
20
|
-
attribute :stop_type, String, nil_if: '-', allowed_values: %w(G N T(50))
|
42
|
+
attribute :period, Time, nil_if: %w(- DFB), format: ['%FT%T', '%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]
|
21
45
|
end
|
22
46
|
end
|
@@ -24,7 +24,7 @@ module IGMarkets
|
|
24
24
|
private
|
25
25
|
|
26
26
|
def gather_activities(dealing_platform)
|
27
|
-
result =
|
27
|
+
result = dealing_platform.account.activities(history_options).select do |activity|
|
28
28
|
activity_filter activity
|
29
29
|
end
|
30
30
|
|
@@ -45,19 +45,6 @@ module IGMarkets
|
|
45
45
|
'type' => :transaction_type
|
46
46
|
}.fetch options[:sort_by]
|
47
47
|
end
|
48
|
-
|
49
|
-
def gather_account_history(method_name, dealing_platform)
|
50
|
-
history_options = if options[:from]
|
51
|
-
from = Date.strptime options[:from], '%F'
|
52
|
-
to = from + options[:days]
|
53
|
-
|
54
|
-
{ from: from, to: to }
|
55
|
-
else
|
56
|
-
{ from: Date.today - options[:days] }
|
57
|
-
end
|
58
|
-
|
59
|
-
dealing_platform.account.send method_name, history_options
|
60
|
-
end
|
61
48
|
end
|
62
49
|
end
|
63
50
|
end
|
@@ -18,7 +18,7 @@ module IGMarkets
|
|
18
18
|
|
19
19
|
desc 'create', 'Creates a new working order'
|
20
20
|
|
21
|
-
option :currency_code,
|
21
|
+
option :currency_code, required: true, desc: 'The 3 character currency code, must be one of the instrument\'s ' \
|
22
22
|
'currencies'
|
23
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'
|
@@ -28,8 +28,10 @@ module IGMarkets
|
|
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'
|
30
30
|
option :limit_distance, type: :numeric, desc: 'The distance away in pips to place the limit'
|
31
|
+
option :limit_level, type: :numeric, desc: 'The level at which to place the limit'
|
31
32
|
option :size, type: :numeric, required: true, desc: 'The size of the order'
|
32
33
|
option :stop_distance, type: :numeric, desc: 'The distance away in pips to place the stop'
|
34
|
+
option :stop_level, type: :numeric, desc: 'The level at which to place the stop'
|
33
35
|
option :type, enum: %w(limit stop), required: true, desc: 'The order type'
|
34
36
|
|
35
37
|
def create
|
@@ -45,7 +47,9 @@ module IGMarkets
|
|
45
47
|
option :good_till_date, desc: 'The date that the order will live till, format: yyyy-mm-ddThh:mm(+|-)zz:zz'
|
46
48
|
option :level, type: :numeric, desc: 'The level at which the order will be triggered'
|
47
49
|
option :limit_distance, desc: 'The distance away in pips to place the limit'
|
50
|
+
option :limit_level, type: :numeric, desc: 'The level at which to place the limit'
|
48
51
|
option :stop_distance, desc: 'The distance away in pips to place the stop'
|
52
|
+
option :stop_level, type: :numeric, desc: 'The level at which to place the stop'
|
49
53
|
option :type, enum: %w(limit stop), desc: 'The order type'
|
50
54
|
|
51
55
|
def update(deal_id)
|
@@ -73,7 +77,7 @@ module IGMarkets
|
|
73
77
|
private
|
74
78
|
|
75
79
|
ATTRIBUTES = [:currency_code, :direction, :epic, :expiry, :force_open, :good_till_date, :guaranteed_stop, :level,
|
76
|
-
:limit_distance, :size, :stop_distance, :type].freeze
|
80
|
+
:limit_distance, :limit_level, :size, :stop_distance, :stop_level, :type].freeze
|
77
81
|
|
78
82
|
def working_order_attributes
|
79
83
|
attributes = Main.filter_options options, ATTRIBUTES
|
@@ -24,7 +24,7 @@ module IGMarkets
|
|
24
24
|
|
25
25
|
desc 'create', 'Creates a new position'
|
26
26
|
|
27
|
-
option :currency_code,
|
27
|
+
option :currency_code, required: true, desc: 'The 3 character currency code, must be one of the instrument\'s ' \
|
28
28
|
'currencies'
|
29
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,7 +31,7 @@ module IGMarkets
|
|
31
31
|
private
|
32
32
|
|
33
33
|
def gather_transactions(dealing_platform)
|
34
|
-
result =
|
34
|
+
result = dealing_platform.account.transactions(history_options).select do |transaction|
|
35
35
|
transaction_filter transaction
|
36
36
|
end
|
37
37
|
|
data/lib/ig_markets/cli/main.rb
CHANGED
@@ -7,7 +7,7 @@ module IGMarkets
|
|
7
7
|
class_option :password, required: true, desc: 'The password for the session'
|
8
8
|
class_option :api_key, required: true, desc: 'The API key for the session'
|
9
9
|
class_option :demo, type: :boolean, desc: 'Use the demo platform (default is production)'
|
10
|
-
class_option :
|
10
|
+
class_option :verbose, type: :boolean, desc: 'Whether to print the raw REST API requests and responses'
|
11
11
|
|
12
12
|
desc 'orders [SUBCOMAND=list ...]', 'Command for working with orders'
|
13
13
|
subcommand 'orders', Orders
|
@@ -21,6 +21,23 @@ module IGMarkets
|
|
21
21
|
desc 'watchlists [SUBCOMAND=list ...]', 'Command for working with watchlists'
|
22
22
|
subcommand 'watchlists', Watchlists
|
23
23
|
|
24
|
+
private
|
25
|
+
|
26
|
+
# Turns the `:days` and `:from` options into a hash with `:from` and `:to` keys that can be passed to
|
27
|
+
# {AccountMethods#activities} and {AccountMethods#transactions}.
|
28
|
+
#
|
29
|
+
# @return [Hash]
|
30
|
+
def history_options
|
31
|
+
if options[:from]
|
32
|
+
from = Date.strptime options[:from], '%F'
|
33
|
+
to = from + options[:days]
|
34
|
+
|
35
|
+
{ from: from, to: to }
|
36
|
+
else
|
37
|
+
{ from: Date.today - options[:days] }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
24
41
|
class << self
|
25
42
|
# This is the initial entry point for the execution of the command-line client. It is responsible for reading
|
26
43
|
# any config files, implementing the --version/-v options, and then invoking the main application.
|
@@ -44,7 +61,7 @@ module IGMarkets
|
|
44
61
|
def begin_session(options)
|
45
62
|
platform = options[:demo] ? :demo : :production
|
46
63
|
|
47
|
-
RequestPrinter.enabled = true if options[:
|
64
|
+
RequestPrinter.enabled = true if options[:verbose]
|
48
65
|
|
49
66
|
@dealing_platform ||= DealingPlatform.new
|
50
67
|
@dealing_platform.sign_in options[:username], options[:password], options[:api_key], platform
|
@@ -143,8 +160,21 @@ Status: #{Format.symbol deal_confirmation.deal_status}
|
|
143
160
|
Result: #{Format.symbol deal_confirmation.status}
|
144
161
|
END
|
145
162
|
|
163
|
+
print_deal_confirmation_profit_loss deal_confirmation
|
164
|
+
|
146
165
|
puts "Reason: #{Format.symbol deal_confirmation.reason}" unless deal_confirmation.deal_status == :accepted
|
147
166
|
end
|
167
|
+
|
168
|
+
# Prints out the profit/loss for the passed deal confirmation if applicable.
|
169
|
+
#
|
170
|
+
# @param [DealConfirmation] deal_confirmation The deal confirmation to print out the profit/loss for.
|
171
|
+
def print_deal_confirmation_profit_loss(deal_confirmation)
|
172
|
+
return unless deal_confirmation.profit
|
173
|
+
|
174
|
+
profit = Format.currency deal_confirmation.profit, deal_confirmation.profit_currency
|
175
|
+
|
176
|
+
puts "Profit/loss: #{profit.colorize(deal_confirmation.profit < 0 ? :red : :green)}"
|
177
|
+
end
|
148
178
|
end
|
149
179
|
end
|
150
180
|
end
|
@@ -17,12 +17,20 @@ module IGMarkets
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def row(activity)
|
20
|
-
|
21
|
-
|
20
|
+
details = activity.details
|
21
|
+
|
22
|
+
[activity.date, activity.channel, activity.type, activity.status, activity.epic, details.market_name,
|
23
|
+
details.size, details.level, details.limit_level, details.stop_level, action_types(details)]
|
22
24
|
end
|
23
25
|
|
24
|
-
def
|
25
|
-
|
26
|
+
def action_types(details)
|
27
|
+
types = details.actions.map(&:action_type).uniq
|
28
|
+
types.delete :unknown
|
29
|
+
|
30
|
+
# Fix a typo in one of the values
|
31
|
+
types.map! { |v| v == :position_opended ? :position_opened : v }
|
32
|
+
|
33
|
+
types.map { |v| format_cell_value v }.join ', '
|
26
34
|
end
|
27
35
|
end
|
28
36
|
end
|
@@ -39,8 +39,8 @@ module IGMarkets
|
|
39
39
|
|
40
40
|
def market_status(market_overview)
|
41
41
|
{ closed: 'Closed', edits_only: 'Edits only', offline: 'Offline', on_auction: 'On auction',
|
42
|
-
on_auction_no_edits: 'On auction no edits', suspended: 'Suspended', tradeable: 'Tradeable'
|
43
|
-
|
42
|
+
on_auction_no_edits: 'On auction no edits', suspended: 'Suspended', tradeable: 'Tradeable' }
|
43
|
+
.fetch market_overview.market_status
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
@@ -84,7 +84,13 @@ module IGMarkets
|
|
84
84
|
end
|
85
85
|
|
86
86
|
def combine_position_deal_ids(positions)
|
87
|
-
|
87
|
+
lines = []
|
88
|
+
|
89
|
+
positions.map(&:deal_id).each_slice(2) do |deal_ids|
|
90
|
+
lines << deal_ids.join(', ')
|
91
|
+
end
|
92
|
+
|
93
|
+
lines.join "\n"
|
88
94
|
end
|
89
95
|
end
|
90
96
|
end
|
@@ -20,9 +20,10 @@ module IGMarkets
|
|
20
20
|
attribute :account_info, Account::Balance
|
21
21
|
attribute :account_type, Symbol, allowed_values: [:cfd, :physical, :spreadbet]
|
22
22
|
attribute :accounts, AccountDetails
|
23
|
-
attribute :authentication_status, Symbol, allowed_values: [
|
24
|
-
|
25
|
-
|
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]
|
26
27
|
attribute :client_id
|
27
28
|
attribute :currency_iso_code, String, regex: Regex::CURRENCY
|
28
29
|
attribute :currency_symbol
|
@@ -18,20 +18,28 @@ module IGMarkets
|
|
18
18
|
attribute :level, Float
|
19
19
|
attribute :limit_distance, Fixnum
|
20
20
|
attribute :limit_level, Float
|
21
|
-
attribute :
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
21
|
+
attribute :profit, Float
|
22
|
+
attribute :profit_currency, String, regex: Regex::CURRENCY
|
23
|
+
attribute :reason, Symbol, allowed_values: [:account_not_enabled_to_trading, :attached_order_level_error,
|
24
|
+
:attached_order_trailing_stop_error, :cannot_change_stop_type,
|
25
|
+
:cannot_remove_stop, :closing_only_trades_accepted_on_this_market,
|
26
|
+
:conflicting_order, :cr_spacing, :duplicate_order_error,
|
27
|
+
:exchange_manual_override, :finance_repeat_dealing,
|
28
|
+
:force_open_on_same_market_different_currency, :general_error,
|
29
|
+
:good_till_date_in_the_past, :instrument_not_found, :insufficient_funds,
|
30
|
+
:level_tolerance_error, :manual_order_timeout, :market_closed,
|
31
|
+
:market_closed_with_edits, :market_closing, :market_not_borrowable,
|
32
|
+
:market_offline, :market_phone_only, :market_rolled,
|
33
|
+
:market_unavailable_to_client, :max_auto_size_exceeded,
|
34
|
+
:minimum_order_size_error, :move_away_only_limit, :move_away_only_stop,
|
35
|
+
:move_away_only_trigger_level, :opposing_direction_orders_not_allowed,
|
36
|
+
:opposing_positions_not_allowed, :order_locked, :order_not_found,
|
37
|
+
:over_normal_market_size, :partially_closed_position_not_deleted,
|
38
|
+
:position_not_available_to_close, :position_not_found,
|
39
|
+
:reject_spreadbet_order_on_cfd_account, :size_increment,
|
40
|
+
:sprint_market_expiry_after_market_close, :stop_or_limit_not_allowed,
|
41
|
+
:stop_required_error, :strike_level_tolerance, :success,
|
42
|
+
:trailing_stop_not_allowed, :unknown, :wrong_side_of_market]
|
35
43
|
attribute :size, Float
|
36
44
|
attribute :status, Symbol, allowed_values: [:amended, :closed, :deleted, :open, :partially_closed]
|
37
45
|
attribute :stop_distance, Fixnum
|
@@ -26,7 +26,10 @@ module IGMarkets
|
|
26
26
|
#
|
27
27
|
# @return [Array<Activity>]
|
28
28
|
def activities(options)
|
29
|
-
|
29
|
+
url_parameters = history_url_parameters options
|
30
|
+
url_parameters[:detailed] = true
|
31
|
+
|
32
|
+
history_request_complete url: 'history/activity', url_parameters: url_parameters, api_version: API_V3,
|
30
33
|
collection_name: :activities, model_class: Activity, date_attribute: :date
|
31
34
|
end
|
32
35
|
|
@@ -42,8 +45,9 @@ module IGMarkets
|
|
42
45
|
def transactions(options)
|
43
46
|
options[:type] ||= :all
|
44
47
|
|
45
|
-
history_request_complete url: 'history/transactions', url_parameters:
|
46
|
-
collection_name: :transactions, model_class: Transaction,
|
48
|
+
history_request_complete url: 'history/transactions', url_parameters: history_url_parameters(options),
|
49
|
+
api_version: API_V2, collection_name: :transactions, model_class: Transaction,
|
50
|
+
date_attribute: :date_utc
|
47
51
|
end
|
48
52
|
|
49
53
|
private
|
@@ -53,11 +57,11 @@ module IGMarkets
|
|
53
57
|
|
54
58
|
# Retrieves historical data for this account (either activities or transactions) in the specified date range. This
|
55
59
|
# methods sends a single GET request with the passed URL parameters and returns the response. The maximum number
|
56
|
-
# of items this method can return is capped at 500 {MAXIMUM_PAGE_SIZE}.
|
60
|
+
# of items this method can return is capped at 500 ({MAXIMUM_PAGE_SIZE}).
|
57
61
|
def history_request(options)
|
58
62
|
url = "#{options[:url]}?#{options[:url_parameters].map { |key, value| "#{key}=#{value.to_s.upcase}" }.join '&'}"
|
59
63
|
|
60
|
-
get_result = @dealing_platform.session.get url,
|
64
|
+
get_result = @dealing_platform.session.get url, options.fetch(:api_version)
|
61
65
|
|
62
66
|
@dealing_platform.instantiate_models options[:model_class], get_result.fetch(options[:collection_name])
|
63
67
|
end
|
@@ -80,12 +84,12 @@ module IGMarkets
|
|
80
84
|
models.uniq
|
81
85
|
end
|
82
86
|
|
83
|
-
# Parses and formats
|
84
|
-
def
|
87
|
+
# Parses and formats options shared by {#activities} and {#transactions} into a set of URL parameters.
|
88
|
+
def history_url_parameters(options)
|
85
89
|
options[:to] ||= Date.today + 1
|
86
90
|
|
87
|
-
options[:from] = options
|
88
|
-
options[:to] = options
|
91
|
+
options[:from] = options.fetch(:from).strftime('%F')
|
92
|
+
options[:to] = options.fetch(:to).strftime('%F')
|
89
93
|
|
90
94
|
options[:pageSize] = MAXIMUM_PAGE_SIZE
|
91
95
|
|
@@ -51,8 +51,8 @@ module IGMarkets
|
|
51
51
|
class SprintMarketPositionCreateAttributes < Model
|
52
52
|
attribute :direction, Symbol, allowed_values: [:buy, :sell]
|
53
53
|
attribute :epic, String, regex: Regex::EPIC
|
54
|
-
attribute :expiry_period, Symbol, allowed_values: [
|
55
|
-
|
54
|
+
attribute :expiry_period, Symbol, allowed_values: [:one_minute, :two_minutes, :five_minutes, :twenty_minutes,
|
55
|
+
:sixty_minutes]
|
56
56
|
attribute :size, Float
|
57
57
|
end
|
58
58
|
|
@@ -44,9 +44,15 @@ module IGMarkets
|
|
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`.
|
46
46
|
# @option attributes [Float] :level The level at which the order will be triggered. Required.
|
47
|
-
# @option attributes [Fixnum] :limit_distance The distance away in pips to place the limit.
|
47
|
+
# @option attributes [Fixnum] :limit_distance The distance away in pips to place the limit. If this is set then
|
48
|
+
# the `:limit_level` option must be omitted. Optional.
|
49
|
+
# @option attributes [Float] :limit_level The level at which to place the limit. If this is set then the
|
50
|
+
# `:limit_distance` option must be omitted. Optional.
|
48
51
|
# @option attributes [Float] :size The size of the working order. Required.
|
49
|
-
# @option attributes [Fixnum] :stop_distance The distance away in pips to place the stop.
|
52
|
+
# @option attributes [Fixnum] :stop_distance The distance away in pips to place the stop. If this is set then the
|
53
|
+
# `:stop_level` option must be omitted. Optional.
|
54
|
+
# @option attributes [Float] :stop_level The level at which to place the stop. If this is set then the
|
55
|
+
# `:stop_distance` option must be omitted. Optional.
|
50
56
|
# @option attributes [:limit, :stop] :type `:limit` means the working order is intended to buy at a price lower
|
51
57
|
# than at present, or to sell at a price higher than at present, i.e. there is an expectation
|
52
58
|
# of a market reversal at the specified `:level`. `:stop` means the working order is intended
|
@@ -56,30 +62,14 @@ module IGMarkets
|
|
56
62
|
# @return [String] The resulting deal reference, use {DealingPlatform#deal_confirmation} to check the result of
|
57
63
|
# the working order creation.
|
58
64
|
def create(attributes)
|
59
|
-
|
60
|
-
|
61
|
-
attributes[:time_in_force] = attributes[:good_till_date] ? :good_till_date : :good_till_cancelled
|
62
|
-
|
63
|
-
model = build_working_order_model attributes
|
65
|
+
model = WorkingOrderCreateAttributes.new attributes
|
66
|
+
model.validate
|
64
67
|
|
65
68
|
payload = PayloadFormatter.format model
|
66
69
|
|
67
70
|
payload[:expiry] ||= '-'
|
68
71
|
|
69
|
-
@dealing_platform.session.post('workingorders/otc', payload, API_V2).fetch
|
70
|
-
end
|
71
|
-
|
72
|
-
private
|
73
|
-
|
74
|
-
def build_working_order_model(attributes)
|
75
|
-
model = WorkingOrderCreateAttributes.new attributes
|
76
|
-
|
77
|
-
required = [:currency_code, :direction, :epic, :guaranteed_stop, :level, :size, :time_in_force, :type]
|
78
|
-
required.each do |attribute|
|
79
|
-
raise ArgumentError, "#{attribute} attribute must be set" if attributes[attribute].nil?
|
80
|
-
end
|
81
|
-
|
82
|
-
model
|
72
|
+
@dealing_platform.session.post('workingorders/otc', payload, API_V2).fetch :deal_reference
|
83
73
|
end
|
84
74
|
|
85
75
|
# Internal model used by {#create}.
|
@@ -93,10 +83,41 @@ module IGMarkets
|
|
93
83
|
attribute :guaranteed_stop, Boolean
|
94
84
|
attribute :level, Float
|
95
85
|
attribute :limit_distance, Fixnum
|
86
|
+
attribute :limit_level, Float
|
96
87
|
attribute :size, Float
|
97
88
|
attribute :stop_distance, Fixnum
|
89
|
+
attribute :stop_level, Float
|
98
90
|
attribute :time_in_force, Symbol, allowed_values: [:good_till_cancelled, :good_till_date]
|
99
91
|
attribute :type, Symbol, allowed_values: [:limit, :stop]
|
92
|
+
|
93
|
+
def initialize(attributes)
|
94
|
+
super
|
95
|
+
|
96
|
+
set_defaults
|
97
|
+
end
|
98
|
+
|
99
|
+
# Runs a series of validations on this model's attributes to check whether it is ready to be sent to the IG
|
100
|
+
# Markets API.
|
101
|
+
def validate
|
102
|
+
required = [:currency_code, :direction, :epic, :guaranteed_stop, :level, :size, :time_in_force, :type]
|
103
|
+
required.each do |attribute|
|
104
|
+
raise ArgumentError, "#{attribute} attribute must be set" if send(attribute).nil?
|
105
|
+
end
|
106
|
+
|
107
|
+
if limit_distance && limit_level
|
108
|
+
raise ArgumentError, 'Do not specify both limit_distance and limit_level options'
|
109
|
+
end
|
110
|
+
|
111
|
+
raise ArgumentError, 'Do not specify both stop_distance and stop_level options' if stop_distance && stop_level
|
112
|
+
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
|
100
121
|
end
|
101
122
|
|
102
123
|
private_constant :WorkingOrderCreateAttributes
|
@@ -135,6 +135,8 @@ module IGMarkets
|
|
135
135
|
model.instance_variable_set :@dealing_platform, self
|
136
136
|
|
137
137
|
attributes.each do |attribute, value|
|
138
|
+
next unless model_class.valid_attribute? attribute
|
139
|
+
|
138
140
|
type = model_class.attribute_type attribute
|
139
141
|
value = instantiate_models(type, value) if type < Model
|
140
142
|
|
@@ -79,10 +79,10 @@ module IGMarkets
|
|
79
79
|
attribute :sprint_markets_minimum_expiry_time, Float
|
80
80
|
attribute :stops_limits_allowed, Boolean
|
81
81
|
attribute :streaming_prices_available, Boolean
|
82
|
-
attribute :type, Symbol, allowed_values: [
|
83
|
-
|
84
|
-
|
85
|
-
|
82
|
+
attribute :type, Symbol, allowed_values: [:binary, :bungee_capped, :bungee_commodities, :bungee_currencies,
|
83
|
+
:bungee_indices, :commodities, :currencies, :indices, :opt_commodities,
|
84
|
+
:opt_currencies, :opt_indices, :opt_rates, :opt_shares, :rates, :sectors,
|
85
|
+
:shares, :sprint_market, :test_market, :unknown]
|
86
86
|
attribute :unit, Symbol, allowed_values: [:amount, :contracts, :shares]
|
87
87
|
attribute :value_of_one_pip
|
88
88
|
end
|
data/lib/ig_markets/market.rb
CHANGED
@@ -11,8 +11,8 @@ module IGMarkets
|
|
11
11
|
attribute :value, Float
|
12
12
|
end
|
13
13
|
|
14
|
-
attribute :market_order_preference, Symbol, allowed_values: [
|
15
|
-
|
14
|
+
attribute :market_order_preference, Symbol, allowed_values: [: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
|
@@ -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: [
|
34
|
-
|
33
|
+
attribute :market_status, Symbol, allowed_values: [: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
|
@@ -53,7 +53,7 @@ module IGMarkets
|
|
53
53
|
end
|
54
54
|
|
55
55
|
def typecaster_date(value, options, name)
|
56
|
-
raise ArgumentError, "#{self}##{name}: invalid
|
56
|
+
raise ArgumentError, "#{self}##{name}: invalid date format" unless options[:format].is_a? String
|
57
57
|
|
58
58
|
if value.is_a? String
|
59
59
|
begin
|
@@ -67,28 +67,36 @@ module IGMarkets
|
|
67
67
|
end
|
68
68
|
|
69
69
|
def typecaster_time(value, options, name)
|
70
|
-
|
70
|
+
format = options[:format]
|
71
|
+
|
72
|
+
raise ArgumentError, "#{self}##{name}: invalid time format" unless [Array, String].include? format.class
|
71
73
|
|
72
74
|
if value.is_a?(String) || value.is_a?(Fixnum)
|
73
|
-
|
75
|
+
parse_formatted_time_value value.to_s, options, name
|
74
76
|
else
|
75
77
|
value
|
76
78
|
end
|
77
79
|
end
|
78
80
|
|
79
|
-
def
|
80
|
-
|
81
|
+
def parse_formatted_time_value(value, options, name)
|
82
|
+
Array(options[:format]).each do |format|
|
83
|
+
begin
|
84
|
+
return parse_time_using_format value, format
|
85
|
+
rescue ArgumentError
|
86
|
+
next
|
87
|
+
end
|
88
|
+
end
|
81
89
|
|
90
|
+
raise ArgumentError, "#{self}##{name}: failed parsing time: #{value}"
|
91
|
+
end
|
92
|
+
|
93
|
+
def parse_time_using_format(value, format)
|
82
94
|
unless format == '%Q'
|
83
95
|
format += '%z'
|
84
96
|
value += '+0000'
|
85
97
|
end
|
86
98
|
|
87
|
-
|
88
|
-
Time.strptime value, format
|
89
|
-
rescue ArgumentError
|
90
|
-
raise ArgumentError, "#{self}##{name}: failed parsing time: #{value}"
|
91
|
-
end
|
99
|
+
Time.strptime value, format
|
92
100
|
end
|
93
101
|
end
|
94
102
|
end
|
data/lib/ig_markets/model.rb
CHANGED
@@ -68,7 +68,7 @@ module IGMarkets
|
|
68
68
|
# @return [Hash] A hash containing details of all attributes that have been defined on this model.
|
69
69
|
attr_accessor :defined_attributes
|
70
70
|
|
71
|
-
# @return [
|
71
|
+
# @return [Array] The names of the deprecated attributes on this model.
|
72
72
|
attr_accessor :deprecated_attributes
|
73
73
|
|
74
74
|
# Returns the names of all currently defined attributes for this model.
|
@@ -78,6 +78,23 @@ module IGMarkets
|
|
78
78
|
Hash(defined_attributes).keys
|
79
79
|
end
|
80
80
|
|
81
|
+
# Returns whether the passed value is a valid attribute name. If the passed attribute name is not recognized then
|
82
|
+
# an error will be printed to `stderr`. Only one warning will be printed for each unrecognized attribute.
|
83
|
+
#
|
84
|
+
# @param [Symbol] name The candidate attribute name.
|
85
|
+
#
|
86
|
+
# @return [Boolean]
|
87
|
+
def valid_attribute?(name)
|
88
|
+
return true if defined_attribute_names.include?(name) || Array(deprecated_attributes).include?(name)
|
89
|
+
|
90
|
+
unless Array(@reported_invalid_attributes).include? name
|
91
|
+
warn "ig_markets: unrecognized attribute #{self}##{name}"
|
92
|
+
(@reported_invalid_attributes ||= []) << name
|
93
|
+
end
|
94
|
+
|
95
|
+
false
|
96
|
+
end
|
97
|
+
|
81
98
|
# Returns the type of the specified attribute.
|
82
99
|
#
|
83
100
|
# @param [Symbol] attribute_name The name of the attribute to return the type for.
|
@@ -108,8 +125,8 @@ module IGMarkets
|
|
108
125
|
# @option options [Array] :nil_if Values that, when set on the attribute, should be converted to `nil`.
|
109
126
|
# @option options [Regexp] :regex When `type` is `String` only values matching this regex will be allowed.
|
110
127
|
# Optional.
|
111
|
-
# @option options [String] :format When `type` is `Date` or `Time` this specifies the format
|
112
|
-
# and `Fixnum` instances assigned to this attribute.
|
128
|
+
# @option options [String] :format When `type` is `Date` or `Time` this specifies the format or formats for
|
129
|
+
# parsing String and `Fixnum` instances assigned to this attribute.
|
113
130
|
#
|
114
131
|
# @macro [attach] attribute
|
115
132
|
# The $1 attribute.
|
@@ -4,9 +4,9 @@ module IGMarkets
|
|
4
4
|
module_function
|
5
5
|
|
6
6
|
# Takes a {Model} and returns its attributes in a hash ready to be passed as a payload to the IG Markets API.
|
7
|
-
# Attribute names will be converted
|
8
|
-
#
|
9
|
-
#
|
7
|
+
# Attribute names will be converted from snake case to camel case, `Symbol` attributes will be converted to strings
|
8
|
+
# and will be uppercased, and both `Date` and `Time` attributes will be converted to strings using their first
|
9
|
+
# available `:format` option.
|
10
10
|
#
|
11
11
|
# @param [Model] model The model instance to convert attributes for.
|
12
12
|
#
|
@@ -32,7 +32,7 @@ module IGMarkets
|
|
32
32
|
|
33
33
|
value = value.utc if options[:type] == Time
|
34
34
|
|
35
|
-
return value.strftime(options.fetch(:format)) if [Date, Time].include? options[:type]
|
35
|
+
return value.strftime(Array(options.fetch(:format)).first) if [Date, Time].include? options[:type]
|
36
36
|
|
37
37
|
value
|
38
38
|
end
|
data/lib/ig_markets/position.rb
CHANGED
@@ -107,8 +107,8 @@ module IGMarkets
|
|
107
107
|
# the result of the position update.
|
108
108
|
def update(new_attributes)
|
109
109
|
new_attributes = { limit_level: limit_level, stop_level: stop_level, trailing_stop: trailing_stop?,
|
110
|
-
trailing_stop_distance: trailing_stop_distance, trailing_stop_increment: trailing_step
|
111
|
-
|
110
|
+
trailing_stop_distance: trailing_stop_distance, trailing_stop_increment: trailing_step }
|
111
|
+
.merge new_attributes
|
112
112
|
|
113
113
|
unless new_attributes[:trailing_stop]
|
114
114
|
new_attributes[:trailing_stop_distance] = new_attributes[:trailing_stop_increment] = nil
|
@@ -8,7 +8,7 @@ module IGMarkets
|
|
8
8
|
attribute :date_utc, Time, format: '%FT%T'
|
9
9
|
attribute :instrument_name
|
10
10
|
attribute :open_level, String, nil_if: %w(- 0)
|
11
|
-
attribute :period, Time, nil_if:
|
11
|
+
attribute :period, Time, nil_if: %w(- DFB), format: ['%FT%T', '%b-%y']
|
12
12
|
attribute :profit_and_loss
|
13
13
|
attribute :reference
|
14
14
|
attribute :size, String, nil_if: '-'
|
data/lib/ig_markets/version.rb
CHANGED
@@ -37,21 +37,23 @@ module IGMarkets
|
|
37
37
|
# @option new_attributes [Time] :good_till_date
|
38
38
|
# @option new_attributes [Float] :level
|
39
39
|
# @option new_attributes [Fixnum] :limit_distance
|
40
|
+
# @option new_attributes [Float] :limit_level
|
40
41
|
# @option new_attributes [Fixnum] :stop_distance
|
42
|
+
# @option new_attributes [Float] :stop_level
|
41
43
|
# @option new_attributes [:limit, :stop] :type
|
42
44
|
#
|
43
45
|
# @return [String] The deal reference of the update operation. Use {DealingPlatform#deal_confirmation} to check
|
44
46
|
# the result of the working order update.
|
45
47
|
def update(new_attributes)
|
46
|
-
|
47
|
-
|
48
|
-
}.merge new_attributes
|
48
|
+
existing_attributes = { good_till_date: good_till_date, level: order_level, limit_distance: limit_distance,
|
49
|
+
stop_distance: stop_distance, time_in_force: time_in_force, type: order_type }
|
49
50
|
|
50
|
-
|
51
|
+
model = WorkingOrderUpdateAttributes.new existing_attributes, new_attributes
|
52
|
+
model.validate
|
51
53
|
|
52
|
-
payload = PayloadFormatter.format
|
54
|
+
payload = PayloadFormatter.format model
|
53
55
|
|
54
|
-
@dealing_platform.session.put("workingorders/otc/#{deal_id}", payload).fetch(:deal_reference)
|
56
|
+
@dealing_platform.session.put("workingorders/otc/#{deal_id}", payload, API_V2).fetch(:deal_reference)
|
55
57
|
end
|
56
58
|
|
57
59
|
# Internal model used by {#update}.
|
@@ -59,9 +61,30 @@ module IGMarkets
|
|
59
61
|
attribute :good_till_date, Time, format: '%Y/%m/%d %R:%S'
|
60
62
|
attribute :level, Float
|
61
63
|
attribute :limit_distance, Fixnum
|
64
|
+
attribute :limit_level, Float
|
62
65
|
attribute :stop_distance, Fixnum
|
66
|
+
attribute :stop_level, Float
|
63
67
|
attribute :time_in_force, Symbol, allowed_values: [:good_till_cancelled, :good_till_date]
|
64
68
|
attribute :type, Symbol, allowed_values: [:limit, :stop]
|
69
|
+
|
70
|
+
def initialize(existing_attributes, new_attributes)
|
71
|
+
existing_attributes.delete :limit_distance if new_attributes.key? :limit_level
|
72
|
+
existing_attributes.delete :stop_distance if new_attributes.key? :stop_level
|
73
|
+
|
74
|
+
super existing_attributes.merge(new_attributes)
|
75
|
+
|
76
|
+
self.time_in_force = good_till_date ? :good_till_date : :good_till_cancelled
|
77
|
+
end
|
78
|
+
|
79
|
+
# Runs a series of validations on this model's attributes to check whether it is ready to be sent to the IG
|
80
|
+
# Markets API.
|
81
|
+
def validate
|
82
|
+
if limit_distance && limit_level
|
83
|
+
raise ArgumentError, 'Do not specify both limit_distance and limit_level options'
|
84
|
+
end
|
85
|
+
|
86
|
+
raise ArgumentError, 'Do not specify both stop_distance and stop_level options' if stop_distance && stop_level
|
87
|
+
end
|
65
88
|
end
|
66
89
|
|
67
90
|
private_constant :WorkingOrderUpdateAttributes
|
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.
|
4
|
+
version: '0.12'
|
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-
|
11
|
+
date: 2016-06-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|
@@ -86,14 +86,14 @@ dependencies:
|
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '0.
|
89
|
+
version: '0.5'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '0.
|
96
|
+
version: '0.5'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: factory_girl
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -170,14 +170,14 @@ dependencies:
|
|
170
170
|
requirements:
|
171
171
|
- - "~>"
|
172
172
|
- !ruby/object:Gem::Version
|
173
|
-
version: '0.
|
173
|
+
version: '0.40'
|
174
174
|
type: :development
|
175
175
|
prerelease: false
|
176
176
|
version_requirements: !ruby/object:Gem::Requirement
|
177
177
|
requirements:
|
178
178
|
- - "~>"
|
179
179
|
- !ruby/object:Gem::Version
|
180
|
-
version: '0.
|
180
|
+
version: '0.40'
|
181
181
|
- !ruby/object:Gem::Dependency
|
182
182
|
name: yard
|
183
183
|
requirement: !ruby/object:Gem::Requirement
|