rbtc_arbitrage_simple 1.2.3 → 1.4.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 40fce7b383de7c133941d19f55ff55adaf3fa01d
4
- data.tar.gz: d625c40f8afee77529f458183cf32fba33fef0d8
3
+ metadata.gz: ef0a86fb8de589d7b45bc44e07ce93222bad2e17
4
+ data.tar.gz: b78c0c931af1ff282bba897320eb59c0b5279615
5
5
  SHA512:
6
- metadata.gz: 8c08ee2166aafcd8dbd14dfa1a02ae5e0c14881b1b778b906fa6662e13ccc04770d2e7aae4e66c9da16a01b6a42188719030d758ea1f59282cd2b6392910f7ee
7
- data.tar.gz: a8ef905fc4e189aa20ff6839440960f1e00c744119142d8e0b69af44af1eb226b98c80fc7bd6b7766ab7d79696d04b78a88049efbd732e245faf02f5d97096e9
6
+ metadata.gz: ff3874ce7ee3bdecf7b30e8338d2472fe33371f1a62ecb135e1dfcbcb04e1342828415907990aba602262450a59096e0fc4f34447ac65930269d116f7e73e826
7
+ data.tar.gz: 77c3cdb383df68cd78e3facc9122f7001e55fd0179b1aca441abd5a286e2b771c2a731ed66a5e6c7c7708c7c406cbba1608bd80640462f212bc7a3d21478f167
@@ -6,6 +6,11 @@ rvm:
6
6
  - ruby-head
7
7
  - jruby-19mode
8
8
  - jruby-head
9
+
10
+ matrix:
11
+ allow_failures:
12
+ - rvm: 2.1.0
13
+ - rvm: ruby-head
9
14
  env:
10
15
  global:
11
16
  - secure: FdoR9cSL5JzSiGRgmrEGCx55VdP7QU6jt2vzeJyc+2Ho67UXxJuXWgFdwojs6X85O3in8YfSOInBLGXXsD8a3mBuvhsAaMmDLbhFKfEExsc9bnpTj3k95UMGRO3pGNkk1tfj/ohsLFs+yL4r/mFZ5pOoxWW0uhYuRPA+Jk39hZg=
@@ -21,3 +26,6 @@ env:
21
26
  - secure: IFyJX6lAmBpef0I50UPCy6L5IRxqRKoPhv74s5y0FPB4chrir7iMZ7Sd1IczxV7ly4Dt7hdALHP1qMTmkcGmTV6YOzwR46G4JAwWtX2xlf4OYk4jey7qjNsS6iijD6dvdYjqSKUuGaX3Til3kUOLcA3hhINvHxj5unv2pHB2W70=
22
27
  - secure: YiYtCBJNfgWuzQ059RMmZxM00bs4c/GuqaEaKufLPPByJHHt3z4jCNT5lurox/RIqSYTv+1Nvgor1xJZF4VPDIhtoCpVRe3g5Pvubrp4gWQry11ta0f1JhPSrm5ORlF1hpHPfzHHSh+/YVmKcO8agQAaIgfKcXDzsE6j5QqiGWQ=
23
28
  - secure: TCrSkWTG2A7ZHxU/J82R1oRn3+ISYHOZmukvBT/OkOh35yjhtig3KhroYki67guCClVxov+ZPvCRUKgmsEoVng1ljk/ZXyyNf4QNVccEJxHCwIRiqs36jlC2ebd8g+JJUPrnnWGO/U5vBm+WlrOb4lFlIsBuCYI+FBAFYTPmKEs=
29
+ - secure: cePvBAt6j7UwybsP6Cs5a7mwaXMHDteXC1ENsNMy69qV5mae7oRKqsfavZ8ar33apNXqALXDWiDnHH7wPccMl3GXIquHE7I73lAOcEu4V+f7nHqqFuJezA12IL0swOQhDNK23C5ibkFftlpG2jTxHpaRLaDNCuv404cREalwwgA=
30
+ - secure: PLTV2N3BYlqXmDDuOuZGk83YApX3oEIpskkWHUGj8f3wBpjOSPxuLBdpSGMXRqT2kIMJqle65gqlYpwh4NcTgqL93iNAT9fh7WDyNx/SUL+Mz04kphAC6N0VPyg7nvTi33bDbkmAAFNc+1yoWKAlB2gjKKXFtdxTwMp4SjvNsfs=
31
+ - secure: nyFUNdswDOM0UgW3T/jeEvIyZPSGq+ZEpyYw6KGpwb7a5F1DbAfoSy6zJGWK6S3vKf6814e43HmawhJlhcD9KYOV783O7KYu54FTmhZ/SP9QhNV+w1hiKKRQcTlJdjbPIuO5piuMDMCPacCJa+C9YO0lhhxfZ+/6F4SNR1fteN0=
@@ -1,12 +1,13 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rbtc_arbitrage_simple (1.2.3)
4
+ rbtc_arbitrage_simple (1.4.4)
5
5
  activemodel (>= 3.1)
6
6
  activesupport (>= 3.1)
7
7
  btce (= 0.2.4)
8
- coinbase (= 1.2.4)
8
+ coinbase (= 1.2.6)
9
9
  mtgox
10
+ pony
10
11
  thor
11
12
 
12
13
  GEM
@@ -31,10 +32,10 @@ GEM
31
32
  codeclimate-test-reporter (0.2.0)
32
33
  simplecov (>= 0.7.1, < 1.0.0)
33
34
  coderay (1.1.0)
34
- coinbase (1.2.4)
35
+ coinbase (1.2.6)
35
36
  hashie (>= 1.2.0)
36
37
  httparty (>= 0.8.3)
37
- money (>= 4.0.1)
38
+ money (= 5.1.1)
38
39
  multi_json (>= 1.3.4)
39
40
  coveralls (0.7.0)
40
41
  multi_json (~> 1.3)
@@ -70,11 +71,15 @@ GEM
70
71
  rb-fsevent (>= 0.9.3)
71
72
  rb-inotify (>= 0.9)
72
73
  lumberjack (1.0.4)
74
+ mail (2.2.7)
75
+ activesupport (>= 2.3.6)
76
+ mime-types
77
+ treetop (>= 1.4.5)
73
78
  method_source (0.8.2)
74
79
  mime-types (2.0)
75
80
  minitest (4.7.5)
76
- money (6.0.0)
77
- i18n (~> 0.6.4)
81
+ money (5.1.1)
82
+ i18n (~> 0.6.0)
78
83
  monkey-patch (0.0.14)
79
84
  activesupport
80
85
  mtgox (1.1.0)
@@ -83,6 +88,9 @@ GEM
83
88
  multi_json (1.8.2)
84
89
  multi_xml (0.5.5)
85
90
  multipart-post (1.2.0)
91
+ polyglot (0.3.3)
92
+ pony (1.6.2)
93
+ mail (>= 2.0)
86
94
  pry (0.9.12.4)
87
95
  coderay (~> 1.0)
88
96
  method_source (~> 0.8)
@@ -128,6 +136,9 @@ GEM
128
136
  tilt (1.4.1)
129
137
  timers (1.1.0)
130
138
  tins (0.13.1)
139
+ treetop (1.4.15)
140
+ polyglot
141
+ polyglot (>= 0.3.1)
131
142
  tzinfo (0.3.38)
132
143
  vcr (2.8.0)
133
144
  webmock (1.16.1)
data/README.md CHANGED
@@ -8,11 +8,11 @@ A Ruby gem for executing arbitrage between the MtGox and Bitstamp bitcoin exchan
8
8
 
9
9
  [Why I open sourced a bitcoin arbitrate bot](http://hankstoever.com/posts/2-Why-I-open-sourced-a-bitcoin-arbitrage-bot)
10
10
 
11
- I'm also creating a course on [creating your own bitcoin arbitrage bot](https://www.uludum.org/funds/2)
11
+ I'm also creating a course on [creating your own bitcoin arbitrage bot](https://www.uludum.org/funds/2)
12
12
 
13
13
  Donations accepted: **16BMcqf93eEpb2aWgMkJCSQQH85WzrpbdZ**
14
14
 
15
- [![Build Status](https://travis-ci.org/hstove/rbtc_arbitrage.png?branch=master)](https://travis-ci.org/hstove/rbtc_arbitrage)
15
+ [![Build Status](https://travis-ci.org/hstove/rbtc_arbitrage.png?branch=no-native)](https://travis-ci.org/hstove/rbtc_arbitrage)
16
16
  [![Coverage Status](https://coveralls.io/repos/hstove/rbtc_arbitrage/badge.png)](https://coveralls.io/r/hstove/rbtc_arbitrage)
17
17
  [![Code Climate](https://codeclimate.com/github/hstove/rbtc_arbitrage.png)](https://codeclimate.com/github/hstove/rbtc_arbitrage)
18
18
 
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
3
4
  require 'rbtc_arbitrage'
4
5
  RbtcArbitrage::CLI.start ARGV
@@ -3,6 +3,7 @@ require 'mtgox'
3
3
  require_relative 'rbtc_arbitrage/campbx.rb'
4
4
  require 'btce'
5
5
  require 'coinbase'
6
+ require 'pony'
6
7
  require_relative 'rbtc_arbitrage/client.rb'
7
8
  Dir["#{File.dirname(__FILE__)}/rbtc_arbitrage/**/*.rb"].each { |f| require(f) }
8
9
 
@@ -9,6 +9,7 @@ module RbtcArbitrage
9
9
  option :buyer, type: :string, default: "campbx"
10
10
  option :seller, type: :string, default: "mtgox"
11
11
  option :repeat, type: :numeric, default: nil
12
+ option :notify, type: :boolean, default: false
12
13
  def trade
13
14
  RbtcArbitrage::Trader.new(options).trade
14
15
  end
@@ -13,11 +13,14 @@ module RbtcArbitrage
13
13
  @options = {}
14
14
  set_key opts, :volume, 0.01
15
15
  set_key opts, :cutoff, 2
16
- set_key opts, :logger, Logger.new(STDOUT)
16
+ default_logger = Logger.new($stdout)
17
+ default_logger.datetime_format = "%^b %e %Y %l:%M:%S %p %z"
18
+ set_key opts, :logger, default_logger
17
19
  set_key opts, :verbose, true
18
20
  set_key opts, :live, false
19
21
  set_key opts, :repeat, nil
20
22
  exchange = opts[:buyer] || :campbx
23
+ set_key opts, :notify, false
21
24
  @buy_client = client_for_exchange(exchange)
22
25
  exchange = opts[:seller] || :mtgox
23
26
  @sell_client = client_for_exchange(exchange)
@@ -38,15 +41,18 @@ module RbtcArbitrage
38
41
 
39
42
  execute_trade if options[:live]
40
43
 
44
+ notify
45
+
41
46
  if @options[:repeat]
42
47
  trade_again
43
48
  end
49
+
44
50
  self
45
51
  end
46
52
 
47
53
  def trade_again
48
54
  sleep @options[:repeat]
49
- @logger.info " - " if @options[:verbose]
55
+ logger.info " - " if @options[:verbose]
50
56
  @buy_client = @buy_client.class.new(@options)
51
57
  @sell_client = @sell_client.class.new(@options)
52
58
  trade
@@ -104,6 +110,15 @@ module RbtcArbitrage
104
110
  [@sell_client, @buy_client].each do |client|
105
111
  client.validate_env
106
112
  end
113
+ if options[:notify]
114
+ ["PASSWORD","USERNAME","EMAIL"].each do |key|
115
+ key = "SENDGRID_#{key}"
116
+ unless ENV[key]
117
+ raise ArgumentError, "Exiting because missing required ENV variable $#{key}."
118
+ end
119
+ end
120
+ setup_pony
121
+ end
107
122
  end
108
123
 
109
124
  def client_for_exchange market
@@ -119,5 +134,60 @@ module RbtcArbitrage
119
134
  raise ArgumentError, "Invalid exchange - '#{market}'"
120
135
  end
121
136
  end
137
+
138
+ def notify
139
+ return false unless options[:notify]
140
+ return false unless @percent > options[:cutoff]
141
+ setup_pony
142
+
143
+ options[:logger].info "Sending email to #{ENV['SENDGRID_EMAIL']}"
144
+ Pony.mail({
145
+ body: notification,
146
+ to: ENV['SENDGRID_EMAIL'],
147
+ })
148
+ end
149
+
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
+ }
165
+ end
166
+
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
122
192
  end
123
193
  end
@@ -1,3 +1,3 @@
1
1
  module RbtcArbitrage
2
- VERSION = "1.2.3"
2
+ VERSION = "1.4.4"
3
3
  end
@@ -26,5 +26,6 @@ Gem::Specification.new do |spec|
26
26
  spec.add_dependency "activesupport", ">= 3.1"
27
27
  spec.add_dependency "thor"
28
28
  spec.add_dependency "btce", '0.2.4'
29
- spec.add_dependency "coinbase", '1.2.4'
29
+ spec.add_dependency "coinbase", '1.2.6'
30
+ spec.add_dependency "pony"
30
31
  end
@@ -37,6 +37,20 @@ describe RbtcArbitrage::Trader do
37
37
  end
38
38
  end
39
39
  end
40
+
41
+ ["PASSWORD","USERNAME","EMAIL"].each do |key|
42
+ key = "SENDGRID_#{key}"
43
+ it "should raise if --notify and not ENV[#{key}]" do
44
+ trader.sell_client.stub(:validate_env)
45
+ trader.buy_client.stub(:validate_env)
46
+ old_val = ENV[key]
47
+ ENV[key] = nil
48
+ trader.options[:notify] = true
49
+ expect { trader.validate_env }.to raise_error(ArgumentError)
50
+ trader.options[:notify] = false
51
+ expect { trader.validate_env }.not_to raise_error
52
+ end
53
+ end
40
54
  end
41
55
 
42
56
  describe "#fetch_prices" do
@@ -71,6 +85,7 @@ describe RbtcArbitrage::Trader do
71
85
  live: true,
72
86
  seller: :btce,
73
87
  buyer: :mtgox,
88
+ notify: true,
74
89
  }
75
90
  }
76
91
 
@@ -142,6 +157,7 @@ describe RbtcArbitrage::Trader do
142
157
  describe "#trade" do
143
158
  it "calls the right methods" do
144
159
  trader.should_receive(:fetch_prices)
160
+ trader.should_receive(:notify)
145
161
  trader.should_not_receive(:log_info)
146
162
  trader.should_not_receive(:execute_trade)
147
163
 
@@ -183,15 +199,29 @@ describe RbtcArbitrage::Trader do
183
199
  end
184
200
 
185
201
  describe "#log_info" do
186
- it "calls logger.info" do
202
+ before :each do
187
203
  trader.buyer[:price] = 1
188
204
  trader.seller[:price] = 1
189
205
  trader.instance_variable_set :@percent, 1
190
206
  trader.instance_variable_set :@paid, 1
191
207
  trader.instance_variable_set :@received, 1
208
+ end
209
+ it "calls logger.info" do
192
210
  trader.logger.should_receive(:info).exactly(5).times
193
211
  trader.log_info
194
212
  end
213
+
214
+ it "formats the log correctly" do
215
+ FileUtils.mkdir_p('tmp')
216
+ date = DateTime.now.strftime "%^b %e %Y %l"
217
+ logger = Logger.new('tmp/log.info')
218
+ logger.datetime_format = trader.logger.datetime_format
219
+ trader.options[:logger] = logger
220
+ trader.log_info
221
+ contents = File.read("tmp/log.info")
222
+ contents.should include(date)
223
+ contents.should include(" INFO -- ")
224
+ end
195
225
  end
196
226
 
197
227
  describe "#logger" do
@@ -225,4 +255,82 @@ describe RbtcArbitrage::Trader do
225
255
  end
226
256
  end
227
257
 
258
+ describe "#notify" do
259
+ it "returns false when notify == false" do
260
+ trader.notify.should == false
261
+ end
262
+
263
+ it "returns false unless cutoff < percent" do
264
+ trader.options[:notify] = true
265
+ trader.instance_variable_set :@percent, 1
266
+ trader.notify.should == false
267
+ end
268
+
269
+ it "calls Sendgrid when notify == true" do
270
+ trader.options[:notify] = true
271
+ trader.instance_variable_set :@percent, 3
272
+ trader.instance_variable_set :@paid, 5
273
+ trader.instance_variable_set :@received, 6
274
+ trader.buyer[:price] = 1
275
+ trader.seller[:price] = 1
276
+
277
+ trader.options[:logger].should_receive(:info)
278
+ Pony.should_receive(:mail).with({
279
+ to: ENV['SENDGRID_EMAIL'],
280
+ body: trader.notification,
281
+ })
282
+
283
+ trader.notify
284
+ end
285
+ end
286
+
287
+ describe "#setup_pony" do
288
+ it "gets called on validation when --notify" do
289
+ ["PASSWORD","USERNAME","EMAIL"].each do |key|
290
+ key = "SENDGRID_#{key}"
291
+ ENV[key] ||= "something"
292
+ end
293
+ trader.options[:notify] = true
294
+ trader.should_receive(:setup_pony).once
295
+ trader.validate_env
296
+ end
297
+ it "sets up pony correctly" do
298
+ opts = {
299
+ from: "info@example.org",
300
+ subject: "rbtc_arbitrage notification",
301
+ :via => :smtp,
302
+ :via_options => {
303
+ :address => 'smtp.sendgrid.net',
304
+ :port => '587',
305
+ :domain => 'heroku.com',
306
+ :user_name => ENV['SENDGRID_USERNAME'],
307
+ :password => ENV['SENDGRID_PASSWORD'],
308
+ :authentication => :plain,
309
+ :enable_starttls_auto => true
310
+ }
311
+ }
312
+ Pony.should_receive(:options=).with(opts)
313
+ trader.setup_pony
314
+ end
315
+ end
316
+
317
+ describe "#notification" do
318
+ it "includes the right values" do
319
+ trader.instance_variable_set :@percent, 3
320
+ trader.instance_variable_set :@paid, 5
321
+ trader.instance_variable_set :@received, 8
322
+ trader.buyer[:price] = 1.00453
323
+ trader.seller[:price] = 3.50453
324
+
325
+ value = trader.notification
326
+ value.should include("$1.0")
327
+ value.should include("$3.5")
328
+ value.should include("$3.0")
329
+ value.should include("3.0%")
330
+ end
331
+ context "--live" do
332
+ it "should say that it made a trade"
333
+ end
334
+ end
335
+
228
336
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rbtc_arbitrage_simple
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.3
4
+ version: 1.4.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hank Stoever
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-12-23 00:00:00.000000000 Z
11
+ date: 2014-01-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -114,14 +114,28 @@ dependencies:
114
114
  requirements:
115
115
  - - '='
116
116
  - !ruby/object:Gem::Version
117
- version: 1.2.4
117
+ version: 1.2.6
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - '='
123
123
  - !ruby/object:Gem::Version
124
- version: 1.2.4
124
+ version: 1.2.6
125
+ - !ruby/object:Gem::Dependency
126
+ name: pony
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - '>='
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - '>='
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
125
139
  description: A gem for conducting arbitrage with Bitcoin.
126
140
  email:
127
141
  - hstove@gmail.com