bitex_bot 0.0.1

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 (41) hide show
  1. data/.gitignore +18 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +50 -0
  6. data/Rakefile +1 -0
  7. data/bin/bitex_bot +5 -0
  8. data/bitex_bot.gemspec +41 -0
  9. data/lib/bitex_bot/database.rb +93 -0
  10. data/lib/bitex_bot/models/buy_closing_flow.rb +34 -0
  11. data/lib/bitex_bot/models/buy_opening_flow.rb +86 -0
  12. data/lib/bitex_bot/models/close_buy.rb +7 -0
  13. data/lib/bitex_bot/models/close_sell.rb +4 -0
  14. data/lib/bitex_bot/models/closing_flow.rb +80 -0
  15. data/lib/bitex_bot/models/open_buy.rb +11 -0
  16. data/lib/bitex_bot/models/open_sell.rb +11 -0
  17. data/lib/bitex_bot/models/opening_flow.rb +114 -0
  18. data/lib/bitex_bot/models/order_book_simulator.rb +75 -0
  19. data/lib/bitex_bot/models/sell_closing_flow.rb +36 -0
  20. data/lib/bitex_bot/models/sell_opening_flow.rb +82 -0
  21. data/lib/bitex_bot/robot.rb +173 -0
  22. data/lib/bitex_bot/settings.rb +13 -0
  23. data/lib/bitex_bot/version.rb +3 -0
  24. data/lib/bitex_bot.rb +18 -0
  25. data/settings.yml.sample +84 -0
  26. data/spec/factories/bitex_buy.rb +12 -0
  27. data/spec/factories/bitex_sell.rb +12 -0
  28. data/spec/factories/buy_opening_flow.rb +17 -0
  29. data/spec/factories/open_buy.rb +17 -0
  30. data/spec/factories/open_sell.rb +17 -0
  31. data/spec/factories/sell_opening_flow.rb +17 -0
  32. data/spec/models/buy_closing_flow_spec.rb +150 -0
  33. data/spec/models/buy_opening_flow_spec.rb +154 -0
  34. data/spec/models/order_book_simulator_spec.rb +57 -0
  35. data/spec/models/robot_spec.rb +103 -0
  36. data/spec/models/sell_closing_flow_spec.rb +160 -0
  37. data/spec/models/sell_opening_flow_spec.rb +156 -0
  38. data/spec/spec_helper.rb +43 -0
  39. data/spec/support/bitex_stubs.rb +66 -0
  40. data/spec/support/bitstamp_stubs.rb +110 -0
  41. metadata +363 -0
@@ -0,0 +1,66 @@
1
+ module BitexStubs
2
+ def ensure_bitex_orders_stub
3
+ begin
4
+ Bitex::Order.active
5
+ rescue Exception => e
6
+ Bitex::Order.stub(active: [])
7
+ end
8
+ end
9
+
10
+ def stub_bitex_bid_create
11
+ ensure_bitex_orders_stub
12
+ Bitex::Bid.stub(:create!) do |specie, to_spend, price|
13
+ bid = Bitex::Bid.new
14
+ bid.id = 12345
15
+ bid.created_at = Time.now
16
+ bid.price = price
17
+ bid.amount = to_spend
18
+ bid.remaining_amount = to_spend
19
+ bid.status = :executing
20
+ bid.specie = specie
21
+ bid.stub(cancel!: true) do
22
+ bid.status = :cancelling
23
+ bid
24
+ end
25
+ Bitex::Order.stub(active: Bitex::Order.active + [bid])
26
+ bid
27
+ end
28
+ end
29
+
30
+ def stub_bitex_ask_create
31
+ ensure_bitex_orders_stub
32
+ Bitex::Ask.stub(:create!) do |specie, to_sell, price|
33
+ ask = Bitex::Ask.new
34
+ ask.id = 12345
35
+ ask.created_at = Time.now
36
+ ask.price = price
37
+ ask.quantity = to_sell
38
+ ask.remaining_quantity = to_sell
39
+ ask.status = :executing
40
+ ask.specie = specie
41
+ ask.stub(cancel!: true) do
42
+ ask.status = :cancelling
43
+ ask
44
+ end
45
+ Bitex::Order.stub(active: Bitex::Order.active + [ask])
46
+ ask
47
+ end
48
+ end
49
+
50
+
51
+ def stub_bitex_transactions(*extra_transactions)
52
+ Bitex::Transaction.stub(all: extra_transactions + [
53
+ build(:bitex_buy),
54
+ build(:bitex_sell),
55
+ Bitex::SpecieWithdrawal
56
+ .from_json([6,Time.now.to_i,946685400,1,100.00000000,1,0]),
57
+ Bitex::UsdWithdrawal
58
+ .from_json([8,Time.now.to_i,946685400,100.00000000,1,0]),
59
+ Bitex::UsdDeposit
60
+ .from_json([7,Time.now.to_i,946685400,1000.00000000,1,1,0]),
61
+ Bitex::SpecieDeposit
62
+ .from_json([5,Time.now.to_i,946685400,1,100.00000000]),
63
+ ])
64
+ end
65
+ end
66
+ RSpec.configuration.include BitexStubs
@@ -0,0 +1,110 @@
1
+ module BitstampStubs
2
+ def stub_bitstamp_balance(usd = nil, coin = nil, fee = nil)
3
+ Bitstamp.stub(balance: bitstamp_balance_stub(usd, coin, fee))
4
+ end
5
+
6
+ def bitstamp_balance_stub(usd = nil, coin = nil, fee = nil)
7
+ {"btc_balance"=> coin || "10.0", "btc_reserved"=> "0", "btc_available"=> coin || "10.0",
8
+ "usd_balance"=> usd || "100.0", "usd_reserved"=>"0", "usd_available"=> usd || "100.0",
9
+ "fee"=> fee || "0.5000"}
10
+ end
11
+
12
+ def stub_bitstamp_order_book
13
+ Bitstamp.stub(order_book: bitstamp_order_book_stub)
14
+ end
15
+
16
+ def bitstamp_order_book_stub
17
+ { 'timestamp' => DateTime.now.to_i.to_s,
18
+ 'bids' =>
19
+ [['30', '3'], ['25', '2'], ['20', '1.5'], ['15', '4'], ['10', '5']],
20
+ 'asks' =>
21
+ [['10', '2'], ['15', '3'], ['20', '1.5'], ['25', '3'], ['30', '3']]
22
+ }
23
+ end
24
+
25
+ def stub_bitstamp_transactions(volume = 0.2)
26
+ Bitstamp.stub(transactions: bitstamp_transactions_stub(volume))
27
+ end
28
+
29
+ def bitstamp_transactions_stub(price = 30, amount = 1)
30
+ transactions = 5.times.collect do |i|
31
+ double(
32
+ tid:i,
33
+ date: (i+1).seconds.ago.to_i.to_s,
34
+ price: price.to_s,
35
+ amount: amount.to_s
36
+ )
37
+ end
38
+ end
39
+
40
+ def stub_bitstamp_user_transactions
41
+ Bitstamp.stub(user_transactions: double(all: []))
42
+ end
43
+
44
+ # Takes all active orders and mockes them as executed in a single transaction.
45
+ # If a ratio is provided then each order is only partially executed and added
46
+ # as a transaction and the order itself is kept in the order list.
47
+ def stub_bitstamp_orders_into_transactions(options={})
48
+ ratio = options[:ratio] || 1
49
+ orders = Bitstamp.orders.all
50
+ transactions = orders.collect do |o|
51
+ usd = o.amount * o.price
52
+ usd, btc = o.type == 0 ? [-usd, o.amount] : [usd, -o.amount]
53
+ double(usd: (usd * ratio).to_s, btc: (btc * ratio).to_s,
54
+ btc_usd: o.price.to_s, order_id: o.id, fee: "0.5", type: 2,
55
+ datetime: DateTime.now.to_s)
56
+ end
57
+ Bitstamp.stub(user_transactions: double(all: transactions))
58
+
59
+ if ratio == 1
60
+ stub_bitstamp_sell
61
+ stub_bitstamp_buy
62
+ end
63
+ end
64
+
65
+ def ensure_bitstamp_orders_stub
66
+ begin
67
+ Bitstamp.orders
68
+ rescue Exception => e
69
+ Bitstamp.stub(orders: double)
70
+ end
71
+ end
72
+
73
+ def stub_bitstamp_sell(remote_id=nil, orders = [])
74
+ ensure_bitstamp_orders_stub
75
+ Bitstamp.orders.stub(all: orders)
76
+ Bitstamp.orders.stub(:sell) do |args|
77
+ remote_id = Bitstamp.orders.all.size + 1 if remote_id.nil?
78
+ ask = double(amount: args[:amount], price: args[:price],
79
+ type: 1, id: remote_id, datetime: DateTime.now.to_s)
80
+ ask.stub(:cancel!) do
81
+ orders = Bitstamp.orders.all.reject do |x|
82
+ x.id.to_s == ask.id.to_s && x.type == 1
83
+ end
84
+ stub_bitstamp_sell(remote_id + 1, orders)
85
+ end
86
+ stub_bitstamp_sell(remote_id + 1, Bitstamp.orders.all + [ask])
87
+ ask
88
+ end
89
+ end
90
+
91
+ def stub_bitstamp_buy(remote_id=nil, orders = [])
92
+ ensure_bitstamp_orders_stub
93
+ Bitstamp.orders.stub(all: orders)
94
+ Bitstamp.orders.stub(:buy) do |args|
95
+ remote_id = Bitstamp.orders.all.size + 1 if remote_id.nil?
96
+ bid = double(amount: args[:amount], price: args[:price],
97
+ type: 0, id: remote_id, datetime: DateTime.now.to_s)
98
+ bid.stub(:cancel!) do
99
+ orders = Bitstamp.orders.all.reject do |x|
100
+ x.id.to_s == bid.id.to_s && x.type == 0
101
+ end
102
+ stub_bitstamp_buy(remote_id + 1, orders)
103
+ end
104
+ stub_bitstamp_buy(remote_id + 1, Bitstamp.orders.all + [bid])
105
+ bid
106
+ end
107
+ end
108
+ end
109
+
110
+ RSpec.configuration.include BitstampStubs
metadata ADDED
@@ -0,0 +1,363 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bitex_bot
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Nubis
9
+ - Eromirou
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2014-07-18 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: settingslogic
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: '0'
31
+ - !ruby/object:Gem::Dependency
32
+ name: activerecord
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ! '>='
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ type: :runtime
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: activesupport
49
+ requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ - !ruby/object:Gem::Dependency
64
+ name: sqlite3
65
+ requirement: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ! '>='
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ type: :runtime
72
+ prerelease: false
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ - !ruby/object:Gem::Dependency
80
+ name: bitstamp
81
+ requirement: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ type: :runtime
88
+ prerelease: false
89
+ version_requirements: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ - !ruby/object:Gem::Dependency
96
+ name: bitex
97
+ requirement: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ! '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ type: :runtime
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: debugger
113
+ requirement: !ruby/object:Gem::Requirement
114
+ none: false
115
+ requirements:
116
+ - - ! '>='
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ type: :runtime
120
+ prerelease: false
121
+ version_requirements: !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ! '>='
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ - !ruby/object:Gem::Dependency
128
+ name: mail
129
+ requirement: !ruby/object:Gem::Requirement
130
+ none: false
131
+ requirements:
132
+ - - ! '>='
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ type: :runtime
136
+ prerelease: false
137
+ version_requirements: !ruby/object:Gem::Requirement
138
+ none: false
139
+ requirements:
140
+ - - ! '>='
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ - !ruby/object:Gem::Dependency
144
+ name: bundler
145
+ requirement: !ruby/object:Gem::Requirement
146
+ none: false
147
+ requirements:
148
+ - - ~>
149
+ - !ruby/object:Gem::Version
150
+ version: '1.3'
151
+ type: :development
152
+ prerelease: false
153
+ version_requirements: !ruby/object:Gem::Requirement
154
+ none: false
155
+ requirements:
156
+ - - ~>
157
+ - !ruby/object:Gem::Version
158
+ version: '1.3'
159
+ - !ruby/object:Gem::Dependency
160
+ name: rake
161
+ requirement: !ruby/object:Gem::Requirement
162
+ none: false
163
+ requirements:
164
+ - - ! '>='
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ type: :development
168
+ prerelease: false
169
+ version_requirements: !ruby/object:Gem::Requirement
170
+ none: false
171
+ requirements:
172
+ - - ! '>='
173
+ - !ruby/object:Gem::Version
174
+ version: '0'
175
+ - !ruby/object:Gem::Dependency
176
+ name: rspec
177
+ requirement: !ruby/object:Gem::Requirement
178
+ none: false
179
+ requirements:
180
+ - - ! '>='
181
+ - !ruby/object:Gem::Version
182
+ version: '0'
183
+ type: :development
184
+ prerelease: false
185
+ version_requirements: !ruby/object:Gem::Requirement
186
+ none: false
187
+ requirements:
188
+ - - ! '>='
189
+ - !ruby/object:Gem::Version
190
+ version: '0'
191
+ - !ruby/object:Gem::Dependency
192
+ name: rspec-mocks
193
+ requirement: !ruby/object:Gem::Requirement
194
+ none: false
195
+ requirements:
196
+ - - ! '>='
197
+ - !ruby/object:Gem::Version
198
+ version: '0'
199
+ type: :development
200
+ prerelease: false
201
+ version_requirements: !ruby/object:Gem::Requirement
202
+ none: false
203
+ requirements:
204
+ - - ! '>='
205
+ - !ruby/object:Gem::Version
206
+ version: '0'
207
+ - !ruby/object:Gem::Dependency
208
+ name: database_cleaner
209
+ requirement: !ruby/object:Gem::Requirement
210
+ none: false
211
+ requirements:
212
+ - - ! '>='
213
+ - !ruby/object:Gem::Version
214
+ version: '0'
215
+ type: :development
216
+ prerelease: false
217
+ version_requirements: !ruby/object:Gem::Requirement
218
+ none: false
219
+ requirements:
220
+ - - ! '>='
221
+ - !ruby/object:Gem::Version
222
+ version: '0'
223
+ - !ruby/object:Gem::Dependency
224
+ name: factory_girl
225
+ requirement: !ruby/object:Gem::Requirement
226
+ none: false
227
+ requirements:
228
+ - - ! '>='
229
+ - !ruby/object:Gem::Version
230
+ version: '0'
231
+ type: :development
232
+ prerelease: false
233
+ version_requirements: !ruby/object:Gem::Requirement
234
+ none: false
235
+ requirements:
236
+ - - ! '>='
237
+ - !ruby/object:Gem::Version
238
+ version: '0'
239
+ - !ruby/object:Gem::Dependency
240
+ name: timecop
241
+ requirement: !ruby/object:Gem::Requirement
242
+ none: false
243
+ requirements:
244
+ - - ! '>='
245
+ - !ruby/object:Gem::Version
246
+ version: '0'
247
+ type: :development
248
+ prerelease: false
249
+ version_requirements: !ruby/object:Gem::Requirement
250
+ none: false
251
+ requirements:
252
+ - - ! '>='
253
+ - !ruby/object:Gem::Version
254
+ version: '0'
255
+ - !ruby/object:Gem::Dependency
256
+ name: shoulda-matchers
257
+ requirement: !ruby/object:Gem::Requirement
258
+ none: false
259
+ requirements:
260
+ - - ! '>='
261
+ - !ruby/object:Gem::Version
262
+ version: '0'
263
+ type: :development
264
+ prerelease: false
265
+ version_requirements: !ruby/object:Gem::Requirement
266
+ none: false
267
+ requirements:
268
+ - - ! '>='
269
+ - !ruby/object:Gem::Version
270
+ version: '0'
271
+ description: ! "Both a trading robot and a library to build trading\n robots.
272
+ The bitex-bot lets you buy cheap on bitex and\n sell on another
273
+ exchange and vice versa."
274
+ email:
275
+ - nb@bitex.la
276
+ - tr@bitex.la
277
+ executables:
278
+ - bitex_bot
279
+ extensions: []
280
+ extra_rdoc_files: []
281
+ files:
282
+ - .gitignore
283
+ - .rspec
284
+ - Gemfile
285
+ - LICENSE.txt
286
+ - README.md
287
+ - Rakefile
288
+ - bin/bitex_bot
289
+ - bitex_bot.gemspec
290
+ - lib/bitex_bot.rb
291
+ - lib/bitex_bot/database.rb
292
+ - lib/bitex_bot/models/buy_closing_flow.rb
293
+ - lib/bitex_bot/models/buy_opening_flow.rb
294
+ - lib/bitex_bot/models/close_buy.rb
295
+ - lib/bitex_bot/models/close_sell.rb
296
+ - lib/bitex_bot/models/closing_flow.rb
297
+ - lib/bitex_bot/models/open_buy.rb
298
+ - lib/bitex_bot/models/open_sell.rb
299
+ - lib/bitex_bot/models/opening_flow.rb
300
+ - lib/bitex_bot/models/order_book_simulator.rb
301
+ - lib/bitex_bot/models/sell_closing_flow.rb
302
+ - lib/bitex_bot/models/sell_opening_flow.rb
303
+ - lib/bitex_bot/robot.rb
304
+ - lib/bitex_bot/settings.rb
305
+ - lib/bitex_bot/version.rb
306
+ - settings.yml.sample
307
+ - spec/factories/bitex_buy.rb
308
+ - spec/factories/bitex_sell.rb
309
+ - spec/factories/buy_opening_flow.rb
310
+ - spec/factories/open_buy.rb
311
+ - spec/factories/open_sell.rb
312
+ - spec/factories/sell_opening_flow.rb
313
+ - spec/models/buy_closing_flow_spec.rb
314
+ - spec/models/buy_opening_flow_spec.rb
315
+ - spec/models/order_book_simulator_spec.rb
316
+ - spec/models/robot_spec.rb
317
+ - spec/models/sell_closing_flow_spec.rb
318
+ - spec/models/sell_opening_flow_spec.rb
319
+ - spec/spec_helper.rb
320
+ - spec/support/bitex_stubs.rb
321
+ - spec/support/bitstamp_stubs.rb
322
+ homepage: ''
323
+ licenses:
324
+ - MIT
325
+ post_install_message:
326
+ rdoc_options: []
327
+ require_paths:
328
+ - lib
329
+ required_ruby_version: !ruby/object:Gem::Requirement
330
+ none: false
331
+ requirements:
332
+ - - ! '>='
333
+ - !ruby/object:Gem::Version
334
+ version: '0'
335
+ required_rubygems_version: !ruby/object:Gem::Requirement
336
+ none: false
337
+ requirements:
338
+ - - ! '>='
339
+ - !ruby/object:Gem::Version
340
+ version: '0'
341
+ requirements: []
342
+ rubyforge_project:
343
+ rubygems_version: 1.8.23
344
+ signing_key:
345
+ specification_version: 3
346
+ summary: A trading robot to do arbitrage between bitex.la and other exchanges!
347
+ test_files:
348
+ - spec/factories/bitex_buy.rb
349
+ - spec/factories/bitex_sell.rb
350
+ - spec/factories/buy_opening_flow.rb
351
+ - spec/factories/open_buy.rb
352
+ - spec/factories/open_sell.rb
353
+ - spec/factories/sell_opening_flow.rb
354
+ - spec/models/buy_closing_flow_spec.rb
355
+ - spec/models/buy_opening_flow_spec.rb
356
+ - spec/models/order_book_simulator_spec.rb
357
+ - spec/models/robot_spec.rb
358
+ - spec/models/sell_closing_flow_spec.rb
359
+ - spec/models/sell_opening_flow_spec.rb
360
+ - spec/spec_helper.rb
361
+ - spec/support/bitex_stubs.rb
362
+ - spec/support/bitstamp_stubs.rb
363
+ has_rdoc: