bitex_bot 0.6.1 → 0.9.0

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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -3
  3. data/Gemfile +3 -1
  4. data/bitex_bot.gemspec +5 -2
  5. data/lib/bitex_bot/database.rb +2 -2
  6. data/lib/bitex_bot/models/api_wrappers/api_wrapper.rb +47 -35
  7. data/lib/bitex_bot/models/api_wrappers/bitex/bitex_api_wrapper.rb +178 -0
  8. data/lib/bitex_bot/models/api_wrappers/bitstamp/bitstamp_api_wrapper.rb +62 -45
  9. data/lib/bitex_bot/models/api_wrappers/itbit/itbit_api_wrapper.rb +52 -28
  10. data/lib/bitex_bot/models/api_wrappers/kraken/kraken_api_wrapper.rb +61 -28
  11. data/lib/bitex_bot/models/api_wrappers/kraken/kraken_order.rb +12 -6
  12. data/lib/bitex_bot/models/buy_closing_flow.rb +3 -2
  13. data/lib/bitex_bot/models/buy_opening_flow.rb +31 -6
  14. data/lib/bitex_bot/models/closing_flow.rb +37 -22
  15. data/lib/bitex_bot/models/open_buy.rb +1 -3
  16. data/lib/bitex_bot/models/open_sell.rb +1 -3
  17. data/lib/bitex_bot/models/opening_flow.rb +42 -28
  18. data/lib/bitex_bot/models/order_book_simulator.rb +14 -13
  19. data/lib/bitex_bot/models/sell_closing_flow.rb +3 -2
  20. data/lib/bitex_bot/models/sell_opening_flow.rb +29 -4
  21. data/lib/bitex_bot/robot.rb +28 -43
  22. data/lib/bitex_bot/settings.rb +2 -0
  23. data/lib/bitex_bot/version.rb +1 -1
  24. data/settings.rb.sample +23 -5
  25. data/spec/bitex_bot/settings_spec.rb +13 -6
  26. data/spec/factories/bitex_ask.rb +14 -0
  27. data/spec/factories/bitex_bid.rb +14 -0
  28. data/spec/factories/bitex_buy.rb +7 -7
  29. data/spec/factories/bitex_sell.rb +7 -7
  30. data/spec/factories/buy_opening_flow.rb +10 -10
  31. data/spec/factories/open_buy.rb +8 -8
  32. data/spec/factories/open_sell.rb +8 -8
  33. data/spec/factories/sell_opening_flow.rb +10 -10
  34. data/spec/fixtures/bitstamp/balance.yml +63 -0
  35. data/spec/fixtures/bitstamp/order_book.yml +60 -0
  36. data/spec/fixtures/bitstamp/orders/all.yml +62 -0
  37. data/spec/fixtures/bitstamp/orders/failure_sell.yml +60 -0
  38. data/spec/fixtures/bitstamp/orders/successful_buy.yml +62 -0
  39. data/spec/fixtures/bitstamp/transactions.yml +244 -0
  40. data/spec/fixtures/bitstamp/user_transactions.yml +223 -0
  41. data/spec/models/api_wrappers/bitex_api_wrapper_spec.rb +147 -0
  42. data/spec/models/api_wrappers/bitstamp_api_wrapper_spec.rb +134 -140
  43. data/spec/models/api_wrappers/itbit_api_wrapper_spec.rb +9 -3
  44. data/spec/models/api_wrappers/kraken_api_wrapper_spec.rb +142 -73
  45. data/spec/models/bitex_api_spec.rb +4 -4
  46. data/spec/models/buy_closing_flow_spec.rb +19 -24
  47. data/spec/models/buy_opening_flow_spec.rb +102 -83
  48. data/spec/models/order_book_simulator_spec.rb +5 -0
  49. data/spec/models/robot_spec.rb +7 -4
  50. data/spec/models/sell_closing_flow_spec.rb +21 -25
  51. data/spec/models/sell_opening_flow_spec.rb +100 -80
  52. data/spec/spec_helper.rb +3 -1
  53. data/spec/support/bitex_stubs.rb +80 -40
  54. data/spec/support/bitstamp/bitstamp_api_wrapper_stubs.rb +2 -2
  55. data/spec/support/bitstamp/bitstamp_stubs.rb +3 -3
  56. data/spec/support/vcr.rb +8 -0
  57. data/spec/support/webmock.rb +8 -0
  58. metadata +77 -10
@@ -1,12 +1,14 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe KrakenApiWrapper do
4
- let(:api_wrapper) { described_class }
4
+ let(:api_wrapper) { BitexBot::Robot.taker }
5
5
  let(:api_client) { api_wrapper.client }
6
6
  let(:taker_settings) do
7
7
  BitexBot::SettingsClass.new(
8
8
  kraken: {
9
- api_key: 'your_api_key', api_secret: 'your_api_secret'
9
+ api_key: 'your_api_key',
10
+ api_secret: 'your_api_secret',
11
+ order_book: 'xbtusd'
10
12
  }
11
13
  )
12
14
  end
@@ -16,63 +18,118 @@ describe KrakenApiWrapper do
16
18
  BitexBot::Robot.setup
17
19
  end
18
20
 
19
- def stub_public_client
20
- api_client.stub(public: double)
21
+ def stub_request_helper(method:, path: '', status: 200, result: {}, error: [], header_params: {})
22
+ stub_request(method, "https://api.kraken.com/0#{path}")
23
+ .with(headers: { 'User-Agent': BitexBot.user_agent }.merge(header_params))
24
+ .to_return(
25
+ status: status,
26
+ body: { error: error, result: result }.to_json,
27
+ headers: { 'Content-Type': 'application/json' }
28
+ )
21
29
  end
22
30
 
23
- def stub_private_client
24
- api_client.stub(private: double)
31
+ def stub_assets
32
+ stub_request_helper(
33
+ method: :get,
34
+ path: '/public/AssetPairs',
35
+ result: {
36
+ XXBTZUSD: {
37
+ altname: 'XBTUSD',
38
+ aclass_base: 'currency',
39
+ base: 'XXBT',
40
+ aclass_quote: 'currency',
41
+ quote: 'ZUSD',
42
+ lot: 'unit',
43
+ pair_decimals: 1,
44
+ lot_decimals: 8,
45
+ lot_multiplier: 1,
46
+ leverage_buy: [2, 3, 4, 5],
47
+ leverage_sell: [2, 3, 4, 5],
48
+ fees: [
49
+ [0, 0.26],
50
+ [50_000, 0.24],
51
+ [100_000, 0.22],
52
+ [250_000, 0.2],
53
+ [500_000, 0.18],
54
+ [1_000_000, 0.16],
55
+ [2_500_000, 0.14],
56
+ [5_000_000, 0.12],
57
+ [10_000_000, 0.1]
58
+ ],
59
+ fees_maker: [
60
+ [0, 0.16],
61
+ [50_000, 0.14],
62
+ [100_000, 0.12],
63
+ [250_000, 0.1],
64
+ [500_000, 0.08],
65
+ [1_000_000, 0.06],
66
+ [2_500_000, 0.04],
67
+ [5_000_000, 0.02],
68
+ [10_000_000, 0]
69
+ ],
70
+ fee_volume_currency: 'ZUSD',
71
+ margin_call: 80,
72
+ margin_stop: 40
73
+ }
74
+ }
75
+ )
25
76
  end
26
77
 
27
78
  it 'Sends User-Agent header' do
28
- url = 'https://api.kraken.com/0/public/Depth?pair=XBTUSD'
29
- stub_stuff = stub_request(:get, url).with(headers: { 'User-Agent': BitexBot.user_agent })
79
+ stub_assets
80
+ stub_stuff = stub_order_book
30
81
 
31
82
  # We don't care about the response
32
- KrakenApiWrapper.order_book rescue nil
83
+ api_wrapper.order_book
33
84
 
34
- expect(stub_stuff).to have_been_requested
85
+ stub_stuff.should have_been_requested
35
86
  end
36
87
 
37
88
  def stub_balance
38
- api_client.private.stub(account_info: [{ taker_fees: '89.2' }])
39
- api_client.private.stub(:balance) do
40
- { 'XXBT': '1433.0939', 'ZUSD': '1230.0233', 'XETH': '99.7497224800' }.with_indifferent_access
41
- end
89
+ stub_request_helper(
90
+ method: :post,
91
+ path: '/private/Balance',
92
+ header_params: { 'Api-Key': api_wrapper.api_key },
93
+ result: { XXBT: '1433.0939', ZUSD: '1230.0233', ETH: '99.7497224800' }
94
+ )
42
95
  end
43
96
 
44
97
  def stub_trade_volume
45
- api_client.private.stub(:trade_volume).with(hash_including(pair: 'XBTUSD')) do
46
- {
47
- 'currency' => 'ZUSD', 'volume' => '3878.8703',
48
- 'fees' => {
49
- 'XXBTZUSD' => {
50
- 'fee' => '0.2600',
51
- 'minfee' => '0.1000',
52
- 'maxfee' => '0.2600',
53
- 'nextfee' => '0.2400',
54
- 'nextvolume' => '10000.0000',
55
- 'tiervolume' => '0.0000'
98
+ stub_request_helper(
99
+ method: :post,
100
+ path: '/private/TradeVolume',
101
+ header_params: { 'Api-Key': api_wrapper.api_key },
102
+ result: {
103
+ currency: 'ZUSD',
104
+ volume: '3878.8703',
105
+ fees: {
106
+ XXBTZUSD: {
107
+ fee: '0.2600',
108
+ minfee: '0.1000',
109
+ maxfee: '0.2600',
110
+ nextfee: '0.2400',
111
+ nextvolume: '10000.0000',
112
+ tiervolume: '0.0000'
56
113
  }
57
114
  },
58
- 'fees_maker' => {
59
- 'XETHZEUR' => {
60
- 'fee' => '0.1600',
61
- 'minfee' => '0.0000',
62
- 'maxfee' => '0.1600',
63
- 'nextfee' => '0.1400',
64
- 'nextvolume' => '10000.0000',
65
- 'tiervolume' => '0.0000'
115
+ fees_maker: {
116
+ XETHZEUR: {
117
+ fee: '0.1600',
118
+ minfee: '0.0000',
119
+ maxfee: '0.1600',
120
+ nextfee: '0.1400',
121
+ nextvolume: '10000.0000',
122
+ tiervolume: '0.0000'
66
123
  }
67
124
  }
68
- }.with_indifferent_access
69
- end
125
+ }
126
+ )
70
127
  end
71
128
 
72
129
  it '#balance' do
73
- stub_private_client
74
- stub_orders
130
+ stub_assets
75
131
  stub_balance
132
+ stub_orders
76
133
  stub_trade_volume
77
134
 
78
135
  balance = api_wrapper.balance
@@ -94,25 +151,26 @@ describe KrakenApiWrapper do
94
151
  end
95
152
 
96
153
  it '#cancel' do
97
- stub_private_client
98
154
  stub_orders
99
155
 
100
- expect(api_wrapper.orders.sample).to respond_to(:cancel!)
156
+ api_wrapper.orders.sample.should respond_to(:cancel!)
101
157
  end
102
158
 
103
159
  def stub_order_book(count: 3, price: 1.5, amount: 2.5)
104
- api_client.public.stub(:order_book) do
105
- {
106
- 'XXBTZUSD' => {
107
- 'bids' => count.times.map { |i| [(price + i).to_d, (amount + i).to_d, 1.seconds.ago.to_i.to_s] },
108
- 'asks' => count.times.map { |i| [(price + i).to_d, (amount + i).to_d, 1.seconds.ago.to_i.to_s] }
160
+ stub_request_helper(
161
+ method: :get,
162
+ path: '/public/Depth?pair=XBTUSD',
163
+ result: {
164
+ XXBTZUSD: {
165
+ bids: count.times.map { |i| [(price + i).to_d, (amount + i).to_d, 1.seconds.ago.to_i.to_s] },
166
+ asks: count.times.map { |i| [(price + i).to_d, (amount + i).to_d, 1.seconds.ago.to_i.to_s] }
109
167
  }
110
- }.with_indifferent_access
111
- end
168
+ }
169
+ )
112
170
  end
113
171
 
114
172
  it '#order_book' do
115
- stub_public_client
173
+ stub_assets
116
174
  stub_order_book
117
175
 
118
176
  order_book = api_wrapper.order_book
@@ -131,34 +189,36 @@ describe KrakenApiWrapper do
131
189
  end
132
190
 
133
191
  def stub_orders
134
- api_client.private.stub(:open_orders) do
135
- {
136
- 'open' => {
137
- 'O5TDV2-WDYB2-6OGJRD' => {
138
- 'refid' => nil, 'userref' => nil, 'status' => 'open', 'opentm' => 1_440_292_821.839, 'starttm' => 0, 'expiretm' => 0,
139
- 'descr' => {
140
- 'pair' => 'ETHEUR', 'type' => 'buy', 'ordertype' => 'limit', 'price' => '1.19000', 'price2' => '0',
141
- 'leverage' => 'none', 'order' => 'buy 1204.00000000 ETHEUR @ limit 1.19000'
192
+ stub_request_helper(
193
+ method: :post,
194
+ path: '/private/OpenOrders',
195
+ header_params: { 'Api-Key': api_wrapper.api_key },
196
+ result: {
197
+ open: {
198
+ 'O5TDV2-WDYB2-6OGJRD': {
199
+ refid: nil, userref: nil, status: 'open', opentm: 1_440_292_821.839, starttm: 0, expiretm: 0,
200
+ descr: {
201
+ pair: 'ETHEUR', type: 'buy', ordertype: 'limit', price: '1.19000', price2: '0',
202
+ leverage: 'none', order: 'buy 1204.00000000 ETHEUR @ limit 1.19000'
142
203
  },
143
- 'vol' => '1204.00000000', 'vol_exec' => '0.00000000', 'cost' => '0.00000', 'fee' => '0.00000',
144
- 'price' => '0.00008', 'misc' => '', 'oflags' => 'fciq'
204
+ vol: '1204.00000000', vol_exec: '0.00000000', cost: '0.00000', fee: '0.00000',
205
+ price: '0.00008', misc: '', oflags: 'fciq'
145
206
  },
146
- 'OGAEYL-LVSPL-BYGGRR' => {
147
- 'refid' => nil, 'userref' => nil, 'status' => 'open', 'opentm' => 1_440_254_004.621, 'starttm' => 0, 'expiretm' => 0,
148
- 'descr' => {
149
- 'pair' => 'ETHEUR', 'type' => 'sell', 'ordertype' => 'limit', 'price' => '1.29000', 'price2' => '0',
150
- 'leverage' => 'none', 'order' => 'sell 99.74972000 ETHEUR @ limit 1.29000'
207
+ 'OGAEYL-LVSPL-BYGGRR': {
208
+ refid: nil, userref: nil, status: 'open', opentm: 1_440_254_004.621, starttm: 0, expiretm: 0,
209
+ descr: {
210
+ pair: 'ETHEUR', type: 'sell', ordertype: 'limit', price: '1.29000', price2: '0',
211
+ leverage: 'none', order: 'sell 99.74972000 ETHEUR @ limit 1.29000'
151
212
  },
152
- 'vol' => '99.74972000', 'vol_exec' => '0.00000000', 'cost' => '0.00000', 'fee' => '0.00000',
153
- 'price' => '0.00009', 'misc' => '', 'oflags' => 'fciq'
213
+ vol: '99.74972000', vol_exec: '0.00000000', cost: '0.00000', fee: '0.00000',
214
+ price: '0.00009', misc: '', oflags: 'fciq'
154
215
  }
155
216
  }
156
- }.with_indifferent_access
157
- end
217
+ }
218
+ )
158
219
  end
159
220
 
160
221
  it '#orders' do
161
- stub_private_client
162
222
  stub_orders
163
223
 
164
224
  api_wrapper.orders.all? { |o| o.should be_a(ApiWrapper::Order) }
@@ -172,18 +232,20 @@ describe KrakenApiWrapper do
172
232
  end
173
233
 
174
234
  def stub_transactions(count: 1, price: 1.5, amount: 2.5)
175
- api_client.public.stub(:trades).with('XBTUSD') do
176
- {
235
+ stub_request_helper(
236
+ method: :get,
237
+ path: '/public/Trades?pair=XBTUSD',
238
+ result: {
177
239
  XXBTZUSD: [
178
240
  ['202.51626', '0.01440000', 1_440_277_319.1_922, 'b', 'l', ''],
179
241
  ['202.54000', '0.10000000', 1_440_277_322.8_993, 'b', 'l', '']
180
242
  ]
181
243
  }
182
- end
244
+ )
183
245
  end
184
246
 
185
247
  it '#transactions' do
186
- stub_public_client
248
+ stub_assets
187
249
  stub_transactions
188
250
 
189
251
  api_wrapper.transactions.all? { |o| o.should be_a(ApiWrapper::Transaction) }
@@ -201,9 +263,16 @@ describe KrakenApiWrapper do
201
263
  end
202
264
 
203
265
  it '#find_lost' do
204
- stub_private_client
205
266
  stub_orders
206
267
 
207
- described_class.orders.all? { |o| described_class.find_lost(o.type, o.price, o.amount).present? }
268
+ api_wrapper.orders.all? { |o| api_wrapper.find_lost(o.type, o.price, o.amount).present? }
269
+ end
270
+
271
+ it '#currency_pair' do
272
+ stub_assets
273
+ BitexBot::Settings.taker.kraken.order_book.should eq taker_settings.kraken.order_book
274
+
275
+ api_wrapper.currency_pair.should be_a(HashWithIndifferentAccess)
276
+ api_wrapper.currency_pair.keys.should include(*%w[altname base quote name])
208
277
  end
209
278
  end
@@ -1,13 +1,13 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe 'BitexApi' do
4
- before(:each) do
5
- BitexBot::Robot.setup
6
- end
4
+ before(:each) { BitexBot::Robot.setup }
5
+ let(:maker) { BitexBot::Robot.maker }
7
6
 
8
7
  it 'Sends User-Agent header' do
9
8
  stub_request(:get, 'https://bitex.la/api-v1/rest/private/profile?api_key=your_bitex_api_key_which_should_be_kept_safe')
10
9
  .with(headers: { 'User-Agent': BitexBot.user_agent })
11
- Bitex::Profile.get rescue nil # we don't care about the response
10
+
11
+ maker.profile rescue nil # we don't care about the response
12
12
  end
13
13
  end
@@ -4,7 +4,10 @@ describe BitexBot::BuyClosingFlow do
4
4
  let(:taker_settings) do
5
5
  BitexBot::SettingsClass.new(
6
6
  bitstamp: {
7
- api_key: 'YOUR_API_KEY', secret: 'YOUR_API_SECRET', client_id: 'YOUR_BITSTAMP_USERNAME'
7
+ api_key: 'YOUR_API_KEY',
8
+ secret: 'YOUR_API_SECRET',
9
+ client_id: 'YOUR_BITSTAMP_USERNAME',
10
+ order_book: 'btcusd'
8
11
  }
9
12
  )
10
13
  end
@@ -85,7 +88,7 @@ describe BitexBot::BuyClosingFlow do
85
88
  flow = BitexBot::BuyClosingFlow.last
86
89
  stub_bitstamp_orders_into_transactions
87
90
 
88
- flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
91
+ flow.sync_closed_positions
89
92
 
90
93
  close = flow.close_positions.last
91
94
  close.amount.should == 624.105
@@ -106,7 +109,7 @@ describe BitexBot::BuyClosingFlow do
106
109
  subject.class.close_open_positions
107
110
 
108
111
  stub_bitstamp_orders_into_transactions
109
- flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
112
+ flow.sync_closed_positions
110
113
  end
111
114
 
112
115
  it 'syncs the executed orders, calculates profit with other fx rate' do
@@ -120,13 +123,11 @@ describe BitexBot::BuyClosingFlow do
120
123
  BitexBot::BuyClosingFlow.close_open_positions
121
124
  flow = BitexBot::BuyClosingFlow.last
122
125
 
123
- expect do
124
- flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
125
- end.not_to change { BitexBot::CloseBuy.count }
126
+ expect { flow.sync_closed_positions }.not_to change { BitexBot::CloseBuy.count }
126
127
  flow.should_not be_done
127
128
 
128
129
  # Immediately calling sync again does not try to cancel the ask.
129
- flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
130
+ flow.sync_closed_positions
130
131
  Bitstamp.orders.all.size.should == 1
131
132
 
132
133
  # Partially executes order, and 61 seconds after that
@@ -134,18 +135,14 @@ describe BitexBot::BuyClosingFlow do
134
135
  stub_bitstamp_orders_into_transactions(ratio: 0.5)
135
136
  Timecop.travel 61.seconds.from_now
136
137
  Bitstamp.orders.all.size.should == 1
137
- expect do
138
- flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
139
- end.not_to change { BitexBot::CloseBuy.count }
138
+ expect { flow.sync_closed_positions }.not_to change { BitexBot::CloseBuy.count }
140
139
  Bitstamp.orders.all.size.should be_zero
141
140
  flow.should_not be_done
142
141
 
143
142
  # Next time we try to sync_closed_positions the flow
144
143
  # detects the previous close_buy was cancelled correctly so
145
144
  # it syncs it's total amounts and tries to place a new one.
146
- expect do
147
- flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
148
- end.to change { BitexBot::CloseBuy.count }.by(1)
145
+ expect { flow.sync_closed_positions }.to change { BitexBot::CloseBuy.count }.by(1)
149
146
 
150
147
  flow.close_positions.first.tap do |close|
151
148
  close.amount.should == 312.0_525
@@ -155,7 +152,7 @@ describe BitexBot::BuyClosingFlow do
155
152
  # The second ask is executed completely so we can wrap it up and consider
156
153
  # this closing flow done.
157
154
  stub_bitstamp_orders_into_transactions
158
- flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
155
+ flow.sync_closed_positions
159
156
  flow.close_positions.last.tap do |close|
160
157
  close.amount.should == 312.02_235
161
158
  close.quantity.should == 1.005
@@ -171,9 +168,7 @@ describe BitexBot::BuyClosingFlow do
171
168
  stub_bitstamp_orders_into_transactions(ratio: 0.999)
172
169
  Bitstamp.orders.all.first.cancel!
173
170
 
174
- expect do
175
- flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
176
- end.not_to change { BitexBot::CloseBuy.count }
171
+ expect { flow.sync_closed_positions }.not_to change { BitexBot::CloseBuy.count }
177
172
 
178
173
  flow.should be_done
179
174
  flow.crypto_profit.should == 0.00_201
@@ -188,12 +183,12 @@ describe BitexBot::BuyClosingFlow do
188
183
 
189
184
  60.times do
190
185
  Timecop.travel 60.seconds.from_now
191
- flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
186
+ flow.sync_closed_positions
192
187
  end
193
188
 
194
189
  stub_bitstamp_orders_into_transactions
195
190
 
196
- flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
191
+ flow.sync_closed_positions
197
192
  flow.reload.should be_done
198
193
  flow.crypto_profit.should be_zero
199
194
  flow.fiat_profit.should == -34.165
@@ -202,8 +197,8 @@ describe BitexBot::BuyClosingFlow do
202
197
 
203
198
  describe 'when there are errors placing the closing order' do
204
199
  it 'keeps trying to place a closed position on bitstamp errors' do
205
- BitstampApiWrapper.stub(send_order: nil)
206
- BitstampApiWrapper.stub(find_lost: nil)
200
+ BitstampApiWrapper.any_instance.stub(send_order: nil)
201
+ BitstampApiWrapper.any_instance.stub(find_lost: nil)
207
202
 
208
203
  open = create :open_buy
209
204
  expect do
@@ -222,9 +217,9 @@ describe BitexBot::BuyClosingFlow do
222
217
  end
223
218
 
224
219
  it 'retries until it finds the lost order' do
225
- BitstampApiWrapper.stub(send_order: nil)
226
- BitstampApiWrapper.stub(:orders) do
227
- [BitstampApiWrapper::Order.new(1, :sell, 310, 2.5, 1.minute.ago.to_i)]
220
+ BitstampApiWrapper.any_instance.stub(send_order: nil)
221
+ BitstampApiWrapper.any_instance.stub(:orders) do
222
+ [ApiWrapper::Order.new(1, :sell, 310, 2.5, 1.minute.ago.to_i)]
228
223
  end
229
224
 
230
225
  open = create(:open_buy)