bitex_bot 0.0.6 → 0.1.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.
- data/bitex_bot.gemspec +1 -1
- data/lib/bitex_bot/database.rb +18 -2
- data/lib/bitex_bot/models/closing_flow.rb +22 -4
- data/lib/bitex_bot/models/opening_flow.rb +2 -2
- data/lib/bitex_bot/models/store.rb +2 -0
- data/lib/bitex_bot/robot.rb +40 -6
- data/lib/bitex_bot/version.rb +1 -1
- data/spec/models/buy_closing_flow_spec.rb +31 -7
- data/spec/models/robot_spec.rb +84 -6
- data/spec/models/sell_closing_flow_spec.rb +37 -12
- metadata +5 -4
data/bitex_bot.gemspec
CHANGED
@@ -26,7 +26,7 @@ Gem::Specification.new do |spec|
|
|
26
26
|
spec.add_dependency "activesupport"
|
27
27
|
spec.add_dependency "sqlite3"
|
28
28
|
spec.add_dependency "bitstamp"
|
29
|
-
spec.add_dependency "bitex", "0.0
|
29
|
+
spec.add_dependency "bitex", "0.1.0"
|
30
30
|
spec.add_dependency "mail"
|
31
31
|
|
32
32
|
spec.add_development_dependency "bundler", "~> 1.3"
|
data/lib/bitex_bot/database.rb
CHANGED
@@ -3,8 +3,8 @@ module BitexBot
|
|
3
3
|
#ActiveRecord::Base.logger = Logger.new(File.open('database.log', 'w'))
|
4
4
|
ActiveRecord::Base.establish_connection(Settings.database)
|
5
5
|
|
6
|
-
|
7
|
-
ActiveRecord::
|
6
|
+
ActiveRecord::Schema.define(version: 1) do
|
7
|
+
if ActiveRecord::Base.connection.tables.empty?
|
8
8
|
create_table :buy_opening_flows do |t|
|
9
9
|
t.decimal :price, precision: 30, scale: 15
|
10
10
|
t.decimal :value_to_use, precision: 30, scale: 15
|
@@ -87,7 +87,23 @@ module BitexBot
|
|
87
87
|
end
|
88
88
|
add_index :close_sells, :order_id
|
89
89
|
end
|
90
|
+
|
91
|
+
unless ActiveRecord::Base.connection.table_exists?('stores')
|
92
|
+
create_table "stores", force: true do |t|
|
93
|
+
t.decimal "bitstamp_usd", precision: 20, scale: 8
|
94
|
+
t.decimal "bitstamp_btc", precision: 20, scale: 8
|
95
|
+
t.boolean "hold", default: false
|
96
|
+
t.text "log"
|
97
|
+
t.decimal "usd_stop", precision: 20, scale: 8
|
98
|
+
t.decimal "usd_warning", precision: 20, scale: 8
|
99
|
+
t.decimal "btc_stop", precision: 20, scale: 8
|
100
|
+
t.decimal "btc_warning", precision: 20, scale: 8
|
101
|
+
t.datetime "last_warning"
|
102
|
+
t.timestamps
|
103
|
+
end
|
104
|
+
end
|
90
105
|
end
|
106
|
+
|
91
107
|
end
|
92
108
|
end
|
93
109
|
|
@@ -23,15 +23,25 @@ module BitexBot
|
|
23
23
|
quantity: quantity,
|
24
24
|
amount: amount,
|
25
25
|
open_positions: open_positions)
|
26
|
-
|
27
|
-
flow.
|
28
|
-
|
26
|
+
|
27
|
+
flow.create_initial_order_and_close_position
|
28
|
+
|
29
29
|
return flow
|
30
30
|
end
|
31
31
|
|
32
|
+
def create_initial_order_and_close_position
|
33
|
+
create_order_and_close_position(quantity, desired_price)
|
34
|
+
end
|
35
|
+
|
32
36
|
def create_order_and_close_position(quantity, price)
|
33
37
|
order = Bitstamp.orders.send(order_method,
|
34
|
-
amount: quantity.round(
|
38
|
+
amount: quantity.round(4), price: price.round(2))
|
39
|
+
if order.nil? || order.id.nil?
|
40
|
+
Robot.logger.error("Closing: Error on #{order_method} for "\
|
41
|
+
"#{self.class.name} ##{id} #{quantity} BTC @ $#{price}."\
|
42
|
+
"#{order.to_s}")
|
43
|
+
return
|
44
|
+
end
|
35
45
|
Robot.logger.info("Closing: Going to #{order_method} ##{order.id} for"\
|
36
46
|
"#{self.class.name} ##{id} #{quantity} BTC @ $#{price}")
|
37
47
|
close_positions.create!(order_id: order.id.to_i)
|
@@ -39,6 +49,14 @@ module BitexBot
|
|
39
49
|
|
40
50
|
def sync_closed_positions(orders, transactions)
|
41
51
|
latest_close = close_positions.last
|
52
|
+
|
53
|
+
# Maybe we couldn't create the bitstamp order when this flow
|
54
|
+
# was created, so we try again when syncing.
|
55
|
+
if latest_close.nil?
|
56
|
+
create_initial_order_and_close_position
|
57
|
+
return
|
58
|
+
end
|
59
|
+
|
42
60
|
order = orders.find{|x| x.id.to_s == latest_close.order_id.to_s }
|
43
61
|
|
44
62
|
# When ask is nil it means the other exchange is done executing it
|
@@ -101,9 +101,9 @@ module BitexBot
|
|
101
101
|
|
102
102
|
def finalise!
|
103
103
|
order = self.class.order_class.find(order_id)
|
104
|
-
if order.status == :cancelled
|
104
|
+
if order.status == :cancelled || order.status == :completed
|
105
105
|
Robot.logger.info(
|
106
|
-
"Opening: #{self.class.order_class.name} ##{order_id}
|
106
|
+
"Opening: #{self.class.order_class.name} ##{order_id} finalised.")
|
107
107
|
self.status = 'finalised'
|
108
108
|
save!
|
109
109
|
else
|
data/lib/bitex_bot/robot.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'debugger'
|
2
|
+
|
1
3
|
trap "INT" do
|
2
4
|
if BitexBot::Robot.graceful_shutdown
|
3
5
|
print "\b"
|
@@ -14,7 +16,10 @@ module BitexBot
|
|
14
16
|
cattr_accessor :cooldown_until
|
15
17
|
cattr_accessor :test_mode
|
16
18
|
cattr_accessor :logger do
|
17
|
-
|
19
|
+
logfile = Settings.log.try(:file) ? File.open(Settings.log.file, 'a') : STDOUT
|
20
|
+
logfile.sync = true
|
21
|
+
$stderr = logfile
|
22
|
+
Logger.new(logfile, 10, 10240000).tap do |l|
|
18
23
|
l.level = Logger.const_get(Settings.log.level.upcase)
|
19
24
|
l.formatter = proc do |severity, datetime, progname, msg|
|
20
25
|
date = datetime.strftime("%m/%d %H:%M:%S.%L")
|
@@ -23,7 +28,7 @@ module BitexBot
|
|
23
28
|
end
|
24
29
|
end
|
25
30
|
cattr_accessor :current_cooldowns do 0 end
|
26
|
-
|
31
|
+
|
27
32
|
# Trade constantly respecting cooldown times so that we don't get
|
28
33
|
# banned by api clients.
|
29
34
|
def self.run!
|
@@ -112,11 +117,10 @@ module BitexBot
|
|
112
117
|
end
|
113
118
|
|
114
119
|
def start_opening_flows_if_needed
|
115
|
-
return if
|
120
|
+
return if store.reload.hold?
|
116
121
|
return if active_closing_flows?
|
117
122
|
return if self.class.graceful_shutdown
|
118
123
|
|
119
|
-
|
120
124
|
recent_buying, recent_selling =
|
121
125
|
[BuyOpeningFlow, SellOpeningFlow].collect do |kind|
|
122
126
|
threshold = (Settings.time_to_live / 2).seconds.ago
|
@@ -126,6 +130,31 @@ module BitexBot
|
|
126
130
|
return if recent_buying && recent_selling
|
127
131
|
|
128
132
|
balances = with_cooldown{ Bitstamp.balance }
|
133
|
+
profile = Bitex::Profile.get
|
134
|
+
|
135
|
+
total_usd = balances['usd_balance'].to_d + profile[:usd_balance]
|
136
|
+
total_btc = balances['btc_balance'].to_d + profile[:btc_balance]
|
137
|
+
|
138
|
+
store.update_attributes(bitstamp_usd: balances['usd_balance'],
|
139
|
+
bitstamp_btc: balances['btc_balance'])
|
140
|
+
|
141
|
+
if store.last_warning.nil? || store.last_warning < 30.minutes.ago
|
142
|
+
if store.usd_warning && total_usd <= store.usd_warning
|
143
|
+
notify("USD balance is too low, it's #{total_usd},"\
|
144
|
+
"make it #{store.usd_warning} to stop this warning.")
|
145
|
+
store.update_attributes(last_warning: Time.now)
|
146
|
+
end
|
147
|
+
|
148
|
+
if store.btc_warning && total_btc <= store.btc_warning
|
149
|
+
notify("BTC balance is too low, it's #{total_btc},"\
|
150
|
+
"make it #{store.btc_warning} to stop this warning.")
|
151
|
+
store.update_attributes(last_warning: Time.now)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
return if store.usd_stop && total_usd <= store.usd_stop
|
156
|
+
return if store.btc_stop && total_btc <= store.btc_stop
|
157
|
+
|
129
158
|
order_book = with_cooldown{ Bitstamp.order_book }
|
130
159
|
transactions = with_cooldown{ Bitstamp.transactions }
|
131
160
|
|
@@ -134,7 +163,7 @@ module BitexBot
|
|
134
163
|
balances['btc_available'].to_d,
|
135
164
|
order_book['bids'],
|
136
165
|
transactions,
|
137
|
-
|
166
|
+
profile[:fee],
|
138
167
|
balances['fee'].to_d )
|
139
168
|
end
|
140
169
|
unless recent_selling
|
@@ -142,7 +171,7 @@ module BitexBot
|
|
142
171
|
balances['usd_available'].to_d,
|
143
172
|
order_book['asks'],
|
144
173
|
transactions,
|
145
|
-
|
174
|
+
profile[:fee],
|
146
175
|
balances['fee'].to_d )
|
147
176
|
end
|
148
177
|
end
|
@@ -169,5 +198,10 @@ module BitexBot
|
|
169
198
|
mail.deliver!
|
170
199
|
end
|
171
200
|
end
|
201
|
+
|
202
|
+
# The trader has a Store
|
203
|
+
def store
|
204
|
+
@store ||= Store.first || Store.create
|
205
|
+
end
|
172
206
|
end
|
173
207
|
end
|
data/lib/bitex_bot/version.rb
CHANGED
@@ -35,6 +35,30 @@ describe BitexBot::BuyClosingFlow do
|
|
35
35
|
close.quantity.should be_nil
|
36
36
|
end
|
37
37
|
|
38
|
+
it 'keeps trying to place a closed position on bitstamp errors' do
|
39
|
+
stub_bitstamp_sell
|
40
|
+
Bitstamp.orders.stub(:sell) do
|
41
|
+
double(id: nil, error: {price: ['Ensure it is good']})
|
42
|
+
end
|
43
|
+
open = create :open_buy
|
44
|
+
flow = BitexBot::BuyClosingFlow.close_open_positions
|
45
|
+
open.reload.closing_flow.should == flow
|
46
|
+
flow.open_positions.should == [open]
|
47
|
+
flow.desired_price.should == 310
|
48
|
+
flow.quantity.should == 2
|
49
|
+
flow.btc_profit.should be_nil
|
50
|
+
flow.usd_profit.should be_nil
|
51
|
+
flow.close_positions.should be_empty
|
52
|
+
|
53
|
+
stub_bitstamp_user_transactions
|
54
|
+
stub_bitstamp_sell
|
55
|
+
flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
|
56
|
+
close = flow.close_positions.first
|
57
|
+
close.order_id.should == 1
|
58
|
+
close.amount.should be_nil
|
59
|
+
close.quantity.should be_nil
|
60
|
+
end
|
61
|
+
|
38
62
|
it "does not try to close if the amount is too low" do
|
39
63
|
open = create :tiny_open_buy
|
40
64
|
expect do
|
@@ -61,11 +85,11 @@ describe BitexBot::BuyClosingFlow do
|
|
61
85
|
stub_bitstamp_orders_into_transactions
|
62
86
|
flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
|
63
87
|
close = flow.close_positions.last
|
64
|
-
close.amount.should == '624.
|
88
|
+
close.amount.should == '624.105'.to_d
|
65
89
|
close.quantity.should == 2.01
|
66
90
|
flow.should be_done
|
67
91
|
flow.btc_profit.should == 0
|
68
|
-
flow.usd_profit.should == '20.
|
92
|
+
flow.usd_profit.should == '20.105'.to_d
|
69
93
|
end
|
70
94
|
|
71
95
|
it "retries closing at a lower price every minute" do
|
@@ -97,7 +121,7 @@ describe BitexBot::BuyClosingFlow do
|
|
97
121
|
flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
|
98
122
|
end.to change{ BitexBot::CloseBuy.count }.by(1)
|
99
123
|
flow.close_positions.first.tap do |close|
|
100
|
-
close.amount.should == '312.
|
124
|
+
close.amount.should == '312.0525'.to_d
|
101
125
|
close.quantity.should == 1.005
|
102
126
|
end
|
103
127
|
|
@@ -106,12 +130,12 @@ describe BitexBot::BuyClosingFlow do
|
|
106
130
|
stub_bitstamp_orders_into_transactions
|
107
131
|
flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
|
108
132
|
flow.close_positions.last.tap do |close|
|
109
|
-
close.amount.should == '312.
|
133
|
+
close.amount.should == '312.0324'.to_d
|
110
134
|
close.quantity.should == 1.005
|
111
135
|
end
|
112
136
|
flow.should be_done
|
113
137
|
flow.btc_profit.should == 0
|
114
|
-
flow.usd_profit.should == '20.
|
138
|
+
flow.usd_profit.should == '20.0849000000001'.to_d
|
115
139
|
end
|
116
140
|
|
117
141
|
it "does not retry for an amount less than minimum_for_closing" do
|
@@ -126,7 +150,7 @@ describe BitexBot::BuyClosingFlow do
|
|
126
150
|
|
127
151
|
flow.should be_done
|
128
152
|
flow.btc_profit.should == 0.00201
|
129
|
-
flow.usd_profit.should == '19.
|
153
|
+
flow.usd_profit.should == '19.480895'.to_d
|
130
154
|
end
|
131
155
|
|
132
156
|
it "can lose USD if price had to be dropped dramatically" do
|
@@ -144,7 +168,7 @@ describe BitexBot::BuyClosingFlow do
|
|
144
168
|
|
145
169
|
flow.reload.should be_done
|
146
170
|
flow.btc_profit.should == 0
|
147
|
-
flow.usd_profit.should == '-16.
|
171
|
+
flow.usd_profit.should == '-16.075'.to_d
|
148
172
|
end
|
149
173
|
end
|
150
174
|
end
|
data/spec/models/robot_spec.rb
CHANGED
@@ -18,7 +18,18 @@ describe BitexBot::Robot do
|
|
18
18
|
)
|
19
19
|
)
|
20
20
|
Bitex.api_key = "valid_key"
|
21
|
-
Bitex::Profile.stub(get: {
|
21
|
+
Bitex::Profile.stub(get: {
|
22
|
+
fee: 0.5,
|
23
|
+
usd_balance: 10000.00, # Total USD balance
|
24
|
+
usd_reserved: 2000.00, # USD reserved in open orders
|
25
|
+
usd_available: 8000.00, # USD available for trading
|
26
|
+
btc_balance: 20.00000000, # Total BTC balance
|
27
|
+
btc_reserved: 5.00000000, # BTC reserved in open orders
|
28
|
+
btc_available: 15.00000000, # BTC available for trading
|
29
|
+
ltc_balance: 250.00000000, # Total LTC balance
|
30
|
+
ltc_reserved: 100.00000000, # LTC reserved in open orders
|
31
|
+
ltc_available: 150.00000000,
|
32
|
+
})
|
22
33
|
stub_bitex_orders
|
23
34
|
stub_bitstamp_sell
|
24
35
|
stub_bitstamp_buy
|
@@ -92,16 +103,83 @@ describe BitexBot::Robot do
|
|
92
103
|
bot.should_not be_active_closing_flows
|
93
104
|
end.to change{ BitexBot::BuyOpeningFlow.count }.by(1)
|
94
105
|
end
|
106
|
+
|
107
|
+
it 'does not place new opening flows when ordered to hold' do
|
108
|
+
other_bot = BitexBot::Robot.new
|
109
|
+
other_bot.store.hold = true
|
110
|
+
other_bot.store.save!
|
111
|
+
expect do
|
112
|
+
bot.trade!
|
113
|
+
end.not_to change{ BitexBot::BuyOpeningFlow.count }
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'stops trading when btc stop is reached' do
|
117
|
+
other_bot = BitexBot::Robot.new
|
118
|
+
other_bot.store.usd_stop = 11000
|
119
|
+
other_bot.store.save!
|
120
|
+
expect do
|
121
|
+
bot.trade!
|
122
|
+
end.not_to change{ BitexBot::BuyOpeningFlow.count }
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'stops trading when usd stop is reached' do
|
126
|
+
other_bot = BitexBot::Robot.new
|
127
|
+
other_bot.store.btc_stop = 30
|
128
|
+
other_bot.store.save!
|
129
|
+
expect do
|
130
|
+
bot.trade!
|
131
|
+
end.not_to change{ BitexBot::BuyOpeningFlow.count }
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'warns every 30 minutes when usd warn is reached' do
|
135
|
+
Bitex::Transaction.stub(all: [])
|
136
|
+
other_bot = BitexBot::Robot.new
|
137
|
+
other_bot.store.usd_warning = 11000
|
138
|
+
other_bot.store.save!
|
139
|
+
expect do
|
140
|
+
bot.trade!
|
141
|
+
end.to change{ Mail::TestMailer.deliveries.count }.by(1)
|
142
|
+
Timecop.travel 1.minute.from_now
|
143
|
+
expect do
|
144
|
+
bot.trade!
|
145
|
+
end.not_to change{ Mail::TestMailer.deliveries.count }
|
146
|
+
Timecop.travel 31.minutes.from_now
|
147
|
+
expect do
|
148
|
+
bot.trade!
|
149
|
+
end.to change{ Mail::TestMailer.deliveries.count }.by(1)
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'warns every 30 minutes when btc warn is reached' do
|
153
|
+
Bitex::Transaction.stub(all: [])
|
154
|
+
other_bot = BitexBot::Robot.new
|
155
|
+
other_bot.store.btc_warning = 30
|
156
|
+
other_bot.store.save!
|
157
|
+
expect do
|
158
|
+
bot.trade!
|
159
|
+
end.to change{ Mail::TestMailer.deliveries.count }.by(1)
|
160
|
+
Timecop.travel 1.minute.from_now
|
161
|
+
expect do
|
162
|
+
bot.trade!
|
163
|
+
end.not_to change{ Mail::TestMailer.deliveries.count }
|
164
|
+
Timecop.travel 31.minutes.from_now
|
165
|
+
expect do
|
166
|
+
bot.trade!
|
167
|
+
end.to change{ Mail::TestMailer.deliveries.count }.by(1)
|
168
|
+
end
|
169
|
+
|
170
|
+
it 'updates bitstamp_usd and bitstamp_btc' do
|
171
|
+
bot.trade!
|
172
|
+
bot.store.bitstamp_usd.should_not be_nil
|
173
|
+
bot.store.bitstamp_btc.should_not be_nil
|
174
|
+
end
|
95
175
|
|
96
176
|
it 'notifies exceptions and sleeps' do
|
97
177
|
Bitstamp.stub(:balance) do
|
98
178
|
raise StandardError.new('oh moova')
|
99
179
|
end
|
100
|
-
|
101
|
-
|
180
|
+
expect do
|
181
|
+
bot.trade!
|
182
|
+
end.to change{ Mail::TestMailer.deliveries.count }.by(1)
|
102
183
|
end
|
103
184
|
|
104
|
-
#it 'goes through all the motions buying and selling' do
|
105
|
-
# pending
|
106
|
-
#end
|
107
185
|
end
|
@@ -36,6 +36,30 @@ describe BitexBot::SellClosingFlow do
|
|
36
36
|
close.amount.should be_nil
|
37
37
|
close.quantity.should be_nil
|
38
38
|
end
|
39
|
+
|
40
|
+
it 'keeps trying to place a closed position on bitstamp errors' do
|
41
|
+
stub_bitstamp_buy
|
42
|
+
Bitstamp.orders.stub(:buy) do
|
43
|
+
double(id: nil, error: {price: ['Ensure it is good']})
|
44
|
+
end
|
45
|
+
open = create :open_sell
|
46
|
+
flow = BitexBot::SellClosingFlow.close_open_positions
|
47
|
+
open.reload.closing_flow.should == flow
|
48
|
+
flow.open_positions.should == [open]
|
49
|
+
flow.desired_price.should == 290
|
50
|
+
flow.quantity.should == 2
|
51
|
+
flow.btc_profit.should be_nil
|
52
|
+
flow.usd_profit.should be_nil
|
53
|
+
flow.close_positions.should be_empty
|
54
|
+
|
55
|
+
stub_bitstamp_user_transactions
|
56
|
+
stub_bitstamp_buy
|
57
|
+
flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
|
58
|
+
close = flow.close_positions.first
|
59
|
+
close.order_id.should == 1
|
60
|
+
close.amount.should be_nil
|
61
|
+
close.quantity.should be_nil
|
62
|
+
end
|
39
63
|
|
40
64
|
it "does not try to close if the amount is too low" do
|
41
65
|
open = create :tiny_open_sell
|
@@ -63,11 +87,11 @@ describe BitexBot::SellClosingFlow do
|
|
63
87
|
stub_bitstamp_orders_into_transactions
|
64
88
|
flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
|
65
89
|
close = flow.close_positions.last
|
66
|
-
close.amount.should == "583.
|
90
|
+
close.amount.should == "583.905".to_d
|
67
91
|
close.quantity.should == 2.01
|
68
92
|
flow.should be_done
|
69
93
|
flow.btc_profit.should == 0
|
70
|
-
flow.usd_profit.should == "20.
|
94
|
+
flow.usd_profit.should == "20.095".to_d
|
71
95
|
end
|
72
96
|
|
73
97
|
it "retries closing at a higher price every minute" do
|
@@ -99,7 +123,7 @@ describe BitexBot::SellClosingFlow do
|
|
99
123
|
flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
|
100
124
|
end.to change{ BitexBot::CloseSell.count }.by(1)
|
101
125
|
flow.close_positions.first.tap do |close|
|
102
|
-
close.amount.should == "291.
|
126
|
+
close.amount.should == "291.9525".to_d
|
103
127
|
close.quantity.should == 1.005
|
104
128
|
end
|
105
129
|
|
@@ -108,12 +132,13 @@ describe BitexBot::SellClosingFlow do
|
|
108
132
|
stub_bitstamp_orders_into_transactions
|
109
133
|
flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
|
110
134
|
flow.close_positions.last.tap do |close|
|
111
|
-
close.amount.should == "291.
|
112
|
-
close.quantity.should == '1.
|
135
|
+
close.amount.should == "291.943548".to_d
|
136
|
+
close.quantity.should == '1.0049'.to_d
|
113
137
|
end
|
114
138
|
flow.should be_done
|
115
|
-
flow.btc_profit.should == '-0.
|
116
|
-
flow.usd_profit.should == '20.
|
139
|
+
flow.btc_profit.should == '-0.0001'.to_d
|
140
|
+
flow.usd_profit.should == '20.1039519999999'.to_d
|
141
|
+
|
117
142
|
end
|
118
143
|
|
119
144
|
it "does not retry for an amount less than minimum_for_closing" do
|
@@ -132,8 +157,8 @@ describe BitexBot::SellClosingFlow do
|
|
132
157
|
end.not_to change{ BitexBot::CloseSell.count }
|
133
158
|
|
134
159
|
flow.should be_done
|
135
|
-
flow.btc_profit.should == '-0.
|
136
|
-
flow.usd_profit.should == '20.
|
160
|
+
flow.btc_profit.should == '-0.0156963'.to_d
|
161
|
+
flow.usd_profit.should == '20.66616775'.to_d
|
137
162
|
end
|
138
163
|
|
139
164
|
it "can lose BTC if price had to be raised dramatically" do
|
@@ -150,11 +175,11 @@ describe BitexBot::SellClosingFlow do
|
|
150
175
|
flow.sync_closed_positions(Bitstamp.orders.all, Bitstamp.user_transactions.all)
|
151
176
|
|
152
177
|
flow.reload.should be_done
|
153
|
-
flow.btc_profit.should == "-0.
|
154
|
-
flow.usd_profit.should == "20.
|
178
|
+
flow.btc_profit.should == "-0.1173".to_d
|
179
|
+
flow.usd_profit.should == "20.10205".to_d
|
155
180
|
close = flow.close_positions.last
|
156
181
|
(close.amount / close.quantity)
|
157
|
-
.should == '308.
|
182
|
+
.should == '308.5'.to_d
|
158
183
|
end
|
159
184
|
end
|
160
185
|
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.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2014-
|
13
|
+
date: 2014-08-08 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: settingslogic
|
@@ -99,7 +99,7 @@ dependencies:
|
|
99
99
|
requirements:
|
100
100
|
- - '='
|
101
101
|
- !ruby/object:Gem::Version
|
102
|
-
version: 0.0
|
102
|
+
version: 0.1.0
|
103
103
|
type: :runtime
|
104
104
|
prerelease: false
|
105
105
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -107,7 +107,7 @@ dependencies:
|
|
107
107
|
requirements:
|
108
108
|
- - '='
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: 0.0
|
110
|
+
version: 0.1.0
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: mail
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -300,6 +300,7 @@ files:
|
|
300
300
|
- lib/bitex_bot/models/order_book_simulator.rb
|
301
301
|
- lib/bitex_bot/models/sell_closing_flow.rb
|
302
302
|
- lib/bitex_bot/models/sell_opening_flow.rb
|
303
|
+
- lib/bitex_bot/models/store.rb
|
303
304
|
- lib/bitex_bot/robot.rb
|
304
305
|
- lib/bitex_bot/settings.rb
|
305
306
|
- lib/bitex_bot/version.rb
|