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.
- checksums.yaml +4 -4
- data/.circleci/config.yml +63 -0
- data/.rubocop.yml +33 -0
- data/Gemfile +1 -1
- data/Rakefile +1 -1
- data/bin/bitex_bot +1 -1
- data/bitex_bot.gemspec +34 -34
- data/lib/bitex_bot/database.rb +67 -67
- data/lib/bitex_bot/models/api_wrappers/api_wrapper.rb +142 -0
- data/lib/bitex_bot/models/api_wrappers/bitstamp/bitstamp_api_wrapper.rb +137 -0
- data/lib/bitex_bot/models/api_wrappers/itbit/itbit_api_wrapper.rb +116 -0
- data/lib/bitex_bot/models/api_wrappers/kraken/kraken_api_wrapper.rb +111 -0
- data/lib/bitex_bot/models/api_wrappers/kraken/kraken_order.rb +117 -0
- data/lib/bitex_bot/models/buy_closing_flow.rb +23 -16
- data/lib/bitex_bot/models/buy_opening_flow.rb +48 -54
- data/lib/bitex_bot/models/close_buy.rb +2 -2
- data/lib/bitex_bot/models/closing_flow.rb +98 -79
- data/lib/bitex_bot/models/open_buy.rb +11 -10
- data/lib/bitex_bot/models/open_sell.rb +11 -10
- data/lib/bitex_bot/models/opening_flow.rb +157 -99
- data/lib/bitex_bot/models/order_book_simulator.rb +62 -67
- data/lib/bitex_bot/models/sell_closing_flow.rb +25 -20
- data/lib/bitex_bot/models/sell_opening_flow.rb +47 -54
- data/lib/bitex_bot/models/store.rb +3 -1
- data/lib/bitex_bot/robot.rb +203 -176
- data/lib/bitex_bot/settings.rb +71 -12
- data/lib/bitex_bot/version.rb +1 -1
- data/lib/bitex_bot.rb +40 -16
- data/settings.rb.sample +43 -66
- data/spec/bitex_bot/settings_spec.rb +87 -15
- data/spec/factories/bitex_buy.rb +3 -3
- data/spec/factories/bitex_sell.rb +3 -3
- data/spec/factories/buy_opening_flow.rb +1 -1
- data/spec/factories/open_buy.rb +12 -10
- data/spec/factories/open_sell.rb +12 -10
- data/spec/factories/sell_opening_flow.rb +1 -1
- data/spec/models/api_wrappers/bitstamp_api_wrapper_spec.rb +200 -0
- data/spec/models/api_wrappers/itbit_api_wrapper_spec.rb +176 -0
- data/spec/models/api_wrappers/kraken_api_wrapper_spec.rb +209 -0
- data/spec/models/bitex_api_spec.rb +1 -1
- data/spec/models/buy_closing_flow_spec.rb +140 -71
- data/spec/models/buy_opening_flow_spec.rb +126 -56
- data/spec/models/order_book_simulator_spec.rb +10 -10
- data/spec/models/robot_spec.rb +61 -47
- data/spec/models/sell_closing_flow_spec.rb +130 -62
- data/spec/models/sell_opening_flow_spec.rb +129 -60
- data/spec/spec_helper.rb +19 -16
- data/spec/support/bitex_stubs.rb +13 -14
- data/spec/support/bitstamp/bitstamp_api_wrapper_stubs.rb +35 -0
- data/spec/support/bitstamp/bitstamp_stubs.rb +91 -0
- metadata +60 -42
- data/lib/bitex_bot/models/bitfinex_api_wrapper.rb +0 -118
- data/lib/bitex_bot/models/bitstamp_api_wrapper.rb +0 -82
- data/lib/bitex_bot/models/itbit_api_wrapper.rb +0 -68
- data/lib/bitex_bot/models/kraken_api_wrapper.rb +0 -188
- data/spec/models/bitfinex_api_wrapper_spec.rb +0 -17
- data/spec/models/bitstamp_api_wrapper_spec.rb +0 -15
- data/spec/models/itbit_api_wrapper_spec.rb +0 -15
- data/spec/support/bitstamp_stubs.rb +0 -110
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bitex_bot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nubis
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2018-06-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -26,7 +26,21 @@ dependencies:
|
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: '4.2'
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
|
-
name:
|
29
|
+
name: hashie
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 3.5.4
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: 3.5.4
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: mail
|
30
44
|
requirement: !ruby/object:Gem::Requirement
|
31
45
|
requirements:
|
32
46
|
- - ">="
|
@@ -40,7 +54,7 @@ dependencies:
|
|
40
54
|
- !ruby/object:Gem::Version
|
41
55
|
version: '0'
|
42
56
|
- !ruby/object:Gem::Dependency
|
43
|
-
name:
|
57
|
+
name: sqlite3
|
44
58
|
requirement: !ruby/object:Gem::Requirement
|
45
59
|
requirements:
|
46
60
|
- - ">="
|
@@ -59,30 +73,30 @@ dependencies:
|
|
59
73
|
requirements:
|
60
74
|
- - '='
|
61
75
|
- !ruby/object:Gem::Version
|
62
|
-
version: '0.
|
76
|
+
version: '0.5'
|
63
77
|
type: :runtime
|
64
78
|
prerelease: false
|
65
79
|
version_requirements: !ruby/object:Gem::Requirement
|
66
80
|
requirements:
|
67
81
|
- - '='
|
68
82
|
- !ruby/object:Gem::Version
|
69
|
-
version: '0.
|
83
|
+
version: '0.5'
|
70
84
|
- !ruby/object:Gem::Dependency
|
71
|
-
name:
|
85
|
+
name: bitstamp
|
72
86
|
requirement: !ruby/object:Gem::Requirement
|
73
87
|
requirements:
|
74
|
-
- -
|
88
|
+
- - ">="
|
75
89
|
- !ruby/object:Gem::Version
|
76
|
-
version: 0
|
90
|
+
version: '0'
|
77
91
|
type: :runtime
|
78
92
|
prerelease: false
|
79
93
|
version_requirements: !ruby/object:Gem::Requirement
|
80
94
|
requirements:
|
81
|
-
- -
|
95
|
+
- - ">="
|
82
96
|
- !ruby/object:Gem::Version
|
83
|
-
version: 0
|
97
|
+
version: '0'
|
84
98
|
- !ruby/object:Gem::Dependency
|
85
|
-
name:
|
99
|
+
name: itbit
|
86
100
|
requirement: !ruby/object:Gem::Requirement
|
87
101
|
requirements:
|
88
102
|
- - '='
|
@@ -110,13 +124,13 @@ dependencies:
|
|
110
124
|
- !ruby/object:Gem::Version
|
111
125
|
version: 1.2.1
|
112
126
|
- !ruby/object:Gem::Dependency
|
113
|
-
name:
|
127
|
+
name: bundler
|
114
128
|
requirement: !ruby/object:Gem::Requirement
|
115
129
|
requirements:
|
116
130
|
- - ">="
|
117
131
|
- !ruby/object:Gem::Version
|
118
132
|
version: '0'
|
119
|
-
type: :
|
133
|
+
type: :development
|
120
134
|
prerelease: false
|
121
135
|
version_requirements: !ruby/object:Gem::Requirement
|
122
136
|
requirements:
|
@@ -124,21 +138,21 @@ dependencies:
|
|
124
138
|
- !ruby/object:Gem::Version
|
125
139
|
version: '0'
|
126
140
|
- !ruby/object:Gem::Dependency
|
127
|
-
name:
|
141
|
+
name: rake
|
128
142
|
requirement: !ruby/object:Gem::Requirement
|
129
143
|
requirements:
|
130
|
-
- - "
|
144
|
+
- - ">="
|
131
145
|
- !ruby/object:Gem::Version
|
132
|
-
version:
|
133
|
-
type: :
|
146
|
+
version: '0'
|
147
|
+
type: :development
|
134
148
|
prerelease: false
|
135
149
|
version_requirements: !ruby/object:Gem::Requirement
|
136
150
|
requirements:
|
137
|
-
- - "
|
151
|
+
- - ">="
|
138
152
|
- !ruby/object:Gem::Version
|
139
|
-
version:
|
153
|
+
version: '0'
|
140
154
|
- !ruby/object:Gem::Dependency
|
141
|
-
name:
|
155
|
+
name: byebug
|
142
156
|
requirement: !ruby/object:Gem::Requirement
|
143
157
|
requirements:
|
144
158
|
- - ">="
|
@@ -152,7 +166,7 @@ dependencies:
|
|
152
166
|
- !ruby/object:Gem::Version
|
153
167
|
version: '0'
|
154
168
|
- !ruby/object:Gem::Dependency
|
155
|
-
name:
|
169
|
+
name: database_cleaner
|
156
170
|
requirement: !ruby/object:Gem::Requirement
|
157
171
|
requirements:
|
158
172
|
- - ">="
|
@@ -166,7 +180,7 @@ dependencies:
|
|
166
180
|
- !ruby/object:Gem::Version
|
167
181
|
version: '0'
|
168
182
|
- !ruby/object:Gem::Dependency
|
169
|
-
name:
|
183
|
+
name: factory_bot
|
170
184
|
requirement: !ruby/object:Gem::Requirement
|
171
185
|
requirements:
|
172
186
|
- - ">="
|
@@ -208,7 +222,7 @@ dependencies:
|
|
208
222
|
- !ruby/object:Gem::Version
|
209
223
|
version: '0'
|
210
224
|
- !ruby/object:Gem::Dependency
|
211
|
-
name:
|
225
|
+
name: rspec_junit_formatter
|
212
226
|
requirement: !ruby/object:Gem::Requirement
|
213
227
|
requirements:
|
214
228
|
- - ">="
|
@@ -222,7 +236,7 @@ dependencies:
|
|
222
236
|
- !ruby/object:Gem::Version
|
223
237
|
version: '0'
|
224
238
|
- !ruby/object:Gem::Dependency
|
225
|
-
name:
|
239
|
+
name: rubocop
|
226
240
|
requirement: !ruby/object:Gem::Requirement
|
227
241
|
requirements:
|
228
242
|
- - ">="
|
@@ -236,7 +250,7 @@ dependencies:
|
|
236
250
|
- !ruby/object:Gem::Version
|
237
251
|
version: '0'
|
238
252
|
- !ruby/object:Gem::Dependency
|
239
|
-
name:
|
253
|
+
name: shoulda-matchers
|
240
254
|
requirement: !ruby/object:Gem::Requirement
|
241
255
|
requirements:
|
242
256
|
- - ">="
|
@@ -250,7 +264,7 @@ dependencies:
|
|
250
264
|
- !ruby/object:Gem::Version
|
251
265
|
version: '0'
|
252
266
|
- !ruby/object:Gem::Dependency
|
253
|
-
name:
|
267
|
+
name: timecop
|
254
268
|
requirement: !ruby/object:Gem::Requirement
|
255
269
|
requirements:
|
256
270
|
- - ">="
|
@@ -278,9 +292,8 @@ dependencies:
|
|
278
292
|
- !ruby/object:Gem::Version
|
279
293
|
version: '0'
|
280
294
|
description: |-
|
281
|
-
Both a trading robot and a library to build trading
|
282
|
-
|
283
|
-
sell on another exchange and vice versa.
|
295
|
+
Both a trading robot and a library to build trading robots. The bitex-bot lets you buy cheap on bitex
|
296
|
+
and sell on another exchange and vice versa.
|
284
297
|
email:
|
285
298
|
- nb@bitex.la
|
286
299
|
- tr@bitex.la
|
@@ -289,8 +302,10 @@ executables:
|
|
289
302
|
extensions: []
|
290
303
|
extra_rdoc_files: []
|
291
304
|
files:
|
305
|
+
- ".circleci/config.yml"
|
292
306
|
- ".gitignore"
|
293
307
|
- ".rspec"
|
308
|
+
- ".rubocop.yml"
|
294
309
|
- Gemfile
|
295
310
|
- LICENSE.txt
|
296
311
|
- README.md
|
@@ -299,15 +314,16 @@ files:
|
|
299
314
|
- bitex_bot.gemspec
|
300
315
|
- lib/bitex_bot.rb
|
301
316
|
- lib/bitex_bot/database.rb
|
302
|
-
- lib/bitex_bot/models/
|
303
|
-
- lib/bitex_bot/models/bitstamp_api_wrapper.rb
|
317
|
+
- lib/bitex_bot/models/api_wrappers/api_wrapper.rb
|
318
|
+
- lib/bitex_bot/models/api_wrappers/bitstamp/bitstamp_api_wrapper.rb
|
319
|
+
- lib/bitex_bot/models/api_wrappers/itbit/itbit_api_wrapper.rb
|
320
|
+
- lib/bitex_bot/models/api_wrappers/kraken/kraken_api_wrapper.rb
|
321
|
+
- lib/bitex_bot/models/api_wrappers/kraken/kraken_order.rb
|
304
322
|
- lib/bitex_bot/models/buy_closing_flow.rb
|
305
323
|
- lib/bitex_bot/models/buy_opening_flow.rb
|
306
324
|
- lib/bitex_bot/models/close_buy.rb
|
307
325
|
- lib/bitex_bot/models/close_sell.rb
|
308
326
|
- lib/bitex_bot/models/closing_flow.rb
|
309
|
-
- lib/bitex_bot/models/itbit_api_wrapper.rb
|
310
|
-
- lib/bitex_bot/models/kraken_api_wrapper.rb
|
311
327
|
- lib/bitex_bot/models/open_buy.rb
|
312
328
|
- lib/bitex_bot/models/open_sell.rb
|
313
329
|
- lib/bitex_bot/models/opening_flow.rb
|
@@ -326,19 +342,20 @@ files:
|
|
326
342
|
- spec/factories/open_buy.rb
|
327
343
|
- spec/factories/open_sell.rb
|
328
344
|
- spec/factories/sell_opening_flow.rb
|
345
|
+
- spec/models/api_wrappers/bitstamp_api_wrapper_spec.rb
|
346
|
+
- spec/models/api_wrappers/itbit_api_wrapper_spec.rb
|
347
|
+
- spec/models/api_wrappers/kraken_api_wrapper_spec.rb
|
329
348
|
- spec/models/bitex_api_spec.rb
|
330
|
-
- spec/models/bitfinex_api_wrapper_spec.rb
|
331
|
-
- spec/models/bitstamp_api_wrapper_spec.rb
|
332
349
|
- spec/models/buy_closing_flow_spec.rb
|
333
350
|
- spec/models/buy_opening_flow_spec.rb
|
334
|
-
- spec/models/itbit_api_wrapper_spec.rb
|
335
351
|
- spec/models/order_book_simulator_spec.rb
|
336
352
|
- spec/models/robot_spec.rb
|
337
353
|
- spec/models/sell_closing_flow_spec.rb
|
338
354
|
- spec/models/sell_opening_flow_spec.rb
|
339
355
|
- spec/spec_helper.rb
|
340
356
|
- spec/support/bitex_stubs.rb
|
341
|
-
- spec/support/
|
357
|
+
- spec/support/bitstamp/bitstamp_api_wrapper_stubs.rb
|
358
|
+
- spec/support/bitstamp/bitstamp_stubs.rb
|
342
359
|
homepage: ''
|
343
360
|
licenses:
|
344
361
|
- MIT
|
@@ -371,16 +388,17 @@ test_files:
|
|
371
388
|
- spec/factories/open_buy.rb
|
372
389
|
- spec/factories/open_sell.rb
|
373
390
|
- spec/factories/sell_opening_flow.rb
|
391
|
+
- spec/models/api_wrappers/bitstamp_api_wrapper_spec.rb
|
392
|
+
- spec/models/api_wrappers/itbit_api_wrapper_spec.rb
|
393
|
+
- spec/models/api_wrappers/kraken_api_wrapper_spec.rb
|
374
394
|
- spec/models/bitex_api_spec.rb
|
375
|
-
- spec/models/bitfinex_api_wrapper_spec.rb
|
376
|
-
- spec/models/bitstamp_api_wrapper_spec.rb
|
377
395
|
- spec/models/buy_closing_flow_spec.rb
|
378
396
|
- spec/models/buy_opening_flow_spec.rb
|
379
|
-
- spec/models/itbit_api_wrapper_spec.rb
|
380
397
|
- spec/models/order_book_simulator_spec.rb
|
381
398
|
- spec/models/robot_spec.rb
|
382
399
|
- spec/models/sell_closing_flow_spec.rb
|
383
400
|
- spec/models/sell_opening_flow_spec.rb
|
384
401
|
- spec/spec_helper.rb
|
385
402
|
- spec/support/bitex_stubs.rb
|
386
|
-
- spec/support/
|
403
|
+
- spec/support/bitstamp/bitstamp_api_wrapper_stubs.rb
|
404
|
+
- spec/support/bitstamp/bitstamp_stubs.rb
|
@@ -1,118 +0,0 @@
|
|
1
|
-
require "bigdecimal"
|
2
|
-
require "bigdecimal/util"
|
3
|
-
|
4
|
-
module Bitfinex
|
5
|
-
module WithUserAgent
|
6
|
-
def new_rest_connection
|
7
|
-
super.tap do |conn|
|
8
|
-
conn.headers['User-Agent'] = BitexBot.user_agent
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
class Client
|
14
|
-
prepend WithUserAgent
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
class BitfinexApiWrapper
|
19
|
-
def self.setup(settings)
|
20
|
-
Bitfinex::Client.configure do |conf|
|
21
|
-
conf.api_key = settings.bitfinex.api_key
|
22
|
-
conf.secret = settings.bitfinex.api_secret
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def self.with_retry(action, &block)
|
27
|
-
begin
|
28
|
-
block.call
|
29
|
-
rescue StandardError, Bitfinex::ClientError => e
|
30
|
-
raise e if BitexBot::Robot.test_mode
|
31
|
-
BitexBot::Robot.logger.info("Bitfinex #{action} failed. Retrying in 5 seconds.")
|
32
|
-
sleep 5
|
33
|
-
retry
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def self.transactions
|
38
|
-
with_retry 'transactions' do
|
39
|
-
Bitfinex::Client.new.trades.collect do |t|
|
40
|
-
Hashie::Mash.new({
|
41
|
-
tid: t['tid'].to_i,
|
42
|
-
price: t['price'],
|
43
|
-
amount: t['amount'],
|
44
|
-
date: t['timestamp']
|
45
|
-
})
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def self.order_book
|
51
|
-
with_retry 'order_book' do
|
52
|
-
book = Bitfinex::Client.new.orderbook
|
53
|
-
{ 'bids' => book['bids'].collect{|b| [b['price'], b['amount']] },
|
54
|
-
'asks' => book['asks'].collect{|a| [a['price'], a['amount']] } }
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def self.balance
|
59
|
-
with_retry 'balance' do
|
60
|
-
balances = Bitfinex::Client.new.balances(type: 'exchange')
|
61
|
-
sleep 1 # Sleep to avoid sending two consecutive requests to bitfinex.
|
62
|
-
fee = Bitfinex::Client.new.account_info.first['taker_fees']
|
63
|
-
btc = balances.find{|b| b['currency'] == 'btc' } || {}
|
64
|
-
usd = balances.find{|b| b['currency'] == 'usd' } || {}
|
65
|
-
{ "btc_balance" => btc['amount'].to_d,
|
66
|
-
"btc_reserved" => btc['amount'].to_d - btc['available'].to_d,
|
67
|
-
"btc_available" => btc['available'].to_d,
|
68
|
-
"usd_balance" => usd['amount'].to_d,
|
69
|
-
"usd_reserved" => usd['amount'].to_d - usd['available'].to_d,
|
70
|
-
"usd_available" => usd['available'].to_d,
|
71
|
-
"fee" => fee.to_d
|
72
|
-
}
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def self.orders
|
77
|
-
with_retry 'orders' do
|
78
|
-
Bitfinex::Client.new.orders.collect{|o| BitfinexOrder.new(o) }
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
# We don't need to fetch the list of transactions
|
83
|
-
# for bitfinex
|
84
|
-
def self.user_transactions
|
85
|
-
[]
|
86
|
-
end
|
87
|
-
|
88
|
-
def self.amount_and_quantity(order_id, transactions)
|
89
|
-
with_retry "find order #{order_id}" do
|
90
|
-
order = Bitfinex::Client.new.order_status(order_id)
|
91
|
-
[order['avg_execution_price'].to_d * order['executed_amount'].to_d, order['executed_amount'].to_d]
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
def self.place_order(type, price, quantity)
|
96
|
-
with_retry "place order #{type} #{price} #{quantity}" do
|
97
|
-
order_data = Bitfinex::Client.new
|
98
|
-
.new_order('btcusd', quantity.round(4), 'exchange limit', type.to_s, price.round(2))
|
99
|
-
BitfinexOrder.new(order_data)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
class BitfinexOrder
|
105
|
-
attr_accessor :id, :amount, :price, :type, :datetime
|
106
|
-
def initialize(order_data)
|
107
|
-
self.id = order_data['id'].to_i
|
108
|
-
self.amount = order_data['original_amount'].to_d
|
109
|
-
self.price = order_data['price'].to_d
|
110
|
-
self.type = order_data['side'].to_sym
|
111
|
-
self.datetime = order_data['timestamp'].to_i
|
112
|
-
end
|
113
|
-
|
114
|
-
def cancel!
|
115
|
-
Bitfinex::Client.new.cancel_orders(id)
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
@@ -1,82 +0,0 @@
|
|
1
|
-
class BitstampApiWrapper
|
2
|
-
def self.setup(settings)
|
3
|
-
Bitstamp.setup do |config|
|
4
|
-
config.key = settings.bitstamp.api_key
|
5
|
-
config.secret = settings.bitstamp.secret
|
6
|
-
config.client_id = settings.bitstamp.client_id.to_s
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
#{
|
11
|
-
# tid:i,
|
12
|
-
# date: (i+1).seconds.ago.to_i.to_s,
|
13
|
-
# price: price.to_s,
|
14
|
-
# amount: amount.to_s
|
15
|
-
#}
|
16
|
-
def self.transactions
|
17
|
-
Bitstamp.transactions
|
18
|
-
end
|
19
|
-
|
20
|
-
# { 'timestamp' => DateTime.now.to_i.to_s,
|
21
|
-
# 'bids' =>
|
22
|
-
# [['30', '3'], ['25', '2'], ['20', '1.5'], ['15', '4'], ['10', '5']],
|
23
|
-
# 'asks' =>
|
24
|
-
# [['10', '2'], ['15', '3'], ['20', '1.5'], ['25', '3'], ['30', '3']]
|
25
|
-
# }
|
26
|
-
def self.order_book(retries = 20)
|
27
|
-
begin
|
28
|
-
book = Bitstamp.order_book
|
29
|
-
age = Time.now.to_i - book["timestamp"].to_i
|
30
|
-
if age > 300
|
31
|
-
BitexBot::Robot.logger.info("Refusing to continue as orderbook is #{age} seconds old")
|
32
|
-
self.order_book(retries)
|
33
|
-
else
|
34
|
-
book
|
35
|
-
end
|
36
|
-
rescue StandardError => e
|
37
|
-
if retries == 0
|
38
|
-
raise
|
39
|
-
else
|
40
|
-
BitexBot::Robot.logger.info("Bitstamp order_book failed, retrying #{retries} more times")
|
41
|
-
sleep 1
|
42
|
-
self.order_book(retries - 1)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
# {"btc_balance"=> "10.0", "btc_reserved"=> "0", "btc_available"=> "10.0",
|
48
|
-
# "usd_balance"=> "100.0", "usd_reserved"=>"0", "usd_available"=> "100.0",
|
49
|
-
# "fee"=> "0.5000"}
|
50
|
-
def self.balance
|
51
|
-
Bitstamp.balance
|
52
|
-
end
|
53
|
-
|
54
|
-
# ask = double(amount: args[:amount], price: args[:price],
|
55
|
-
# type: 1, id: remote_id, datetime: DateTime.now.to_s)
|
56
|
-
# ask.stub(:cancel!) do
|
57
|
-
def self.orders
|
58
|
-
Bitstamp.orders.all
|
59
|
-
end
|
60
|
-
|
61
|
-
# double(usd: (usd * ratio).to_s, btc: (btc * ratio).to_s,
|
62
|
-
# btc_usd: o.price.to_s, order_id: o.id, fee: "0.5", type: 2,
|
63
|
-
# datetime: DateTime.now.to_s)
|
64
|
-
def self.user_transactions
|
65
|
-
Bitstamp.user_transactions.all
|
66
|
-
end
|
67
|
-
|
68
|
-
def self.order_is_done?(order)
|
69
|
-
order.nil?
|
70
|
-
end
|
71
|
-
|
72
|
-
def self.amount_and_quantity(order_id, transactions)
|
73
|
-
closes = transactions.select{|t| t.order_id.to_s == order_id}
|
74
|
-
amount = closes.collect{|x| x.usd.to_d }.sum.abs
|
75
|
-
quantity = closes.collect{|x| x.btc.to_d }.sum.abs
|
76
|
-
[amount, quantity]
|
77
|
-
end
|
78
|
-
|
79
|
-
def self.place_order(type, price, quantity)
|
80
|
-
Bitstamp.orders.send(type, amount: quantity.round(4), price: price.round(2))
|
81
|
-
end
|
82
|
-
end
|
@@ -1,68 +0,0 @@
|
|
1
|
-
class ItbitApiWrapper
|
2
|
-
def self.setup(settings)
|
3
|
-
Itbit.client_key = settings.itbit.client_key
|
4
|
-
Itbit.secret = settings.itbit.secret
|
5
|
-
Itbit.user_id = settings.itbit.user_id
|
6
|
-
Itbit.default_wallet_id = settings.itbit.default_wallet_id
|
7
|
-
Itbit.sandbox = settings.sandbox
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.transactions
|
11
|
-
Itbit::XBTUSDMarketData.trades.collect{|t| Hashie::Mash.new(t) }
|
12
|
-
end
|
13
|
-
|
14
|
-
def self.order_book
|
15
|
-
Itbit::XBTUSDMarketData.orders.stringify_keys
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.balance
|
19
|
-
balances = Itbit::Wallet.all
|
20
|
-
.find{|i| i[:id] == Itbit.default_wallet_id }[:balances]
|
21
|
-
usd = balances.find{|x| x[:currency] == :usd }
|
22
|
-
btc = balances.find{|x| x[:currency] == :xbt }
|
23
|
-
{ "btc_balance" => btc[:total_balance],
|
24
|
-
"btc_reserved" => btc[:total_balance] - btc[:available_balance],
|
25
|
-
"btc_available" => btc[:available_balance],
|
26
|
-
"usd_balance" => usd[:total_balance],
|
27
|
-
"usd_reserved" => usd[:total_balance] - usd[:available_balance],
|
28
|
-
"usd_available" => usd[:available_balance],
|
29
|
-
"fee" => 0.5
|
30
|
-
}
|
31
|
-
end
|
32
|
-
|
33
|
-
def self.orders
|
34
|
-
Itbit::Order.all(status: :open)
|
35
|
-
end
|
36
|
-
|
37
|
-
# We don't need to fetch the list of transactions
|
38
|
-
# for itbit since we wont actually use them later.
|
39
|
-
def self.user_transactions
|
40
|
-
[]
|
41
|
-
end
|
42
|
-
|
43
|
-
def self.amount_and_quantity(order_id, transactions)
|
44
|
-
order = Itbit::Order.find(order_id)
|
45
|
-
[order.volume_weighted_average_price * order.amount_filled, order.amount_filled]
|
46
|
-
end
|
47
|
-
|
48
|
-
def self.place_order(type, price, quantity)
|
49
|
-
begin
|
50
|
-
return Itbit::Order.create!(type, :xbtusd, quantity.round(4), price.round(2), wait: true)
|
51
|
-
rescue RestClient::RequestTimeout => e
|
52
|
-
# On timeout errors, we still look for the latest active closing order
|
53
|
-
# that may be available. We have a magic threshold of 5 minutes
|
54
|
-
# and also use the price to recognize an order as the current one.
|
55
|
-
# TODO: Maybe we can identify the order using metadata instead of price.
|
56
|
-
BitexBot::Robot.logger.error("Captured Timeout on itbit")
|
57
|
-
latest = Itbit::Order.all.select do |x|
|
58
|
-
x.price == price && (x.created_time - Time.now.to_i).abs < 500
|
59
|
-
end.first
|
60
|
-
if latest
|
61
|
-
return latest
|
62
|
-
else
|
63
|
-
BitexBot::Robot.logger.error("Could not find my order")
|
64
|
-
raise e
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|