mexbt 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []