trade-o-matic 0.2.1 → 0.3.0

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: 74776e7f65da3df4d74c5ab9dd6e644bd3921f55
4
- data.tar.gz: 8800ca9874d710757acb209fa72f891b5dd93435
3
+ metadata.gz: 69c3f0ffd768200acac1e0ccd836c5daaac08e59
4
+ data.tar.gz: 7e41570aa4c2a894861134cb50a670787384fe40
5
5
  SHA512:
6
- metadata.gz: 756a98df8523873f62a16a4d777e82d8588123ab912415c3dc88a908e3b879927936032eee1df52721c5f5fac486668f91811fea8c32a98e36755aae39c1b7e9
7
- data.tar.gz: 1078355996be86bc4a7432afd9b02d820058cca913a41bf0b768a32131d91d5453c4460e026365f7558fddaa168e0df258bc96b01f12d904d4ae8647bd5564b1
6
+ metadata.gz: 3dc8f24f61ba90595a9e5a39dfdd66f753762f3b32fb749e873f299f57ff6156bab77780180811446d5ae576ee1a45fc8e1f2efec4e9d9660c3b96ec5f0687e4
7
+ data.tar.gz: 470ce3b882cd7f45fee5330ccbd258c382e494be8836bf5392c70aaf0736f965de6f0741877ae820748002d55bb80ca5ab580944df440aa9f742d38a11e75d0d
@@ -21,8 +21,8 @@ module Trader
21
21
  class BitstampOrder < RawAccountOrder
22
22
  attr_mapped(:id, 'raw') # use original order information as id
23
23
  attr_mapped(:pair) { |r| MAIN_MARKET }
24
- attr_mapped(:price) { |r| r['raw']['price'].to_f }
25
- attr_mapped(:volume) { |r| r['raw']['amount'].to_f }
24
+ attr_mapped(:price) { |r| r['raw']['price'] }
25
+ attr_mapped(:volume) { |r| r['raw']['amount'] }
26
26
  attr_mapped(:executed_volume)
27
27
  attr_mapped(:instruction) { |r| r['raw']['type'] == 0 ? Order::BID : Order::ASK }
28
28
 
@@ -31,7 +31,7 @@ module Trader
31
31
  when 'Open'
32
32
  AccountOrder::OPEN
33
33
  when 'Finished'
34
- r['executed_volume'] < r['raw']['amount'].to_f ? AccountOrder::CANCELED : AccountOrder::CLOSED
34
+ r['executed_volume'] < big(r['raw']['amount']) ? AccountOrder::CANCELED : AccountOrder::CLOSED
35
35
  else
36
36
  AccountOrder::PENDING
37
37
  end
@@ -56,12 +56,12 @@ module Trader
56
56
  _book.prepare Time.now
57
57
 
58
58
  ob = execute_request(nil, 'order_book')
59
- ob['bids'].each { |o| _book.add_bid(o[0].to_f, o[1].to_f) }
60
- ob['asks'].each { |o| _book.add_ask(o[0].to_f, o[1].to_f) }
59
+ ob['bids'].each { |o| _book.add_bid(o[0], o[1]) }
60
+ ob['asks'].each { |o| _book.add_ask(o[0], o[1]) }
61
61
 
62
62
  tx = execute_request(nil, 'transactions')
63
63
  tx.each do |t|
64
- _book.add_transaction t['price'].to_f, t['amount'].to_f, Time.at(t['date'].to_i)
64
+ _book.add_transaction t['price'], t['amount'], Time.at(t['date'].to_i)
65
65
  end
66
66
  end
67
67
 
@@ -75,9 +75,9 @@ module Trader
75
75
  raw = execute_request(_session || session, 'balance')
76
76
 
77
77
  if _currency == BASE_CUR
78
- return BackendBalance.new raw['btc_balance'].to_f, raw['btc_available'].to_f
78
+ return BackendBalance.new raw['btc_balance'], raw['btc_available']
79
79
  else
80
- return BackendBalance.new raw['usd_balance'].to_f, raw['usd_available'].to_f
80
+ return BackendBalance.new raw['usd_balance'], raw['usd_available']
81
81
  end
82
82
  end
83
83
 
@@ -95,7 +95,7 @@ module Trader
95
95
  normalize_raw_order execute_request(
96
96
  _session || session,
97
97
  _type == Order::BID ? 'buy' : 'sell',
98
- { amount: _volume, price: _price }
98
+ { amount: _volume.to_f, price: _price.to_f }
99
99
  )
100
100
  end
101
101
 
@@ -146,14 +146,14 @@ module Trader
146
146
  def normalize_raw_order(_order)
147
147
  BitstampOrder.new({
148
148
  'raw' => _order,
149
- 'executed_volume' => 0.0,
149
+ 'executed_volume' => big(0),
150
150
  'status' => 'In Queue'
151
151
  })
152
152
  end
153
153
 
154
154
  def normalize_raw_order_status(_id, _status)
155
- executed_volume = _status['transactions'].inject(0.0) { |r, t| r + t['btc'].to_f }
156
- executed_price = _status['transactions'].inject(0.0) { |r, t| r + (t['price'].to_f * t['btc'].to_f) }
155
+ executed_volume = _status['transactions'].inject(big(0)) { |r, t| r + big(t['btc']) }
156
+ executed_price = _status['transactions'].inject(big(0)) { |r, t| r + (big(t['price']) * big(t['btc'])) }
157
157
 
158
158
  BitstampOrder.new({
159
159
  'raw' => _id,
@@ -162,5 +162,9 @@ module Trader
162
162
  'status' => _status['status']
163
163
  })
164
164
  end
165
+
166
+ def big(_string)
167
+ BigDecimal.new _string
168
+ end
165
169
  end
166
170
  end
@@ -10,12 +10,12 @@ module Trader
10
10
  _book.prepare Time.now
11
11
 
12
12
  ob = fetch_raw_order_book _book.pair
13
- ob['bids'].each { |o| _book.add_bid(o[0].to_f, o[1].to_f) }
14
- ob['asks'].each { |o| _book.add_ask(o[0].to_f, o[1].to_f) }
13
+ ob['bids'].each { |o| _book.add_bid(o[0], o[1]) }
14
+ ob['asks'].each { |o| _book.add_ask(o[0], o[1]) }
15
15
 
16
16
  tx = fetch_raw_transactions _book.pair
17
17
  tx['recentTrades'].each do |t|
18
- _book.add_transaction t['price'].to_f, t['amount'].to_f, Time.parse(t['timestamp'])
18
+ _book.add_transaction t['price'], t['amount'], Time.parse(t['timestamp'])
19
19
  end
20
20
  end
21
21
 
@@ -28,16 +28,16 @@ module Trader
28
28
  end
29
29
 
30
30
  class SurbtcBalanceBTC < RawBalance
31
- attr_mapped(:amount) { |r| r['amount'].to_f }
32
- attr_mapped(:available_amount) { |r| r['available_amount'].to_f }
31
+ attr_mapped(:amount) { |r| r['amount'] }
32
+ attr_mapped(:available_amount) { |r| r['available_amount'] }
33
33
  end
34
34
 
35
35
  class SurbtcOrder < RawAccountOrder
36
36
  attr_mapped(:id)
37
37
  attr_mapped(:pair) { |r| MAIN_MARKET }
38
38
  attr_mapped(:price) { |r| r['limit'] }
39
- attr_mapped(:volume) { |r| r['original_amount'].to_f }
40
- attr_mapped(:executed_volume) { |r| r['total_exchanged'].to_f }
39
+ attr_mapped(:volume) { |r| r['original_amount'] }
40
+ attr_mapped(:executed_volume) { |r| r['total_exchanged'] }
41
41
  attr_mapped(:instruction) { |r| TYPE_MAP[r['type'].downcase] }
42
42
  attr_mapped(:status) { |r| STATUS_MAP[r['state']] }
43
43
  attr_mapped(:limit?) { |r| r['price_type'] == 'limit' }
@@ -132,14 +132,14 @@ module Trader
132
132
  def build_order_json(_price, _volume, _instruction)
133
133
  if _price.nil?
134
134
  {
135
- amount: _volume,
135
+ amount: _volume.to_i,
136
136
  type: _instruction == Order::BID ? 'bid' : 'ask',
137
137
  price_type: 'market'
138
138
  }
139
139
  else
140
140
  {
141
- limit: _price,
142
- amount: _volume,
141
+ limit: _price.to_i,
142
+ amount: _volume.to_i,
143
143
  type: _instruction == Order::BID ? 'bid' : 'ask',
144
144
  price_type: 'limit'
145
145
  }
@@ -6,8 +6,12 @@ module Trader
6
6
  @converters = _converters
7
7
  end
8
8
 
9
- def rate
10
- converters.inject(1.0) { |r, c| c.rate * r }
9
+ def apply(_value, _invert=false)
10
+ unless _invert
11
+ converters.inject(_value) { |r, c| c.apply(r, false) }
12
+ else
13
+ converters.reverse.inject(_value) { |r, c| c.apply(r, true) }
14
+ end
11
15
  end
12
16
  end
13
17
  end
@@ -1,9 +1,22 @@
1
1
  module Trader
2
2
  class FixedConverter < Converter
3
- attr_accessor :rate
3
+ attr_reader :rate
4
4
 
5
5
  def initialize(_rate)
6
6
  @rate = _rate
7
+ # TODO: maybe require rate to be a Standard.amount
8
+ end
9
+
10
+ def current_rate
11
+ rate
12
+ end
13
+
14
+ def apply(_value, _invert=false)
15
+ if _invert
16
+ _value / rate
17
+ else
18
+ _value * rate
19
+ end
7
20
  end
8
21
  end
9
22
  end
@@ -1,13 +1,18 @@
1
1
  module Trader
2
2
  class InverseConverter < Converter
3
- attr_reader :inverse
3
+ attr_reader :other
4
4
 
5
- def initialize(_inverse)
6
- @inverse = _inverse
5
+ def initialize(_other)
6
+ @other = _other
7
7
  end
8
8
 
9
- def rate
10
- 1.0 / inverse.rate
9
+ def current_rate
10
+ return nil if other.current_rate.nil?
11
+ 1.0 / other.current_rate
12
+ end
13
+
14
+ def apply(_value, _invert=false)
15
+ @other.apply(_value, !_invert)
11
16
  end
12
17
  end
13
18
  end
@@ -13,7 +13,7 @@ module Trader
13
13
  json_string = RestClient.get _url
14
14
  json = JSON.parse json_string
15
15
  value = _path.inject(json) { |r, k| r[k] }
16
- value.to_f
16
+ Standard.amount value
17
17
  end
18
18
  end
19
19
  end
@@ -1,8 +1,9 @@
1
1
  module Trader
2
- class SyncConverter < Converter
2
+ class SyncConverter < FixedConverter
3
3
  attr_reader :ttl
4
4
 
5
5
  def initialize(_ttl, &_block)
6
+ super nil
6
7
  @ttl = _ttl
7
8
  @block = _block
8
9
  end
@@ -16,7 +17,6 @@ module Trader
16
17
  @rate = @block.call
17
18
  @last_sync = Time.now
18
19
  end
19
-
20
20
  @rate
21
21
  end
22
22
  end
@@ -0,0 +1,13 @@
1
+ require 'bigdecimal'
2
+
3
+ module Trader
4
+ module Standard
5
+ extend self
6
+
7
+ def amount(_number)
8
+ return _number if _number.is_a? BigDecimal
9
+ return BigDecimal.new _number.to_s if _number.is_a? Float
10
+ BigDecimal.new _number
11
+ end
12
+ end
13
+ end
@@ -1,7 +1,12 @@
1
1
  module Trader
2
2
  class Converter
3
- def rate
4
- raise NotImplementedError, 'rate method not implemented'
3
+
4
+ def current_rate
5
+ nil # current rate not available
6
+ end
7
+
8
+ def apply(_value, _invert=false)
9
+ raise NotImplementedError, 'apply method not implemented'
5
10
  end
6
11
  end
7
12
  end
@@ -1,12 +1,15 @@
1
1
  module Trader
2
2
  class Currency
3
- def self.register_conversion(_from, _to, _converter=nil, &_block)
3
+ def self.register_conversion(_from, _to, _converter=nil, _options={}, &_block)
4
4
  if !_block.nil?
5
- _converter = SyncConverter.new(60, &_block)
6
- elsif _converter.is_a? Integer or _converter.is_a? Float
5
+ _options = _converter || {}
6
+ _converter = SyncConverter.new(_options.fetch(:interval, 60.0), &_block)
7
+ elsif _converter.is_a? Numeric
7
8
  _converter = FixedConverter.new(_converter)
8
9
  end
9
10
 
11
+ _converter = inverse(_converter) if _options[:inverse]
12
+
10
13
  converters[_from.to_sym][_to.to_sym] = _converter
11
14
  reset_comp_cache
12
15
  end
@@ -78,7 +81,8 @@ module Trader
78
81
  end
79
82
 
80
83
  def convert(_value, _to)
81
- klass.converter_for!(code, _to.to_sym).rate * _value
84
+ converter = klass.converter_for!(code, _to.to_sym)
85
+ converter.apply _value
82
86
  end
83
87
 
84
88
  def pack(_value)
@@ -100,11 +104,11 @@ module Trader
100
104
  _value.amount
101
105
  end
102
106
  elsif _value.nil?
103
- _options[:default]
107
+ Standard.amount _options[:default]
104
108
  elsif _options.fetch(:strict, true)
105
109
  raise ArgumentError, "Must provide a currency bound price"
106
110
  else
107
- _value
111
+ Standard.amount _value
108
112
  end
109
113
  end
110
114
 
@@ -161,6 +165,14 @@ module Trader
161
165
  end)
162
166
  end
163
167
 
168
+ def self.inverse(_converter)
169
+ if _converter.is_a? InverseConverter
170
+ _converter.other
171
+ else
172
+ InverseConverter.new _converter
173
+ end
174
+ end
175
+
164
176
  def klass
165
177
  self.class
166
178
  end
@@ -4,7 +4,7 @@ module Trader
4
4
 
5
5
  def initialize(_currency, _amount)
6
6
  @currency = Currency.for_code _currency
7
- @amount = _amount
7
+ @amount = Standard.amount _amount
8
8
  end
9
9
 
10
10
  def pack(_amount)
@@ -37,6 +37,5 @@ module Trader
37
37
  Price.new currency, amount.public_send(op, _other)
38
38
  end
39
39
  end
40
-
41
40
  end
42
41
  end
@@ -7,8 +7,8 @@ module Trader
7
7
  type = conv['type'] || detect_type(conv)
8
8
  converter = send "configure_yaml_#{type}", conv
9
9
 
10
- Currency.register_conversion conv['from'], conv['to'], converter
11
- Currency.register_conversion conv['to'], conv['from'], invert(converter) if conv['symetric']
10
+ Currency.register_conversion conv['from'], conv['to'], converter, inverse: !!conv['inverse']
11
+ Currency.register_conversion conv['to'], conv['from'], converter, inverse: !conv['inverse'] if conv['symetric']
12
12
  end
13
13
  end
14
14
 
@@ -1,3 +1,3 @@
1
1
  module Trader
2
- VERSION = "0.2.1"
2
+ VERSION = "0.3.0"
3
3
  end
data/lib/trade-o-matic.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require "trade-o-matic/version"
2
+ require 'trade-o-matic/standard'
2
3
 
3
4
  require 'trade-o-matic/structs/currency'
4
5
  require 'trade-o-matic/structs/currency_pair'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trade-o-matic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ignacio Baixas
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-11 00:00:00.000000000 Z
11
+ date: 2016-03-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rest-client
@@ -257,6 +257,7 @@ files:
257
257
  - lib/trade-o-matic/core/market.rb
258
258
  - lib/trade-o-matic/core/market_loader.rb
259
259
  - lib/trade-o-matic/services/backend_factory.rb
260
+ - lib/trade-o-matic/standard.rb
260
261
  - lib/trade-o-matic/structs/ask_slope.rb
261
262
  - lib/trade-o-matic/structs/bid_slope.rb
262
263
  - lib/trade-o-matic/structs/book.rb