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.
Files changed (93) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +15 -0
  3. data/.gitignore +9 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +2 -0
  6. data/.travis.yml +10 -0
  7. data/.yardopts +4 -0
  8. data/Gemfile +2 -0
  9. data/LICENSE.md +25 -0
  10. data/README.md +134 -0
  11. data/ig_markets.gemspec +28 -0
  12. data/lib/ig_markets.rb +42 -0
  13. data/lib/ig_markets/account.rb +23 -0
  14. data/lib/ig_markets/account_activity.rb +24 -0
  15. data/lib/ig_markets/account_transaction.rb +49 -0
  16. data/lib/ig_markets/api_versions.rb +10 -0
  17. data/lib/ig_markets/application.rb +22 -0
  18. data/lib/ig_markets/boolean.rb +5 -0
  19. data/lib/ig_markets/client_sentiment.rb +16 -0
  20. data/lib/ig_markets/deal_confirmation.rb +41 -0
  21. data/lib/ig_markets/dealing_platform.rb +105 -0
  22. data/lib/ig_markets/dealing_platform/account_methods.rb +92 -0
  23. data/lib/ig_markets/dealing_platform/client_sentiment_methods.rb +26 -0
  24. data/lib/ig_markets/dealing_platform/market_methods.rb +59 -0
  25. data/lib/ig_markets/dealing_platform/position_methods.rb +164 -0
  26. data/lib/ig_markets/dealing_platform/sprint_market_position_methods.rb +46 -0
  27. data/lib/ig_markets/dealing_platform/watchlist_methods.rb +42 -0
  28. data/lib/ig_markets/dealing_platform/working_order_methods.rb +115 -0
  29. data/lib/ig_markets/historical_price_result.rb +33 -0
  30. data/lib/ig_markets/instrument.rb +89 -0
  31. data/lib/ig_markets/market.rb +99 -0
  32. data/lib/ig_markets/market_hierarchy_result.rb +13 -0
  33. data/lib/ig_markets/market_overview.rb +24 -0
  34. data/lib/ig_markets/model.rb +185 -0
  35. data/lib/ig_markets/password_encryptor.rb +31 -0
  36. data/lib/ig_markets/payload_formatter.rb +38 -0
  37. data/lib/ig_markets/position.rb +191 -0
  38. data/lib/ig_markets/regex.rb +10 -0
  39. data/lib/ig_markets/request_failed_error.rb +21 -0
  40. data/lib/ig_markets/response_parser.rb +35 -0
  41. data/lib/ig_markets/session.rb +186 -0
  42. data/lib/ig_markets/sprint_market_position.rb +17 -0
  43. data/lib/ig_markets/version.rb +4 -0
  44. data/lib/ig_markets/watchlist.rb +37 -0
  45. data/lib/ig_markets/working_order.rb +68 -0
  46. data/spec/factories/ig_markets/account.rb +14 -0
  47. data/spec/factories/ig_markets/account_activity.rb +21 -0
  48. data/spec/factories/ig_markets/account_balance.rb +8 -0
  49. data/spec/factories/ig_markets/account_transaction.rb +15 -0
  50. data/spec/factories/ig_markets/application.rb +21 -0
  51. data/spec/factories/ig_markets/client_sentiment.rb +7 -0
  52. data/spec/factories/ig_markets/deal_confirmation.rb +20 -0
  53. data/spec/factories/ig_markets/historical_price_result.rb +7 -0
  54. data/spec/factories/ig_markets/historical_price_result_data_allowance.rb +7 -0
  55. data/spec/factories/ig_markets/historical_price_result_price.rb +7 -0
  56. data/spec/factories/ig_markets/historical_price_result_snapshot.rb +10 -0
  57. data/spec/factories/ig_markets/instrument.rb +32 -0
  58. data/spec/factories/ig_markets/instrument_currency.rb +9 -0
  59. data/spec/factories/ig_markets/instrument_expiry_details.rb +6 -0
  60. data/spec/factories/ig_markets/instrument_margin_deposit_band.rb +8 -0
  61. data/spec/factories/ig_markets/instrument_opening_hours.rb +6 -0
  62. data/spec/factories/ig_markets/instrument_rollover_details.rb +6 -0
  63. data/spec/factories/ig_markets/instrument_slippage_factor.rb +6 -0
  64. data/spec/factories/ig_markets/market.rb +7 -0
  65. data/spec/factories/ig_markets/market_dealing_rules.rb +11 -0
  66. data/spec/factories/ig_markets/market_dealing_rules_rule_details.rb +6 -0
  67. data/spec/factories/ig_markets/market_hierarchy_result.rb +6 -0
  68. data/spec/factories/ig_markets/market_hierarchy_result_hierarchy_node.rb +6 -0
  69. data/spec/factories/ig_markets/market_overview.rb +22 -0
  70. data/spec/factories/ig_markets/market_snapshot.rb +17 -0
  71. data/spec/factories/ig_markets/position.rb +19 -0
  72. data/spec/factories/ig_markets/sprint_market_position.rb +16 -0
  73. data/spec/factories/ig_markets/watchlist.rb +9 -0
  74. data/spec/factories/ig_markets/working_order.rb +21 -0
  75. data/spec/ig_markets/account_transaction_spec.rb +30 -0
  76. data/spec/ig_markets/dealing_platform/account_methods_spec.rb +58 -0
  77. data/spec/ig_markets/dealing_platform/client_sentiment_methods_spec.rb +29 -0
  78. data/spec/ig_markets/dealing_platform/market_methods_spec.rb +80 -0
  79. data/spec/ig_markets/dealing_platform/position_methods_spec.rb +137 -0
  80. data/spec/ig_markets/dealing_platform/sprint_market_position_methods_spec.rb +39 -0
  81. data/spec/ig_markets/dealing_platform/watchlist_methods_spec.rb +89 -0
  82. data/spec/ig_markets/dealing_platform/working_order_methods_spec.rb +120 -0
  83. data/spec/ig_markets/dealing_platform_spec.rb +40 -0
  84. data/spec/ig_markets/model_spec.rb +127 -0
  85. data/spec/ig_markets/password_encryptor_spec.rb +23 -0
  86. data/spec/ig_markets/payload_formatter_spec.rb +19 -0
  87. data/spec/ig_markets/position_spec.rb +37 -0
  88. data/spec/ig_markets/response_parser_spec.rb +13 -0
  89. data/spec/ig_markets/session_spec.rb +134 -0
  90. data/spec/spec_helper.rb +14 -0
  91. data/spec/support/factory_girl.rb +7 -0
  92. data/spec/support/random_test_order.rb +3 -0
  93. metadata +261 -0
@@ -0,0 +1,80 @@
1
+ describe IGMarkets::DealingPlatform::MarketMethods do
2
+ let(:session) { IGMarkets::Session.new }
3
+ let(:platform) do
4
+ IGMarkets::DealingPlatform.new.tap do |platform|
5
+ platform.instance_variable_set :@session, session
6
+ end
7
+ end
8
+
9
+ it 'can retrieve the market hierarchy root' do
10
+ result = build :market_hierarchy_result
11
+
12
+ expect(session).to receive(:get).with('marketnavigation', IGMarkets::API_V1).and_return(result)
13
+ expect(platform.markets.hierarchy).to eq(result)
14
+ end
15
+
16
+ it 'can retrieve a market hierarchy node' do
17
+ result = build :market_hierarchy_result
18
+
19
+ expect(session).to receive(:get).with('marketnavigation/1', IGMarkets::API_V1).and_return(result)
20
+ expect(platform.markets.hierarchy(1)).to eq(result)
21
+ end
22
+
23
+ it 'can retrieve a market from an EPIC' do
24
+ get_result = {
25
+ market_details: [{
26
+ dealing_rules: build(:market_dealing_rules),
27
+ instrument: build(:instrument),
28
+ snapshot: build(:market_snapshot)
29
+ }]
30
+ }
31
+
32
+ expect(session).to receive(:get).with('markets?epics=ABCDEF', IGMarkets::API_V2).and_return(get_result)
33
+ expect(platform.markets['ABCDEF']).to eq(IGMarkets::Market.from(get_result[:market_details])[0])
34
+ end
35
+
36
+ it 'can search for markets' do
37
+ markets = [build(:market_overview)]
38
+
39
+ expect(session).to receive(:get).with('markets?searchTerm=USD', IGMarkets::API_V1).and_return(markets: markets)
40
+ expect(platform.markets.search('USD')).to eq(markets)
41
+ end
42
+
43
+ it 'can retrieve a specified number of historical prices for a market' do
44
+ markets_get_result = {
45
+ market_details: [{
46
+ dealing_rules: build(:market_dealing_rules),
47
+ instrument: build(:instrument),
48
+ snapshot: build(:market_snapshot)
49
+ }]
50
+ }
51
+
52
+ historical_price_result = build :historical_price_result
53
+
54
+ expect(session).to receive(:get).with('markets?epics=ABCDEF', IGMarkets::API_V2).and_return(markets_get_result)
55
+ expect(session).to receive(:get).with('prices/ABCDEF/DAY/5', IGMarkets::API_V2).and_return(historical_price_result)
56
+ expect(platform.markets['ABCDEF'].recent_prices(:day, 5)).to eq(historical_price_result)
57
+ end
58
+
59
+ it 'can retrieve a date range of historical prices for a market' do
60
+ from_date = DateTime.new 2014, 1, 2, 3, 4, 5
61
+ to_date = DateTime.new 2014, 2, 3, 4, 5, 6
62
+
63
+ markets_get_result = {
64
+ market_details: [{
65
+ dealing_rules: build(:market_dealing_rules),
66
+ instrument: build(:instrument),
67
+ snapshot: build(:market_snapshot)
68
+ }]
69
+ }
70
+
71
+ historical_price_result = build :historical_price_result
72
+
73
+ expect(session).to receive(:get).with('markets?epics=ABCDEF', IGMarkets::API_V2).and_return(markets_get_result)
74
+ expect(session).to receive(:get)
75
+ .with('prices/ABCDEF/DAY/2014-01-02T03:04:05/2014-02-03T04:05:06', IGMarkets::API_V2)
76
+ .and_return(historical_price_result)
77
+
78
+ expect(platform.markets['ABCDEF'].prices_in_date_range(:day, from_date, to_date)).to eq(historical_price_result)
79
+ end
80
+ end
@@ -0,0 +1,137 @@
1
+ describe IGMarkets::DealingPlatform::PositionMethods do
2
+ let(:session) { IGMarkets::Session.new }
3
+ let(:platform) do
4
+ IGMarkets::DealingPlatform.new.tap do |platform|
5
+ platform.instance_variable_set :@session, session
6
+ end
7
+ end
8
+
9
+ it 'can retrieve the current positions' do
10
+ positions = [build(:position)]
11
+
12
+ get_result = {
13
+ positions: positions.map(&:attributes).map do |a|
14
+ { market: a[:market], position: a }
15
+ end
16
+ }
17
+
18
+ expect(session).to receive(:get).with('positions', IGMarkets::API_V2).and_return(get_result)
19
+ expect(platform.positions.all).to eq(positions)
20
+ end
21
+
22
+ it 'can retrieve a single position' do
23
+ position = build :position
24
+
25
+ expect(session).to receive(:get)
26
+ .with("positions/#{position.deal_id}", IGMarkets::API_V2)
27
+ .and_return(position: position.attributes, market: position.market)
28
+
29
+ expect(platform.positions[position.deal_id]).to eq(position)
30
+ end
31
+
32
+ it 'can create a position' do
33
+ attributes = {
34
+ currency_code: 'USD',
35
+ direction: :buy,
36
+ epic: 'CS.D.EURUSD.CFD.IP',
37
+ size: 2.0
38
+ }
39
+
40
+ payload = {
41
+ currencyCode: 'USD',
42
+ direction: 'BUY',
43
+ epic: 'CS.D.EURUSD.CFD.IP',
44
+ expiry: '-',
45
+ forceOpen: false,
46
+ guaranteedStop: false,
47
+ orderType: 'MARKET',
48
+ size: 2.0,
49
+ timeInForce: 'EXECUTE_AND_ELIMINATE'
50
+ }
51
+
52
+ result = { deal_reference: 'reference' }
53
+
54
+ expect(session).to receive(:post).with('positions/otc', payload, IGMarkets::API_V2).and_return(result)
55
+ expect(platform.positions.create(attributes)).to eq(result.fetch(:deal_reference))
56
+ end
57
+
58
+ it 'validates position creation attributes correctly' do
59
+ attributes = {
60
+ currency_code: 'USD',
61
+ direction: :buy,
62
+ epic: 'CS.D.EURUSD.CFD.IP',
63
+ size: 2.0,
64
+ time_in_force: :execute_and_eliminate
65
+ }
66
+
67
+ create_position = proc do |override_attributes = {}|
68
+ platform.positions.create attributes.merge override_attributes
69
+ end
70
+
71
+ expect(session).to receive(:post).exactly(10).times.and_return(deal_reference: 'reference')
72
+
73
+ expect { create_position.call }.to_not raise_error
74
+ expect { create_position.call order_type: :quote }.to raise_error(ArgumentError)
75
+ expect { create_position.call order_type: :quote, quote_id: 'a' }.to raise_error(ArgumentError)
76
+ expect { create_position.call order_type: :quote, level: 1 }.to raise_error(ArgumentError)
77
+ expect { create_position.call order_type: :quote, quote_id: 'a', level: 1 }.to_not raise_error
78
+ expect { create_position.call order_type: :limit }.to raise_error(ArgumentError)
79
+ expect { create_position.call order_type: :limit, level: 1 }.to_not raise_error
80
+ expect { create_position.call trailing_stop: true, stop_distance: 1 }.to raise_error(ArgumentError)
81
+ expect { create_position.call trailing_stop: true, stop_distance: 1, trailing_stop_increment: 1 }.not_to raise_error
82
+ expect { create_position.call limit_distance: 1 }.not_to raise_error
83
+ expect { create_position.call limit_level: 1 }.not_to raise_error
84
+ expect { create_position.call limit_distance: 1, limit_level: 1 }.to raise_error(ArgumentError)
85
+ expect { create_position.call stop_distance: 1 }.not_to raise_error
86
+ expect { create_position.call stop_level: 1 }.not_to raise_error
87
+ expect { create_position.call stop_distance: 1, stop_level: 1 }.to raise_error(ArgumentError)
88
+ expect { create_position.call guaranteed_stop: true }.to raise_error(ArgumentError)
89
+ expect { create_position.call guaranteed_stop: true, stop_distance: 1 }.not_to raise_error
90
+ expect { create_position.call guaranteed_stop: true, stop_level: 1 }.not_to raise_error
91
+ end
92
+
93
+ it 'can update a position' do
94
+ position = build :position, deal_id: '1'
95
+
96
+ get_result = { position: position.attributes, market: position.market }
97
+ payload = { limitLevel: 2.0, stopLevel: 1.0, trailingStop: false }
98
+ put_result = { deal_reference: 'reference' }
99
+
100
+ expect(session).to receive(:get).with('positions/1', IGMarkets::API_V2).and_return(get_result)
101
+ expect(session).to receive(:put).with('positions/otc/1', payload, IGMarkets::API_V2).and_return(put_result)
102
+ expect(platform.positions['1'].update(stop_level: 1, limit_level: 2)).to eq('reference')
103
+ end
104
+
105
+ it 'can close a position' do
106
+ position = build :position, deal_id: '1', size: 5
107
+
108
+ get_result = { position: position.attributes, market: position.market }
109
+ payload = { dealId: '1', direction: 'SELL', orderType: 'MARKET', size: 5.0, timeInForce: 'EXECUTE_AND_ELIMINATE' }
110
+ delete_result = { deal_reference: 'reference' }
111
+
112
+ expect(session).to receive(:get).with('positions/1', IGMarkets::API_V2).and_return(get_result)
113
+ expect(session).to receive(:delete).with('positions/otc', payload, IGMarkets::API_V1).and_return(delete_result)
114
+ expect(platform.positions['1'].close).to eq('reference')
115
+ end
116
+
117
+ it 'validates position close attributes correctly' do
118
+ position = build :position, deal_id: '1'
119
+ position.instance_variable_set :@dealing_platform, platform
120
+
121
+ attributes = { time_in_force: :execute_and_eliminate }
122
+
123
+ close_position = proc do |override_attributes = {}|
124
+ position.close attributes.merge override_attributes
125
+ end
126
+
127
+ expect(session).to receive(:delete).exactly(3).times.and_return(deal_reference: 'reference')
128
+
129
+ expect { close_position.call }.to_not raise_error
130
+ expect { close_position.call order_type: :quote }.to raise_error(ArgumentError)
131
+ expect { close_position.call order_type: :quote, quote_id: 'a' }.to raise_error(ArgumentError)
132
+ expect { close_position.call order_type: :quote, level: 1 }.to raise_error(ArgumentError)
133
+ expect { close_position.call order_type: :quote, quote_id: 'a', level: 1 }.to_not raise_error
134
+ expect { close_position.call order_type: :limit }.to raise_error(ArgumentError)
135
+ expect { close_position.call order_type: :limit, level: 1 }.to_not raise_error
136
+ end
137
+ end
@@ -0,0 +1,39 @@
1
+ describe IGMarkets::DealingPlatform::SprintMarketPositionMethods do
2
+ let(:session) { IGMarkets::Session.new }
3
+ let(:platform) do
4
+ IGMarkets::DealingPlatform.new.tap do |platform|
5
+ platform.instance_variable_set :@session, session
6
+ end
7
+ end
8
+
9
+ it 'can retrieve the current sprint market positions' do
10
+ positions = [build(:sprint_market_position)]
11
+
12
+ expect(session).to receive(:get)
13
+ .with('positions/sprintmarkets', IGMarkets::API_V1)
14
+ .and_return(sprint_market_positions: positions)
15
+
16
+ expect(platform.sprint_market_positions.all).to eq(positions)
17
+ end
18
+
19
+ it 'can create a sprint market position' do
20
+ attributes = {
21
+ direction: :buy,
22
+ epic: 'CS.D.EURUSD.CFD.IP',
23
+ expiry_period: :five_minutes,
24
+ size: 2.0
25
+ }
26
+
27
+ payload = {
28
+ direction: 'BUY',
29
+ epic: 'CS.D.EURUSD.CFD.IP',
30
+ expiryPeriod: 'FIVE_MINUTES',
31
+ size: 2.0
32
+ }
33
+
34
+ result = { deal_reference: 'reference' }
35
+
36
+ expect(session).to receive(:post).with('positions/sprintmarkets', payload, IGMarkets::API_V1).and_return(result)
37
+ expect(platform.sprint_market_positions.create(attributes)).to eq(result.fetch(:deal_reference))
38
+ end
39
+ end
@@ -0,0 +1,89 @@
1
+ describe IGMarkets::DealingPlatform::WatchlistMethods do
2
+ let(:session) { IGMarkets::Session.new }
3
+ let(:platform) do
4
+ IGMarkets::DealingPlatform.new.tap do |platform|
5
+ platform.instance_variable_set :@session, session
6
+ end
7
+ end
8
+
9
+ it 'can retrieve the watchlists' do
10
+ watchlists = [build(:watchlist)]
11
+
12
+ expect(session).to receive(:get).with('watchlists', IGMarkets::API_V1).and_return(watchlists: watchlists)
13
+ expect(platform.watchlists.all).to eq(watchlists)
14
+ end
15
+
16
+ it 'can retrieve the markets for a watchlist' do
17
+ markets = [build(:market_overview)]
18
+
19
+ expect(session).to receive(:get).with('watchlists', IGMarkets::API_V1).and_return(watchlists: [{ id: 1 }])
20
+ expect(session).to receive(:get).with('watchlists/1', IGMarkets::API_V1).and_return(markets: markets)
21
+ expect(platform.watchlists['1'].markets).to eq(markets)
22
+ end
23
+
24
+ it 'can create a watchlist' do
25
+ watchlist_id = '1000'
26
+ name = 'New Watchlist'
27
+ epics = ['ABCDEF']
28
+
29
+ expect(session).to receive(:post)
30
+ .with('watchlists', { name: name, epics: epics }, IGMarkets::API_V1)
31
+ .and_return(watchlist_id: watchlist_id, status: 'SUCCESS')
32
+
33
+ expect(session).to receive(:get)
34
+ .with('watchlists', IGMarkets::API_V1)
35
+ .and_return(watchlists: [{ id: watchlist_id }])
36
+
37
+ expect(platform.watchlists.create(name, epics)).to eq(IGMarkets::Watchlist.new(id: watchlist_id))
38
+ end
39
+
40
+ it 'can delete a watchlist' do
41
+ watchlist_id = '1000'
42
+
43
+ result = { status: 'SUCCESS' }
44
+
45
+ expect(session).to receive(:get)
46
+ .with('watchlists', IGMarkets::API_V1)
47
+ .and_return(watchlists: [{ id: watchlist_id }])
48
+
49
+ expect(session).to receive(:delete)
50
+ .with("watchlists/#{watchlist_id}", nil, IGMarkets::API_V1)
51
+ .and_return(result)
52
+
53
+ expect(platform.watchlists[watchlist_id].delete).to eq(result)
54
+ end
55
+
56
+ it 'can add a market to a watchlist' do
57
+ watchlist_id = '1000'
58
+ epic = 'ABCDEF'
59
+
60
+ result = { status: 'SUCCESS' }
61
+
62
+ expect(session).to receive(:get)
63
+ .with('watchlists', IGMarkets::API_V1)
64
+ .and_return(watchlists: [{ id: watchlist_id }])
65
+
66
+ expect(session).to receive(:put)
67
+ .with("watchlists/#{watchlist_id}", { epic: epic }, IGMarkets::API_V1)
68
+ .and_return(result)
69
+
70
+ expect(platform.watchlists[watchlist_id].add_market(epic)).to eq(result)
71
+ end
72
+
73
+ it 'can remove a market from a watchlist' do
74
+ watchlist_id = '1000'
75
+ epic = 'ABCDEF'
76
+
77
+ result = { status: 'SUCCESS' }
78
+
79
+ expect(session).to receive(:get)
80
+ .with('watchlists', IGMarkets::API_V1)
81
+ .and_return(watchlists: [{ id: watchlist_id }])
82
+
83
+ expect(session).to receive(:delete)
84
+ .with("watchlists/#{watchlist_id}/#{epic}", nil, IGMarkets::API_V1)
85
+ .and_return(result)
86
+
87
+ expect(platform.watchlists[watchlist_id].remove_market(epic)).to eq(result)
88
+ end
89
+ end
@@ -0,0 +1,120 @@
1
+ describe IGMarkets::DealingPlatform::WorkingOrderMethods do
2
+ let(:session) { IGMarkets::Session.new }
3
+ let(:platform) do
4
+ IGMarkets::DealingPlatform.new.tap do |platform|
5
+ platform.instance_variable_set :@session, session
6
+ end
7
+ end
8
+
9
+ it 'can retrieve the current working orders' do
10
+ orders = [build(:working_order)]
11
+
12
+ get_result = {
13
+ working_orders: orders.map(&:attributes).map do |a|
14
+ { market_data: a[:market], working_order_data: a }
15
+ end
16
+ }
17
+
18
+ expect(session).to receive(:get).with('workingorders', IGMarkets::API_V2).and_return(get_result)
19
+ expect(platform.working_orders.all).to eq(orders)
20
+ end
21
+
22
+ it 'can retrieve a single working order' do
23
+ orders = [build(:working_order, deal_id: 'id')]
24
+
25
+ get_result = {
26
+ working_orders: orders.map(&:attributes).map do |a|
27
+ { market_data: a[:market], working_order_data: a }
28
+ end
29
+ }
30
+
31
+ expect(session).to receive(:get).with('workingorders', IGMarkets::API_V2).and_return(get_result)
32
+ expect(platform.working_orders['id']).to eq(orders[0])
33
+ end
34
+
35
+ it 'can create a working order' do
36
+ attributes = {
37
+ currency_code: 'USD',
38
+ direction: :buy,
39
+ epic: 'CS.D.EURUSD.CFD.IP',
40
+ level: 1.0,
41
+ size: 2.0,
42
+ time_in_force: :good_till_cancelled,
43
+ type: :limit
44
+ }
45
+
46
+ payload = {
47
+ currencyCode: 'USD',
48
+ direction: 'BUY',
49
+ epic: 'CS.D.EURUSD.CFD.IP',
50
+ expiry: '-',
51
+ forceOpen: false,
52
+ guaranteedStop: false,
53
+ level: 1.0,
54
+ size: 2.0,
55
+ timeInForce: 'GOOD_TILL_CANCELLED',
56
+ type: 'LIMIT'
57
+ }
58
+
59
+ result = { deal_reference: 'reference' }
60
+
61
+ expect(session).to receive(:post).with('workingorders/otc', payload, IGMarkets::API_V2).and_return(result)
62
+ expect(platform.working_orders.create(attributes)).to eq(result.fetch(:deal_reference))
63
+ end
64
+
65
+ it 'requires good_till_date if time_in_force is :good_till_date' do
66
+ attributes = {
67
+ currency_code: 'USD',
68
+ direction: :buy,
69
+ epic: 'CS.D.EURUSD.CFD.IP',
70
+ level: 1.0,
71
+ size: 2.0,
72
+ time_in_force: :good_till_date,
73
+ type: :limit
74
+ }
75
+
76
+ expect { platform.working_orders.create attributes }.to raise_error(ArgumentError)
77
+ end
78
+
79
+ it 'can delete a working order' do
80
+ orders = [build(:working_order, deal_id: '1')]
81
+
82
+ get_result = {
83
+ working_orders: orders.map(&:attributes).map do |a|
84
+ { market_data: a[:market], working_order_data: a }
85
+ end
86
+ }
87
+
88
+ del_result = { deal_reference: 'reference' }
89
+
90
+ expect(session).to receive(:get).with('workingorders', IGMarkets::API_V2).and_return(get_result)
91
+ expect(session).to receive(:delete).with('workingorders/otc/1', {}, IGMarkets::API_V1).and_return(del_result)
92
+
93
+ expect(platform.working_orders['1'].delete).to eq('reference')
94
+ end
95
+
96
+ it 'can update a working order' do
97
+ orders = [build(:working_order, deal_id: '1')]
98
+
99
+ get_result = {
100
+ working_orders: orders.map(&:attributes).map do |a|
101
+ { market_data: a[:market], working_order_data: a }
102
+ end
103
+ }
104
+
105
+ payload = {
106
+ goodTillDate: '2015/10/20 10:45',
107
+ level: 1.03,
108
+ limitDistance: 20,
109
+ stopDistance: 30,
110
+ timeInForce: 'GOOD_TILL_DATE',
111
+ type: 'LIMIT'
112
+ }
113
+
114
+ put_result = { deal_reference: 'reference' }
115
+
116
+ expect(session).to receive(:get).with('workingorders', IGMarkets::API_V2).and_return(get_result)
117
+ expect(session).to receive(:put).with('workingorders/otc/1', payload, IGMarkets::API_V1).and_return(put_result)
118
+ expect(platform.working_orders['1'].update(level: 1.03, limit_distance: 20, stop_distance: 30)).to eq('reference')
119
+ end
120
+ end