bitex_bot 0.6.1 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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)