bitex_bot 0.0.6 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|