bitex_bot 0.3.7 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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,102 +1,128 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe BitexBot::BuyClosingFlow 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_sell
6
19
  open = create :open_buy
7
- flow = BitexBot::BuyClosingFlow.close_open_positions
20
+ BitexBot::BuyClosingFlow.close_open_positions
21
+ flow = BitexBot::BuyClosingFlow.last
22
+
8
23
  open.reload.closing_flow.should == flow
24
+
9
25
  flow.open_positions.should == [open]
10
26
  flow.desired_price.should == 310
11
27
  flow.quantity.should == 2
28
+ flow.amount.should == 600
12
29
  flow.btc_profit.should be_nil
13
- flow.usd_profit.should be_nil
30
+ flow.fiat_profit.should be_nil
31
+
14
32
  close = flow.close_positions.first
15
33
  close.order_id.should == '1'
16
34
  close.amount.should be_nil
17
35
  close.quantity.should be_nil
18
36
  end
19
-
20
- it "closes an aggregate of several open positions" do
37
+
38
+ it 'closes an aggregate of several open positions' do
21
39
  stub_bitstamp_sell
22
40
  open_one = create :tiny_open_buy
23
41
  open_two = create :open_buy
24
- flow = BitexBot::BuyClosingFlow.close_open_positions
42
+ BitexBot::BuyClosingFlow.close_open_positions
43
+ flow = BitexBot::BuyClosingFlow.last
44
+
25
45
  close = flow.close_positions.first
46
+
26
47
  open_one.reload.closing_flow.should == flow
27
48
  open_two.reload.closing_flow.should == flow
49
+
28
50
  flow.open_positions.should == [open_one, open_two]
29
- flow.desired_price.round(15).should == '310.497512437810945'.to_d
51
+ flow.desired_price.round(10).should == '310.4_975_124_378'.to_d
30
52
  flow.quantity.should == 2.01
53
+ flow.amount.should == 604
31
54
  flow.btc_profit.should be_nil
32
- flow.usd_profit.should be_nil
33
- close.order_id.should == '1'
34
- close.amount.should be_nil
35
- close.quantity.should be_nil
36
- end
37
-
38
- it 'keeps trying to place a closed position on bitstamp errors' do
39
- stub_bitstamp_sell
40
- Bitstamp.orders.stub(:sell) do
41
- double(id: nil, error: {price: ['Ensure it is good']})
42
- end
43
- open = create :open_buy
44
- flow = BitexBot::BuyClosingFlow.close_open_positions
45
- open.reload.closing_flow.should == flow
46
- flow.open_positions.should == [open]
47
- flow.desired_price.should == 310
48
- flow.quantity.should == 2
49
- flow.btc_profit.should be_nil
50
- flow.usd_profit.should be_nil
51
- flow.close_positions.should be_empty
55
+ flow.fiat_profit.should be_nil
52
56
 
53
- stub_bitstamp_user_transactions
54
- stub_bitstamp_sell
55
- flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
56
- close = flow.close_positions.first
57
57
  close.order_id.should == '1'
58
58
  close.amount.should be_nil
59
59
  close.quantity.should be_nil
60
60
  end
61
-
62
- it "does not try to close if the amount is too low" do
61
+
62
+ it 'does not try to close if the amount is too low' do
63
63
  open = create :tiny_open_buy
64
64
  expect do
65
65
  BitexBot::BuyClosingFlow.close_open_positions.should be_nil
66
- end.not_to change{ BitexBot::BuyClosingFlow.count }
66
+ end.not_to change { BitexBot::BuyClosingFlow.count }
67
67
  end
68
-
69
- it "does not try to close if there are no open positions" do
68
+
69
+ it 'does not try to close if there are no open positions' do
70
70
  expect do
71
71
  BitexBot::BuyClosingFlow.close_open_positions.should be_nil
72
- end.not_to change{ BitexBot::BuyClosingFlow.count }
72
+ end.not_to change { BitexBot::BuyClosingFlow.count }
73
73
  end
74
-
75
- describe "when syncinc executed orders" do
74
+
75
+ describe 'when syncinc executed orders' do
76
76
  before(:each) do
77
77
  stub_bitstamp_sell
78
- stub_bitstamp_user_transactions
78
+ stub_bitstamp_empty_user_transactions
79
79
  create :tiny_open_buy
80
80
  create :open_buy
81
81
  end
82
-
83
- it "syncs the executed orders, calculates profit" do
84
- flow = BitexBot::BuyClosingFlow.close_open_positions
82
+
83
+ it 'syncs the executed orders, calculates profit' do
84
+ BitexBot::BuyClosingFlow.close_open_positions
85
+ flow = BitexBot::BuyClosingFlow.last
85
86
  stub_bitstamp_orders_into_transactions
87
+
86
88
  flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
89
+
87
90
  close = flow.close_positions.last
88
- close.amount.should == '624.105'.to_d
91
+ close.amount.should == 624.105
89
92
  close.quantity.should == 2.01
93
+
90
94
  flow.should be_done
91
- flow.btc_profit.should == 0
92
- flow.usd_profit.should == '20.105'.to_d
95
+ flow.btc_profit.should be_zero
96
+ flow.fiat_profit.should == 20.105
93
97
  end
94
-
95
- it "retries closing at a lower price every minute" do
96
- flow = BitexBot::BuyClosingFlow.close_open_positions
98
+
99
+ context 'with other fx rate and closed open positions' do
100
+ let(:fx_rate) { 10.to_d }
101
+ let(:flow) { subject.class.last }
102
+ let(:positions_balance_amount) { flow.positions_balance_amount - flow.open_positions.sum(:amount) }
103
+
104
+ before(:each) do
105
+ BitexBot::Settings.stub(fx_rate: fx_rate)
106
+ subject.class.close_open_positions
107
+
108
+ stub_bitstamp_orders_into_transactions
109
+ flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
110
+ end
111
+
112
+ it 'syncs the executed orders, calculates profit with other fx rate' do
113
+ flow.should be_done
114
+ flow.btc_profit.should be_zero
115
+ flow.fiat_profit.should eq positions_balance_amount
116
+ end
117
+ end
118
+
119
+ it 'retries closing at a lower price every minute' do
120
+ BitexBot::BuyClosingFlow.close_open_positions
121
+ flow = BitexBot::BuyClosingFlow.last
122
+
97
123
  expect do
98
124
  flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
99
- end.not_to change{ BitexBot::CloseBuy.count }
125
+ end.not_to change { BitexBot::CloseBuy.count }
100
126
  flow.should_not be_done
101
127
 
102
128
  # Immediately calling sync again does not try to cancel the ask.
@@ -110,18 +136,19 @@ describe BitexBot::BuyClosingFlow do
110
136
  Bitstamp.orders.all.size.should == 1
111
137
  expect do
112
138
  flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
113
- end.not_to change{ BitexBot::CloseBuy.count }
114
- Bitstamp.orders.all.size.should == 0
139
+ end.not_to change { BitexBot::CloseBuy.count }
140
+ Bitstamp.orders.all.size.should be_zero
115
141
  flow.should_not be_done
116
-
142
+
117
143
  # Next time we try to sync_closed_positions the flow
118
144
  # detects the previous close_buy was cancelled correctly so
119
145
  # it syncs it's total amounts and tries to place a new one.
120
146
  expect do
121
147
  flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
122
- end.to change{ BitexBot::CloseBuy.count }.by(1)
148
+ end.to change { BitexBot::CloseBuy.count }.by(1)
149
+
123
150
  flow.close_positions.first.tap do |close|
124
- close.amount.should == '312.0525'.to_d
151
+ close.amount.should == 312.0_525
125
152
  close.quantity.should == 1.005
126
153
  end
127
154
 
@@ -130,34 +157,36 @@ describe BitexBot::BuyClosingFlow do
130
157
  stub_bitstamp_orders_into_transactions
131
158
  flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
132
159
  flow.close_positions.last.tap do |close|
133
- close.amount.should == '312.02235'.to_d
160
+ close.amount.should == 312.02_235
134
161
  close.quantity.should == 1.005
135
162
  end
136
163
  flow.should be_done
137
- flow.btc_profit.should == 0
138
- flow.usd_profit.should == '20.07485'.to_d
164
+ flow.btc_profit.should be_zero
165
+ flow.fiat_profit.should == 20.07_485
139
166
  end
140
-
141
- it "does not retry for an amount less than minimum_for_closing" do
142
- flow = BitexBot::BuyClosingFlow.close_open_positions
143
167
 
168
+ it 'does not retry for an amount less than minimum_for_closing' do
169
+ BitexBot::BuyClosingFlow.close_open_positions
170
+ flow = BitexBot::BuyClosingFlow.last
144
171
  stub_bitstamp_orders_into_transactions(ratio: 0.999)
145
172
  Bitstamp.orders.all.first.cancel!
146
173
 
147
174
  expect do
148
175
  flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
149
- end.not_to change{ BitexBot::CloseBuy.count }
176
+ end.not_to change { BitexBot::CloseBuy.count }
150
177
 
151
178
  flow.should be_done
152
- flow.btc_profit.should == 0.00201
153
- flow.usd_profit.should == '19.480895'.to_d
179
+ flow.btc_profit.should == 0.00_201
180
+ flow.fiat_profit.should == 19.480_895
154
181
  end
155
-
156
- it "can lose USD if price had to be dropped dramatically" do
182
+
183
+ it 'can lose USD if price had to be dropped dramatically' do
157
184
  # This flow is forced to sell the original BTC quantity for less, thus regaining
158
185
  # less USD than what was spent on bitex.
159
- flow = BitexBot::BuyClosingFlow.close_open_positions
160
- 60.times do
186
+ BitexBot::BuyClosingFlow.close_open_positions
187
+ flow = BitexBot::BuyClosingFlow.last
188
+
189
+ 60.times do
161
190
  Timecop.travel 60.seconds.from_now
162
191
  flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
163
192
  end
@@ -165,10 +194,50 @@ describe BitexBot::BuyClosingFlow do
165
194
  stub_bitstamp_orders_into_transactions
166
195
 
167
196
  flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
168
-
169
197
  flow.reload.should be_done
170
- flow.btc_profit.should == 0
171
- flow.usd_profit.should == '-34.165'.to_d
198
+ flow.btc_profit.should be_zero
199
+ flow.fiat_profit.should == -34.165
200
+ end
201
+ end
202
+
203
+ describe 'when there are errors placing the closing order' do
204
+ it 'keeps trying to place a closed position on bitstamp errors' do
205
+ BitstampApiWrapper.stub(send_order: nil)
206
+ BitstampApiWrapper.stub(find_lost: nil)
207
+
208
+ open = create :open_buy
209
+ expect do
210
+ BitexBot::BuyClosingFlow.close_open_positions
211
+ end.to raise_exception(OrderNotFound)
212
+ flow = BitexBot::BuyClosingFlow.last
213
+
214
+ open.reload.closing_flow.should == flow
215
+
216
+ flow.open_positions.should == [open]
217
+ flow.desired_price.should == 310
218
+ flow.quantity.should == 2
219
+ flow.btc_profit.should be_nil
220
+ flow.fiat_profit.should be_nil
221
+ flow.close_positions.should be_empty
222
+ end
223
+
224
+ 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)]
228
+ end
229
+
230
+ open = create(:open_buy)
231
+ BitexBot::BuyClosingFlow.close_open_positions
232
+ flow = BitexBot::BuyClosingFlow.last
233
+
234
+ flow.close_positions.should_not be_empty
235
+ flow.close_positions.first do |position|
236
+ position.id.should eq 1234
237
+ position.type.should eq 1
238
+ position.amount.should eq 1000
239
+ position.price.should eq 2000
240
+ end
172
241
  end
173
242
  end
174
243
  end
@@ -1,91 +1,141 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe BitexBot::BuyOpeningFlow do
4
- before(:each) do
5
- Bitex.api_key = "valid_key"
6
- end
7
- let(:store){ BitexBot::Store.create }
4
+ before(:each) { Bitex.api_key = 'valid_key' }
5
+
6
+ let(:store) { BitexBot::Store.create }
8
7
 
9
8
  it { should validate_presence_of :status }
10
9
  it { should validate_presence_of :price }
11
10
  it { should validate_presence_of :value_to_use }
12
11
  it { should validate_presence_of :order_id }
13
- it { should(validate_inclusion_of(:status)
14
- .in_array(BitexBot::BuyOpeningFlow.statuses)) }
12
+ it { should(validate_inclusion_of(:status).in_array(BitexBot::BuyOpeningFlow.statuses)) }
15
13
 
16
- describe "when creating a buying flow" do
17
- it "spends 50 usd" do
14
+ describe 'when creating a buying flow' do
15
+ it 'spends 50 usd' do
18
16
  stub_bitex_orders
19
17
  BitexBot::Settings.stub(time_to_live: 3,
20
18
  buying: double(amount_to_spend_per_order: 50, profit: 0))
21
19
 
22
20
  flow = BitexBot::BuyOpeningFlow.create_for_market(100,
23
- bitstamp_order_book_stub['bids'], bitstamp_transactions_stub, 0.5, 0.25, store)
24
-
21
+ bitstamp_api_wrapper_order_book.bids, bitstamp_api_wrapper_transactions_stub, 0.5, 0.25,
22
+ store)
23
+
24
+ flow.order_id.should == 12345
25
25
  flow.value_to_use.should == 50
26
26
  flow.price.should <= flow.suggested_closing_price
27
- flow.price.round(14).should == "19.85074626865672".to_d
27
+ flow.price.round(14).should == '19.85074626865672'.to_d
28
28
  flow.suggested_closing_price.should == 20
29
- flow.order_id.should == 12345
30
29
  end
31
30
 
32
- it "spends 100 usd" do
31
+ let(:order_id) { 12_345 }
32
+ let(:usd_price) { '14.888_059_701_492'.to_d }
33
+ let(:suggested_closing_price) { 15.to_d }
34
+ let(:amount_to_spend) { 100.to_d }
35
+ let(:btc_balance) { 100_000.to_d }
36
+ let(:maker_fee) { 0.5.to_d }
37
+ let(:taker_fee) { 0.25.to_d }
38
+ let(:order_book) { bitstamp_api_wrapper_order_book.bids }
39
+ let(:transactions) { bitstamp_api_wrapper_transactions_stub }
40
+
41
+ it 'spends 100 usd' do
42
+ BitexBot::Settings.stub(
43
+ time_to_live: 3,
44
+ buying: double(amount_to_spend_per_order: amount_to_spend, profit: 0)
45
+ )
33
46
  stub_bitex_orders
34
- BitexBot::Settings.stub(time_to_live: 3,
35
- buying: double(amount_to_spend_per_order: 100, profit: 0))
36
47
 
37
- flow = BitexBot::BuyOpeningFlow.create_for_market(100000,
38
- bitstamp_order_book_stub['bids'], bitstamp_transactions_stub, 0.5, 0.25, store)
39
- flow.value_to_use.should == 100
40
- flow.price.should <= flow.suggested_closing_price
41
- flow.price.should == "14.88805970149254".to_d
42
- flow.suggested_closing_price.should == 15
43
- flow.order_id.should == 12345
48
+ flow =
49
+ BitexBot::BuyOpeningFlow.create_for_market(
50
+ btc_balance,
51
+ order_book,
52
+ transactions,
53
+ maker_fee,
54
+ taker_fee,
55
+ store
56
+ )
57
+
58
+ flow.order_id.should eq order_id
59
+ flow.value_to_use.should eq amount_to_spend
60
+ flow.price.should.should <= flow.suggested_closing_price
61
+ flow.price.truncate(12).should eq usd_price
62
+ flow.suggested_closing_price.should eq suggested_closing_price
63
+ end
64
+
65
+ let(:other_fx_rate) { 10.to_d }
66
+
67
+ it 'spends 100 usd with other fx_rate' do
68
+ BitexBot::Settings.stub(
69
+ fx_rate: other_fx_rate,
70
+ time_to_live: 3,
71
+ buying: double(amount_to_spend_per_order: amount_to_spend, profit: 0)
72
+ )
73
+ stub_bitex_orders
74
+
75
+ flow =
76
+ BitexBot::BuyOpeningFlow.create_for_market(
77
+ btc_balance,
78
+ order_book,
79
+ transactions,
80
+ maker_fee,
81
+ taker_fee,
82
+ store
83
+ )
84
+
85
+ flow.order_id.should eq order_id
86
+ flow.value_to_use.should eq amount_to_spend
87
+ flow.price.should <= flow.suggested_closing_price * other_fx_rate
88
+ flow.price.truncate(11).should eq usd_price * other_fx_rate
89
+ flow.suggested_closing_price.should eq suggested_closing_price
44
90
  end
45
-
46
- it "lowers the price to pay on bitex to take a profit" do
91
+
92
+ it 'lowers the price to pay on bitex to take a profit' do
47
93
  stub_bitex_orders
48
94
  BitexBot::Settings.stub(time_to_live: 3,
49
- buying: double(amount_to_spend_per_order: 100, profit: 50))
95
+ buying: double(amount_to_spend_per_order: 100, profit: 50.to_d))
50
96
 
51
97
  flow = BitexBot::BuyOpeningFlow.create_for_market(100000,
52
- bitstamp_order_book_stub['bids'], bitstamp_transactions_stub, 0.5, 0.25, store)
98
+ bitstamp_api_wrapper_order_book.bids, bitstamp_api_wrapper_transactions_stub, 0.5, 0.25,
99
+ store)
100
+
101
+ flow.order_id.should == 12345
53
102
  flow.value_to_use.should == 100
54
103
  flow.price.should <= flow.suggested_closing_price
55
- flow.price.round(15).should == "7.44402985074627".to_d
104
+ flow.price.should == '7.44402985074627'.to_d
56
105
  flow.suggested_closing_price.should == 15
57
- flow.order_id.should == 12345
58
106
  end
59
-
60
- it "fails when there is a problem placing the bid on bitex" do
61
- Bitex::Bid.stub(:create!) do
62
- raise StandardError.new("Cannot Create")
63
- end
107
+
108
+ it 'fails when there is a problem placing the bid on bitex' do
109
+ Bitex::Bid.stub(:create!) { raise StandardError.new('Cannot Create') }
64
110
 
65
111
  BitexBot::Settings.stub(time_to_live: 3,
66
112
  buying: double(amount_to_spend_per_order: 100, profit: 0))
67
113
 
68
114
  expect do
69
115
  flow = BitexBot::BuyOpeningFlow.create_for_market(100000,
70
- bitstamp_order_book_stub['bids'], bitstamp_transactions_stub, 0.5, 0.25, store)
116
+ bitstamp_api_wrapper_order_book.bids, bitstamp_api_wrapper_transactions_stub, 0.5, 0.25,
117
+ store)
118
+
71
119
  flow.should be_nil
72
120
  BitexBot::BuyOpeningFlow.count.should == 0
73
121
  end.to raise_exception(BitexBot::CannotCreateFlow)
74
122
  end
75
-
76
- it "fails when there are not enough bitcoin to sell in the other exchange" do
123
+
124
+ it 'fails when there are not enough bitcoin to sell in the other exchange' do
77
125
  stub_bitex_orders
78
126
  BitexBot::Settings.stub(time_to_live: 3,
79
127
  buying: double(amount_to_spend_per_order: 100, profit: 0))
80
128
 
81
129
  expect do
82
130
  flow = BitexBot::BuyOpeningFlow.create_for_market(1,
83
- bitstamp_order_book_stub['bids'], bitstamp_transactions_stub, 0.5, 0.25, store)
131
+ bitstamp_api_wrapper_order_book.bids, bitstamp_api_wrapper_transactions_stub, 0.5, 0.25,
132
+ store)
133
+
84
134
  flow.should be_nil
85
135
  BitexBot::BuyOpeningFlow.count.should == 0
86
136
  end.to raise_exception(BitexBot::CannotCreateFlow)
87
137
  end
88
-
138
+
89
139
  it 'prioritizes profit from store' do
90
140
  store = BitexBot::Store.new(buying_profit: 0.5)
91
141
  stub_bitex_orders
@@ -93,20 +143,23 @@ describe BitexBot::BuyOpeningFlow do
93
143
  buying: double(amount_to_spend_per_order: 50, profit: 0))
94
144
 
95
145
  flow = BitexBot::BuyOpeningFlow.create_for_market(100,
96
- bitstamp_order_book_stub['bids'], bitstamp_transactions_stub, 0.5, 0.25, store)
97
-
98
- flow.price.round(13).should == "19.7514925373134".to_d
146
+ bitstamp_api_wrapper_order_book.bids, bitstamp_api_wrapper_transactions_stub, 0.5, 0.25,
147
+ store)
148
+
149
+ flow.price.round(13).should == '19.7514925373134'.to_d
99
150
  end
100
151
  end
101
-
102
- describe "when fetching open positions" do
103
- let(:flow){ create(:buy_opening_flow) }
152
+
153
+ describe 'when fetching open positions' do
154
+ let(:flow) { create(:buy_opening_flow) }
104
155
 
105
156
  it 'only gets buys' do
106
157
  flow.order_id.should == 12345
107
158
  stub_bitex_transactions
159
+
108
160
  expect do
109
161
  all = BitexBot::BuyOpeningFlow.sync_open_positions
162
+
110
163
  all.size.should == 1
111
164
  all.first.tap do |o|
112
165
  o.price == 300.0
@@ -115,9 +168,9 @@ describe BitexBot::BuyOpeningFlow do
115
168
  o.transaction_id.should == 12345678
116
169
  o.opening_flow.should == flow
117
170
  end
118
- end.to change{ BitexBot::OpenBuy.count }.by(1)
171
+ end.to change { BitexBot::OpenBuy.count }.by(1)
119
172
  end
120
-
173
+
121
174
  it 'does not register the same buy twice' do
122
175
  flow.order_id.should == 12345
123
176
  stub_bitex_transactions
@@ -125,40 +178,57 @@ describe BitexBot::BuyOpeningFlow do
125
178
  BitexBot::OpenBuy.count.should == 1
126
179
  Timecop.travel 1.second.from_now
127
180
  stub_bitex_transactions(build(:bitex_buy, id: 23456))
181
+
128
182
  expect do
129
183
  news = BitexBot::BuyOpeningFlow.sync_open_positions
130
184
  news.first.transaction_id.should == 23456
131
- end.to change{ BitexBot::OpenBuy.count }.by(1)
185
+ end.to change { BitexBot::OpenBuy.count }.by(1)
132
186
  end
133
-
134
- it 'does not register litecoin buys' do
187
+
188
+ it 'does not register buys from another order book' do
135
189
  flow.order_id.should == 12345
136
- Bitex::Trade.stub(all: [build(:bitex_buy, id: 23456, specie: :ltc)])
190
+ Bitex::Trade.stub(all: [build(:bitex_buy, id: 23456, order_book: :btc_ars)])
191
+
137
192
  expect do
138
193
  BitexBot::BuyOpeningFlow.sync_open_positions.should be_empty
139
- end.not_to change{ BitexBot::OpenBuy.count }
194
+ end.not_to change { BitexBot::OpenBuy.count }
140
195
  BitexBot::OpenBuy.count.should == 0
141
196
  end
142
-
197
+
143
198
  it 'does not register buys from unknown bids' do
144
199
  stub_bitex_transactions
200
+
145
201
  expect do
146
202
  BitexBot::BuyOpeningFlow.sync_open_positions.should be_empty
147
- end.not_to change{ BitexBot::OpenBuy.count }
203
+ end.not_to change { BitexBot::OpenBuy.count }
148
204
  end
149
205
  end
150
-
206
+
151
207
  it 'cancels the associated bitex bid' do
152
208
  stub_bitex_orders
153
209
  BitexBot::Settings.stub(time_to_live: 3,
154
210
  buying: double(amount_to_spend_per_order: 50, profit: 0))
155
211
 
156
212
  flow = BitexBot::BuyOpeningFlow.create_for_market(100,
157
- bitstamp_order_book_stub['bids'], bitstamp_transactions_stub, 0.5, 0.25, store)
158
-
213
+ bitstamp_api_wrapper_order_book.bids, bitstamp_api_wrapper_transactions_stub, 0.5, 0.25,
214
+ store)
215
+
159
216
  flow.finalise!
160
217
  flow.should be_settling
161
218
  flow.finalise!
162
219
  flow.should be_finalised
163
220
  end
221
+
222
+ it 'order has expected order book' do
223
+ stub_bitex_orders
224
+ BitexBot::Settings.stub(time_to_live: 3,
225
+ buying: double(amount_to_spend_per_order: 50, profit: 0))
226
+
227
+ flow = subject.class.create_for_market(100,
228
+ bitstamp_api_wrapper_order_book.bids, bitstamp_api_wrapper_transactions_stub, 0.5, 0.25,
229
+ store)
230
+
231
+ order = subject.class.order_class.find(flow.order_id)
232
+ order.order_book.should eq BitexBot::Settings.maker_settings.order_book
233
+ end
164
234
  end
@@ -3,8 +3,8 @@ require 'spec_helper'
3
3
  describe BitexBot::OrderBookSimulator do
4
4
  describe 'when buying on bitex to sell somewhere else' do
5
5
  def simulate(volatility, amount)
6
- BitexBot::OrderBookSimulator.run(volatility, bitstamp_transactions_stub,
7
- bitstamp_order_book_stub['bids'], amount, nil)
6
+ BitexBot::OrderBookSimulator.run(volatility, bitstamp_api_wrapper_transactions_stub,
7
+ bitstamp_api_wrapper_order_book.bids, amount, nil)
8
8
  end
9
9
 
10
10
  it 'gets the safest price' do
@@ -14,15 +14,15 @@ describe BitexBot::OrderBookSimulator do
14
14
  it 'adjusts for medium volatility' do
15
15
  simulate(3, 20).should == 25
16
16
  end
17
-
17
+
18
18
  it 'adjusts for high volatility' do
19
19
  simulate(6, 20).should == 20
20
20
  end
21
-
21
+
22
22
  it 'big orders dig deep' do
23
23
  simulate(0, 180).should == 15
24
24
  end
25
-
25
+
26
26
  it 'big orders with high volatility' do
27
27
  simulate(6, 100).should == 10
28
28
  end
@@ -34,8 +34,8 @@ describe BitexBot::OrderBookSimulator do
34
34
 
35
35
  describe 'when selling on bitex to buy somewhere else' do
36
36
  def simulate(volatility, quantity)
37
- BitexBot::OrderBookSimulator.run(volatility, bitstamp_transactions_stub,
38
- bitstamp_order_book_stub['asks'], nil, quantity)
37
+ BitexBot::OrderBookSimulator.run(volatility, bitstamp_api_wrapper_transactions_stub,
38
+ bitstamp_api_wrapper_order_book.asks, nil, quantity)
39
39
  end
40
40
 
41
41
  it 'gets the safest price' do
@@ -45,15 +45,15 @@ describe BitexBot::OrderBookSimulator do
45
45
  it 'adjusts for medium volatility' do
46
46
  simulate(3, 2).should == 15
47
47
  end
48
-
48
+
49
49
  it 'adjusts for high volatility' do
50
50
  simulate(6, 2).should == 25
51
51
  end
52
-
52
+
53
53
  it 'big orders dig deep' do
54
54
  simulate(0, 8).should == 25
55
55
  end
56
-
56
+
57
57
  it 'big orders with high volatility dig deep' do
58
58
  simulate(6, 6).should == 30
59
59
  end