ig_markets 0.1
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 +7 -0
- data/.codeclimate.yml +15 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.rubocop.yml +2 -0
- data/.travis.yml +10 -0
- data/.yardopts +4 -0
- data/Gemfile +2 -0
- data/LICENSE.md +25 -0
- data/README.md +134 -0
- data/ig_markets.gemspec +28 -0
- data/lib/ig_markets.rb +42 -0
- data/lib/ig_markets/account.rb +23 -0
- data/lib/ig_markets/account_activity.rb +24 -0
- data/lib/ig_markets/account_transaction.rb +49 -0
- data/lib/ig_markets/api_versions.rb +10 -0
- data/lib/ig_markets/application.rb +22 -0
- data/lib/ig_markets/boolean.rb +5 -0
- data/lib/ig_markets/client_sentiment.rb +16 -0
- data/lib/ig_markets/deal_confirmation.rb +41 -0
- data/lib/ig_markets/dealing_platform.rb +105 -0
- data/lib/ig_markets/dealing_platform/account_methods.rb +92 -0
- data/lib/ig_markets/dealing_platform/client_sentiment_methods.rb +26 -0
- data/lib/ig_markets/dealing_platform/market_methods.rb +59 -0
- data/lib/ig_markets/dealing_platform/position_methods.rb +164 -0
- data/lib/ig_markets/dealing_platform/sprint_market_position_methods.rb +46 -0
- data/lib/ig_markets/dealing_platform/watchlist_methods.rb +42 -0
- data/lib/ig_markets/dealing_platform/working_order_methods.rb +115 -0
- data/lib/ig_markets/historical_price_result.rb +33 -0
- data/lib/ig_markets/instrument.rb +89 -0
- data/lib/ig_markets/market.rb +99 -0
- data/lib/ig_markets/market_hierarchy_result.rb +13 -0
- data/lib/ig_markets/market_overview.rb +24 -0
- data/lib/ig_markets/model.rb +185 -0
- data/lib/ig_markets/password_encryptor.rb +31 -0
- data/lib/ig_markets/payload_formatter.rb +38 -0
- data/lib/ig_markets/position.rb +191 -0
- data/lib/ig_markets/regex.rb +10 -0
- data/lib/ig_markets/request_failed_error.rb +21 -0
- data/lib/ig_markets/response_parser.rb +35 -0
- data/lib/ig_markets/session.rb +186 -0
- data/lib/ig_markets/sprint_market_position.rb +17 -0
- data/lib/ig_markets/version.rb +4 -0
- data/lib/ig_markets/watchlist.rb +37 -0
- data/lib/ig_markets/working_order.rb +68 -0
- data/spec/factories/ig_markets/account.rb +14 -0
- data/spec/factories/ig_markets/account_activity.rb +21 -0
- data/spec/factories/ig_markets/account_balance.rb +8 -0
- data/spec/factories/ig_markets/account_transaction.rb +15 -0
- data/spec/factories/ig_markets/application.rb +21 -0
- data/spec/factories/ig_markets/client_sentiment.rb +7 -0
- data/spec/factories/ig_markets/deal_confirmation.rb +20 -0
- data/spec/factories/ig_markets/historical_price_result.rb +7 -0
- data/spec/factories/ig_markets/historical_price_result_data_allowance.rb +7 -0
- data/spec/factories/ig_markets/historical_price_result_price.rb +7 -0
- data/spec/factories/ig_markets/historical_price_result_snapshot.rb +10 -0
- data/spec/factories/ig_markets/instrument.rb +32 -0
- data/spec/factories/ig_markets/instrument_currency.rb +9 -0
- data/spec/factories/ig_markets/instrument_expiry_details.rb +6 -0
- data/spec/factories/ig_markets/instrument_margin_deposit_band.rb +8 -0
- data/spec/factories/ig_markets/instrument_opening_hours.rb +6 -0
- data/spec/factories/ig_markets/instrument_rollover_details.rb +6 -0
- data/spec/factories/ig_markets/instrument_slippage_factor.rb +6 -0
- data/spec/factories/ig_markets/market.rb +7 -0
- data/spec/factories/ig_markets/market_dealing_rules.rb +11 -0
- data/spec/factories/ig_markets/market_dealing_rules_rule_details.rb +6 -0
- data/spec/factories/ig_markets/market_hierarchy_result.rb +6 -0
- data/spec/factories/ig_markets/market_hierarchy_result_hierarchy_node.rb +6 -0
- data/spec/factories/ig_markets/market_overview.rb +22 -0
- data/spec/factories/ig_markets/market_snapshot.rb +17 -0
- data/spec/factories/ig_markets/position.rb +19 -0
- data/spec/factories/ig_markets/sprint_market_position.rb +16 -0
- data/spec/factories/ig_markets/watchlist.rb +9 -0
- data/spec/factories/ig_markets/working_order.rb +21 -0
- data/spec/ig_markets/account_transaction_spec.rb +30 -0
- data/spec/ig_markets/dealing_platform/account_methods_spec.rb +58 -0
- data/spec/ig_markets/dealing_platform/client_sentiment_methods_spec.rb +29 -0
- data/spec/ig_markets/dealing_platform/market_methods_spec.rb +80 -0
- data/spec/ig_markets/dealing_platform/position_methods_spec.rb +137 -0
- data/spec/ig_markets/dealing_platform/sprint_market_position_methods_spec.rb +39 -0
- data/spec/ig_markets/dealing_platform/watchlist_methods_spec.rb +89 -0
- data/spec/ig_markets/dealing_platform/working_order_methods_spec.rb +120 -0
- data/spec/ig_markets/dealing_platform_spec.rb +40 -0
- data/spec/ig_markets/model_spec.rb +127 -0
- data/spec/ig_markets/password_encryptor_spec.rb +23 -0
- data/spec/ig_markets/payload_formatter_spec.rb +19 -0
- data/spec/ig_markets/position_spec.rb +37 -0
- data/spec/ig_markets/response_parser_spec.rb +13 -0
- data/spec/ig_markets/session_spec.rb +134 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/support/factory_girl.rb +7 -0
- data/spec/support/random_test_order.rb +3 -0
- metadata +261 -0
@@ -0,0 +1,10 @@
|
|
1
|
+
module IGMarkets
|
2
|
+
# Contains regex's for validating specific types of strings.
|
3
|
+
module Regex
|
4
|
+
# Regex used to validate an ISO currency code.
|
5
|
+
CURRENCY = /\A[A-Z]{3}\Z/
|
6
|
+
|
7
|
+
# Regex used to validate an EPIC.
|
8
|
+
EPIC = /\A[A-Z,a-z,0-9,.,_]{6,30}\Z/
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module IGMarkets
|
2
|
+
# This error class is raised by {Session} when a request to the IG Markets API fails.
|
3
|
+
class RequestFailedError < StandardError
|
4
|
+
# @return [String] A description of the error that occurred when the request was attempted.
|
5
|
+
attr_reader :error
|
6
|
+
|
7
|
+
# @return [Fixnum] The HTTP code that was returned, or `nil` if unknown.
|
8
|
+
attr_reader :http_code
|
9
|
+
|
10
|
+
# Initializes this request failure error with a message and an HTTP code.
|
11
|
+
#
|
12
|
+
# @param [String] error The error description.
|
13
|
+
# @param [Integer] http_code The HTTP code for the request failure, if known.
|
14
|
+
def initialize(error, http_code = nil)
|
15
|
+
@error = error.to_s
|
16
|
+
@http_code = http_code ? http_code.to_i : nil
|
17
|
+
|
18
|
+
super "#<#{self.class.name} error: @error#{http_code ? ", http_code: #{http_code}" : ''}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module IGMarkets
|
2
|
+
# Contains methods for parsing responses received from the IG Markets API.
|
3
|
+
module ResponseParser
|
4
|
+
module_function
|
5
|
+
|
6
|
+
# Parses the specified value that was returned from a call to the IG Markets API.
|
7
|
+
#
|
8
|
+
# @param [Hash, Array, Object] response The response or part of a reponse that should be parsed. If this is of type
|
9
|
+
# `Hash` then all hash keys will converted from camel case into snake case and their values each to parsed
|
10
|
+
# individually by a recursive call. If this is of type `Array` then each item will be parsed indidiaully by a
|
11
|
+
# recursive call. All other types are passed through unchanged.
|
12
|
+
#
|
13
|
+
# @return [Hash, Array, Object] The parsed object, the type depends on the type of the `response` parameter.
|
14
|
+
def parse(response)
|
15
|
+
if response.is_a? Hash
|
16
|
+
response.each_with_object({}) do |(key, value), new_hash|
|
17
|
+
new_hash[camel_case_to_snake_case(key).downcase.to_sym] = parse(value)
|
18
|
+
end
|
19
|
+
elsif response.is_a? Array
|
20
|
+
response.map { |item| parse item }
|
21
|
+
else
|
22
|
+
response
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Converts a camel case string to a snake case string.
|
27
|
+
#
|
28
|
+
# @param [String, Symbol] camel_case The camel case `String` or `Symbol` to convert to snake case.
|
29
|
+
#
|
30
|
+
# @return [String]
|
31
|
+
def camel_case_to_snake_case(camel_case)
|
32
|
+
camel_case.to_s.gsub(/([a-z])([A-Z])/, '\1_\2').gsub(/([A-Z])([A-Z])([a-z])/, '\1_\2\3')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
module IGMarkets
|
2
|
+
# Manages a session with the IG Markets REST API, including signing in, signing out, and the sending of requests.
|
3
|
+
# In order to sign in, {#username}, {#password}, {#api_key} and {#platform} must be set. {#platform} must be
|
4
|
+
# either `:demo` or `:production` depending on which platform is being targeted.
|
5
|
+
class Session
|
6
|
+
# @return [String] The username to use to authenticate this session.
|
7
|
+
attr_accessor :username
|
8
|
+
|
9
|
+
# @return [String] The password to use to authenticate this session.
|
10
|
+
attr_accessor :password
|
11
|
+
|
12
|
+
# @return [String] The API key to use to authenticate this session.
|
13
|
+
attr_accessor :api_key
|
14
|
+
|
15
|
+
# @return [:demo, :production] The platform variant to log into for this session.
|
16
|
+
attr_accessor :platform
|
17
|
+
|
18
|
+
# @return [String] The CST for the currently logged in session, or nil if there is no active session.
|
19
|
+
attr_reader :cst
|
20
|
+
|
21
|
+
# @return [String] The security token for the currently logged in session, or nil if there is no active session.
|
22
|
+
attr_reader :x_security_token
|
23
|
+
|
24
|
+
# Signs in to IG Markets using the values of {#username}, {#password}, {#api_key} and {#platform}. If an error
|
25
|
+
# occurs then {RequestFailedError} will be raised.
|
26
|
+
def sign_in
|
27
|
+
validate_authentication
|
28
|
+
|
29
|
+
payload = { identifier: username, password: password_encryptor.encrypt(password), encryptedPassword: true }
|
30
|
+
|
31
|
+
sign_in_result = request method: :post, url: 'session', payload: payload, api_version: API_V1
|
32
|
+
|
33
|
+
headers = sign_in_result.fetch(:response).headers
|
34
|
+
@cst = headers.fetch :cst
|
35
|
+
@x_security_token = headers.fetch :x_security_token
|
36
|
+
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
|
40
|
+
# Signs out of IG Markets, ending the current session (if any). If an error occurs then {RequestFailedError} will be
|
41
|
+
# raised.
|
42
|
+
def sign_out
|
43
|
+
delete 'session', nil, API_V1 if alive?
|
44
|
+
|
45
|
+
@cst = @x_security_token = nil
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns whether this session is currently alive and successfully signed in.
|
49
|
+
#
|
50
|
+
# @return [Boolean]
|
51
|
+
def alive?
|
52
|
+
!cst.nil? && !x_security_token.nil?
|
53
|
+
end
|
54
|
+
|
55
|
+
# Sends a POST request to the IG Markets API. If an error occurs then {RequestFailedError} will be raised.
|
56
|
+
#
|
57
|
+
# @param [String] url The URL to send the POST request to.
|
58
|
+
# @param [nil, String, Hash] payload The payload to include with the POST request, this will be encoded as JSON.
|
59
|
+
# @param [Fixnum] api_version The API version to target.
|
60
|
+
#
|
61
|
+
# @return [Hash] The response from the IG Markets API.
|
62
|
+
def post(url, payload, api_version)
|
63
|
+
request(method: :post, url: url, payload: payload, api_version: api_version).fetch :result
|
64
|
+
end
|
65
|
+
|
66
|
+
# Sends a GET request to the IG Markets API. If an error occurs then {RequestFailedError} will be raised.
|
67
|
+
#
|
68
|
+
# @param [String] url The URL to send the GET request to.
|
69
|
+
# @param [Fixnum] api_version The API version to target.
|
70
|
+
#
|
71
|
+
# @return [Hash] The response from the IG Markets API.
|
72
|
+
def get(url, api_version)
|
73
|
+
request(method: :get, url: url, api_version: api_version).fetch :result
|
74
|
+
end
|
75
|
+
|
76
|
+
# Sends a PUT request to the IG Markets API. If an error occurs then {RequestFailedError} will be raised.
|
77
|
+
#
|
78
|
+
# @param [String] url The URL to send the PUT request to.
|
79
|
+
# @param [nil, String, Hash] payload The payload to include with the PUT request, this will be encoded as JSON.
|
80
|
+
# @param [Fixnum] api_version The API version to target.
|
81
|
+
#
|
82
|
+
# @return [Hash] The response from the IG Markets API.
|
83
|
+
def put(url, payload, api_version)
|
84
|
+
request(method: :put, url: url, payload: payload, api_version: api_version).fetch :result
|
85
|
+
end
|
86
|
+
|
87
|
+
# Sends a DELETE request to the IG Markets API. If an error occurs then {RequestFailedError} will be raised.
|
88
|
+
#
|
89
|
+
# @param [String] url The URL to send the DELETE request to.
|
90
|
+
# @param [nil, String, Hash] payload The payload to include with the DELETE request, this will be encoded as JSON.
|
91
|
+
# @param [Fixnum] api_version The API version to target.
|
92
|
+
#
|
93
|
+
# @return [Hash] The response from the IG Markets API.
|
94
|
+
def delete(url, payload, api_version)
|
95
|
+
request(method: :delete, url: url, payload: payload, api_version: api_version).fetch :result
|
96
|
+
end
|
97
|
+
|
98
|
+
# Returns a human-readable string containing this session's details.
|
99
|
+
#
|
100
|
+
# @return [String]
|
101
|
+
def inspect
|
102
|
+
"#<#{self.class.name} #{cst}, #{x_security_token}>"
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
HOST_URLS = {
|
108
|
+
demo: 'https://demo-api.ig.com/gateway/deal/',
|
109
|
+
production: 'https://api.ig.com/gateway/deal/'
|
110
|
+
}.freeze
|
111
|
+
|
112
|
+
def validate_authentication
|
113
|
+
%i(username password api_key).each do |attribute|
|
114
|
+
raise ArgumentError, "#{attribute} is not set" if send(attribute).to_s.empty?
|
115
|
+
end
|
116
|
+
|
117
|
+
raise ArgumentError, 'platform is invalid' unless HOST_URLS.key? platform
|
118
|
+
end
|
119
|
+
|
120
|
+
def password_encryptor
|
121
|
+
result = get 'session/encryptionKey', API_V1
|
122
|
+
|
123
|
+
PasswordEncryptor.new.tap do |encryptor|
|
124
|
+
encryptor.encoded_public_key = result.fetch :encryption_key
|
125
|
+
encryptor.time_stamp = result.fetch :time_stamp
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def request(options)
|
130
|
+
options[:url] = "#{HOST_URLS.fetch(platform)}#{URI.escape(options[:url])}"
|
131
|
+
options[:headers] = request_headers(options)
|
132
|
+
options[:payload] = options[:payload] && options[:payload].to_json
|
133
|
+
|
134
|
+
response = execute_request options
|
135
|
+
result = process_response response
|
136
|
+
|
137
|
+
{ response: response, result: result }
|
138
|
+
end
|
139
|
+
|
140
|
+
def request_headers(options)
|
141
|
+
headers = {}
|
142
|
+
|
143
|
+
headers[:content_type] = headers[:accept] = 'application/json; charset=UTF-8'
|
144
|
+
headers[:'X-IG-API-KEY'] = api_key
|
145
|
+
headers[:version] = options.delete :api_version
|
146
|
+
|
147
|
+
headers[:cst] = cst if cst
|
148
|
+
headers[:x_security_token] = x_security_token if x_security_token
|
149
|
+
|
150
|
+
headers
|
151
|
+
end
|
152
|
+
|
153
|
+
def use_post_for_delete_with_payload(options)
|
154
|
+
if options[:method] == :delete && options[:payload]
|
155
|
+
options[:headers]['_method'] = :delete
|
156
|
+
options[:method] = :post
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def execute_request(options)
|
161
|
+
use_post_for_delete_with_payload options
|
162
|
+
|
163
|
+
RestClient::Request.execute options
|
164
|
+
rescue RestClient::Exception => exception
|
165
|
+
return exception.response if exception.response
|
166
|
+
|
167
|
+
raise RequestFailedError, exception.message
|
168
|
+
rescue SocketError => socket_error
|
169
|
+
raise RequestFailedError, socket_error
|
170
|
+
end
|
171
|
+
|
172
|
+
def process_response(response)
|
173
|
+
result = begin
|
174
|
+
ResponseParser.parse JSON.parse(response.body, symbolize_names: true)
|
175
|
+
rescue JSON::ParserError
|
176
|
+
{}
|
177
|
+
end
|
178
|
+
|
179
|
+
unless response.code >= 200 && response.code < 300
|
180
|
+
raise RequestFailedError.new(result[:error_code], response.code)
|
181
|
+
end
|
182
|
+
|
183
|
+
result
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module IGMarkets
|
2
|
+
# Contains details on a sprint market position. Returned by {DealingPlatform::SprintMarketPositionMethods#all}.
|
3
|
+
class SprintMarketPosition < Model
|
4
|
+
attribute :created_date, DateTime, format: '%Y/%m/%d %H:%M:%S:%L'
|
5
|
+
attribute :currency, String, regex: Regex::CURRENCY
|
6
|
+
attribute :deal_id
|
7
|
+
attribute :description
|
8
|
+
attribute :direction, Symbol, allowed_values: [:buy, :sell]
|
9
|
+
attribute :epic, String, regex: Regex::EPIC
|
10
|
+
attribute :expiry_time, DateTime, format: '%Y/%m/%d %H:%M:%S:%L'
|
11
|
+
attribute :instrument_name
|
12
|
+
attribute :market_status, Symbol, allowed_values: Market::Snapshot.allowed_values(:market_status)
|
13
|
+
attribute :payout_amount, Float
|
14
|
+
attribute :size, Fixnum
|
15
|
+
attribute :strike_level, Float
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module IGMarkets
|
2
|
+
# Contains details on a watchlist. Returned by {DealingPlatform::WatchlistMethods#all} and
|
3
|
+
# {DealingPlatform::WatchlistMethods#[]}.
|
4
|
+
class Watchlist < Model
|
5
|
+
attribute :default_system_watchlist, Boolean
|
6
|
+
attribute :deleteable, Boolean
|
7
|
+
attribute :editable, Boolean
|
8
|
+
attribute :id
|
9
|
+
attribute :name
|
10
|
+
|
11
|
+
# Returns the markets for this watchlist.
|
12
|
+
#
|
13
|
+
# @return [Array<Market>]
|
14
|
+
def markets
|
15
|
+
@dealing_platform.gather "watchlists/#{id}", :markets, MarketOverview
|
16
|
+
end
|
17
|
+
|
18
|
+
# Deletes this watchlist.
|
19
|
+
def delete
|
20
|
+
@dealing_platform.session.delete "watchlists/#{id}", nil, API_V1
|
21
|
+
end
|
22
|
+
|
23
|
+
# Adds a market to this watchlist.
|
24
|
+
#
|
25
|
+
# @param [String] epic The EPIC of the market to add to this watchlist.
|
26
|
+
def add_market(epic)
|
27
|
+
@dealing_platform.session.put "watchlists/#{id}", { epic: epic }, API_V1
|
28
|
+
end
|
29
|
+
|
30
|
+
# Removes a market from this watchlist.
|
31
|
+
#
|
32
|
+
# @param [String] epic The EPIC of the market to remove from this watchlist.
|
33
|
+
def remove_market(epic)
|
34
|
+
@dealing_platform.session.delete "watchlists/#{id}/#{epic}", nil, API_V1
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module IGMarkets
|
2
|
+
# Contains details on a working order. Returned by {DealingPlatform::WorkingOrderMethods#all} and
|
3
|
+
# {DealingPlatform::WorkingOrderMethods#[]}.
|
4
|
+
class WorkingOrder < Model
|
5
|
+
attribute :created_date, DateTime, format: '%Y/%m/%d %H:%M:%S:%L'
|
6
|
+
attribute :created_date_utc, DateTime, format: '%Y-%m-%dT%H:%M:%S'
|
7
|
+
attribute :currency_code, String, regex: Regex::CURRENCY
|
8
|
+
attribute :deal_id
|
9
|
+
attribute :direction, Symbol, allowed_values: [:buy, :sell]
|
10
|
+
attribute :dma, Boolean
|
11
|
+
attribute :epic, String, regex: Regex::EPIC
|
12
|
+
attribute :good_till_date, DateTime, format: '%Y/%m/%d %H:%M'
|
13
|
+
attribute :good_till_date_iso, DateTime, format: '%Y-%m-%dT%H:%M'
|
14
|
+
attribute :guaranteed_stop, Boolean
|
15
|
+
attribute :limit_distance, Fixnum
|
16
|
+
attribute :order_level, Float
|
17
|
+
attribute :order_size, Float
|
18
|
+
attribute :order_type, Symbol, allowed_values: [:limit, :stop]
|
19
|
+
attribute :stop_distance, Fixnum
|
20
|
+
attribute :time_in_force, Symbol, allowed_values: [:good_till_cancelled, :good_till_date]
|
21
|
+
|
22
|
+
attribute :market, MarketOverview
|
23
|
+
|
24
|
+
# Deletes this working order.
|
25
|
+
#
|
26
|
+
# @return [String] The deal reference of the deletion operation. Use {DealingPlatform#deal_confirmation} to check
|
27
|
+
# the result of the working order deletion.
|
28
|
+
def delete
|
29
|
+
@dealing_platform.session.delete("workingorders/otc/#{deal_id}", {}, API_V1).fetch(:deal_reference)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Updates this working order. No attributes are mandatory, and any attributes not specified will be kept at the
|
33
|
+
# current value.
|
34
|
+
#
|
35
|
+
# @param [Hash] new_attributes The attributes of this working order to update. See
|
36
|
+
# {DealingPlatform::WorkingOrderMethods#create} for a description of the attributes.
|
37
|
+
# @option new_attributes [DateTime] :good_till_date
|
38
|
+
# @option new_attributes [Float] :level
|
39
|
+
# @option new_attributes [Float] :limit_distance
|
40
|
+
# @option new_attributes [Float] :stop_distance
|
41
|
+
# @option new_attributes [:good_till_cancelled, :good_till_date] :time_in_force
|
42
|
+
# @option new_attributes [:limit, :stop] :type
|
43
|
+
#
|
44
|
+
# @return [String] The deal reference of the update operation. Use {DealingPlatform#deal_confirmation} to check
|
45
|
+
# the result of the working order update.
|
46
|
+
def update(new_attributes)
|
47
|
+
new_attributes = { good_till_date: good_till_date, level: order_level, limit_distance: limit_distance,
|
48
|
+
stop_distance: stop_distance, time_in_force: time_in_force, type: order_type
|
49
|
+
}.merge new_attributes
|
50
|
+
|
51
|
+
payload = PayloadFormatter.format WorkingOrderUpdateAttributes.new new_attributes
|
52
|
+
|
53
|
+
@dealing_platform.session.put("workingorders/otc/#{deal_id}", payload, API_V1).fetch(:deal_reference)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Internal model used by {#update}.
|
57
|
+
class WorkingOrderUpdateAttributes < Model
|
58
|
+
attribute :good_till_date, DateTime, format: '%Y/%m/%d %H:%M'
|
59
|
+
attribute :limit_distance, Float
|
60
|
+
attribute :level, Float
|
61
|
+
attribute :type, Symbol, allowed_values: [:limit, :stop]
|
62
|
+
attribute :stop_distance, Float
|
63
|
+
attribute :time_in_force, Symbol, allowed_values: [:good_till_cancelled, :good_till_date]
|
64
|
+
end
|
65
|
+
|
66
|
+
private_constant :WorkingOrderUpdateAttributes
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
factory :account, class: IGMarkets::Account do
|
3
|
+
account_alias 'alias'
|
4
|
+
account_id 'A1234'
|
5
|
+
account_name 'CFD'
|
6
|
+
account_type 'CFD'
|
7
|
+
balance { build :account_balance }
|
8
|
+
can_transfer_from true
|
9
|
+
can_transfer_to true
|
10
|
+
currency 'USD'
|
11
|
+
preferred true
|
12
|
+
status 'ENABLED'
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
factory :account_activity, class: IGMarkets::AccountActivity do
|
3
|
+
action_status 'ACCEPT'
|
4
|
+
activity 'S&L'
|
5
|
+
activity_history_id '443487452'
|
6
|
+
channel 'Charts'
|
7
|
+
currency '$'
|
8
|
+
date '20/12/15'
|
9
|
+
deal_id 'DIAAAAA4HDKPQEQ'
|
10
|
+
epic 'CS.D.NZDUSD.CFD.IP'
|
11
|
+
level '0.664'
|
12
|
+
limit '0.6649'
|
13
|
+
market_name 'Spot FX NZD/USD'
|
14
|
+
period '-'
|
15
|
+
result 'Result'
|
16
|
+
size '+1'
|
17
|
+
stop '-'
|
18
|
+
stop_type '-'
|
19
|
+
time '07:00'
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
FactoryGirl.define do
|
2
|
+
factory :account_transaction, class: IGMarkets::AccountTransaction do
|
3
|
+
cash_transaction false
|
4
|
+
close_level '0.8'
|
5
|
+
currency 'US'
|
6
|
+
date '23/06/15'
|
7
|
+
instrument_name 'instrument'
|
8
|
+
open_level '0.8'
|
9
|
+
period '-'
|
10
|
+
profit_and_loss '0.0'
|
11
|
+
reference 'reference'
|
12
|
+
size '+1'
|
13
|
+
transaction_type 'DEAL'
|
14
|
+
end
|
15
|
+
end
|