bitex_bot 0.9.0 → 0.9.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8a52c57b2cb3f955ac849623421abc8296b1dc9c
4
- data.tar.gz: b1a88154cb71ef5868c510f9316f0e755b161c33
3
+ metadata.gz: 84beba74777fdc3e278589d5caf543ecba824116
4
+ data.tar.gz: 9dd73af6332116ece29196635b7b057114333781
5
5
  SHA512:
6
- metadata.gz: 1cb5d465e54e321a5d181aa86e988c0183938a70540ffcb5434000abf55627d9e8f875da413d67dd1cfa07892f0198c6be7d7c628d2e46a1a31caed5c6afa17d
7
- data.tar.gz: 8cef55c3f44533c9b43c7f82bede8a7fb2777e248ad533845a50ac6cc9006cf59bdb95499d94a5f8a6b509fa0a7bff46347d6020bb765f5cd503358a34512dea
6
+ metadata.gz: '0438c07f2f3f8111b9de9b66e5f942ef193f9036c9f8136739b77dc1933f2a73cf020e2f6a6fccf445e2450a5b98e163f1959871cab4a52bdc070c030fdd2b46'
7
+ data.tar.gz: 7296518d188e5ea3ac4e12128585b0f1701e08a76cd60405caa7c3833f92635783163aa3ed97a00fb58491a9fa9469d1caa73aafa934d616ca8bba15586f60fe
@@ -11,7 +11,7 @@ Metrics/LineLength:
11
11
  Max: 130
12
12
 
13
13
  Metrics/MethodLength:
14
- Max: 30
14
+ Max: 40
15
15
 
16
16
  Metrics/ParameterLists:
17
17
  Max: 7
@@ -62,6 +62,10 @@ class ApiWrapper
62
62
  :timestamp # Epoch Integer
63
63
  )
64
64
 
65
+ def name
66
+ self.class.name.underscore.split('_').first.capitalize
67
+ end
68
+
65
69
  # @return [Array<Transaction>]
66
70
  def transactions
67
71
  raise 'self subclass responsibility'
@@ -95,20 +99,27 @@ class ApiWrapper
95
99
  # @param type
96
100
  # @param price
97
101
  # @param quantity
102
+ # rubocop:disable Metrics/AbcSize
98
103
  def place_order(type, price, quantity)
99
104
  order = send_order(type, price, quantity)
100
105
  return order unless order.nil? || order.id.nil?
101
106
 
102
- BitexBot::Robot.log(:debug, "Captured error when placing order on #{self.class}")
107
+ BitexBot::Robot.log(:debug, "Captured error when placing order on #{name}")
103
108
  # Order may have gone through and be stuck somewhere in Wrapper's pipeline.
104
109
  # We just sleep for a bit and then look for the order.
105
- 20.times do
106
- BitexBot::Robot.sleep_for(10)
110
+ 5.times do |i|
111
+ BitexBot::Robot.log(
112
+ :info,
113
+ "#{name} cauldn't place #{type} order #{i} times for #{base.upcase} #{quantity} @ #{quote.upcase} #{price}.\n"\
114
+ "Going to sleep 10 seconds.\n"
115
+ )
116
+ BitexBot::Robot.sleep_for(15)
107
117
  order = find_lost(type, price, quantity)
108
118
  return order if order.present?
109
119
  end
110
- raise OrderNotFound, "Closing: #{type} order not found for #{quantity} #{base} @ #{quote} #{price}. #{order}"
120
+ raise OrderNotFound, "Closing: #{type} order not found for #{base.upcase} #{quantity} @ #{quote.upcase} #{price}."
111
121
  end
122
+ # rubocop:enable Metrics/AbcSize
112
123
 
113
124
  # Hook Method - arguments could not be used in their entirety by the subclasses
114
125
  def send_order(_type, _price, _quantity)
@@ -67,7 +67,8 @@ class BitexApiWrapper < ApiWrapper
67
67
  end
68
68
 
69
69
  def send_order(type, price, quantity, wait = false)
70
- { sell: Bitex::Ask, buy: Bitex::Bid }[type].create!(base_quote.to_sym, quantity, price, wait)
70
+ order = { sell: Bitex::Ask, buy: Bitex::Bid }[type].create!(base_quote.to_sym, quantity, price, wait)
71
+ order_parser(order) if order.present?
71
72
  end
72
73
 
73
74
  def transactions
@@ -44,11 +44,19 @@ class ItbitApiWrapper < ApiWrapper
44
44
  end
45
45
 
46
46
  def orders
47
- Itbit::Order.all(instrument: currency_pair, status: :open).map { |o| order_parser(o) }
47
+ Itbit::Order.all(instrument: currency_pair[:name], status: :open).map { |o| order_parser(o) }
48
48
  end
49
49
 
50
- def place_order(type, price, quantity)
51
- Itbit::Order.create!(type, currency_pair, quantity.round(4), price.round(2), wait: true, currency: currency_base)
50
+ def send_order(type, price, quantity)
51
+ order = Itbit::Order.create!(
52
+ type,
53
+ currency_pair[:name],
54
+ quantity.round(4),
55
+ price.round(2),
56
+ wait: true,
57
+ currency: currency_pair[:base]
58
+ )
59
+ order_parser(order) if order.present?
52
60
  rescue RestClient::RequestTimeout => e
53
61
  # On timeout errors, we still look for the latest active closing order that may be available.
54
62
  # We have a magic threshold of 5 minutes and also use the price to recognize an order as the current one.
@@ -32,7 +32,8 @@ class KrakenApiWrapper < ApiWrapper
32
32
  end
33
33
 
34
34
  def find_lost(type, price, quantity)
35
- KrakenOrder.find_lost(type, price, quantity)
35
+ order = KrakenOrder.find_lost(type, price, quantity)
36
+ order_parser(order) if order.present?
36
37
  end
37
38
 
38
39
  def order_book
@@ -42,11 +43,12 @@ class KrakenApiWrapper < ApiWrapper
42
43
  end
43
44
 
44
45
  def orders
45
- KrakenOrder.open.map { |ko| order_parser(ko) }
46
+ KrakenOrder.open.map { |o| order_parser(o) }
46
47
  end
47
48
 
48
49
  def send_order(type, price, quantity)
49
- KrakenOrder.create!(type, price, quantity)
50
+ order = KrakenOrder.create!(type, price, quantity)
51
+ order_parser(order) if order.present?
50
52
  end
51
53
 
52
54
  def transactions
@@ -65,8 +67,8 @@ class KrakenApiWrapper < ApiWrapper
65
67
  def balance_summary_parser(balances)
66
68
  open_orders = KrakenOrder.open
67
69
  BalanceSummary.new(
68
- balance_parser(balances, currency_pair[:base], btc_reserved(open_orders)),
69
- balance_parser(balances, currency_pair[:quote], usd_reserved(open_orders)),
70
+ balance_parser(balances, currency_pair[:base], crypto_reserved(open_orders)),
71
+ balance_parser(balances, currency_pair[:quote], fiat_reserved(open_orders)),
70
72
  client.private.trade_volume(pair: currency_pair[:altname])[:fees][currency_pair[:name]][:fee].to_d
71
73
  )
72
74
  end
@@ -76,12 +78,12 @@ class KrakenApiWrapper < ApiWrapper
76
78
  Balance.new(balances[currency].to_d, reserved, balances[currency].to_d - reserved)
77
79
  end
78
80
 
79
- def btc_reserved(open_orders)
80
- orders_by(open_orders, :sell).map { |o| (o.amount - o.executed_amount).to_d }.sum
81
+ def crypto_reserved(open_orders)
82
+ orders_by(open_orders, :sell).sum { |o| (o.amount - o.executed_amount).to_d }
81
83
  end
82
84
 
83
- def usd_reserved(open_orders)
84
- orders_by(open_orders, :buy).map { |o| (o.amount - o.executed_amount) * o.price.to_d }.sum
85
+ def fiat_reserved(open_orders)
86
+ orders_by(open_orders, :buy).sum { |o| (o.amount - o.executed_amount) * o.price.to_d }
85
87
  end
86
88
 
87
89
  def orders_by(open_orders, order_type)
@@ -100,9 +102,10 @@ class KrakenApiWrapper < ApiWrapper
100
102
  stock_market.map { |stock| OrderSummary.new(stock[0].to_d, stock[1].to_d) }
101
103
  end
102
104
 
103
- # <KrakenOrder: @id='O5TDV2-WDYB2-6OGJRD', @type=:buy, @price='1.01', @amount='1.00000000', @datetime='2013-09-26 23:15:04'>
105
+ # <KrakenOrder:0x007faf255382d0 @id="OGZ3HI-5I322-OIOV52", @type=:sell, @datetime=1546971756, @amount=0.248752e-2,
106
+ # @executed_amount=0.248752e-2, @price=0.40025e4, @avg_price=0.40074e4>
104
107
  def order_parser(order)
105
- Order.new(order.id.to_s, order.type, order.price, order.amount, order.datetime, order)
108
+ Order.new(order.id, order.type, order.price, order.amount, order.datetime, order)
106
109
  end
107
110
 
108
111
  # [
@@ -8,7 +8,9 @@ class KrakenOrder
8
8
  # rubocop:disable Metrics/AbcSize
9
9
  def self.create!(type, price, quantity)
10
10
  self.last_closed_order = closed.first.try(:id) || Time.now.to_i
11
- find(order_info_by(type, price.truncate(1), quantity.truncate(8))['txid'].first)
11
+ order = place_order(type, price.truncate(1), quantity.truncate(8))
12
+ order_id = order['txid'].first
13
+ find(order_id)
12
14
  rescue KrakenClient::ErrorResponse => e
13
15
  # Order could not be placed
14
16
  if e.message == 'EService:Unavailable'
@@ -23,9 +25,11 @@ class KrakenOrder
23
25
  end
24
26
  # rubocop:enable Metrics/AbcSize
25
27
 
26
- def self.order_info_by(type, price, quantity)
28
+ # <KrakenOrder:0x007faf255382d0 @id="OGZ3HI-5I322-OIOV52", @type=:sell, @datetime=1546971756, @amount=0.248752e-2,
29
+ # @executed_amount=0.248752e-2, @price=0.40025e4, @avg_price=0.40074e4>
30
+ def self.place_order(type, price, quantity)
27
31
  api_wrapper.client.private.add_order(
28
- pair: KrakenApiWrapper.currency_pair[:altname],
32
+ pair: api_wrapper.currency_pair[:altname],
29
33
  type: type,
30
34
  ordertype: 'limit',
31
35
  price: price,
@@ -39,6 +43,7 @@ class KrakenOrder
39
43
  retry
40
44
  end
41
45
 
46
+ # [BigDecimal, BigDecimal]
42
47
  def self.amount_and_quantity(order_id)
43
48
  order = find(order_id)
44
49
  amount = order.avg_price * order.executed_amount
@@ -61,12 +66,12 @@ class KrakenOrder
61
66
 
62
67
  def self.find_lost(type, price, quantity)
63
68
  BitexBot::Robot.log(:debug, "Looking for #{type} order in open orders...")
64
- order = open_order_by(type, price, quantity)
69
+ order = open_order_by(type, price.truncate(2), quantity.truncate(8))
65
70
  return log_and_return(order, :open) if order.present?
66
71
 
67
72
  BitexBot::Robot.log(:debug, "Looking for #{type} order in closed orders...")
68
- order = closed_order_by(type, price, quantity)
69
- return log_and_return(order, :closed) if order && order.id != last_closed_order
73
+ order = closed_order_by(type, price.truncate(2), quantity.truncate(8))
74
+ return log_and_return(order, :closed) if order.present? && order.id != last_closed_order
70
75
  end
71
76
 
72
77
  def self.log_and_return(order, status)
@@ -76,12 +81,12 @@ class KrakenOrder
76
81
 
77
82
  # description: [type, price, quantity]
78
83
  def self.open_order_by(type, price, quantity)
79
- open.detect { |o| o == [type, price, quantity] }
84
+ open.detect { |order| order == [type, price, quantity] }
80
85
  end
81
86
 
82
87
  # description: [type, price, quantity]
83
88
  def self.closed_order_by(type, price, quantity)
84
- closed(start: last_closed_order).detect { |o| o == [type, price, quantity] }
89
+ closed(start: last_closed_order).detect { |order| order == [type, price, quantity] }
85
90
  end
86
91
 
87
92
  # id: 'O5TDV2-WDYB2-6OGJRD'
@@ -102,5 +102,13 @@ module BitexBot
102
102
  def self.taker_specie_to_obtain
103
103
  Robot.taker.quote.upcase
104
104
  end
105
+
106
+ def self.maker_balance
107
+ store.maker_fiat
108
+ end
109
+
110
+ def self.available_maker_balance
111
+ Robot.maker.balance.fiat.available
112
+ end
105
113
  end
106
114
  end
@@ -8,6 +8,7 @@ module BitexBot
8
8
  cattr_reader(:close_time_to_live) { 30 }
9
9
 
10
10
  # Start a new CloseBuy that closes existing OpenBuy's by selling on another exchange what was just bought on bitex.
11
+ # rubocop:disable Metrics/AbcSize
11
12
  def self.close_open_positions
12
13
  return unless open_positions.any?
13
14
 
@@ -15,11 +16,18 @@ module BitexBot
15
16
  quantity = positions.sum(&:quantity)
16
17
  amount = positions.sum(&:amount) / fx_rate
17
18
  price = suggested_amount(positions) / quantity
18
-
19
- return unless Robot.taker.enough_order_size?(quantity, price)
19
+ unless Robot.taker.enough_order_size?(quantity, price)
20
+ Robot.log(
21
+ :info,
22
+ "Closing: #{Robot.taker.name} - enough order size for #{Robot.taker.base.upcase} #{quantity}"\
23
+ " @ #{Robot.taker.quote.upcase} #{price}"
24
+ )
25
+ return
26
+ end
20
27
 
21
28
  create_closing_flow!(price, quantity, amount, positions)
22
29
  end
30
+ # rubocop:enable Metrics/AbcSize
23
31
 
24
32
  def self.open_positions
25
33
  open_position_class.open
@@ -31,8 +39,13 @@ module BitexBot
31
39
  end
32
40
 
33
41
  def self.create_closing_flow!(price, quantity, amount, open_positions)
34
- create!(desired_price: price, quantity: quantity, amount: amount, open_positions: open_positions)
35
- .create_initial_order_and_close_position!
42
+ flow = create!(desired_price: price, quantity: quantity, amount: amount, open_positions: open_positions)
43
+ Robot.log(
44
+ :info,
45
+ "Closing: created #{self}##{flow.id}, desired price: #{flow.desired_price}, quantity: #{flow.quantity}, "\
46
+ "amount: #{flow.amount}."
47
+ )
48
+ flow.create_initial_order_and_close_position!
36
49
  nil
37
50
  end
38
51
  # end: close_open_positions helpers
@@ -105,7 +118,7 @@ module BitexBot
105
118
  Robot.log(
106
119
  :info,
107
120
  "Closing: Finished #{self.class} ##{id} earned"\
108
- "#{Robot.maker.quote.upcase} #{fiat_profit} and #{Robot.maker.base.upcase} #{crypto_profit}."
121
+ " #{Robot.maker.quote.upcase} #{fiat_profit} and #{Robot.maker.base.upcase} #{crypto_profit}."
109
122
  )
110
123
  end
111
124
  end
@@ -126,6 +139,7 @@ module BitexBot
126
139
 
127
140
  # This use hooks methods, these must be defined in the subclass:
128
141
  # order_type
142
+ # rubocop:disable Metrics/AbcSize
129
143
  def create_order_and_close_position(quantity, price)
130
144
  # TODO: investigate how to generate an ID to insert in the fields of goals where possible.
131
145
  Robot.log(
@@ -134,7 +148,14 @@ module BitexBot
134
148
  " #{Robot.taker.base.upcase} #{quantity} @ #{Robot.taker.quote.upcase} #{price}"
135
149
  )
136
150
  order = Robot.taker.place_order(order_type, price, quantity)
151
+ Robot.log(
152
+ :info,
153
+ "Closing: #{Robot.taker.name} placed #{order.type} with price: #{order.price} @ quantity #{order.amount}.\n"\
154
+ "Closing: Going to create Close#{order.type.to_s.capitalize} position.\n"
155
+ )
156
+
137
157
  close_positions.create!(order_id: order.id)
138
158
  end
159
+ # rubocop:enable Metrics/AbcSize
139
160
  end
140
161
  end
@@ -35,6 +35,12 @@ module BitexBot
35
35
  self.store = store
36
36
 
37
37
  remote_value, safest_price = calc_remote_value(maker_fee, taker_fee, taker_orders, taker_transactions)
38
+ Robot.log(
39
+ :info,
40
+ "Opening: Need #{taker_specie_to_spend} #{remote_value.truncate(8)} on #{Robot.taker.name} taker,"\
41
+ " has #{taker_balance.truncate(8)}."
42
+ )
43
+
38
44
  unless enough_remote_funds?(taker_balance, remote_value)
39
45
  raise CannotCreateFlow,
40
46
  "Needed #{remote_value} but you only have #{taker_specie_to_spend} #{taker_balance} on your taker market."
@@ -45,22 +51,26 @@ module BitexBot
45
51
  order = create_order!(price)
46
52
  unless enough_funds?(order)
47
53
  raise CannotCreateFlow,
48
- "You need to have #{maker_specie_to_spend} #{value_per_order} on Bitex to place this #{order_class}."
54
+ "Needed #{maker_specie_to_spend} #{value_per_order} on #{Robot.maker.name} maker to place this #{order_class}"\
55
+ " but you only have #{maker_specie_to_spend} #{available_maker_balance}."
49
56
  end
50
57
 
51
- Robot.log(
52
- :info,
53
- "Opening: Placed #{order_class} ##{order.id} #{value_per_order} @ #{Robot.maker.quote.upcase} #{price}"\
54
- " (#{maker_specie_to_obtain} #{remote_value})"
55
- )
56
-
57
- create!(
58
+ flow = create!(
58
59
  price: price,
59
60
  value_to_use: value_to_use,
60
61
  suggested_closing_price: safest_price,
61
62
  status: 'executing',
62
63
  order_id: order.id
63
64
  )
65
+
66
+ Robot.log(
67
+ :info,
68
+ "Opening: Placed #{order_class} ##{order.id} #{maker_specie_to_spend} #{value_per_order} @ #{price.truncate(2)}."\
69
+ " (#{maker_specie_to_obtain} #{remote_value})."\
70
+ " #{name.demodulize}##{flow.id} suggests closing price #{Robot.taker.quote.upcase}"\
71
+ " #{flow.suggested_closing_price}."
72
+ )
73
+ flow
64
74
  rescue StandardError => e
65
75
  raise CannotCreateFlow, e.message
66
76
  end
@@ -115,8 +125,8 @@ module BitexBot
115
125
  def self.create_open_position!(transaction, flow)
116
126
  Robot.log(
117
127
  :info,
118
- "Opening: #{name} ##{flow.id} was hit for #{transaction.raw.quantity} #{Robot.maker.base.upcase}"\
119
- " @ #{Robot.maker.quote.upcase} #{transaction.price}"
128
+ "Opening: #{self} ##{flow.id} was hit for #{Robot.maker.base.upcase} #{transaction.raw.quantity}"\
129
+ " @ #{Robot.maker.quote.upcase} #{transaction.price}. Creating #{open_position_class}..."
120
130
  )
121
131
 
122
132
  open_position_class.create!(
@@ -102,5 +102,13 @@ module BitexBot
102
102
  def self.taker_specie_to_obtain
103
103
  Robot.taker.base.upcase
104
104
  end
105
+
106
+ def self.maker_balance
107
+ store.maker_crypto
108
+ end
109
+
110
+ def self.available_maker_balance
111
+ Robot.maker.balance.crypto.available
112
+ end
105
113
  end
106
114
  end
@@ -71,7 +71,7 @@ module BitexBot
71
71
 
72
72
  def self.start_robot
73
73
  setup
74
- log(:info, 'Loading trading robot, ctrl+c *once* to exit gracefully.')
74
+ log(:info, "Loading trading robot, ctrl+c *once* to exit gracefully.\n")
75
75
  new
76
76
  end
77
77
 
@@ -84,19 +84,19 @@ module BitexBot
84
84
  sync_closing_flows if active_closing_flows?
85
85
  start_opening_flows_if_needed
86
86
  rescue CannotCreateFlow => e
87
- notify("#{e.message}:\n\n#{e.backtrace.join("\n")}")
87
+ notify("#{e.class} - #{e.message}\n\n#{e.backtrace.join("\n")}")
88
88
  sleep_for(60 * 3)
89
89
  rescue Curl::Err::TimeoutError => e
90
- log(:error, "#{e.class} - #{e.message}:\n\n#{e.backtrace.join("\n")}")
90
+ notify("#{e.class} - #{e.message}\n\n#{e.backtrace.join("\n")}")
91
91
  sleep_for(15)
92
92
  rescue OrderNotFound => e
93
- notify("#{e.class} - #{e.message}:\n\n#{e.backtrace.join("\n")}")
93
+ notify("#{e.class} - #{e.message}\n\n#{e.backtrace.join("\n")}")
94
94
  rescue ApiWrapperError => e
95
- notify("#{e.class} - #{e.message}:\n\n#{e.backtrace.join("\n")}")
95
+ notify("#{e.class} - #{e.message}\n\n#{e.backtrace.join("\n")}")
96
96
  rescue OrderArgumentError => e
97
- notify("#{e.class} - #{e.message}:\n\n#{e.backtrace.join("\n")}")
97
+ notify("#{e.class} - #{e.message}\n\n#{e.backtrace.join("\n")}")
98
98
  rescue StandardError => e
99
- notify("#{e.class} - #{e.message}:\n\n#{e.backtrace.join("\n")}")
99
+ notify("#{e.class} - #{e.message}\n\n#{e.backtrace.join("\n")}")
100
100
  sleep_for(60 * 2)
101
101
  end
102
102
  # rubocop:enable Metrics/AbcSize
@@ -168,7 +168,9 @@ module BitexBot
168
168
 
169
169
  maker_balance = with_cooldown { maker.balance }
170
170
  taker_balance = with_cooldown { taker.balance }
171
+
171
172
  sync_log_and_store(maker_balance, taker_balance)
173
+ log_balances('Store: Current balances.')
172
174
 
173
175
  check_balance_warning if expired_last_warning?
174
176
  return if stop_opening_flows?
@@ -188,6 +190,7 @@ module BitexBot
188
190
  end
189
191
 
190
192
  def sync_log_and_store(maker_balance, taker_balance)
193
+ log_balances('Store: Updating log, maker and taker balances...')
191
194
  file = Settings.log.try(:file)
192
195
  last_log = `tail -c 61440 #{file}` if file.present?
193
196
 
@@ -198,13 +201,24 @@ module BitexBot
198
201
  )
199
202
  end
200
203
 
204
+ # rubocop:disable Metrics/AbcSize
205
+ def log_balances(header)
206
+ log(
207
+ :info,
208
+ "#{header}\n"\
209
+ "Store: #{maker.name} maker - #{maker.base.upcase}: #{store.maker_crypto}, #{maker.quote.upcase}: #{store.maker_fiat}.\n"\
210
+ "Store: #{taker.name} taker - #{taker.base.upcase}: #{store.taker_crypto}, #{taker.quote.upcase}: #{store.taker_fiat}.\n"
211
+ )
212
+ end
213
+ # rubocop:enable Metrics/AbcSize
214
+
201
215
  def expired_last_warning?
202
216
  store.last_warning.nil? || store.last_warning < 30.minutes.ago
203
217
  end
204
218
 
205
219
  def stop_opening_flows?
206
- (log(:debug, "Not placing new orders, #{maker.quote.upcase} target not met") if alert?(:fiat, :stop)) ||
207
- (log(:debug, "Not placing new orders, #{maker.base.upcase} target not met") if alert?(:crypto, :stop))
220
+ (log(:info, "Opening: Not placing new orders, #{maker.quote.upcase} target not met") if alert?(:fiat, :stop)) ||
221
+ (log(:info, "Opening: Not placing new orders, #{maker.base.upcase} target not met") if alert?(:crypto, :stop))
208
222
  end
209
223
 
210
224
  def check_balance_warning
@@ -229,7 +243,7 @@ module BitexBot
229
243
  end
230
244
 
231
245
  def notify(message, subj = 'Notice from your robot trader')
232
- log(:error, message)
246
+ log(:info, "Sending mail with subject: #{subj}\n\n#{message}")
233
247
  return unless Settings.mailer.present?
234
248
 
235
249
  new_mail(subj, message).tap do |mail|
@@ -1,3 +1,3 @@
1
1
  module BitexBot
2
- VERSION = '0.9.0'.freeze
2
+ VERSION = '0.9.1'.freeze
3
3
  end
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.9.0
4
+ version: 0.9.1
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: 2019-01-04 00:00:00.000000000 Z
12
+ date: 2019-01-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord