ig_markets 0.32 → 0.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG.md +8 -0
- data/README.md +12 -12
- data/bin/ig_markets +1 -1
- data/lib/ig_markets.rb +2 -2
- data/lib/ig_markets/cli/commands/performance_command.rb +2 -2
- data/lib/ig_markets/cli/commands/prices_command.rb +2 -2
- data/lib/ig_markets/cli/main.rb +4 -4
- data/lib/ig_markets/cli/tables/table.rb +1 -1
- data/lib/ig_markets/dealing_platform/account_methods.rb +46 -35
- data/lib/ig_markets/dealing_platform/client_sentiment_methods.rb +21 -7
- data/lib/ig_markets/dealing_platform/streaming_methods.rb +0 -2
- data/lib/ig_markets/format.rb +1 -1
- data/lib/ig_markets/market.rb +1 -1
- data/lib/ig_markets/request_formatter.rb +75 -0
- data/lib/ig_markets/session.rb +16 -3
- data/lib/ig_markets/streaming/account_state.rb +4 -2
- data/lib/ig_markets/streaming/market_subscription_manager.rb +1 -1
- data/lib/ig_markets/streaming/market_update.rb +2 -2
- data/lib/ig_markets/version.rb +1 -1
- data/lib/ig_markets/working_order.rb +1 -3
- metadata +14 -14
- data/lib/ig_markets/request_printer.rb +0 -68
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: de92f7363906f7bb64fe6d258c8975cb4b506f6b029e888122038a6677911394
|
|
4
|
+
data.tar.gz: 90abc4b017ba8b6a107917b9fdf0573f713d2330cd31e57fd6a1e0426fc2694f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dd929726e98a24eb65e9c293e2e86348ab51db440cf878cf4e9f9778ff930de22b66ddcafc8d43b6b485a61415aa207adac9ca9dea5062af67f77ff91cda7eaa
|
|
7
|
+
data.tar.gz: 220263722e82b7dd44c8aca7a5e1821e61481454ee997b7506599d398ea4ca65926204f1e6cb4521758865bdfdd48bbbf41f6ddb4fdc2342e2def9e07694c503
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# IG Markets Changelog
|
|
2
2
|
|
|
3
|
+
### 0.33 — December 30, 2017
|
|
4
|
+
|
|
5
|
+
- Added `DealingPlatform::ClientSentimentMethods#find` for retrieving multiple client sentiments in one request
|
|
6
|
+
- Added support for the `tradeable_no_edit` market state
|
|
7
|
+
- Added `IGMarkets::Sessions#log_sinks` for directing debug log output to arbitrary locations
|
|
8
|
+
- Use the paging support provided by the IG API when fetching large numbers of activities and transactions
|
|
9
|
+
- Switch to using the `ColorizedString` class instead of relying on extensions to the `String` class for colorizing
|
|
10
|
+
|
|
3
11
|
### 0.32 — May 27, 2017
|
|
4
12
|
|
|
5
13
|
- The `force_open` option now defaults to true for working orders, and is automatically set to true when creating a
|
data/README.md
CHANGED
|
@@ -168,7 +168,7 @@ ig_markets console --verbose
|
|
|
168
168
|
|
|
169
169
|
#### Documentation
|
|
170
170
|
|
|
171
|
-
API documentation is available [here](http://www.rubydoc.info/github/
|
|
171
|
+
API documentation is available [here](http://www.rubydoc.info/github/richard-viney/ig_markets/master).
|
|
172
172
|
|
|
173
173
|
#### Examples
|
|
174
174
|
|
|
@@ -268,15 +268,15 @@ Gem created by Richard Viney. All contributions welcome.
|
|
|
268
268
|
|
|
269
269
|
[gem-link]: https://rubygems.org/gems/ig_markets
|
|
270
270
|
[gem-badge]: https://badge.fury.io/rb/ig_markets.svg
|
|
271
|
-
[travis-ci-link]: http://travis-ci.org/
|
|
272
|
-
[travis-ci-badge]: https://travis-ci.org/
|
|
273
|
-
[test-coverage-link]: https://codeclimate.com/github/
|
|
274
|
-
[test-coverage-badge]: https://codeclimate.com/github/
|
|
275
|
-
[code-climate-link]: https://codeclimate.com/github/
|
|
276
|
-
[code-climate-badge]: https://codeclimate.com/github/
|
|
277
|
-
[dependencies-link]: https://gemnasium.com/
|
|
278
|
-
[dependencies-badge]: https://gemnasium.com/
|
|
279
|
-
[documentation-link]: https://inch-ci.org/github/
|
|
280
|
-
[documentation-badge]: https://inch-ci.org/github/
|
|
281
|
-
[license-link]: https://github.com/
|
|
271
|
+
[travis-ci-link]: http://travis-ci.org/richard-viney/ig_markets
|
|
272
|
+
[travis-ci-badge]: https://travis-ci.org/richard-viney/ig_markets.svg?branch=master
|
|
273
|
+
[test-coverage-link]: https://codeclimate.com/github/richard-viney/ig_markets/coverage
|
|
274
|
+
[test-coverage-badge]: https://codeclimate.com/github/richard-viney/ig_markets/badges/coverage.svg
|
|
275
|
+
[code-climate-link]: https://codeclimate.com/github/richard-viney/ig_markets
|
|
276
|
+
[code-climate-badge]: https://codeclimate.com/github/richard-viney/ig_markets/badges/gpa.svg
|
|
277
|
+
[dependencies-link]: https://gemnasium.com/richard-viney/ig_markets
|
|
278
|
+
[dependencies-badge]: https://gemnasium.com/richard-viney/ig_markets.svg
|
|
279
|
+
[documentation-link]: https://inch-ci.org/github/richard-viney/ig_markets
|
|
280
|
+
[documentation-badge]: https://inch-ci.org/github/richard-viney/ig_markets.svg?branch=master
|
|
281
|
+
[license-link]: https://github.com/richard-viney/ig_markets/blob/master/LICENSE.md
|
|
282
282
|
[license-badge]: https://img.shields.io/badge/license-MIT-blue.svg
|
data/bin/ig_markets
CHANGED
data/lib/ig_markets.rb
CHANGED
|
@@ -5,7 +5,7 @@ require 'securerandom'
|
|
|
5
5
|
require 'time'
|
|
6
6
|
require 'yaml'
|
|
7
7
|
|
|
8
|
-
require '
|
|
8
|
+
require 'colorized_string'
|
|
9
9
|
require 'excon'
|
|
10
10
|
require 'lightstreamer'
|
|
11
11
|
require 'pry'
|
|
@@ -44,7 +44,7 @@ require 'ig_markets/market_hierarchy_result'
|
|
|
44
44
|
require 'ig_markets/password_encryptor'
|
|
45
45
|
require 'ig_markets/position'
|
|
46
46
|
require 'ig_markets/request_body_formatter'
|
|
47
|
-
require 'ig_markets/
|
|
47
|
+
require 'ig_markets/request_formatter'
|
|
48
48
|
require 'ig_markets/response_parser'
|
|
49
49
|
require 'ig_markets/session'
|
|
50
50
|
require 'ig_markets/sprint_market_position'
|
|
@@ -61,13 +61,13 @@ module IGMarkets
|
|
|
61
61
|
profit_loss = performances.map { |h| h[:profit_loss] }.inject(:+)
|
|
62
62
|
currency = performances.first[:transactions].first.currency
|
|
63
63
|
|
|
64
|
-
puts <<-
|
|
64
|
+
puts <<-MSG
|
|
65
65
|
|
|
66
66
|
Note: this table only shows the profit/loss made from dealing, it does not include interest payments,
|
|
67
67
|
dividends, or other adjustments that may have occurred over this period.
|
|
68
68
|
|
|
69
69
|
Total: #{Format.colored_currency profit_loss, currency}
|
|
70
|
-
|
|
70
|
+
MSG
|
|
71
71
|
end
|
|
72
72
|
end
|
|
73
73
|
end
|
|
@@ -21,12 +21,12 @@ module IGMarkets
|
|
|
21
21
|
|
|
22
22
|
table = Tables::HistoricalPriceResultSnapshotsTable.new result.prices, title: "Prices for #{options[:epic]}"
|
|
23
23
|
|
|
24
|
-
puts <<-
|
|
24
|
+
puts <<-MSG
|
|
25
25
|
#{table}
|
|
26
26
|
|
|
27
27
|
Allowance: #{allowance.total_allowance}
|
|
28
28
|
Remaining: #{allowance.remaining_allowance}
|
|
29
|
-
|
|
29
|
+
MSG
|
|
30
30
|
end
|
|
31
31
|
end
|
|
32
32
|
|
data/lib/ig_markets/cli/main.rb
CHANGED
|
@@ -67,9 +67,9 @@ module IGMarkets
|
|
|
67
67
|
def begin_session(options)
|
|
68
68
|
platform = options[:demo] ? :demo : :live
|
|
69
69
|
|
|
70
|
-
RequestPrinter.enabled = true if options[:verbose]
|
|
71
|
-
|
|
72
70
|
@dealing_platform ||= DealingPlatform.new
|
|
71
|
+
@dealing_platform.session.log_sinks = [$stdout] if options[:verbose]
|
|
72
|
+
|
|
73
73
|
@dealing_platform.sign_in options[:username], options[:password], options[:api_key], platform
|
|
74
74
|
|
|
75
75
|
yield @dealing_platform
|
|
@@ -159,11 +159,11 @@ module IGMarkets
|
|
|
159
159
|
|
|
160
160
|
# Prints out details of the passed deal confirmation.
|
|
161
161
|
def print_deal_confirmation(deal_confirmation)
|
|
162
|
-
puts <<-
|
|
162
|
+
puts <<-MSG
|
|
163
163
|
Deal ID: #{deal_confirmation.deal_id}
|
|
164
164
|
Status: #{Format.symbol deal_confirmation.deal_status}
|
|
165
165
|
Result: #{Format.symbol deal_confirmation.status}
|
|
166
|
-
|
|
166
|
+
MSG
|
|
167
167
|
|
|
168
168
|
print_deal_confirmation_profit_loss deal_confirmation
|
|
169
169
|
|
|
@@ -26,11 +26,7 @@ module IGMarkets
|
|
|
26
26
|
#
|
|
27
27
|
# @return [Array<Activity>]
|
|
28
28
|
def activities(options)
|
|
29
|
-
|
|
30
|
-
url_parameters[:detailed] = true
|
|
31
|
-
|
|
32
|
-
history_request_complete url: 'history/activity', url_parameters: url_parameters, api_version: API_V3,
|
|
33
|
-
collection_name: :activities, model_class: Activity, date_attribute: :date
|
|
29
|
+
activities_request build_url_parameters(options).merge(detailed: true)
|
|
34
30
|
end
|
|
35
31
|
|
|
36
32
|
# Returns transactions for this account in the specified time range.
|
|
@@ -49,55 +45,70 @@ module IGMarkets
|
|
|
49
45
|
raise ArgumentError, "invalid transaction type: #{options[:type]}"
|
|
50
46
|
end
|
|
51
47
|
|
|
52
|
-
|
|
53
|
-
api_version: API_V2, collection_name: :transactions, model_class: Transaction,
|
|
54
|
-
date_attribute: :date_utc
|
|
48
|
+
tranaactions_request build_url_parameters(options)
|
|
55
49
|
end
|
|
56
50
|
|
|
57
51
|
private
|
|
58
52
|
|
|
59
|
-
#
|
|
60
|
-
|
|
53
|
+
# Parses and formats options shared by {#activities} and {#transactions} into a set of URL parameters.
|
|
54
|
+
def build_url_parameters(options)
|
|
55
|
+
options[:to] ||= Time.now
|
|
61
56
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
# of items this method can return is capped at 500 ({MAXIMUM_PAGE_SIZE}).
|
|
65
|
-
def history_request(options)
|
|
66
|
-
url = "#{options[:url]}?#{options[:url_parameters].map { |key, value| "#{key}=#{value.to_s.upcase}" }.join '&'}"
|
|
57
|
+
options[:from] = options.fetch(:from).utc.strftime('%FT%T')
|
|
58
|
+
options[:to] = options.fetch(:to).utc.strftime('%FT%T')
|
|
67
59
|
|
|
68
|
-
|
|
60
|
+
options[:pageSize] = 500
|
|
61
|
+
options[:type] = options[:type].to_s.upcase if options.key? :type
|
|
69
62
|
|
|
70
|
-
|
|
63
|
+
options
|
|
71
64
|
end
|
|
72
65
|
|
|
73
|
-
#
|
|
74
|
-
#
|
|
75
|
-
def
|
|
76
|
-
|
|
66
|
+
# Performs repeated requests to the IG Markets API to retrieve all pages of activities returned by the given set
|
|
67
|
+
# of URL parameters.
|
|
68
|
+
def activities_request(url_parameters)
|
|
69
|
+
activities = []
|
|
77
70
|
|
|
78
|
-
|
|
79
|
-
request_result = history_request options
|
|
80
|
-
models += request_result
|
|
71
|
+
url = 'history/activity'
|
|
81
72
|
|
|
82
|
-
|
|
73
|
+
while url
|
|
74
|
+
request_result = history_request url: url, api_version: API_V3, url_parameters: url_parameters
|
|
75
|
+
activities += @dealing_platform.instantiate_models(Activity, request_result.fetch(:activities))
|
|
83
76
|
|
|
84
|
-
|
|
85
|
-
|
|
77
|
+
url = request_result.fetch(:metadata).fetch(:paging).fetch(:next)
|
|
78
|
+
url_parameters = {}
|
|
86
79
|
end
|
|
87
80
|
|
|
88
|
-
|
|
81
|
+
activities
|
|
89
82
|
end
|
|
90
83
|
|
|
91
|
-
#
|
|
92
|
-
|
|
93
|
-
|
|
84
|
+
# Performs repeated requests to the IG Markets API to retrieve all pages of transactions returned by the given set
|
|
85
|
+
# of URL parameters.
|
|
86
|
+
def tranaactions_request(url_parameters)
|
|
87
|
+
transactions = []
|
|
94
88
|
|
|
95
|
-
|
|
96
|
-
options[:to] = options.fetch(:to).utc.strftime('%FT%T')
|
|
89
|
+
page_number = 1
|
|
97
90
|
|
|
98
|
-
|
|
91
|
+
loop do
|
|
92
|
+
request_result = history_request url: 'history/transactions', api_version: API_V2,
|
|
93
|
+
url_parameters: url_parameters.merge(pageNumber: page_number)
|
|
99
94
|
|
|
100
|
-
|
|
95
|
+
transactions += @dealing_platform.instantiate_models Transaction, request_result.fetch(:transactions)
|
|
96
|
+
|
|
97
|
+
break if page_number == request_result.fetch(:metadata).fetch(:page_data).fetch(:total_pages)
|
|
98
|
+
|
|
99
|
+
page_number += 1
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
transactions
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def history_request(options)
|
|
106
|
+
params = URI.encode_www_form options.fetch(:url_parameters)
|
|
107
|
+
|
|
108
|
+
url = options[:url]
|
|
109
|
+
url += "?#{params}" unless params.empty?
|
|
110
|
+
|
|
111
|
+
@dealing_platform.session.get url, options.fetch(:api_version)
|
|
101
112
|
end
|
|
102
113
|
end
|
|
103
114
|
end
|
|
@@ -9,19 +9,33 @@ module IGMarkets
|
|
|
9
9
|
@dealing_platform = WeakRef.new dealing_platform
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
# Returns
|
|
12
|
+
# Returns client sentiments for the specified markets.
|
|
13
13
|
#
|
|
14
|
-
# @param [String]
|
|
14
|
+
# @param [Array<String>] market_ids The IDs of the markets to return client sentiments for.
|
|
15
15
|
#
|
|
16
|
-
# @return [ClientSentiment]
|
|
17
|
-
def
|
|
18
|
-
result = @dealing_platform.session.get "clientsentiment
|
|
16
|
+
# @return [Array<ClientSentiment>]
|
|
17
|
+
def find(*market_ids)
|
|
18
|
+
result = @dealing_platform.session.get "clientsentiment?marketIds=#{market_ids.join ','}"
|
|
19
19
|
|
|
20
|
-
@dealing_platform.instantiate_models
|
|
20
|
+
models = @dealing_platform.instantiate_models ClientSentiment, result.fetch(:client_sentiments)
|
|
21
|
+
|
|
22
|
+
# Invalid market IDs are returned with both percentages set to zero
|
|
23
|
+
models.each do |client_sentiment|
|
|
21
24
|
if client_sentiment.long_position_percentage == 0.0 && client_sentiment.short_position_percentage == 0.0
|
|
22
|
-
raise ArgumentError, "unknown market '#{market_id}'"
|
|
25
|
+
raise ArgumentError, "unknown market '#{client_sentiment.market_id}'"
|
|
23
26
|
end
|
|
24
27
|
end
|
|
28
|
+
|
|
29
|
+
models
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Returns client sentiment for the specified market.
|
|
33
|
+
#
|
|
34
|
+
# @param [String] market_id The ID of the market to return client sentiment for.
|
|
35
|
+
#
|
|
36
|
+
# @return [ClientSentiment]
|
|
37
|
+
def [](market_id)
|
|
38
|
+
find(market_id).first
|
|
25
39
|
end
|
|
26
40
|
end
|
|
27
41
|
end
|
|
@@ -7,14 +7,12 @@ module IGMarkets
|
|
|
7
7
|
# @param [DealingPlatform] dealing_platform The dealing platform.
|
|
8
8
|
def initialize(dealing_platform)
|
|
9
9
|
@dealing_platform = WeakRef.new dealing_platform
|
|
10
|
-
@queue = Queue.new
|
|
11
10
|
@on_error_callbacks = []
|
|
12
11
|
end
|
|
13
12
|
|
|
14
13
|
# Connects the streaming session. Raises a `Lightstreamer::LightstreamerError` if an error occurs.
|
|
15
14
|
def connect
|
|
16
15
|
@lightstreamer.disconnect if @lightstreamer
|
|
17
|
-
@queue.clear
|
|
18
16
|
|
|
19
17
|
@lightstreamer = Lightstreamer::Session.new username: username, password: password, server_url: server_url
|
|
20
18
|
@lightstreamer.on_error { |error| @on_error_callbacks.each { |callback| callback.call error } }
|
data/lib/ig_markets/format.rb
CHANGED
|
@@ -45,7 +45,7 @@ module IGMarkets
|
|
|
45
45
|
|
|
46
46
|
color = amount < 0 ? :red : :green
|
|
47
47
|
|
|
48
|
-
currency(amount, currency_name).
|
|
48
|
+
ColorizedString[currency(amount, currency_name)].colorize color
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
# Returns a formatted string for the specified number of seconds in the format `[<hours>:]<minutes>:<seconds>`.
|
data/lib/ig_markets/market.rb
CHANGED
|
@@ -31,7 +31,7 @@ module IGMarkets
|
|
|
31
31
|
attribute :high, Float
|
|
32
32
|
attribute :low, Float
|
|
33
33
|
attribute :market_status, Symbol, allowed_values: %i[closed edits_only offline on_auction
|
|
34
|
-
on_auction_no_edits suspended tradeable]
|
|
34
|
+
on_auction_no_edits suspended tradeable tradeable_no_edit]
|
|
35
35
|
attribute :net_change, Float
|
|
36
36
|
attribute :offer, Float
|
|
37
37
|
attribute :percentage_change, Float
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
module IGMarkets
|
|
2
|
+
# This class contains methods for formatting a REST request and its response for inspection and debugging.
|
|
3
|
+
#
|
|
4
|
+
# @private
|
|
5
|
+
class RequestFormatter
|
|
6
|
+
class << self
|
|
7
|
+
# Formats a request options hash that is ready to be passed to `Excon`.
|
|
8
|
+
#
|
|
9
|
+
# @param [Hash] options The request options.
|
|
10
|
+
#
|
|
11
|
+
# @return [String] The formatted request.
|
|
12
|
+
def format_request(options)
|
|
13
|
+
result = "#{options[:method].to_s.upcase} #{options[:url]}\n"
|
|
14
|
+
|
|
15
|
+
result += format_request_headers options[:headers]
|
|
16
|
+
result += format_request_body options[:body]
|
|
17
|
+
|
|
18
|
+
result
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Formats a response received from `Excon`.
|
|
22
|
+
#
|
|
23
|
+
# @param [#headers, #body] response The response.
|
|
24
|
+
#
|
|
25
|
+
# @return [String] The formatted response.
|
|
26
|
+
def format_response(response)
|
|
27
|
+
result = " Response:\n"
|
|
28
|
+
|
|
29
|
+
result += format_response_headers response.headers
|
|
30
|
+
result += format_response_body response.body
|
|
31
|
+
|
|
32
|
+
result
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def format_request_headers(headers)
|
|
38
|
+
result = " Headers:\n"
|
|
39
|
+
|
|
40
|
+
headers.each do |name, value|
|
|
41
|
+
result += " #{name}: #{value}\n"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
result
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def format_request_body(body)
|
|
48
|
+
return '' if body.nil?
|
|
49
|
+
|
|
50
|
+
result = " Body:\n "
|
|
51
|
+
result += JSON.pretty_generate(JSON.parse(body)).gsub("\n", "\n ")
|
|
52
|
+
|
|
53
|
+
result + "\n"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def format_response_headers(headers)
|
|
57
|
+
result = " Headers:\n"
|
|
58
|
+
|
|
59
|
+
headers.each do |name, value|
|
|
60
|
+
result += " #{name}: #{value}\n"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
result
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def format_response_body(body)
|
|
67
|
+
result = " Body:\n "
|
|
68
|
+
result += JSON.pretty_generate(JSON.parse(body)).gsub "\n", "\n "
|
|
69
|
+
result + "\n"
|
|
70
|
+
rescue JSON::ParserError
|
|
71
|
+
result + body + "\n"
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
data/lib/ig_markets/session.rb
CHANGED
|
@@ -23,6 +23,9 @@ module IGMarkets
|
|
|
23
23
|
# is no active session.
|
|
24
24
|
attr_reader :x_security_token
|
|
25
25
|
|
|
26
|
+
# @return [Array<#write>] the array of streams to write log output to.
|
|
27
|
+
attr_accessor :log_sinks
|
|
28
|
+
|
|
26
29
|
# Signs in to IG Markets using the values of {#username}, {#password}, {#api_key} and {#platform}. If an error
|
|
27
30
|
# occurs then an {IGMarketsError} will be raised.
|
|
28
31
|
#
|
|
@@ -110,7 +113,7 @@ module IGMarkets
|
|
|
110
113
|
end
|
|
111
114
|
|
|
112
115
|
def request(options)
|
|
113
|
-
options[:url] =
|
|
116
|
+
options[:url] = HOST_URLS.fetch(platform) + options.fetch(:url)
|
|
114
117
|
options[:headers] = request_headers(options)
|
|
115
118
|
|
|
116
119
|
# The IG Markets API requires that DELETE requests with a body are sent as POST requests with a special header
|
|
@@ -138,17 +141,27 @@ module IGMarkets
|
|
|
138
141
|
end
|
|
139
142
|
|
|
140
143
|
def execute_request(options)
|
|
141
|
-
|
|
144
|
+
write_to_log_sinks { RequestFormatter.format_request options }
|
|
142
145
|
|
|
143
146
|
response = Excon.send options[:method], options[:url], headers: options[:headers], body: options[:body]
|
|
144
147
|
|
|
145
|
-
|
|
148
|
+
write_to_log_sinks { RequestFormatter.format_response response }
|
|
146
149
|
|
|
147
150
|
process_response response, options
|
|
148
151
|
rescue Excon::Error => error
|
|
149
152
|
raise Errors::ConnectionError, error.message
|
|
150
153
|
end
|
|
151
154
|
|
|
155
|
+
def write_to_log_sinks
|
|
156
|
+
return if (log_sinks || []).empty?
|
|
157
|
+
|
|
158
|
+
content = yield
|
|
159
|
+
|
|
160
|
+
log_sinks.each do |sink|
|
|
161
|
+
sink.write content
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
152
165
|
def process_response(response, options)
|
|
153
166
|
body = parse_body response
|
|
154
167
|
|
|
@@ -124,8 +124,10 @@ module IGMarkets
|
|
|
124
124
|
end
|
|
125
125
|
|
|
126
126
|
def convert_market_status(status)
|
|
127
|
-
{
|
|
128
|
-
|
|
127
|
+
{
|
|
128
|
+
auction: :on_auction, auction_no_edit: :on_auction_no_edits, closed: :closed, edit: :edits_only,
|
|
129
|
+
offline: :offline, suspended: :suspended, tradeable: :tradeable, tradeable_no_edit: :tradeable_no_edit
|
|
130
|
+
}.fetch status
|
|
129
131
|
end
|
|
130
132
|
|
|
131
133
|
def on_position_update(position_update)
|
|
@@ -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: %i[
|
|
13
|
-
|
|
12
|
+
attribute :market_state, Symbol, allowed_values: %i[auction auction_no_edit closed edit offline suspended
|
|
13
|
+
tradeable tradeable_no_edit unavailable]
|
|
14
14
|
attribute :mid_open, Float
|
|
15
15
|
attribute :odds, Float
|
|
16
16
|
attribute :offer, Float
|
data/lib/ig_markets/version.rb
CHANGED
|
@@ -85,9 +85,7 @@ module IGMarkets
|
|
|
85
85
|
# Runs a series of validations on this model's attributes to check whether it is ready to be sent to the IG
|
|
86
86
|
# Markets API.
|
|
87
87
|
def validate
|
|
88
|
-
if limit_distance && limit_level
|
|
89
|
-
raise ArgumentError, 'do not specify both limit_distance and limit_level'
|
|
90
|
-
end
|
|
88
|
+
raise ArgumentError, 'do not specify both limit_distance and limit_level' if limit_distance && limit_level
|
|
91
89
|
|
|
92
90
|
raise ArgumentError, 'do not specify both stop_distance and stop_level' if stop_distance && stop_level
|
|
93
91
|
end
|
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.33'
|
|
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-
|
|
11
|
+
date: 2017-12-30 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: colorize
|
|
@@ -58,14 +58,14 @@ dependencies:
|
|
|
58
58
|
requirements:
|
|
59
59
|
- - "~>"
|
|
60
60
|
- !ruby/object:Gem::Version
|
|
61
|
-
version: 0.10
|
|
61
|
+
version: '0.10'
|
|
62
62
|
type: :runtime
|
|
63
63
|
prerelease: false
|
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
65
|
requirements:
|
|
66
66
|
- - "~>"
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
|
-
version: 0.10
|
|
68
|
+
version: '0.10'
|
|
69
69
|
- !ruby/object:Gem::Dependency
|
|
70
70
|
name: terminal-table
|
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -109,19 +109,19 @@ dependencies:
|
|
|
109
109
|
- !ruby/object:Gem::Version
|
|
110
110
|
version: '1.0'
|
|
111
111
|
- !ruby/object:Gem::Dependency
|
|
112
|
-
name:
|
|
112
|
+
name: factory_bot
|
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
|
114
114
|
requirements:
|
|
115
115
|
- - "~>"
|
|
116
116
|
- !ruby/object:Gem::Version
|
|
117
|
-
version: '4.
|
|
117
|
+
version: '4.8'
|
|
118
118
|
type: :development
|
|
119
119
|
prerelease: false
|
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
|
121
121
|
requirements:
|
|
122
122
|
- - "~>"
|
|
123
123
|
- !ruby/object:Gem::Version
|
|
124
|
-
version: '4.
|
|
124
|
+
version: '4.8'
|
|
125
125
|
- !ruby/object:Gem::Dependency
|
|
126
126
|
name: github-markup
|
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -184,28 +184,28 @@ dependencies:
|
|
|
184
184
|
requirements:
|
|
185
185
|
- - "~>"
|
|
186
186
|
- !ruby/object:Gem::Version
|
|
187
|
-
version:
|
|
187
|
+
version: 0.52.1
|
|
188
188
|
type: :development
|
|
189
189
|
prerelease: false
|
|
190
190
|
version_requirements: !ruby/object:Gem::Requirement
|
|
191
191
|
requirements:
|
|
192
192
|
- - "~>"
|
|
193
193
|
- !ruby/object:Gem::Version
|
|
194
|
-
version:
|
|
194
|
+
version: 0.52.1
|
|
195
195
|
- !ruby/object:Gem::Dependency
|
|
196
196
|
name: rubocop-rspec
|
|
197
197
|
requirement: !ruby/object:Gem::Requirement
|
|
198
198
|
requirements:
|
|
199
199
|
- - "~>"
|
|
200
200
|
- !ruby/object:Gem::Version
|
|
201
|
-
version: '1.
|
|
201
|
+
version: '1.21'
|
|
202
202
|
type: :development
|
|
203
203
|
prerelease: false
|
|
204
204
|
version_requirements: !ruby/object:Gem::Requirement
|
|
205
205
|
requirements:
|
|
206
206
|
- - "~>"
|
|
207
207
|
- !ruby/object:Gem::Version
|
|
208
|
-
version: '1.
|
|
208
|
+
version: '1.21'
|
|
209
209
|
- !ruby/object:Gem::Dependency
|
|
210
210
|
name: simplecov
|
|
211
211
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -310,7 +310,7 @@ files:
|
|
|
310
310
|
- lib/ig_markets/position.rb
|
|
311
311
|
- lib/ig_markets/regex.rb
|
|
312
312
|
- lib/ig_markets/request_body_formatter.rb
|
|
313
|
-
- lib/ig_markets/
|
|
313
|
+
- lib/ig_markets/request_formatter.rb
|
|
314
314
|
- lib/ig_markets/response_parser.rb
|
|
315
315
|
- lib/ig_markets/session.rb
|
|
316
316
|
- lib/ig_markets/sprint_market_position.rb
|
|
@@ -327,7 +327,7 @@ files:
|
|
|
327
327
|
- lib/ig_markets/version.rb
|
|
328
328
|
- lib/ig_markets/watchlist.rb
|
|
329
329
|
- lib/ig_markets/working_order.rb
|
|
330
|
-
homepage: https://github.com/
|
|
330
|
+
homepage: https://github.com/richard-viney/ig_markets
|
|
331
331
|
licenses:
|
|
332
332
|
- MIT
|
|
333
333
|
metadata: {}
|
|
@@ -347,7 +347,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
347
347
|
version: '0'
|
|
348
348
|
requirements: []
|
|
349
349
|
rubyforge_project:
|
|
350
|
-
rubygems_version: 2.
|
|
350
|
+
rubygems_version: 2.7.3
|
|
351
351
|
signing_key:
|
|
352
352
|
specification_version: 4
|
|
353
353
|
summary: Library and command-line client for accessing the IG Markets dealing platform.
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
module IGMarkets
|
|
2
|
-
# This class contains methods for printing a REST request and its response for inspection and debugging. Request
|
|
3
|
-
# printing is enabled by setting {enabled} to `true`.
|
|
4
|
-
#
|
|
5
|
-
# @private
|
|
6
|
-
class RequestPrinter
|
|
7
|
-
class << self
|
|
8
|
-
# Whether the request printer is enabled.
|
|
9
|
-
#
|
|
10
|
-
# @return [Boolean]
|
|
11
|
-
attr_accessor :enabled
|
|
12
|
-
|
|
13
|
-
# Prints out a request options hash that is ready to be passed to `Excon`.
|
|
14
|
-
#
|
|
15
|
-
# @param [Hash] options The request options.
|
|
16
|
-
def print_request(options)
|
|
17
|
-
return unless enabled
|
|
18
|
-
|
|
19
|
-
puts "#{options[:method].to_s.upcase} #{options[:url]}"
|
|
20
|
-
|
|
21
|
-
print_request_headers options[:headers]
|
|
22
|
-
print_request_body options[:body]
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
# Formats and prints a response received form `Excon`.
|
|
26
|
-
#
|
|
27
|
-
# @param [#headers, #body] response The response.
|
|
28
|
-
def print_response(response)
|
|
29
|
-
return unless enabled
|
|
30
|
-
|
|
31
|
-
puts ' Response:'
|
|
32
|
-
|
|
33
|
-
print_response_headers response.headers
|
|
34
|
-
print_response_body response.body
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
private
|
|
38
|
-
|
|
39
|
-
def print_request_headers(headers)
|
|
40
|
-
puts ' Headers:'
|
|
41
|
-
headers.each do |name, value|
|
|
42
|
-
puts " #{name}: #{value}"
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def print_request_body(body)
|
|
47
|
-
return unless body
|
|
48
|
-
|
|
49
|
-
print " Body:\n "
|
|
50
|
-
puts JSON.pretty_generate(JSON.parse(body)).gsub("\n", "\n ")
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def print_response_headers(headers)
|
|
54
|
-
puts ' Headers:'
|
|
55
|
-
headers.each do |name, value|
|
|
56
|
-
puts " #{name}: #{value}"
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def print_response_body(body)
|
|
61
|
-
print " Body:\n "
|
|
62
|
-
puts JSON.pretty_generate(JSON.parse(body)).gsub "\n", "\n "
|
|
63
|
-
rescue JSON::ParserError
|
|
64
|
-
puts body
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
end
|
|
68
|
-
end
|