Skip to content

Commit

Permalink
Merge 179b5ee into 0186ac4
Browse files Browse the repository at this point in the history
  • Loading branch information
tocheto committed Dec 5, 2016
2 parents 0186ac4 + 179b5ee commit 300df79
Show file tree
Hide file tree
Showing 17 changed files with 986 additions and 23 deletions.
7 changes: 4 additions & 3 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,18 @@ source 'https://rubygems.org'
gemspec
group :development do
gem 'rspec'
gem "activemodel", ">= 3.1"
gem "activesupport", ">= 3.1"
gem "activemodel"
gem "activesupport"
gem 'guard'
gem 'ruby_gntp'
gem 'guard-rspec'
gem 'simplecov'
gem 'coveralls', require: false
gem "webmock"
gem "webmock", "1.16"
gem 'vcr'
gem 'codeclimate-test-reporter'
gem 'hashie'
gem 'sinatra'
gem 'dotenv'
gem 'mexbt', "0.0.9"
end
44 changes: 26 additions & 18 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ PATH
coinbase (= 2.1.0)
faraday (= 0.8.8)
mail (= 2.6.1)
mexbt (= 0.0.9)
pony (= 1.10)
rake (= 10.1.1)
stathat (= 0.1.7)
Expand All @@ -20,16 +21,16 @@ PATH
GEM
remote: https://rubygems.org/
specs:
activemodel (4.1.5)
activesupport (= 4.1.5)
activemodel (4.1.12)
activesupport (= 4.1.12)
builder (~> 3.1)
activesupport (4.1.5)
activesupport (4.1.12)
i18n (~> 0.6, >= 0.6.9)
json (~> 1.7, >= 1.7.7)
minitest (~> 5.1)
thread_safe (~> 0.1)
tzinfo (~> 1.1)
addressable (2.3.5)
addressable (2.3.8)
bitstamp-rbtc-arbitrage (0.4.0)
activemodel (>= 3.1)
activesupport
Expand Down Expand Up @@ -58,9 +59,9 @@ GEM
simplecov (>= 0.7)
term-ansicolor
thor
crack (0.4.1)
safe_yaml (~> 0.9.0)
curb (0.8.6)
crack (0.4.2)
safe_yaml (~> 1.0.0)
curb (0.8.8)
diff-lcs (1.2.5)
docile (1.1.1)
dotenv (0.11.1)
Expand All @@ -80,12 +81,12 @@ GEM
guard (>= 2.1.1)
rspec (~> 3.0.0.beta, >= 2.14, < 4.0)
hashie (2.0.5)
httparty (0.13.1)
httparty (0.13.5)
json (~> 1.8)
multi_xml (>= 0.5.2)
i18n (0.6.9)
json (1.8.1)
jwt (1.0.0)
json (1.8.3)
jwt (1.5.1)
listen (2.4.0)
celluloid (>= 0.15.2)
rb-fsevent (>= 0.9.3)
Expand All @@ -94,17 +95,21 @@ GEM
mail (2.6.1)
mime-types (>= 1.16, < 3)
method_source (0.8.2)
mexbt (0.0.9)
activesupport (>= 4.1.8)
rest_client (= 1.8.2)
mime-types (2.0)
minitest (5.4.0)
minitest (5.7.0)
monetize (0.3.0)
money (~> 6.1.0.beta1)
money (6.1.1)
i18n (~> 0.6.4)
monkey-patch (0.0.16)
monkey-patch (0.0.17)
activesupport
multi_json (1.10.1)
multi_xml (0.5.5)
multipart-post (1.2.0)
netrc (0.7.9)
oauth2 (0.9.4)
faraday (>= 0.8, < 0.10)
jwt (~> 1.0)
Expand All @@ -126,6 +131,8 @@ GEM
ffi (>= 0.5.0)
rest-client (1.6.7)
mime-types (>= 1.16)
rest_client (1.8.2)
netrc (~> 0.7.7)
rspec (3.0.0.beta1)
rspec-core (= 3.0.0.beta1)
rspec-expectations (= 3.0.0.beta1)
Expand All @@ -140,7 +147,7 @@ GEM
rspec-support (3.0.0.beta1)
ruby-hmac (0.4.0)
ruby_gntp (0.3.4)
safe_yaml (0.9.7)
safe_yaml (1.0.4)
simplecov (0.8.2)
docile (~> 1.1.0)
multi_json
Expand All @@ -156,33 +163,34 @@ GEM
term-ansicolor (1.2.2)
tins (~> 0.8)
thor (0.18.1)
thread_safe (0.3.4)
thread_safe (0.3.5)
tilt (1.4.1)
timers (1.1.0)
tins (0.13.1)
tzinfo (1.2.2)
thread_safe (~> 0.1)
vcr (2.8.0)
webmock (1.16.1)
webmock (1.16.0)
addressable (>= 2.2.7)
crack (>= 0.3.2)

PLATFORMS
ruby

DEPENDENCIES
activemodel (>= 3.1)
activesupport (>= 3.1)
activemodel
activesupport
codeclimate-test-reporter
coveralls
dotenv
guard
guard-rspec
hashie
mexbt (= 0.0.9)
rbtc_arbitrage!
rspec
ruby_gntp
simplecov
sinatra
vcr
webmock
webmock (= 1.16)
91 changes: 91 additions & 0 deletions lib/rbtc_arbitrage/bitso.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
## Ruby module for working with BITSO API
## July 2015

require 'json'
require 'net/http'
require 'uri'
require 'openssl'

class Bitso
API_BASE = 'https://api.bitso.com/v2/'
CALLS = {
'ticker' => [FALSE, [] ],
'order_book' => [FALSE, ['book', 'group'] ],
'transactions' => [TRUE, [] ],
'balance' => [TRUE, [] ],
'user_transactions' => [TRUE, ['offset', 'limit', 'sort', 'book'] ],
'open_orders' => [TRUE, ['book'] ],
'lookup_order' => [TRUE, [ 'id' ] ],
'cancel_order' => [TRUE, [ 'id' ] ],
'buy' => [TRUE, [ 'amount', 'price'] ],
'sell' => [TRUE, [ 'amount', 'price'] ],
'bitcoin_deposit_address' => [TRUE, [] ],
'bitcoin_withdrawal' => [TRUE, [ 'address', 'amount' ] ]
}
@@last = Time.new(0)

def initialize(client_id, key, secret)
@client_id = client_id
@key = key
@secret = secret

CALLS.each do |name|
define_singleton_method name[0], lambda { |*args|
data = CALLS[name[0]]
api_request( [name[0],data[0]], Hash[data[1].zip( args )] )
}
end
end

def api_request( info, post_data={} )
url, auth = info
uri = URI.parse(API_BASE + url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl=TRUE
# CampBX advises latency can be >4 minutes when markets are volatile
http.read_timeout = 300
res = nil

request = Net::HTTP::Get.new(uri.request_uri)
if auth then
nonce = (Time.now.to_f*10000).to_i.to_s
sign_string = (nonce + @client_id + @key)
signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), @secret, sign_string)

post_data.merge!({
'key' => @key,
'nonce' => nonce,
'signature' => signature.upcase
})

request = Net::HTTP::Post.new(uri.request_uri)
request.set_form_data( post_data )
end

make_request(http, request)
end

def make_request http, request
# CampBX API: max 1 request per 500ms
delta = Time.now - @@last
#puts delta*1000
if delta*1000 <= 500 then
#puts "sleeping! for #{0.5 - delta}"
sleep(0.5 - delta)
end

res = http.request(request)

@@last = Time.now # Update time after request returns
if res.message == 'OK' then # HTTP OK
begin
JSON.parse( res.body )
rescue
res.body
end
else # HTTP ERROR
warn "HTTP Error: + #{res.code}"
end
end

end
4 changes: 2 additions & 2 deletions lib/rbtc_arbitrage/cli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ class CLI < Thor
option :cutoff, type: :numeric, default: 2, desc: "The minimum profit level required to execute a trade."
option :volume, type: :numeric, default: 0.01, desc: "The amount of bitcoins to trade per transaction."
option :verbose, type: :boolean, default: true, desc: "Whether you wish to log information."
option :buyer, type: :string, default: "bitstamp"
option :seller, type: :string, default: "campbx"
option :buyer, type: :string, default: "bitso"
option :seller, type: :string, default: "bitso"
option :repeat, type: :numeric, default: nil
option :notify, type: :boolean, default: false
def trade
Expand Down
56 changes: 56 additions & 0 deletions lib/rbtc_arbitrage/clients/bitso_client.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
module RbtcArbitrage
module Clients
class BitsoClient
include RbtcArbitrage::Client

def exchange
:bitso
end

def balance
return @balance if @balance
balances = interface.balance
puts "balances: #{balances['mxn_available']}"

@balance = [balances['btc_available'].to_f, balances['mxn_available'].to_f]
end

def interface
@interface ||= Bitso.new(ENV["BITSO_CLIENT_ID"], ENV["BITSO_KEY"], ENV["BITSO_SECRET"])
end

def validate_env
validate_keys :bitso_key, :bitso_client_id, :bitso_secret
end

def price action
return @price if @price
action = {
buy: 'ask',
sell: 'bid',
}[action]

@price = interface.ticker[action].to_f
end

def trade action
price(action) unless @price #memoize
multiple = {
buy: 1,
sell: -1,
}[action]
price = (@price + 0.001 * multiple)
amount = @options[:volume]
interface.send(action, *[amount, price])
end

def transfer other_client
interface.bitcoin_withdrawal(other_client.address, @options[:volume])
end

def address
@address ||= interface.bitcoin_deposit_address
end
end
end
end
59 changes: 59 additions & 0 deletions lib/rbtc_arbitrage/clients/mexbt_client.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
module RbtcArbitrage
module Clients
class MexbtClient
include RbtcArbitrage::Client

def balance
return @balance if @balance
balances = interface.balance
@balance = [balances[0].to_f, balances[1].to_f]
end

def validate_env
validate_keys :mexbt_public_key, :mexbt_private_key, :mexbt_user_id
Mexbt.configure do |config|
config.public_key = ENV['MEXBT_PUBLIC_KEY']
config.private_key = ENV['MEXBT_PRIVATE_KEY']
config.user_id = ENV['MEXBT_USER_ID'] # Your registered email address
end
end

def exchange
:mexbt
end

def interface
@interface ||= Mexbt::Account.new
end

def price action
return @price if @price
action = {
buy: :ask,
sell: :bid,
}[action]
@price = Mexbt.ticker[action].to_f
end

def trade action
price(action) unless @price #memoize
multiple = {
buy: 1,
sell: -1
}[action]
mexbt_options = {
price: (@price + 0.001 * multiple),
amount: @options[:volume],
side: action,
currency_pair: 'btcmxn'
}

interface.create_order(mexbt_options)
end

def transfer other_client
Mexbt.transfer(@options[:volume], other_client.address)
end
end
end
end
1 change: 1 addition & 0 deletions rbtc_arbitrage.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,5 @@ Gem::Specification.new do |spec|
spec.add_dependency "bitstamp-rbtc-arbitrage", "0.4.0"
spec.add_dependency "tzinfo", '~> 1.1'
spec.add_dependency "mail", "2.6.1"
spec.add_dependency 'mexbt', "0.0.9"
end
Loading

0 comments on commit 300df79

Please sign in to comment.