bitex_bot 0.9.0 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/lib/bitex_bot/models/api_wrappers/api_wrapper.rb +15 -4
- data/lib/bitex_bot/models/api_wrappers/bitex/bitex_api_wrapper.rb +2 -1
- data/lib/bitex_bot/models/api_wrappers/itbit/itbit_api_wrapper.rb +11 -3
- data/lib/bitex_bot/models/api_wrappers/kraken/kraken_api_wrapper.rb +14 -11
- data/lib/bitex_bot/models/api_wrappers/kraken/kraken_order.rb +13 -8
- data/lib/bitex_bot/models/buy_opening_flow.rb +8 -0
- data/lib/bitex_bot/models/closing_flow.rb +26 -5
- data/lib/bitex_bot/models/opening_flow.rb +20 -10
- data/lib/bitex_bot/models/sell_opening_flow.rb +8 -0
- data/lib/bitex_bot/robot.rb +24 -10
- data/lib/bitex_bot/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 84beba74777fdc3e278589d5caf543ecba824116
|
4
|
+
data.tar.gz: 9dd73af6332116ece29196635b7b057114333781
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '0438c07f2f3f8111b9de9b66e5f942ef193f9036c9f8136739b77dc1933f2a73cf020e2f6a6fccf445e2450a5b98e163f1959871cab4a52bdc070c030fdd2b46'
|
7
|
+
data.tar.gz: 7296518d188e5ea3ac4e12128585b0f1701e08a76cd60405caa7c3833f92635783163aa3ed97a00fb58491a9fa9469d1caa73aafa934d616ca8bba15586f60fe
|
data/.rubocop.yml
CHANGED
@@ -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 #{
|
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
|
-
|
106
|
-
BitexBot::Robot.
|
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 #{
|
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
|
51
|
-
Itbit::Order.create!(
|
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 { |
|
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],
|
69
|
-
balance_parser(balances, currency_pair[:quote],
|
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
|
80
|
-
orders_by(open_orders, :sell).
|
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
|
84
|
-
orders_by(open_orders, :buy).
|
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=
|
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
|
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
|
-
|
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
|
-
|
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:
|
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 { |
|
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 { |
|
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
|
-
|
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
|
-
|
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
|
-
"
|
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
|
-
|
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: #{
|
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
|
data/lib/bitex_bot/robot.rb
CHANGED
@@ -71,7 +71,7 @@ module BitexBot
|
|
71
71
|
|
72
72
|
def self.start_robot
|
73
73
|
setup
|
74
|
-
log(:info,
|
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}
|
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
|
-
|
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}
|
93
|
+
notify("#{e.class} - #{e.message}\n\n#{e.backtrace.join("\n")}")
|
94
94
|
rescue ApiWrapperError => e
|
95
|
-
notify("#{e.class} - #{e.message}
|
95
|
+
notify("#{e.class} - #{e.message}\n\n#{e.backtrace.join("\n")}")
|
96
96
|
rescue OrderArgumentError => e
|
97
|
-
notify("#{e.class} - #{e.message}
|
97
|
+
notify("#{e.class} - #{e.message}\n\n#{e.backtrace.join("\n")}")
|
98
98
|
rescue StandardError => e
|
99
|
-
notify("#{e.class} - #{e.message}
|
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(:
|
207
|
-
(log(:
|
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(:
|
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|
|
data/lib/bitex_bot/version.rb
CHANGED
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.
|
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-
|
12
|
+
date: 2019-01-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|