-
Notifications
You must be signed in to change notification settings - Fork 94
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
17 changed files
with
986 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.