trade-o-matic 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/trade-o-matic/adapters/bitstamp_backend.rb +16 -12
- data/lib/trade-o-matic/adapters/itbit_backend.rb +3 -3
- data/lib/trade-o-matic/adapters/surbtc_backend.rb +7 -7
- data/lib/trade-o-matic/converters/compound_converter.rb +6 -2
- data/lib/trade-o-matic/converters/fixed_converter.rb +14 -1
- data/lib/trade-o-matic/converters/inverse_converter.rb +10 -5
- data/lib/trade-o-matic/converters/json_api_converter.rb +1 -1
- data/lib/trade-o-matic/converters/sync_converter.rb +2 -2
- data/lib/trade-o-matic/standard.rb +13 -0
- data/lib/trade-o-matic/structs/converter.rb +7 -2
- data/lib/trade-o-matic/structs/currency.rb +18 -6
- data/lib/trade-o-matic/structs/price.rb +1 -2
- data/lib/trade-o-matic/support/converter_configurator.rb +2 -2
- data/lib/trade-o-matic/version.rb +1 -1
- data/lib/trade-o-matic.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 69c3f0ffd768200acac1e0ccd836c5daaac08e59
|
4
|
+
data.tar.gz: 7e41570aa4c2a894861134cb50a670787384fe40
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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']
|
25
|
-
attr_mapped(:volume) { |r| r['raw']['amount']
|
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']
|
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]
|
60
|
-
ob['asks'].each { |o| _book.add_ask(o[0]
|
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']
|
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']
|
78
|
+
return BackendBalance.new raw['btc_balance'], raw['btc_available']
|
79
79
|
else
|
80
|
-
return BackendBalance.new raw['usd_balance']
|
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
|
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
|
156
|
-
executed_price = _status['transactions'].inject(0
|
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]
|
14
|
-
ob['asks'].each { |o| _book.add_ask(o[0]
|
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']
|
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']
|
32
|
-
attr_mapped(:available_amount) { |r| r['available_amount']
|
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']
|
40
|
-
attr_mapped(:executed_volume) { |r| r['total_exchanged']
|
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
|
10
|
-
|
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
|
-
|
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 :
|
3
|
+
attr_reader :other
|
4
4
|
|
5
|
-
def initialize(
|
6
|
-
@
|
5
|
+
def initialize(_other)
|
6
|
+
@other = _other
|
7
7
|
end
|
8
8
|
|
9
|
-
def
|
10
|
-
|
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
|
@@ -1,8 +1,9 @@
|
|
1
1
|
module Trader
|
2
|
-
class SyncConverter <
|
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
|
@@ -1,7 +1,12 @@
|
|
1
1
|
module Trader
|
2
2
|
class Converter
|
3
|
-
|
4
|
-
|
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
|
-
|
6
|
-
|
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)
|
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'],
|
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
|
|
data/lib/trade-o-matic.rb
CHANGED
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.
|
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
|
+
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
|