rbtc_arbitrage_simple 1.4.4 → 2.0.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.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +16 -14
  3. data/Gemfile.lock +17 -21
  4. data/lib/rbtc_arbitrage.rb +3 -1
  5. data/lib/rbtc_arbitrage/campbx.rb +3 -4
  6. data/lib/rbtc_arbitrage/cli.rb +2 -2
  7. data/lib/rbtc_arbitrage/clients/coinbase_client.rb +3 -2
  8. data/lib/rbtc_arbitrage/trader.rb +21 -75
  9. data/lib/rbtc_arbitrage/trader/logger.rb +31 -0
  10. data/lib/rbtc_arbitrage/trader/notifier.rb +60 -0
  11. data/lib/rbtc_arbitrage/version.rb +1 -1
  12. data/rbtc_arbitrage.gemspec +1 -1
  13. data/spec/clients/coinbase_client_spec.rb +2 -3
  14. data/spec/rbtc_arbitrage_spec.rb +1 -1
  15. data/spec/spec_helper.rb +2 -1
  16. data/spec/support/cassettes/RbtcArbitrage_Trader/_execute_trade/should_raise_SecurityError_if_not_live.yml +30 -25
  17. data/spec/support/cassettes/RbtcArbitrage_Trader/_execute_trade/when_live/raises_SecurityError_if_not_enough_BTC.yml +38 -24
  18. data/spec/support/cassettes/RbtcArbitrage_Trader/_execute_trade/when_live/raises_SecurityError_if_not_enough_USD.yml +40 -26
  19. data/spec/support/cassettes/RbtcArbitrage_Trader/_execute_trade/when_live/should_fetch_balance.yml +30 -25
  20. data/spec/support/cassettes/RbtcArbitrage_Trader/_execute_trade/when_live/shouldn_t_raise_security_error.yml +72 -53
  21. data/spec/support/cassettes/RbtcArbitrage_Trader/_fetch_prices/gets_the_right_price_set.yml +60 -50
  22. data/spec/trader_spec.rb +8 -8
  23. metadata +10 -19
  24. data/lib/rbtc_arbitrage/clients/mtgox_client.rb +0 -56
  25. data/spec/clients/mtgox_client_spec.rb +0 -53
  26. data/spec/support/cassettes/RbtcArbitrage_Clients_MtGoxClient/_balance/fetches_the_balance_correctly.yml +0 -77
  27. data/spec/support/cassettes/RbtcArbitrage_Clients_MtGoxClient/_price/fetches_price_for_buy_correctly.yml +0 -44
  28. data/spec/support/cassettes/RbtcArbitrage_Clients_MtGoxClient/_price/fetches_price_for_sell_correctly.yml +0 -44
  29. data/spec/support/cassettes/RbtcArbitrage_Clients_MtGoxClient/_price/fetches_prices_correctly.yml +0 -85
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ef0a86fb8de589d7b45bc44e07ce93222bad2e17
4
- data.tar.gz: b78c0c931af1ff282bba897320eb59c0b5279615
3
+ metadata.gz: f4cfee1b5de308aa0ec6007b8173a7220b4d4501
4
+ data.tar.gz: b67691a517aa55e2d8fe337f493acc172de76f68
5
5
  SHA512:
6
- metadata.gz: ff3874ce7ee3bdecf7b30e8338d2472fe33371f1a62ecb135e1dfcbcb04e1342828415907990aba602262450a59096e0fc4f34447ac65930269d116f7e73e826
7
- data.tar.gz: 77c3cdb383df68cd78e3facc9122f7001e55fd0179b1aca441abd5a286e2b771c2a731ed66a5e6c7c7708c7c406cbba1608bd80640462f212bc7a3d21478f167
6
+ metadata.gz: 827f92b92f8728f3802e0a8c341d5f2d0958a3b659841934cd1c15f790ea5dd9ddc1130831af239fa44d1f9e6b06564e680c922894cb12f9a60f2ef69e269aaa
7
+ data.tar.gz: 303826e5db0cf919370ed927c60930747b99b6d00962d18547a465743a819c8b38d72907d532f22ff783dc1e88c4b66fdcc8f8e4bb03c1147f246c2fbdd36557
data/Gemfile CHANGED
@@ -2,17 +2,19 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in rbtc_arbitrage.gemspec
4
4
  gemspec
5
- gem 'rspec'
6
- gem "activemodel", ">= 3.1"
7
- gem "activesupport", ">= 3.1"
8
- gem 'guard'
9
- gem 'ruby_gntp'
10
- # gem 'awesome_print'
11
- gem 'guard-rspec'
12
- gem 'simplecov'
13
- gem 'coveralls', require: false
14
- gem "webmock"
15
- gem 'vcr'
16
- gem 'codeclimate-test-reporter'
17
- gem 'hashie'
18
- gem 'sinatra'
5
+ group :development do
6
+ gem 'rspec'
7
+ gem "activemodel", ">= 3.1"
8
+ gem "activesupport", ">= 3.1"
9
+ gem 'guard'
10
+ gem 'ruby_gntp'
11
+ # gem 'awesome_print'
12
+ gem 'guard-rspec'
13
+ gem 'simplecov'
14
+ gem 'coveralls', require: false
15
+ gem "webmock"
16
+ gem 'vcr'
17
+ gem 'codeclimate-test-reporter'
18
+ gem 'hashie'
19
+ gem 'sinatra'
20
+ end
data/Gemfile.lock CHANGED
@@ -1,29 +1,29 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rbtc_arbitrage_simple (1.4.4)
4
+ rbtc_arbitrage_simple (2.0.1)
5
5
  activemodel (>= 3.1)
6
6
  activesupport (>= 3.1)
7
7
  btce (= 0.2.4)
8
8
  coinbase (= 1.2.6)
9
- mtgox
9
+ faraday (= 0.8.8)
10
10
  pony
11
11
  thor
12
12
 
13
13
  GEM
14
14
  remote: https://rubygems.org/
15
15
  specs:
16
- activemodel (4.0.2)
17
- activesupport (= 4.0.2)
16
+ activemodel (4.0.4)
17
+ activesupport (= 4.0.4)
18
18
  builder (~> 3.1.0)
19
- activesupport (4.0.2)
20
- i18n (~> 0.6, >= 0.6.4)
19
+ activesupport (4.0.4)
20
+ i18n (~> 0.6, >= 0.6.9)
21
21
  minitest (~> 4.2)
22
22
  multi_json (~> 1.3)
23
23
  thread_safe (~> 0.1)
24
24
  tzinfo (~> 0.3.37)
25
25
  addressable (2.3.5)
26
- atomic (1.1.14)
26
+ atomic (1.1.16)
27
27
  btce (0.2.4)
28
28
  monkey-patch
29
29
  builder (3.1.4)
@@ -61,7 +61,7 @@ GEM
61
61
  guard (>= 2.1.1)
62
62
  rspec (~> 3.0.0.beta, >= 2.14, < 4.0)
63
63
  hashie (2.0.5)
64
- httparty (0.12.0)
64
+ httparty (0.13.0)
65
65
  json (~> 1.8)
66
66
  multi_xml (>= 0.5.2)
67
67
  i18n (0.6.9)
@@ -80,16 +80,13 @@ GEM
80
80
  minitest (4.7.5)
81
81
  money (5.1.1)
82
82
  i18n (~> 0.6.0)
83
- monkey-patch (0.0.14)
83
+ monkey-patch (0.0.16)
84
84
  activesupport
85
- mtgox (1.1.0)
86
- faraday (~> 0.8, < 0.10)
87
- json (~> 1.7, >= 1.7.7)
88
- multi_json (1.8.2)
85
+ multi_json (1.9.2)
89
86
  multi_xml (0.5.5)
90
87
  multipart-post (1.2.0)
91
- polyglot (0.3.3)
92
- pony (1.6.2)
88
+ polyglot (0.3.4)
89
+ pony (1.8)
93
90
  mail (>= 2.0)
94
91
  pry (0.9.12.4)
95
92
  coderay (~> 1.0)
@@ -131,15 +128,14 @@ GEM
131
128
  term-ansicolor (1.2.2)
132
129
  tins (~> 0.8)
133
130
  thor (0.18.1)
134
- thread_safe (0.1.3)
135
- atomic
131
+ thread_safe (0.3.1)
132
+ atomic (>= 1.1.7, < 2)
136
133
  tilt (1.4.1)
137
134
  timers (1.1.0)
138
135
  tins (0.13.1)
139
- treetop (1.4.15)
140
- polyglot
141
- polyglot (>= 0.3.1)
142
- tzinfo (0.3.38)
136
+ treetop (1.5.3)
137
+ polyglot (~> 0.3)
138
+ tzinfo (0.3.39)
143
139
  vcr (2.8.0)
144
140
  webmock (1.16.1)
145
141
  addressable (>= 2.2.7)
@@ -1,10 +1,12 @@
1
+ require 'bundler'
2
+ Bundler.require(:default)
1
3
  require 'thor'
2
- require 'mtgox'
3
4
  require_relative 'rbtc_arbitrage/campbx.rb'
4
5
  require 'btce'
5
6
  require 'coinbase'
6
7
  require 'pony'
7
8
  require_relative 'rbtc_arbitrage/client.rb'
9
+ Dir["#{File.dirname(__FILE__)}/rbtc_arbitrage/trader/*.rb"].each { |f| require(f) }
8
10
  Dir["#{File.dirname(__FILE__)}/rbtc_arbitrage/**/*.rb"].each { |f| require(f) }
9
11
 
10
12
  module RbtcArbitrage
@@ -70,10 +70,10 @@ module CampBX
70
70
  request.set_form_data( post_data )
71
71
  end
72
72
 
73
- # debug # need to test w/valid credentials
74
- #puts "Sending request to #{uri}"
75
- #puts "Post Data: #{post_data}"
73
+ make_request(http, request)
74
+ end
76
75
 
76
+ def make_request http, request
77
77
  # CampBX API: max 1 request per 500ms
78
78
  delta = Time.now - @@last
79
79
  #puts delta*1000
@@ -90,7 +90,6 @@ module CampBX
90
90
  else # HTTP ERROR
91
91
  warn "HTTP Error: + #{res.code}"
92
92
  end
93
-
94
93
  end
95
94
 
96
95
  end
@@ -6,8 +6,8 @@ module RbtcArbitrage
6
6
  option :cutoff, type: :numeric, default: 2, desc: "The minimum profit level required to execute a trade."
7
7
  option :volume, type: :numeric, default: 0.01, desc: "The amount of bitcoins to trade per transaction."
8
8
  option :verbose, type: :boolean, default: true, desc: "Whether you wish to log information."
9
- option :buyer, type: :string, default: "campbx"
10
- option :seller, type: :string, default: "mtgox"
9
+ option :buyer, type: :string, default: "btce"
10
+ option :seller, type: :string, default: "campbx"
11
11
  option :repeat, type: :numeric, default: nil
12
12
  option :notify, type: :boolean, default: false
13
13
  def trade
@@ -16,10 +16,11 @@ module RbtcArbitrage
16
16
  if @options[:verbose]
17
17
  warning = "Coinbase doesn't provide a USD balance because"
18
18
  warning << " it connects to your bank account. Be careful, "
19
- warning << "because this will withdraw directly from your accounts."
19
+ warning << "because this will withdraw directly from your accounts"
20
+ warning << "when you trade live."
20
21
  logger.warn warning
21
22
  end
22
- @balance ||= [interface.balance.to_f, max_float]
23
+ @balance ||= [max_float, max_float]
23
24
  end
24
25
 
25
26
  # Configures the client's API keys.
@@ -1,5 +1,8 @@
1
1
  module RbtcArbitrage
2
2
  class Trader
3
+ include RbtcArbitrage::TraderHelpers::Notifier
4
+ include RbtcArbitrage::TraderHelpers::Logger
5
+
3
6
  attr_reader :buy_client, :sell_client, :received
4
7
  attr_accessor :buyer, :seller, :options
5
8
 
@@ -19,10 +22,10 @@ module RbtcArbitrage
19
22
  set_key opts, :verbose, true
20
23
  set_key opts, :live, false
21
24
  set_key opts, :repeat, nil
22
- exchange = opts[:buyer] || :campbx
25
+ exchange = opts[:buyer] || :btce
23
26
  set_key opts, :notify, false
24
27
  @buy_client = client_for_exchange(exchange)
25
- exchange = opts[:seller] || :mtgox
28
+ exchange = opts[:seller] || :campbx
26
29
  @sell_client = client_for_exchange(exchange)
27
30
  self
28
31
  end
@@ -64,14 +67,7 @@ module RbtcArbitrage
64
67
  raise SecurityError, "--live flag is false. Not executing trade." unless options[:live]
65
68
  get_balance
66
69
  if @percent > @options[:cutoff]
67
- if @paid > buyer[:usd] || @options[:volume] > seller[:btc]
68
- raise SecurityError, "Not enough funds. Exiting."
69
- else
70
- logger.info "Trading live!" if options[:verbose]
71
- @buy_client.buy
72
- @sell_client.sell
73
- @buy_client.transfer @sell_client
74
- end
70
+ buy_and_transfer!
75
71
  else
76
72
  logger.info "Not trading live because cutoff is higher than profit." if @options[:verbose]
77
73
  end
@@ -82,19 +78,8 @@ module RbtcArbitrage
82
78
  buyer[:price] = @buy_client.price(:buy)
83
79
  seller[:price] = @sell_client.price(:sell)
84
80
  prices = [buyer[:price], seller[:price]]
85
- @paid = buyer[:price] * 1.006 * @options[:volume]
86
- @received = seller[:price] * 0.994 * @options[:volume]
87
- @percent = ((received/@paid - 1) * 100).round(2)
88
- end
89
81
 
90
- def log_info
91
- lower_ex = @buy_client.exchange.to_s.capitalize
92
- higher_ex = @sell_client.exchange.to_s.capitalize
93
- logger.info "#{lower_ex}: $#{buyer[:price].round(2)}"
94
- logger.info "#{higher_ex}: $#{seller[:price].round(2)}"
95
- logger.info "buying #{@options[:volume]} btc from #{lower_ex} for $#{@paid.round(2)}"
96
- logger.info "selling #{@options[:volume]} btc on #{higher_ex} for $#{@received.round(2)}"
97
- logger.info "profit: $#{(@received - @paid).round(2)} (#{@percent.round(2)}%)"
82
+ calculate_profit
98
83
  end
99
84
 
100
85
  def get_balance
@@ -102,10 +87,6 @@ module RbtcArbitrage
102
87
  @buyer[:btc], @buyer[:usd] = @buy_client.balance
103
88
  end
104
89
 
105
- def logger
106
- @options[:logger]
107
- end
108
-
109
90
  def validate_env
110
91
  [@sell_client, @buy_client].each do |client|
111
92
  client.validate_env
@@ -135,59 +116,24 @@ module RbtcArbitrage
135
116
  end
136
117
  end
137
118
 
138
- def notify
139
- return false unless options[:notify]
140
- return false unless @percent > options[:cutoff]
141
- setup_pony
119
+ private
142
120
 
143
- options[:logger].info "Sending email to #{ENV['SENDGRID_EMAIL']}"
144
- Pony.mail({
145
- body: notification,
146
- to: ENV['SENDGRID_EMAIL'],
147
- })
121
+ def calculate_profit
122
+ @paid = buyer[:price] * 1.006 * @options[:volume]
123
+ @received = seller[:price] * 0.994 * @options[:volume]
124
+ @percent = ((received/@paid - 1) * 100).round(2)
148
125
  end
149
126
 
150
- def setup_pony
151
- Pony.options = {
152
- from: ENV['FROM_EMAIL'] || "info@example.org",
153
- subject: "rbtc_arbitrage notification",
154
- via: :smtp,
155
- via_options: {
156
- address: 'smtp.sendgrid.net',
157
- port: '587',
158
- domain: 'heroku.com',
159
- user_name: ENV['SENDGRID_USERNAME'],
160
- password: ENV['SENDGRID_PASSWORD'],
161
- authentication: :plain,
162
- enable_starttls_auto: true
163
- }
164
- }
127
+ def buy_and_transfer!
128
+ if @paid > buyer[:usd] || @options[:volume] > seller[:btc]
129
+ raise SecurityError, "Not enough funds. Exiting."
130
+ else
131
+ logger.info "Trading live!" if options[:verbose]
132
+ @buy_client.buy
133
+ @sell_client.sell
134
+ @buy_client.transfer @sell_client
135
+ end
165
136
  end
166
137
 
167
- def notification
168
- lower_ex = @buy_client.exchange.to_s.capitalize
169
- higher_ex = @sell_client.exchange.to_s.capitalize
170
- <<-eos
171
- Update from your friendly rbtc_arbitrage trader:
172
-
173
- -------------------
174
-
175
- #{lower_ex}: $#{buyer[:price].round(2)}
176
- #{higher_ex}: $#{seller[:price].round(2)}
177
- buying #{@options[:volume]} btc from #{lower_ex} for $#{@paid.round(2)}
178
- selling #{@options[:volume]} btc on #{higher_ex} for $#{@received.round(2)}
179
- profit: $#{(@received - @paid).round(2)} (#{@percent.round(2)}%)
180
-
181
- -------------------
182
-
183
- options:
184
-
185
- #{options.reject{|k,v| v.is_a?(Logger)}.collect{|k,v| "#{k}: #{v.to_s}"}.join(" | ")}
186
-
187
- -------------------
188
-
189
- https://github.com/hstove/rbtc_arbitrage
190
- eos
191
- end
192
138
  end
193
139
  end
@@ -0,0 +1,31 @@
1
+ module RbtcArbitrage
2
+ module TraderHelpers
3
+ module Logger
4
+ def logger
5
+ @options[:logger]
6
+ end
7
+
8
+ def log_info
9
+ lower_ex = @buy_client.exchange.to_s.capitalize
10
+ higher_ex = @sell_client.exchange.to_s.capitalize
11
+ logger.info "#{lower_ex}: $#{buyer[:price].round(2)}"
12
+ logger.info "#{higher_ex}: $#{seller[:price].round(2)}"
13
+ logger.info "buying #{@options[:volume]} btc from #{lower_ex} for $#{@paid.round(2)}"
14
+ logger.info "selling #{@options[:volume]} btc on #{higher_ex} for $#{@received.round(2)}"
15
+
16
+ log_profit
17
+ end
18
+
19
+ private
20
+
21
+ def log_profit
22
+ profit_msg = "profit: $#{(@received - @paid).round(2)} (#{@percent.round(2)}%)"
23
+ if cutoff = @options[:cutoff]
24
+ profit_msg << " is #{@percent < cutoff ? 'below' : 'above'} cutoff"
25
+ profit_msg << " of #{cutoff}%."
26
+ end
27
+ logger.info profit_msg
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,60 @@
1
+ module RbtcArbitrage
2
+ module TraderHelpers
3
+ module Notifier
4
+ def notify
5
+ return false unless options[:notify]
6
+ return false unless @percent > options[:cutoff]
7
+ setup_pony
8
+
9
+ options[:logger].info "Sending email to #{ENV['SENDGRID_EMAIL']}"
10
+ Pony.mail({
11
+ body: notification,
12
+ to: ENV['SENDGRID_EMAIL'],
13
+ })
14
+ end
15
+
16
+ def setup_pony
17
+ Pony.options = {
18
+ from: ENV['FROM_EMAIL'] || "info@example.org",
19
+ subject: "rbtc_arbitrage notification",
20
+ via: :smtp,
21
+ via_options: {
22
+ address: 'smtp.sendgrid.net',
23
+ port: '587',
24
+ domain: 'heroku.com',
25
+ user_name: ENV['SENDGRID_USERNAME'],
26
+ password: ENV['SENDGRID_PASSWORD'],
27
+ authentication: :plain,
28
+ enable_starttls_auto: true
29
+ }
30
+ }
31
+ end
32
+
33
+ def notification
34
+ lower_ex = @buy_client.exchange.to_s.capitalize
35
+ higher_ex = @sell_client.exchange.to_s.capitalize
36
+ <<-eos
37
+ Update from your friendly rbtc_arbitrage trader:
38
+
39
+ -------------------
40
+
41
+ #{lower_ex}: $#{buyer[:price].round(2)}
42
+ #{higher_ex}: $#{seller[:price].round(2)}
43
+ buying #{@options[:volume]} btc from #{lower_ex} for $#{@paid.round(2)}
44
+ selling #{@options[:volume]} btc on #{higher_ex} for $#{@received.round(2)}
45
+ profit: $#{(@received - @paid).round(2)} (#{@percent.round(2)}%)
46
+
47
+ -------------------
48
+
49
+ options:
50
+
51
+ #{options.reject{|k,v| v.is_a?(Logger)}.collect{|k,v| "#{k}: #{v.to_s}"}.join(" | ")}
52
+
53
+ -------------------
54
+
55
+ https://github.com/hstove/rbtc_arbitrage
56
+ eos
57
+ end
58
+ end
59
+ end
60
+ end
@@ -1,3 +1,3 @@
1
1
  module RbtcArbitrage
2
- VERSION = "1.4.4"
2
+ VERSION = "2.0.1"
3
3
  end
@@ -21,7 +21,7 @@ Gem::Specification.new do |spec|
21
21
  spec.add_development_dependency "bundler", "~> 1.3"
22
22
  spec.add_development_dependency "rake"
23
23
 
24
- spec.add_dependency "mtgox"
24
+ spec.add_dependency "faraday", "0.8.8"
25
25
  spec.add_dependency "activemodel", ">= 3.1"
26
26
  spec.add_dependency "activesupport", ">= 3.1"
27
27
  spec.add_dependency "thor"