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