mexbt 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 15732e233077f44d567ce9daae9097843322d1d3
4
- data.tar.gz: 5a29f9c01b744e4636864b5a7fcd171be33e1365
3
+ metadata.gz: b5d3d42c18c0d316d920d381e853d2e2767cb141
4
+ data.tar.gz: a0508b7182b66874add7b2af78c764014cdcb5d5
5
5
  SHA512:
6
- metadata.gz: 39e9ad6cc488e0b18fb9b00cc21862be8af7a4c3ce5be9bcf26915db7ddbf9ba5e9f9546c3a9ab8bbc43cf570f93dd3b79eed7ba0462de623f71a0efb644c37d
7
- data.tar.gz: 2d5ed961b26805dce2795e429c2cb4b7f03f7361241344755d576cb833ac321c814de5bf6cbe52f78b58d42802a585c0197f0598e59a59be8bbe12a6a79e4b77
6
+ metadata.gz: 1da58e0313428224f94604448d3af8d4a7488c2048ee101c141ecd92c17998afa2a1304275213675772e4fcef2ff5d7a5a136b0a7afc52b86eb75e50486c6b28
7
+ data.tar.gz: c9a6c57a86e57f64b2037482350a72688f5dc60fcb40387acf2ec1070c4e2b266c30741a7b5aeaa34db797178157fea289247f2b921b29d5f946efd47cbb47cd
data/Gemfile.lock CHANGED
@@ -1,7 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mexbt (0.0.1)
4
+ mexbt (0.0.3)
5
+ activesupport (>= 4.1.8)
6
+ rest_client (= 1.8.2)
5
7
 
6
8
  GEM
7
9
  remote: http://rubygems.org/
@@ -40,9 +42,7 @@ PLATFORMS
40
42
  ruby
41
43
 
42
44
  DEPENDENCIES
43
- activesupport
44
45
  bundler (~> 1.6)
45
46
  mexbt!
46
47
  rake
47
- rest_client
48
48
  rspec
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Mexbt ruby API client
2
2
 
3
- This is a lightweight ruby client for the Mexbt exchange API. It doesn't try and do anything clever with the JSON response from the API, it simply
3
+ This is a lightweight ruby client for the [meXBT](https://mexbt.com) exchange API. It doesn't try and do anything clever with the JSON response from the API, it simply
4
4
  returns it as-is.
5
5
 
6
6
  # Install
@@ -23,6 +23,8 @@ You can access all the Public API functions with zero configuration. By default
23
23
  Mexbt.order_book
24
24
  Mexbt.trades(start_index: -1, count: 20)
25
25
  Mexbt.trades_by_date(from: Date.civil(2014, 11, 1).to_time.to_i, to: Date.today.to_time.to_i)
26
+ Mexbt.simulate_market_order(side: :buy, second_currency: 1000, currency_pair: 'btcmxn') # Simulates a market order, which will estimate how many btc you will receive for 1000 mxn
27
+ Mexbt.simulate_market_order(side: :buy, first_currency: 1, currency_pair: 'btcmxn') # Simulates a market order, which will estimate how many mxn you will spend for 1 btc
26
28
 
27
29
  If you want to choose another currency pair, you can configure it for all calls:
28
30
 
@@ -78,3 +80,8 @@ API docs for the Private API are at http://docs.mexbtprivateapi.apiary.io
78
80
 
79
81
  There are also docs for the Private API sandbox at http://docs.mexbtprivateapisandbox.apiary.io
80
82
 
83
+
84
+ # TODO
85
+
86
+ Mock out web calls with WebMock so that specs don't break everytime sandbox db is cleaned.
87
+
data/Rakefile CHANGED
@@ -2,4 +2,6 @@ begin
2
2
  require 'rspec/core/rake_task'
3
3
  RSpec::Core::RakeTask.new(:spec)
4
4
  rescue LoadError
5
- end
5
+ end
6
+
7
+ task default: [:spec]
data/lib/mexbt/client.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'rest_client'
2
+ require 'active_support'
2
3
 
3
4
  module Mexbt
4
5
  module Client
@@ -31,11 +32,11 @@ module Mexbt
31
32
  if res.length === 0
32
33
  raise "Empty response from API"
33
34
  end
34
- json_response = JSON.parse(res)
35
- if json_response["isAccepted"]
35
+ json_response = ActiveSupport::HashWithIndifferentAccess.new(JSON.parse(res))
36
+ if json_response[:isAccepted]
36
37
  json_response
37
38
  else
38
- raise json_response["rejectReason"]
39
+ raise json_response[:rejectReason]
39
40
  end
40
41
  end
41
42
  end
data/lib/mexbt/orders.rb CHANGED
@@ -18,8 +18,7 @@ module Mexbt
18
18
  ins: currency_pair,
19
19
  side: side,
20
20
  orderType: type,
21
- qty: amount,
22
- sessionToken: "c545f765-ce47-4ea5-b206-a9ac0db55fc3"
21
+ qty: amount
23
22
  }
24
23
  params[:px] = price if price
25
24
  call("orders/create", params)
@@ -45,5 +44,6 @@ module Mexbt
45
44
  end
46
45
  call("orders/modify", { ins: currency_pair, serverOrderId: id, modifyAction: action } )
47
46
  end
47
+
48
48
  end
49
- end
49
+ end
data/lib/mexbt/public.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'mexbt/client'
2
2
  require 'mexbt/common'
3
+ require 'active_support'
3
4
 
4
5
  module Mexbt
5
6
  module Public
@@ -29,5 +30,70 @@ module Mexbt
29
30
  def trades_by_date(currency_pair: Mexbt.currency_pair, from:, to:)
30
31
  call("trades-by-date", { ins: currency_pair, startDate: from, endDate: to })
31
32
  end
33
+
34
+ def simulate_market_order(side: :buy, first_currency: 0, second_currency: 0, currency_pair: Mexbt.currency_pair)
35
+ if first_currency === 0 and second_currency === 0
36
+ raise "You must specify either 'first_currency' or 'second_currency' (from the currency pair)"
37
+ end
38
+ order_book = order_book(currency_pair: currency_pair)
39
+ orders =
40
+ if side.to_s === 'buy'
41
+ order_book["asks"].sort { |a, b| a["px"] <=> b["px"] }
42
+ else
43
+ order_book["bids"].sort { |a, b| b["px"] <=> a["px"] }
44
+ end
45
+ if second_currency > 0
46
+ threshold_target = second_currency
47
+ threshold_symbol = :cost
48
+ other_symbol = :amount
49
+ else
50
+ threshold_target = first_currency
51
+ threshold_symbol = :amount
52
+ other_symbol = :cost
53
+ end
54
+ sums = {
55
+ amount: BigDecimal.new(0, 15),
56
+ cost: BigDecimal.new(0, 15)
57
+ }
58
+ orders.each do |order|
59
+ next_order = {
60
+ amount: BigDecimal.new(order["qty"], 15),
61
+ cost: BigDecimal.new(order["px"], 15) * BigDecimal.new(order["qty"], 15)
62
+ }
63
+ threshold_check = sums[threshold_symbol] + next_order[threshold_symbol]
64
+ if threshold_check > threshold_target
65
+ over = threshold_check - threshold_target
66
+ percent_needed = (next_order[threshold_symbol] - over) / next_order[threshold_symbol]
67
+ sums[other_symbol] += next_order[other_symbol] * percent_needed
68
+ sums[threshold_symbol] = threshold_target
69
+ break
70
+ else
71
+ sums[:amount] += next_order[:amount]
72
+ sums[:cost] += next_order[:cost]
73
+ break if sums[threshold_symbol] == threshold_target
74
+ end
75
+ end
76
+ if sums[threshold_symbol] < threshold_target
77
+ raise "Order book does not contain enough orders to satify simulated order!"
78
+ end
79
+ res = {
80
+ first_amount: round(sums[:amount], currency_pair, :first),
81
+ second_amount: round(sums[:cost], currency_pair, :second)
82
+ }
83
+ ActiveSupport::HashWithIndifferentAccess.new(res)
84
+ end
85
+
86
+ private
87
+
88
+ def round(amount, pair, which)
89
+ currency = which === :first ? pair.to_s[0,3] : pair.to_s[-3..-1]
90
+ decimal_places =
91
+ if ['btc', 'ltc'].include?(currency.downcase)
92
+ 8
93
+ else
94
+ 2
95
+ end
96
+ amount.round(decimal_places).to_f
97
+ end
32
98
  end
33
99
  end
data/lib/mexbt/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Mexbt
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
data/mexbt.gemspec CHANGED
@@ -5,6 +5,7 @@ require 'mexbt/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "mexbt"
8
+ spec.description = "A lightweight ruby client for the meXBT exchange API"
8
9
  spec.version = Mexbt::VERSION
9
10
  spec.authors = ["williamcoates"]
10
11
  spec.email = ["william@mexbt.com"]
@@ -15,7 +16,7 @@ Gem::Specification.new do |spec|
15
16
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
16
17
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
18
  spec.require_paths = ["lib"]
18
- spec.add_runtime_dependency "activesupport", ["= 4.1.8"]
19
+ spec.add_runtime_dependency "activesupport", [">= 4.1.8"]
19
20
  spec.add_runtime_dependency "rest_client", ["= 1.8.2"]
20
21
  spec.add_development_dependency "bundler", "~> 1.6"
21
22
  spec.add_development_dependency "rake"
@@ -22,4 +22,46 @@ describe Mexbt do
22
22
  expect(res["trades"]).to eql([])
23
23
  end
24
24
 
25
+ context "simulating market orders" do
26
+
27
+ before do
28
+ allow(Mexbt).to receive(:order_book) do
29
+ {
30
+ "asks" => [{"px" => 1000, "qty" => 0.5}, {"px" => 2000, "qty" => 1}],
31
+ "bids" => [{"px" => 1000, "qty" => 0.5}, {"px" => 2000, "qty" => 1}]
32
+ }
33
+ end
34
+ end
35
+
36
+ it "calculates correctly buy orders with second_currency as the target currency" do
37
+ expect(Mexbt.simulate_market_order(second_currency: 100)["first_amount"]).to eql(0.1)
38
+ expect(Mexbt.simulate_market_order(second_currency: 500)["first_amount"]).to eql(0.5)
39
+ expect(Mexbt.simulate_market_order(second_currency: 600)["first_amount"]).to eql(0.55)
40
+ expect(Mexbt.simulate_market_order(second_currency: 1500)["first_amount"]).to eql(1.0)
41
+ expect(Mexbt.simulate_market_order(second_currency: 2500)["first_amount"]).to eql(1.5)
42
+ expect { Mexbt.simulate_market_order(second_currency: 2501)}.to raise_error("Order book does not contain enough orders to satify simulated order!")
43
+ end
44
+
45
+ it "calculates correctly buy orders with first_currency as the target currency" do
46
+ expect(Mexbt.simulate_market_order(first_currency: 0.5)["second_amount"]).to eql(500.0)
47
+ expect(Mexbt.simulate_market_order(first_currency: 1.5)["second_amount"]).to eql(2500.0)
48
+ expect(Mexbt.simulate_market_order(first_currency: 0.1)["second_amount"]).to eql(100.0)
49
+ expect(Mexbt.simulate_market_order(first_currency: 0.6)["second_amount"]).to eql(700.0)
50
+ end
51
+
52
+ it "calculates correctly sell orders with first_currency as the target currency" do
53
+ expect(Mexbt.simulate_market_order(side: :sell, first_currency: 0.01)["second_amount"]).to eql(20.0)
54
+ expect(Mexbt.simulate_market_order(side: :sell, first_currency: 0.1)["second_amount"]).to eql(200.0)
55
+ expect(Mexbt.simulate_market_order(side: :sell, first_currency: 1)["second_amount"]).to eql(2000.0)
56
+ expect(Mexbt.simulate_market_order(side: :sell, first_currency: 1.1)["second_amount"]).to eql(2100.0)
57
+ expect(Mexbt.simulate_market_order(side: :sell, first_currency: 1.4)["second_amount"]).to eql(2400.0)
58
+ end
59
+
60
+ it "calculates correctly sell orders with second_currency as the target currency" do
61
+ expect(Mexbt.simulate_market_order(side: :sell, second_currency: 1000)["first_amount"]).to eql(0.5)
62
+ expect(Mexbt.simulate_market_order(side: :sell, second_currency: 2001)["first_amount"]).to eql(1.001)
63
+ expect(Mexbt.simulate_market_order(side: :sell, second_currency: 2500)["first_amount"]).to eql(1.5)
64
+ end
65
+ end
66
+
25
67
  end
metadata CHANGED
@@ -1,27 +1,27 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mexbt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - williamcoates
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-28 00:00:00.000000000 Z
11
+ date: 2014-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '='
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: 4.1.8
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '='
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 4.1.8
27
27
  - !ruby/object:Gem::Dependency
@@ -80,7 +80,7 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
- description:
83
+ description: A lightweight ruby client for the meXBT exchange API
84
84
  email:
85
85
  - william@mexbt.com
86
86
  executables: []