huo 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/.rspec +3 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +50 -0
- data/huo.gemspec +14 -0
- data/lib/huo.rb +5 -0
- data/lib/huo/market.rb +38 -0
- data/lib/huo/trade.rb +121 -0
- data/spec/spec_helper.rb +76 -0
- data/spec/unit/market_spec.rb +18 -0
- data/spec/unit/trade_spec.rb +46 -0
- metadata +58 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 36f03c83926d4cf08e53e1a0a7e8e8999d1ebcba
|
4
|
+
data.tar.gz: d4ab97bb58b58501dbe94d2438263eb03b3a730e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b8767ad3abaf6e65f44020e6f735f8238a81ad6bb8fe83a52d6bd240183517d9d49f6739646916a81460ddd508245a867e8578663fefd4c8b043e088569abcd7
|
7
|
+
data.tar.gz: 04caf012fa9da168abad4bc550f2ae520dd76cde1af07307713aeb671cf68f86379ea73266b94efd8f8a93a6e03b27b378cb7f7a42c37085e8e2720325cfc3c0
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
GEM
|
2
|
+
remote: https://rubygems.org/
|
3
|
+
specs:
|
4
|
+
awesome_print (1.6.1)
|
5
|
+
coderay (1.1.0)
|
6
|
+
diff-lcs (1.2.5)
|
7
|
+
domain_name (0.5.25)
|
8
|
+
unf (>= 0.0.5, < 1.0.0)
|
9
|
+
http-cookie (1.0.2)
|
10
|
+
domain_name (~> 0.5)
|
11
|
+
method_source (0.8.2)
|
12
|
+
mime-types (2.99)
|
13
|
+
netrc (0.11.0)
|
14
|
+
pry (0.10.3)
|
15
|
+
coderay (~> 1.1.0)
|
16
|
+
method_source (~> 0.8.1)
|
17
|
+
slop (~> 3.4)
|
18
|
+
rest-client (1.8.0)
|
19
|
+
http-cookie (>= 1.0.2, < 2.0)
|
20
|
+
mime-types (>= 1.16, < 3.0)
|
21
|
+
netrc (~> 0.7)
|
22
|
+
rspec (3.3.0)
|
23
|
+
rspec-core (~> 3.3.0)
|
24
|
+
rspec-expectations (~> 3.3.0)
|
25
|
+
rspec-mocks (~> 3.3.0)
|
26
|
+
rspec-core (3.3.2)
|
27
|
+
rspec-support (~> 3.3.0)
|
28
|
+
rspec-expectations (3.3.1)
|
29
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
30
|
+
rspec-support (~> 3.3.0)
|
31
|
+
rspec-mocks (3.3.2)
|
32
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
33
|
+
rspec-support (~> 3.3.0)
|
34
|
+
rspec-support (3.3.0)
|
35
|
+
slop (3.6.0)
|
36
|
+
unf (0.1.4)
|
37
|
+
unf_ext
|
38
|
+
unf_ext (0.0.7.1)
|
39
|
+
|
40
|
+
PLATFORMS
|
41
|
+
ruby
|
42
|
+
|
43
|
+
DEPENDENCIES
|
44
|
+
awesome_print
|
45
|
+
pry
|
46
|
+
rest-client
|
47
|
+
rspec
|
48
|
+
|
49
|
+
BUNDLED WITH
|
50
|
+
1.10.6
|
data/huo.gemspec
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'huo'
|
3
|
+
s.version = '0.0.1'
|
4
|
+
s.date = '2015-12-27'
|
5
|
+
s.summary = 'huo'
|
6
|
+
s.description = 'Huobi SDK for Ruby'
|
7
|
+
s.authors = ['Ming Qu']
|
8
|
+
s.email = 'qucool@gmail.com'
|
9
|
+
s.files = `git ls-files`.split("\n")
|
10
|
+
s.test_files = `git ls-files -- spec/*`.split("\n")
|
11
|
+
s.homepage = 'http://rubygems.org/gems/huo'
|
12
|
+
s.license = 'MIT'
|
13
|
+
end
|
14
|
+
|
data/lib/huo.rb
ADDED
data/lib/huo/market.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'rest-client'
|
2
|
+
|
3
|
+
module Huo
|
4
|
+
class Market
|
5
|
+
DETAIL_API_PATH = 'http://api.huobi.com/staticmarket/detail_btc_json.js'
|
6
|
+
SIMPLE_API_PATH = 'http://api.huobi.com/staticmarket/ticker_btc_json.js'
|
7
|
+
|
8
|
+
def get_simple_data
|
9
|
+
json = nil
|
10
|
+
begin
|
11
|
+
json = RestClient.get(SIMPLE_API_PATH)
|
12
|
+
rescue SocketError
|
13
|
+
return nil
|
14
|
+
end
|
15
|
+
JSON.parse(json).tap { |h| h['time'] = Time.at(h['time'].to_i) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def get_detail_data
|
19
|
+
json = RestClient.get(DETAIL_API_PATH)
|
20
|
+
JSON.parse(json)
|
21
|
+
end
|
22
|
+
|
23
|
+
def api_path_for(param = '1min')
|
24
|
+
period = case param
|
25
|
+
when '1min' then '001'
|
26
|
+
when '5min' then '005'
|
27
|
+
when '15min' then '015'
|
28
|
+
when '30min' then '030'
|
29
|
+
when '60min' then '060'
|
30
|
+
when 'day' then '100'
|
31
|
+
when 'week' then '200'
|
32
|
+
when 'month' then '300'
|
33
|
+
when 'year' then '400'
|
34
|
+
end
|
35
|
+
"http://api.huobi.com/staticmarket/btc_kline_#{period}_json.js"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/huo/trade.rb
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'digest'
|
2
|
+
require 'yaml'
|
3
|
+
require 'rest-client'
|
4
|
+
|
5
|
+
module Huo
|
6
|
+
REQUEST_URL = 'https://api.huobi.com/apiv3'
|
7
|
+
REQUEST_HEADER = {
|
8
|
+
'Content-Type' => 'application/x-www-form-urlencoded'
|
9
|
+
}
|
10
|
+
|
11
|
+
class Trade
|
12
|
+
def initialize(options = {})
|
13
|
+
path = options[:tokens_path]
|
14
|
+
config = path ? YAML.load_file(path) : {}
|
15
|
+
@access_key = config['access_key'] || options[:access_key]
|
16
|
+
@secret_key = config['secret_key'] || options[:secret_key]
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_account_info
|
20
|
+
get(method: __method__)
|
21
|
+
end
|
22
|
+
|
23
|
+
def get_orders(options = {})
|
24
|
+
get(method: __method__, coin_type: 1)
|
25
|
+
end
|
26
|
+
|
27
|
+
def order_info
|
28
|
+
end
|
29
|
+
|
30
|
+
def buy(options = {})
|
31
|
+
args = {
|
32
|
+
method: __method__,
|
33
|
+
coin_type: 1,
|
34
|
+
price: options.fetch(:price),
|
35
|
+
amount: options.fetch(:btc_amount, 0.001)
|
36
|
+
}
|
37
|
+
get(args)
|
38
|
+
end
|
39
|
+
|
40
|
+
def buy_market(options = {})
|
41
|
+
args = {
|
42
|
+
method: __method__,
|
43
|
+
coin_type: 1,
|
44
|
+
amount: options.fetch(:rmb_amount, 1)
|
45
|
+
}
|
46
|
+
get(args)
|
47
|
+
end
|
48
|
+
|
49
|
+
def sell(options = {})
|
50
|
+
args = {
|
51
|
+
method: __method__,
|
52
|
+
coin_type: 1,
|
53
|
+
price: options.fetch(:price),
|
54
|
+
amount: options.fetch(:amount, 0.001)
|
55
|
+
}
|
56
|
+
get(args)
|
57
|
+
end
|
58
|
+
|
59
|
+
def sell_market(options = {})
|
60
|
+
args = {
|
61
|
+
method: __method__,
|
62
|
+
coin_type: 1,
|
63
|
+
amount: options.fetch(:btc_amount, 0.001)
|
64
|
+
}
|
65
|
+
get(args)
|
66
|
+
end
|
67
|
+
|
68
|
+
def get(options)
|
69
|
+
params = options.fetch(:params, options)
|
70
|
+
digest = options.fetch(:digest, params)
|
71
|
+
digest_keys = digest.is_a?(Hash) ? digest.keys : digest
|
72
|
+
|
73
|
+
rest_options = {
|
74
|
+
params: pack_params(params, digest_keys),
|
75
|
+
header: REQUEST_HEADER,
|
76
|
+
accept: :json
|
77
|
+
}
|
78
|
+
response = RestClient.get(REQUEST_URL, rest_options)
|
79
|
+
normalize_json(response)
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def to_param(hash)
|
85
|
+
hash.sort.map {|a| "#{a[0]}=#{a[1]}"}.join('&')
|
86
|
+
end
|
87
|
+
|
88
|
+
def normalize_json(json)
|
89
|
+
object = JSON.parse(json)
|
90
|
+
return object if object.is_a? Array
|
91
|
+
new_hash = {}
|
92
|
+
object.each do |key, value|
|
93
|
+
if value.is_a?(String) && value.match(/\A\d+\.\d+\z/)
|
94
|
+
new_hash[key] = value.to_f
|
95
|
+
else
|
96
|
+
new_hash[key] = value
|
97
|
+
end
|
98
|
+
end
|
99
|
+
new_hash
|
100
|
+
end
|
101
|
+
|
102
|
+
def pack_params(params, digest_keys)
|
103
|
+
with_signature(with_tokens(with_created_at params), digest_keys)
|
104
|
+
end
|
105
|
+
|
106
|
+
def with_created_at(params)
|
107
|
+
params.merge(created: Time.now.to_i)
|
108
|
+
end
|
109
|
+
|
110
|
+
def with_tokens(params)
|
111
|
+
params.merge(access_key: @access_key, secret_key: @secret_key)
|
112
|
+
end
|
113
|
+
|
114
|
+
def with_signature(params, digest_keys)
|
115
|
+
digest_keys << :access_key << :secret_key << :created
|
116
|
+
digest_params = params.select { |k, v| digest_keys.include?(k) }
|
117
|
+
sign = Digest::MD5.hexdigest(to_param(digest_params))
|
118
|
+
params.merge(sign: sign)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
RSpec.configure do |config|
|
2
|
+
# rspec-expectations config goes here. You can use an alternate
|
3
|
+
# assertion/expectation library such as wrong or the stdlib/minitest
|
4
|
+
# assertions if you prefer.
|
5
|
+
config.expect_with :rspec do |expectations|
|
6
|
+
# This option will default to `true` in RSpec 4. It makes the `description`
|
7
|
+
# and `failure_message` of custom matchers include text for helper methods
|
8
|
+
# defined using `chain`, e.g.:
|
9
|
+
# be_bigger_than(2).and_smaller_than(4).description
|
10
|
+
# # => "be bigger than 2 and smaller than 4"
|
11
|
+
# ...rather than:
|
12
|
+
# # => "be bigger than 2"
|
13
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
14
|
+
end
|
15
|
+
|
16
|
+
# rspec-mocks config goes here. You can use an alternate test double
|
17
|
+
# library (such as bogus or mocha) by changing the `mock_with` option here.
|
18
|
+
config.mock_with :rspec do |mocks|
|
19
|
+
# Prevents you from mocking or stubbing a method that does not exist on
|
20
|
+
# a real object. This is generally recommended, and will default to
|
21
|
+
# `true` in RSpec 4.
|
22
|
+
mocks.verify_partial_doubles = true
|
23
|
+
end
|
24
|
+
|
25
|
+
# The settings below are suggested to provide a good initial experience
|
26
|
+
# with RSpec, but feel free to customize to your heart's content.
|
27
|
+
# These two settings work together to allow you to limit a spec run
|
28
|
+
# to individual examples or groups you care about by tagging them with
|
29
|
+
# `:focus` metadata. When nothing is tagged with `:focus`, all examples
|
30
|
+
# get run.
|
31
|
+
config.filter_run :focus
|
32
|
+
config.run_all_when_everything_filtered = true
|
33
|
+
|
34
|
+
# Allows RSpec to persist some state between runs in order to support
|
35
|
+
# the `--only-failures` and `--next-failure` CLI options. We recommend
|
36
|
+
# you configure your source control system to ignore this file.
|
37
|
+
config.example_status_persistence_file_path = "spec/examples.txt"
|
38
|
+
|
39
|
+
# Limits the available syntax to the non-monkey patched syntax that is
|
40
|
+
# recommended. For more details, see:
|
41
|
+
# - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
|
42
|
+
# - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
|
43
|
+
# - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
|
44
|
+
config.disable_monkey_patching!
|
45
|
+
|
46
|
+
# This setting enables warnings. It's recommended, but in some cases may
|
47
|
+
# be too noisy due to issues in dependencies.
|
48
|
+
# config.warnings = true
|
49
|
+
|
50
|
+
# Many RSpec users commonly either run the entire suite or an individual
|
51
|
+
# file, and it's useful to allow more verbose output when running an
|
52
|
+
# individual spec file.
|
53
|
+
# if config.files_to_run.one?
|
54
|
+
# Use the documentation formatter for detailed output,
|
55
|
+
# unless a formatter has already been configured
|
56
|
+
# (e.g. via a command-line flag).
|
57
|
+
# config.default_formatter = 'doc'
|
58
|
+
# end
|
59
|
+
|
60
|
+
# Print the 10 slowest examples and example groups at the
|
61
|
+
# end of the spec run, to help surface which specs are running
|
62
|
+
# particularly slow.
|
63
|
+
# config.profile_examples = 10
|
64
|
+
|
65
|
+
# Run specs in random order to surface order dependencies. If you find an
|
66
|
+
# order dependency and want to debug it, you can fix the order by providing
|
67
|
+
# the seed, which is printed after each run.
|
68
|
+
# --seed 1234
|
69
|
+
config.order = :random
|
70
|
+
|
71
|
+
# Seed global randomization in this process using the `--seed` CLI option.
|
72
|
+
# Setting this allows you to use `--seed` to deterministically reproduce
|
73
|
+
# test failures related to randomization by passing the same `--seed` value
|
74
|
+
# as the one that triggered the failure.
|
75
|
+
Kernel.srand config.seed
|
76
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'pry'
|
2
|
+
require 'awesome_print'
|
3
|
+
require_relative '../spec_helper'
|
4
|
+
require_relative '../../lib/huo/market'
|
5
|
+
|
6
|
+
RSpec.describe Huo::Market do
|
7
|
+
let(:market) { Huo::Market.new }
|
8
|
+
|
9
|
+
it '#get_detail_data' do
|
10
|
+
response = market.get_detail_data
|
11
|
+
expect(response['top_buy'].count).to eq 5
|
12
|
+
end
|
13
|
+
|
14
|
+
it '#get_simple_data' do
|
15
|
+
response = market.get_simple_data
|
16
|
+
expect(response['ticker']['last']).not_to be_nil
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'pry'
|
2
|
+
require 'awesome_print'
|
3
|
+
require_relative '../spec_helper'
|
4
|
+
require_relative '../../lib/huo/trade'
|
5
|
+
|
6
|
+
RSpec.describe Huo::Trade do
|
7
|
+
let(:trade) do
|
8
|
+
path = File.expand_path('../../../config/tokens.yml', __FILE__)
|
9
|
+
Huo::Trade.new(tokens_path: path)
|
10
|
+
end
|
11
|
+
|
12
|
+
it '#get_account_info' do
|
13
|
+
response = trade.get_account_info
|
14
|
+
ap response
|
15
|
+
expect(response['available_cny_display']).to be_a Float
|
16
|
+
end
|
17
|
+
|
18
|
+
it '#get_orders' do
|
19
|
+
response = trade.get_orders
|
20
|
+
expect(response).to be_a Array
|
21
|
+
end
|
22
|
+
|
23
|
+
it '#buy_market', :skip do
|
24
|
+
response = trade.buy_market
|
25
|
+
expect(response['result']).to eq 'success'
|
26
|
+
expect(response['id']).to be_a Fixnum
|
27
|
+
end
|
28
|
+
|
29
|
+
it '#sell_market', :skip do
|
30
|
+
response = trade.sell_market
|
31
|
+
expect(response['result']).to eq 'success'
|
32
|
+
expect(response['id']).to be_a Fixnum
|
33
|
+
end
|
34
|
+
|
35
|
+
it '#buy', :skip do
|
36
|
+
response = trade.buy(price: 2995)
|
37
|
+
expect(response['result']).to eq 'success'
|
38
|
+
expect(response['id']).to be_a Fixnum
|
39
|
+
end
|
40
|
+
|
41
|
+
it '#sell', :skip do
|
42
|
+
response = trade.sell(price: 2998)
|
43
|
+
expect(response['result']).to eq 'success'
|
44
|
+
expect(response['id']).to be_a Fixnum
|
45
|
+
end
|
46
|
+
end
|
metadata
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: huo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ming Qu
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-12-27 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Huobi SDK for Ruby
|
14
|
+
email: qucool@gmail.com
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- ".gitignore"
|
20
|
+
- ".rspec"
|
21
|
+
- Gemfile
|
22
|
+
- Gemfile.lock
|
23
|
+
- huo.gemspec
|
24
|
+
- lib/huo.rb
|
25
|
+
- lib/huo/market.rb
|
26
|
+
- lib/huo/trade.rb
|
27
|
+
- spec/spec_helper.rb
|
28
|
+
- spec/unit/market_spec.rb
|
29
|
+
- spec/unit/trade_spec.rb
|
30
|
+
homepage: http://rubygems.org/gems/huo
|
31
|
+
licenses:
|
32
|
+
- MIT
|
33
|
+
metadata: {}
|
34
|
+
post_install_message:
|
35
|
+
rdoc_options: []
|
36
|
+
require_paths:
|
37
|
+
- lib
|
38
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '0'
|
43
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
requirements: []
|
49
|
+
rubyforge_project:
|
50
|
+
rubygems_version: 2.4.5.1
|
51
|
+
signing_key:
|
52
|
+
specification_version: 4
|
53
|
+
summary: huo
|
54
|
+
test_files:
|
55
|
+
- spec/spec_helper.rb
|
56
|
+
- spec/unit/market_spec.rb
|
57
|
+
- spec/unit/trade_spec.rb
|
58
|
+
has_rdoc:
|