bitex_bot 0.3.7 → 0.4.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 (59) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +63 -0
  3. data/.rubocop.yml +33 -0
  4. data/Gemfile +1 -1
  5. data/Rakefile +1 -1
  6. data/bin/bitex_bot +1 -1
  7. data/bitex_bot.gemspec +34 -34
  8. data/lib/bitex_bot/database.rb +67 -67
  9. data/lib/bitex_bot/models/api_wrappers/api_wrapper.rb +142 -0
  10. data/lib/bitex_bot/models/api_wrappers/bitstamp/bitstamp_api_wrapper.rb +137 -0
  11. data/lib/bitex_bot/models/api_wrappers/itbit/itbit_api_wrapper.rb +116 -0
  12. data/lib/bitex_bot/models/api_wrappers/kraken/kraken_api_wrapper.rb +111 -0
  13. data/lib/bitex_bot/models/api_wrappers/kraken/kraken_order.rb +117 -0
  14. data/lib/bitex_bot/models/buy_closing_flow.rb +23 -16
  15. data/lib/bitex_bot/models/buy_opening_flow.rb +48 -54
  16. data/lib/bitex_bot/models/close_buy.rb +2 -2
  17. data/lib/bitex_bot/models/closing_flow.rb +98 -79
  18. data/lib/bitex_bot/models/open_buy.rb +11 -10
  19. data/lib/bitex_bot/models/open_sell.rb +11 -10
  20. data/lib/bitex_bot/models/opening_flow.rb +157 -99
  21. data/lib/bitex_bot/models/order_book_simulator.rb +62 -67
  22. data/lib/bitex_bot/models/sell_closing_flow.rb +25 -20
  23. data/lib/bitex_bot/models/sell_opening_flow.rb +47 -54
  24. data/lib/bitex_bot/models/store.rb +3 -1
  25. data/lib/bitex_bot/robot.rb +203 -176
  26. data/lib/bitex_bot/settings.rb +71 -12
  27. data/lib/bitex_bot/version.rb +1 -1
  28. data/lib/bitex_bot.rb +40 -16
  29. data/settings.rb.sample +43 -66
  30. data/spec/bitex_bot/settings_spec.rb +87 -15
  31. data/spec/factories/bitex_buy.rb +3 -3
  32. data/spec/factories/bitex_sell.rb +3 -3
  33. data/spec/factories/buy_opening_flow.rb +1 -1
  34. data/spec/factories/open_buy.rb +12 -10
  35. data/spec/factories/open_sell.rb +12 -10
  36. data/spec/factories/sell_opening_flow.rb +1 -1
  37. data/spec/models/api_wrappers/bitstamp_api_wrapper_spec.rb +200 -0
  38. data/spec/models/api_wrappers/itbit_api_wrapper_spec.rb +176 -0
  39. data/spec/models/api_wrappers/kraken_api_wrapper_spec.rb +209 -0
  40. data/spec/models/bitex_api_spec.rb +1 -1
  41. data/spec/models/buy_closing_flow_spec.rb +140 -71
  42. data/spec/models/buy_opening_flow_spec.rb +126 -56
  43. data/spec/models/order_book_simulator_spec.rb +10 -10
  44. data/spec/models/robot_spec.rb +61 -47
  45. data/spec/models/sell_closing_flow_spec.rb +130 -62
  46. data/spec/models/sell_opening_flow_spec.rb +129 -60
  47. data/spec/spec_helper.rb +19 -16
  48. data/spec/support/bitex_stubs.rb +13 -14
  49. data/spec/support/bitstamp/bitstamp_api_wrapper_stubs.rb +35 -0
  50. data/spec/support/bitstamp/bitstamp_stubs.rb +91 -0
  51. metadata +60 -42
  52. data/lib/bitex_bot/models/bitfinex_api_wrapper.rb +0 -118
  53. data/lib/bitex_bot/models/bitstamp_api_wrapper.rb +0 -82
  54. data/lib/bitex_bot/models/itbit_api_wrapper.rb +0 -68
  55. data/lib/bitex_bot/models/kraken_api_wrapper.rb +0 -188
  56. data/spec/models/bitfinex_api_wrapper_spec.rb +0 -17
  57. data/spec/models/bitstamp_api_wrapper_spec.rb +0 -15
  58. data/spec/models/itbit_api_wrapper_spec.rb +0 -15
  59. data/spec/support/bitstamp_stubs.rb +0 -110
@@ -1,15 +1,21 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe BitexBot::Robot do
4
+ let(:taker_settings) do
5
+ BitexBot::SettingsClass.new(
6
+ bitstamp: {
7
+ api_key: 'YOUR_API_KEY', secret: 'YOUR_API_SECRET', client_id: 'YOUR_BITSTAMP_USERNAME'
8
+ }
9
+ )
10
+ end
11
+
4
12
  before(:each) do
13
+ BitexBot::Settings.stub(taker: taker_settings)
14
+ BitexBot::Robot.setup
5
15
  BitexBot::Settings.stub(
6
16
  time_to_live: 10,
7
- buying: double(
8
- amount_to_spend_per_order: 50,
9
- profit: 0),
10
- selling: double(
11
- quantity_to_sell_per_order: 1,
12
- profit: 0),
17
+ buying: double(amount_to_spend_per_order: 50, profit: 0),
18
+ selling: double(quantity_to_sell_per_order: 1, profit: 0),
13
19
  mailer: double(
14
20
  from: 'test@test.com',
15
21
  to: 'test@test.com',
@@ -17,7 +23,6 @@ describe BitexBot::Robot do
17
23
  options: {}
18
24
  )
19
25
  )
20
- Bitex.api_key = "valid_key"
21
26
  Bitex::Profile.stub(get: {
22
27
  fee: 0.5,
23
28
  usd_balance: 10000.00, # Total USD balance
@@ -28,20 +33,22 @@ describe BitexBot::Robot do
28
33
  btc_available: 15.00000000, # BTC available for trading
29
34
  ltc_balance: 250.00000000, # Total LTC balance
30
35
  ltc_reserved: 100.00000000, # LTC reserved in open orders
31
- ltc_available: 150.00000000,
36
+ ltc_available: 150.00000000 # LTC available for trading
32
37
  })
33
38
  stub_bitex_orders
34
39
  stub_bitstamp_sell
35
40
  stub_bitstamp_buy
36
- stub_bitstamp_balance
37
- stub_bitstamp_order_book
41
+ stub_bitstamp_api_wrapper_balance
42
+ stub_bitstamp_api_wrapper_order_book
38
43
  stub_bitstamp_transactions
39
- stub_bitstamp_user_transactions
44
+ stub_bitstamp_empty_user_transactions
40
45
  end
41
- let(:bot){ BitexBot::Robot.new }
46
+
47
+ let(:bot) { BitexBot::Robot.new }
42
48
 
43
49
  it 'Starts out by creating opening flows that timeout' do
44
50
  stub_bitex_orders
51
+ stub_bitstamp_api_wrapper_order_book
45
52
  bot.trade!
46
53
  stub_bitex_transactions
47
54
  buying = BitexBot::BuyOpeningFlow.last
@@ -49,7 +56,7 @@ describe BitexBot::Robot do
49
56
 
50
57
  Timecop.travel 10.minutes.from_now
51
58
  bot.trade!
52
-
59
+
53
60
  buying.reload.should be_settling
54
61
  selling.reload.should be_settling
55
62
 
@@ -57,7 +64,7 @@ describe BitexBot::Robot do
57
64
  buying.reload.should be_finalised
58
65
  selling.reload.should be_finalised
59
66
  end
60
-
67
+
61
68
  it 'creates alternating opening flows' do
62
69
  Bitex::Trade.stub(all: [])
63
70
  bot.trade!
@@ -68,7 +75,7 @@ describe BitexBot::Robot do
68
75
  Timecop.travel 5.seconds.from_now
69
76
  bot.trade!
70
77
  BitexBot::BuyOpeningFlow.active.count.should == 2
71
-
78
+
72
79
  # When transactions appear, all opening flows
73
80
  # should get old and die.
74
81
  # We stub our finder to make it so all orders
@@ -89,7 +96,7 @@ describe BitexBot::Robot do
89
96
  stub_bitex_transactions
90
97
  expect do
91
98
  bot.trade!
92
- end.to change{ BitexBot::BuyClosingFlow.count }.by(1)
99
+ end.to change { BitexBot::BuyClosingFlow.count }.by(1)
93
100
 
94
101
  Timecop.travel 15.seconds.from_now
95
102
  bot.trade!
@@ -101,25 +108,25 @@ describe BitexBot::Robot do
101
108
  expect do
102
109
  bot.trade!
103
110
  bot.should_not be_active_closing_flows
104
- end.to change{ BitexBot::BuyOpeningFlow.count }.by(1)
111
+ end.to change { BitexBot::BuyOpeningFlow.count }.by(1)
105
112
  end
106
-
113
+
107
114
  it 'does not place new opening flows when ordered to hold' do
108
115
  other_bot = BitexBot::Robot.new
109
116
  other_bot.store.hold = true
110
117
  other_bot.store.save!
111
118
  expect do
112
119
  bot.trade!
113
- end.not_to change{ BitexBot::BuyOpeningFlow.count }
120
+ end.not_to change { BitexBot::BuyOpeningFlow.count }
114
121
  end
115
122
 
116
- it 'stops trading when btc stop is reached' do
123
+ it 'stops trading when fiat stop is reached' do
117
124
  other_bot = BitexBot::Robot.new
118
- other_bot.store.usd_stop = 11000
125
+ other_bot.store.btc_stop = 30
119
126
  other_bot.store.save!
120
127
  expect do
121
128
  bot.trade!
122
- end.not_to change{ BitexBot::BuyOpeningFlow.count }
129
+ end.not_to change { BitexBot::BuyOpeningFlow.count }
123
130
  end
124
131
 
125
132
  it 'stops trading when usd stop is reached' do
@@ -128,27 +135,36 @@ describe BitexBot::Robot do
128
135
  other_bot.store.save!
129
136
  expect do
130
137
  bot.trade!
131
- end.not_to change{ BitexBot::BuyOpeningFlow.count }
138
+ end.not_to change { BitexBot::BuyOpeningFlow.count }
139
+ end
140
+
141
+ it 'stops trading when btc stop is reached' do
142
+ other_bot = BitexBot::Robot.new
143
+ other_bot.store.fiat_stop = 11000
144
+ other_bot.store.save!
145
+ expect do
146
+ bot.trade!
147
+ end.not_to change { BitexBot::BuyOpeningFlow.count }
132
148
  end
133
149
 
134
150
  it 'warns every 30 minutes when usd warn is reached' do
135
151
  Bitex::Trade.stub(all: [])
136
152
  other_bot = BitexBot::Robot.new
137
- other_bot.store.usd_warning = 11000
153
+ other_bot.store.fiat_warning = 11000
138
154
  other_bot.store.save!
139
155
  expect do
140
156
  bot.trade!
141
- end.to change{ Mail::TestMailer.deliveries.count }.by(1)
157
+ end.to change { Mail::TestMailer.deliveries.count }.by(1)
142
158
  Timecop.travel 1.minute.from_now
143
- stub_bitstamp_order_book # Re-stub so orderbook does not get old
159
+ stub_bitstamp_order_book # Re-stub so order book does not get old
144
160
  expect do
145
161
  bot.trade!
146
- end.not_to change{ Mail::TestMailer.deliveries.count }
162
+ end.not_to change { Mail::TestMailer.deliveries.count }
147
163
  Timecop.travel 31.minutes.from_now
148
- stub_bitstamp_order_book # Re-stub so orderbook does not get old
164
+ stub_bitstamp_order_book # Re-stub so order book does not get old
149
165
  expect do
150
166
  bot.trade!
151
- end.to change{ Mail::TestMailer.deliveries.count }.by(1)
167
+ end.to change { Mail::TestMailer.deliveries.count }.by(1)
152
168
  end
153
169
 
154
170
  it 'warns every 30 minutes when btc warn is reached' do
@@ -156,38 +172,36 @@ describe BitexBot::Robot do
156
172
  other_bot = BitexBot::Robot.new
157
173
  other_bot.store.btc_warning = 30
158
174
  other_bot.store.save!
175
+
159
176
  expect do
160
177
  bot.trade!
161
- end.to change{ Mail::TestMailer.deliveries.count }.by(1)
178
+ end.to change { Mail::TestMailer.deliveries.count }.by(1)
179
+
162
180
  Timecop.travel 1.minute.from_now
163
- stub_bitstamp_order_book # Re-stub so orderbook does not get old
181
+ stub_bitstamp_order_book # Re-stub so order book does not get old
164
182
  expect do
165
183
  bot.trade!
166
- end.not_to change{ Mail::TestMailer.deliveries.count }
184
+ end.not_to change { Mail::TestMailer.deliveries.count }
185
+
167
186
  Timecop.travel 31.minutes.from_now
168
- stub_bitstamp_order_book # Re-stub so orderbook does not get old
187
+ stub_bitstamp_order_book # Re-stub so order book does not get old
188
+
169
189
  expect do
170
190
  bot.trade!
171
- end.to change{ Mail::TestMailer.deliveries.count }.by(1)
191
+ end.to change { Mail::TestMailer.deliveries.count }.by(1)
172
192
  end
173
-
174
- it 'updates taker_usd and taker_btc' do
193
+
194
+ it 'updates taker_fiat and taker_btc' do
175
195
  bot.trade!
176
- bot.store.taker_usd.should_not be_nil
196
+ bot.store.taker_fiat.should_not be_nil
177
197
  bot.store.taker_btc.should_not be_nil
178
198
  end
179
-
199
+
180
200
  it 'notifies exceptions and sleeps' do
181
- Bitstamp.stub(:balance) do
182
- raise StandardError.new('oh moova')
183
- end
201
+ BitstampApiWrapper.stub(:balance) { raise StandardError.new('oh moova') }
202
+
184
203
  expect do
185
204
  bot.trade!
186
- end.to change{ Mail::TestMailer.deliveries.count }.by(1)
187
- end
188
-
189
- it 'knows how to setup sandbox mode for both gems' do
190
- pending
191
- fail
205
+ end.to change { Mail::TestMailer.deliveries.count }.by(1)
192
206
  end
193
207
  end
@@ -1,101 +1,166 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe BitexBot::SellClosingFlow do
4
- it "closes a single open position completely" do
4
+ let(:taker_settings) do
5
+ BitexBot::SettingsClass.new(
6
+ bitstamp: {
7
+ api_key: 'YOUR_API_KEY', secret: 'YOUR_API_SECRET', client_id: 'YOUR_BITSTAMP_USERNAME'
8
+ }
9
+ )
10
+ end
11
+
12
+ before(:each) do
13
+ BitexBot::Settings.stub(taker: taker_settings)
14
+ BitexBot::Robot.setup
15
+ end
16
+
17
+ it 'closes a single open position completely' do
5
18
  stub_bitstamp_buy
6
19
  open = create :open_sell
7
- flow = BitexBot::SellClosingFlow.close_open_positions
20
+ BitexBot::SellClosingFlow.close_open_positions
21
+ flow = BitexBot::SellClosingFlow.last
22
+
8
23
  open.reload.closing_flow.should == flow
24
+
9
25
  flow.open_positions.should == [open]
10
26
  flow.desired_price.should == 290
11
27
  flow.quantity.should == 2
12
28
  flow.amount.should == 600
13
29
  flow.btc_profit.should be_nil
14
- flow.usd_profit.should be_nil
30
+ flow.fiat_profit.should be_nil
31
+
15
32
  close = flow.close_positions.first
16
33
  close.order_id.should == '1'
17
34
  close.amount.should be_nil
18
35
  close.quantity.should be_nil
19
36
  end
20
-
21
- it "closes an aggregate of several open positions" do
37
+
38
+ it 'closes an aggregate of several open positions' do
22
39
  stub_bitstamp_buy
23
40
  open_one = create :tiny_open_sell
24
41
  open_two = create :open_sell
25
- flow = BitexBot::SellClosingFlow.close_open_positions
42
+ BitexBot::SellClosingFlow.close_open_positions
43
+ flow = BitexBot::SellClosingFlow.last
44
+
26
45
  close = flow.close_positions.first
46
+
27
47
  open_one.reload.closing_flow.should == flow
28
48
  open_two.reload.closing_flow.should == flow
49
+
29
50
  flow.open_positions.should == [open_one, open_two]
30
- flow.desired_price.round(15).should == '290.497512437810945'.to_d
51
+ flow.desired_price.round(10).should == '290.4975124378'.to_d
31
52
  flow.quantity.should == 2.01
32
53
  flow.amount.should == 604
33
54
  flow.btc_profit.should be_nil
34
- flow.usd_profit.should be_nil
55
+ flow.fiat_profit.should be_nil
56
+
35
57
  close.order_id.should == '1'
36
58
  close.amount.should be_nil
37
59
  close.quantity.should be_nil
38
60
  end
39
61
 
40
- it 'keeps trying to place a closed position on bitstamp errors' do
41
- stub_bitstamp_buy
42
- Bitstamp.orders.stub(:buy) do
43
- double(id: nil, error: {price: ['Ensure it is good']})
62
+ describe 'when there are errors placing the closing order' do
63
+ it 'keeps trying to place a closed position on bitstamp errors' do
64
+ BitstampApiWrapper.stub(send_order: nil)
65
+ BitstampApiWrapper.stub(find_lost: nil)
66
+
67
+ open = create :open_sell
68
+ expect do
69
+ flow = BitexBot::SellClosingFlow.close_open_positions
70
+ end.to raise_exception(OrderNotFound)
71
+ flow = BitexBot::SellClosingFlow.last
72
+
73
+ open.reload.closing_flow.should == flow
74
+
75
+ flow.open_positions.should == [open]
76
+ flow.desired_price.should == 290
77
+ flow.quantity.should == 2
78
+ flow.btc_profit.should be_nil
79
+ flow.fiat_profit.should be_nil
80
+ flow.close_positions.should be_empty
44
81
  end
45
- open = create :open_sell
46
- flow = BitexBot::SellClosingFlow.close_open_positions
47
- open.reload.closing_flow.should == flow
48
- flow.open_positions.should == [open]
49
- flow.desired_price.should == 290
50
- flow.quantity.should == 2
51
- flow.btc_profit.should be_nil
52
- flow.usd_profit.should be_nil
53
- flow.close_positions.should be_empty
54
82
 
55
- stub_bitstamp_user_transactions
56
- stub_bitstamp_buy
57
- flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
58
- close = flow.close_positions.first
59
- close.order_id.should == '1'
60
- close.amount.should be_nil
61
- close.quantity.should be_nil
83
+ it 'retries until it finds the lost order' do
84
+ BitstampApiWrapper.stub(send_order: nil)
85
+ BitstampApiWrapper.stub(:orders) do
86
+ [BitstampApiWrapper::Order.new(1, :buy, 290, 2, 1.minute.ago.to_i)]
87
+ end
88
+
89
+ open = create(:open_sell)
90
+ BitexBot::SellClosingFlow.close_open_positions
91
+ flow = BitexBot::SellClosingFlow.last
92
+
93
+ flow.close_positions.should_not be_empty
94
+ flow.close_positions.first do |position|
95
+ position.id.should eq 1234
96
+ position.type.should eq 1
97
+ position.amount.should eq 1000
98
+ position.price.should eq 2000
99
+ end
100
+ end
62
101
  end
63
-
64
- it "does not try to close if the amount is too low" do
102
+
103
+ it 'does not try to close if the amount is too low' do
65
104
  open = create :tiny_open_sell
66
105
  expect do
67
106
  BitexBot::SellClosingFlow.close_open_positions.should be_nil
68
107
  end.not_to change{ BitexBot::SellClosingFlow.count }
69
108
  end
70
-
71
- it "does not try to close if there are no open positions" do
109
+
110
+ it 'does not try to close if there are no open positions' do
72
111
  expect do
73
112
  BitexBot::SellClosingFlow.close_open_positions.should be_nil
74
113
  end.not_to change{ BitexBot::SellClosingFlow.count }
75
114
  end
76
-
77
- describe "when syncinc executed orders" do
115
+
116
+ describe 'when syncinc executed orders' do
78
117
  before(:each) do
79
118
  stub_bitstamp_buy
80
- stub_bitstamp_user_transactions
119
+ stub_bitstamp_empty_user_transactions
81
120
  create :tiny_open_sell
82
121
  create :open_sell
83
122
  end
84
-
85
- it "syncs the executed orders, calculates profit" do
86
- flow = BitexBot::SellClosingFlow.close_open_positions
123
+
124
+ it 'syncs the executed orders, calculates profit' do
125
+ BitexBot::SellClosingFlow.close_open_positions
126
+ flow = BitexBot::SellClosingFlow.last
87
127
  stub_bitstamp_orders_into_transactions
128
+
88
129
  flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
130
+
89
131
  close = flow.close_positions.last
90
- close.amount.should == "583.905".to_d
132
+ close.amount.should == '583.905'.to_d
91
133
  close.quantity.should == 2.01
134
+
92
135
  flow.should be_done
93
136
  flow.btc_profit.should == 0
94
- flow.usd_profit.should == "20.095".to_d
137
+ flow.fiat_profit.should == '20.095'.to_d
95
138
  end
96
-
97
- it "retries closing at a higher price every minute" do
98
- flow = BitexBot::SellClosingFlow.close_open_positions
139
+
140
+ context 'with other fx rate and closed open positions' do
141
+ let(:fx_rate) { 10.to_d }
142
+ let(:flow) { subject.class.last }
143
+ let(:positions_balance_amount) { flow.open_positions.sum(:amount) - flow.positions_balance_amount }
144
+
145
+ before(:each) do
146
+ BitexBot::Settings.stub(fx_rate: fx_rate)
147
+ subject.class.close_open_positions
148
+
149
+ stub_bitstamp_orders_into_transactions
150
+ flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
151
+ end
152
+
153
+ it 'syncs the executed orders, calculates profit with other fx rate' do
154
+ flow.should be_done
155
+ flow.btc_profit.should be_zero
156
+ flow.fiat_profit.should eq positions_balance_amount
157
+ end
158
+ end
159
+
160
+ it 'retries closing at a higher price every minute' do
161
+ BitexBot::SellClosingFlow.close_open_positions
162
+ flow = BitexBot::SellClosingFlow.last
163
+
99
164
  expect do
100
165
  flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
101
166
  end.not_to change{ BitexBot::CloseSell.count }
@@ -115,36 +180,38 @@ describe BitexBot::SellClosingFlow do
115
180
  end.not_to change{ BitexBot::CloseSell.count }
116
181
  Bitstamp.orders.all.size.should == 0
117
182
  flow.should_not be_done
118
-
183
+
119
184
  # Next time we try to sync_closed_positions the flow
120
185
  # detects the previous close_buy was cancelled correctly so
121
186
  # it syncs it's total amounts and tries to place a new one.
122
187
  expect do
123
188
  flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
124
189
  end.to change{ BitexBot::CloseSell.count }.by(1)
190
+
125
191
  flow.close_positions.first.tap do |close|
126
- close.amount.should == "291.9525".to_d
192
+ close.amount.should == '291.9525'.to_d
127
193
  close.quantity.should == 1.005
128
194
  end
129
195
 
130
196
  # The second ask is executed completely so we can wrap it up and consider
131
197
  # this closing flow done.
132
198
  stub_bitstamp_orders_into_transactions
199
+
133
200
  flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
134
201
  flow.close_positions.last.tap do |close|
135
- close.amount.should == "291.953597".to_d
202
+ close.amount.should == '291.953597'.to_d
136
203
  close.quantity.should == '1.0049'.to_d
137
204
  end
138
205
  flow.should be_done
139
206
  flow.btc_profit.should == '-0.0001'.to_d
140
- flow.usd_profit.should == '20.093903'.to_d
141
-
207
+ flow.fiat_profit.should == '20.093903'.to_d
142
208
  end
143
-
144
- it "does not retry for an amount less than minimum_for_closing" do
145
- flow = BitexBot::SellClosingFlow.close_open_positions
146
209
 
147
- 20.times do
210
+ it 'does not retry for an amount less than minimum_for_closing' do
211
+ BitexBot::SellClosingFlow.close_open_positions
212
+ flow = BitexBot::SellClosingFlow.last
213
+
214
+ 20.times do
148
215
  Timecop.travel 60.seconds.from_now
149
216
  flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
150
217
  end
@@ -158,14 +225,16 @@ describe BitexBot::SellClosingFlow do
158
225
 
159
226
  flow.should be_done
160
227
  flow.btc_profit.should == '-0.0224895'.to_d
161
- flow.usd_profit.should == '20.66566825'.to_d
228
+ flow.fiat_profit.should == '20.66566825'.to_d
162
229
  end
163
-
164
- it "can lose BTC if price had to be raised dramatically" do
230
+
231
+ it 'can lose BTC if price had to be raised dramatically' do
165
232
  # This flow is forced to spend the original USD amount paying more than
166
233
  # expected, thus regaining less BTC than what was sold on bitex.
167
- flow = BitexBot::SellClosingFlow.close_open_positions
168
- 60.times do
234
+ BitexBot::SellClosingFlow.close_open_positions
235
+ flow = BitexBot::SellClosingFlow.last
236
+
237
+ 60.times do
169
238
  Timecop.travel 60.seconds.from_now
170
239
  flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
171
240
  end
@@ -173,13 +242,12 @@ describe BitexBot::SellClosingFlow do
173
242
  stub_bitstamp_orders_into_transactions
174
243
 
175
244
  flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
176
-
177
245
  flow.reload.should be_done
178
- flow.btc_profit.should == "-0.1709".to_d
179
- flow.usd_profit.should == "20.08575".to_d
246
+ flow.btc_profit.should == '-0.1709'.to_d
247
+ flow.fiat_profit.should == '20.08575'.to_d
248
+
180
249
  close = flow.close_positions.last
181
- (close.amount / close.quantity)
182
- .should == '317.5'.to_d
250
+ (close.amount / close.quantity).should == '317.5'.to_d
183
251
  end
184
252
  end
185
253
  end