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,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