Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

a #25

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open

a #25

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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