trade-o-matic 0.3.2 → 0.4.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/base/raw_resource.rb +0 -2
- data/lib/trade-o-matic/adapters/base_backend.rb +62 -0
- data/lib/trade-o-matic/adapters/bitfinex_backend.rb +30 -15
- data/lib/trade-o-matic/adapters/bitstamp_backend.rb +4 -19
- data/lib/trade-o-matic/adapters/fake_backend.rb +2 -2
- data/lib/trade-o-matic/adapters/game_backend.rb +8 -3
- data/lib/trade-o-matic/adapters/itbit_backend.rb +1 -1
- data/lib/trade-o-matic/adapters/surbtc_backend.rb +5 -13
- data/lib/trade-o-matic/core/account.rb +2 -3
- data/lib/trade-o-matic/core/account_order.rb +1 -3
- data/lib/trade-o-matic/core/account_proxy.rb +0 -1
- data/lib/trade-o-matic/core/balance.rb +19 -4
- data/lib/trade-o-matic/core/exchange.rb +1 -2
- data/lib/trade-o-matic/core/market.rb +0 -2
- data/lib/trade-o-matic/core/market_loader.rb +5 -4
- data/lib/trade-o-matic/endpoints/base_endpoint.rb +5 -0
- data/lib/trade-o-matic/endpoints/bitcoin_address.rb +9 -0
- data/lib/trade-o-matic/errors.rb +23 -0
- data/lib/trade-o-matic/version.rb +1 -1
- data/lib/trade-o-matic.rb +6 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 10edb6d47a3ca071570ab17ed6559306c6a3f1c3
|
4
|
+
data.tar.gz: 0fd5ae2dec38031376ec526f6dcd9050c012eb63
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7b6fdc892965766b66919c22e237fdb944fc1d81b6693c273e3d9e8b4644c556a1b317f46596e376b6b713dd2a4e581c97311ce64280a90001be91c506a44ad9
|
7
|
+
data.tar.gz: 27ebedede4d516d9c33b5e88a32854790adee9d66f7cf7a295518b73394646631760949ab5358917ae6ca8f3360a1532dce5fedd3cd7942cb7207d342582f7f6
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'trade-o-matic/adapters/base/raw_account_order'
|
2
|
+
require 'trade-o-matic/adapters/base/raw_balance'
|
3
|
+
|
4
|
+
module Trader
|
5
|
+
class BaseBackend
|
6
|
+
attr_reader :name
|
7
|
+
|
8
|
+
def initialize(_name)
|
9
|
+
@name = _name
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_available_markets
|
13
|
+
[]
|
14
|
+
end
|
15
|
+
|
16
|
+
def fill_book(_book)
|
17
|
+
not_supported :book
|
18
|
+
end
|
19
|
+
|
20
|
+
def get_session(_credentials)
|
21
|
+
_credentials
|
22
|
+
end
|
23
|
+
|
24
|
+
def get_balance(_session, _currency)
|
25
|
+
not_supported :get_balance
|
26
|
+
end
|
27
|
+
|
28
|
+
def generate_endpoint(_session, _currency)
|
29
|
+
not_supported :deposit
|
30
|
+
end
|
31
|
+
|
32
|
+
def withdraw_to_endpoint(_session, _currency, _amount, _endpoint)
|
33
|
+
not_supported :withdraw
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_orders(_session, _pair)
|
37
|
+
not_supported :list_orders
|
38
|
+
end
|
39
|
+
|
40
|
+
def create_order(_session, _pair, _volume, _price, _type)
|
41
|
+
not_supported :create_order
|
42
|
+
end
|
43
|
+
|
44
|
+
def fetch_order(_session, _id)
|
45
|
+
not_supported :fetch_order
|
46
|
+
end
|
47
|
+
|
48
|
+
def cancel_order(_session, _id)
|
49
|
+
not_supported :cancel_order
|
50
|
+
end
|
51
|
+
|
52
|
+
def not_supported(_feature)
|
53
|
+
raise NotSupportedError.new name, _feature
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def error(_messsage)
|
59
|
+
raise BackendError.new name, _messsage
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -1,11 +1,9 @@
|
|
1
1
|
require 'rest-client'
|
2
2
|
require 'base64'
|
3
3
|
require 'json'
|
4
|
-
require 'trade-o-matic/adapters/base/raw_account_order'
|
5
|
-
require 'trade-o-matic/adapters/base/raw_balance'
|
6
4
|
|
7
5
|
module Trader
|
8
|
-
class BitfinexBackend
|
6
|
+
class BitfinexBackend < BaseBackend
|
9
7
|
BASE_CUR = Currency.for_code(:BTC)
|
10
8
|
QUOTE_CUR = Currency.for_code(:BITFINEX_USD)
|
11
9
|
MAIN_MARKET = CurrencyPair.new BASE_CUR, QUOTE_CUR
|
@@ -42,8 +40,8 @@ module Trader
|
|
42
40
|
end
|
43
41
|
end
|
44
42
|
|
45
|
-
def initialize
|
46
|
-
|
43
|
+
def initialize
|
44
|
+
super :bitfinex
|
47
45
|
end
|
48
46
|
|
49
47
|
def get_available_markets
|
@@ -65,28 +63,29 @@ module Trader
|
|
65
63
|
end
|
66
64
|
end
|
67
65
|
|
68
|
-
def get_session(
|
69
|
-
|
66
|
+
def get_session(_cred)
|
67
|
+
raise AssertError, 'missing credentials' if !_cred.key?(:api_key) || !_cred.key?(:secret)
|
68
|
+
_cred
|
70
69
|
end
|
71
70
|
|
72
71
|
def get_balance(_session, _currency)
|
73
|
-
raise "#{_currency} not supported" unless _currency == BASE_CUR || _currency == QUOTE_CUR
|
74
|
-
|
75
72
|
raw = auth_post(_session, 'balances')
|
76
73
|
wrap_balance raw, _currency
|
77
74
|
end
|
78
75
|
|
79
|
-
def
|
80
|
-
|
76
|
+
def withdraw_to_endpoint(_session, _currency, _amount, _endpoint)
|
77
|
+
not_supported "usd withdrawals" if _currency == QUOTE_CUR
|
78
|
+
execute_btc_withdraw(_session, _amount, _endpoint)
|
79
|
+
end
|
81
80
|
|
81
|
+
def get_orders(_session, _pair)
|
82
82
|
raw = auth_post(_session, 'orders')
|
83
83
|
raw = raw.select { |o| o['type'].include? 'limit' }
|
84
84
|
raw.map { |o| wrap_order o }
|
85
85
|
end
|
86
86
|
|
87
87
|
def create_order(_session, _pair, _volume, _price, _type)
|
88
|
-
|
89
|
-
raise 'market orders not supported' if _price.nil?
|
88
|
+
not_supported "market orders" if _price.nil?
|
90
89
|
|
91
90
|
wrap_order auth_post(_session, 'order/new', {
|
92
91
|
exchange: "bitfinex",
|
@@ -118,8 +117,6 @@ module Trader
|
|
118
117
|
end
|
119
118
|
|
120
119
|
def auth_post(_creds, _url, _data = {})
|
121
|
-
raise ArgumentError if !_creds.key?(:api_key) or !_creds.key?(:secret)
|
122
|
-
|
123
120
|
payload = build_payload("/v1/#{_url}", _data)
|
124
121
|
headers = {
|
125
122
|
'Content-Type' => 'application/json',
|
@@ -158,5 +155,23 @@ module Trader
|
|
158
155
|
def wrap_order(_raw)
|
159
156
|
OrderAdaptor.new _raw
|
160
157
|
end
|
158
|
+
|
159
|
+
def execute_btc_withdraw(_session, _amount, _endpoint)
|
160
|
+
case _endpoint
|
161
|
+
when BitcoinAddress
|
162
|
+
auth_post(_session, 'withdraw', {
|
163
|
+
withdraw_type: 'bitcoin',
|
164
|
+
walletselected: 'exchange',
|
165
|
+
amount: _amount.to_s('F'),
|
166
|
+
address: _endpoint.address
|
167
|
+
})
|
168
|
+
else
|
169
|
+
not_supported "endpoint not supported"
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def process_withdraw(_raw)
|
174
|
+
error _raw['message'] if _raw['status'] == 'error'
|
175
|
+
end
|
161
176
|
end
|
162
177
|
end
|
@@ -1,10 +1,8 @@
|
|
1
1
|
require 'rest-client'
|
2
2
|
require 'json'
|
3
|
-
require 'trade-o-matic/adapters/base/raw_account_order'
|
4
|
-
require 'trade-o-matic/adapters/base/raw_balance'
|
5
3
|
|
6
4
|
module Trader
|
7
|
-
class BitstampBackend
|
5
|
+
class BitstampBackend < BaseBackend
|
8
6
|
BASE_CUR = Currency.for_code(:BTC)
|
9
7
|
QUOTE_CUR = Currency.for_code(:BITSTAMP_USD)
|
10
8
|
MAIN_MARKET = CurrencyPair.new BASE_CUR, QUOTE_CUR
|
@@ -42,8 +40,8 @@ module Trader
|
|
42
40
|
end
|
43
41
|
end
|
44
42
|
|
45
|
-
def initialize
|
46
|
-
|
43
|
+
def initialize
|
44
|
+
super :bitstamp
|
47
45
|
end
|
48
46
|
|
49
47
|
def get_available_markets
|
@@ -65,13 +63,7 @@ module Trader
|
|
65
63
|
end
|
66
64
|
end
|
67
65
|
|
68
|
-
def get_session(_credentials)
|
69
|
-
_credentials
|
70
|
-
end
|
71
|
-
|
72
66
|
def get_balance(_session, _currency)
|
73
|
-
raise "#{_currency} not supported" unless _currency == BASE_CUR || _currency == QUOTE_CUR
|
74
|
-
|
75
67
|
raw = execute_request(_session || session, 'balance')
|
76
68
|
|
77
69
|
if _currency == BASE_CUR
|
@@ -82,15 +74,12 @@ module Trader
|
|
82
74
|
end
|
83
75
|
|
84
76
|
def get_orders(_session, _pair)
|
85
|
-
raise 'market not supported' unless _pair == MAIN_MARKET
|
86
|
-
|
87
77
|
raw_orders = execute_request(_session || session, 'open_orders')
|
88
78
|
raw_orders.map { |o| normalize_raw_order o }
|
89
79
|
end
|
90
80
|
|
91
81
|
def create_order(_session, _pair, _volume, _price, _type)
|
92
|
-
|
93
|
-
raise 'market orders not supported' if _price.nil?
|
82
|
+
not_supported('market orders') if _price.nil?
|
94
83
|
|
95
84
|
normalize_raw_order execute_request(
|
96
85
|
_session || session,
|
@@ -107,10 +96,6 @@ module Trader
|
|
107
96
|
)
|
108
97
|
end
|
109
98
|
|
110
|
-
def cancel_order(_session, _id)
|
111
|
-
# TODO
|
112
|
-
end
|
113
|
-
|
114
99
|
private
|
115
100
|
|
116
101
|
attr_reader :session
|
@@ -1,11 +1,10 @@
|
|
1
1
|
require 'rest-client'
|
2
2
|
require 'json'
|
3
|
-
require 'trade-o-matic/adapters/base/raw_account_order'
|
4
3
|
require 'rainbow'
|
5
4
|
require 'rainbow/ext/string'
|
6
5
|
|
7
6
|
module Trader
|
8
|
-
class FakeBackend
|
7
|
+
class FakeBackend < BaseBackend
|
9
8
|
class FakeBalance < Struct.new(:amount, :available_amount);
|
10
9
|
end
|
11
10
|
|
@@ -46,6 +45,7 @@ module Trader
|
|
46
45
|
end
|
47
46
|
|
48
47
|
def initialize(_config=nil)
|
48
|
+
super :fake
|
49
49
|
get_session(_config) unless _config.nil?
|
50
50
|
end
|
51
51
|
|
@@ -1,8 +1,12 @@
|
|
1
1
|
require 'json'
|
2
2
|
require 'rainbow'
|
3
3
|
require 'rainbow/ext/string'
|
4
|
-
|
5
|
-
|
4
|
+
|
5
|
+
module Trader
|
6
|
+
# This is needed to prevent one of the subclass files from defining
|
7
|
+
# the class without the superclass.
|
8
|
+
class GameBackend < BaseBackend; end
|
9
|
+
end
|
6
10
|
|
7
11
|
require 'trade-o-matic/adapters/game_backend/configuration'
|
8
12
|
require 'trade-o-matic/adapters/game_backend/sfm'
|
@@ -40,6 +44,7 @@ module Trader
|
|
40
44
|
attr_reader :verbose, :state
|
41
45
|
|
42
46
|
def initialize
|
47
|
+
super :game
|
43
48
|
@state = State.new
|
44
49
|
end
|
45
50
|
|
@@ -81,7 +86,7 @@ module Trader
|
|
81
86
|
end
|
82
87
|
|
83
88
|
def get_session(_config)
|
84
|
-
raise
|
89
|
+
raise AssertError, 'must provide login information' if _config.nil? or _config[:name].nil?
|
85
90
|
_config[:name]
|
86
91
|
end
|
87
92
|
|
@@ -1,10 +1,8 @@
|
|
1
1
|
require 'rest-client'
|
2
2
|
require 'json'
|
3
|
-
require 'trade-o-matic/adapters/base/raw_account_order'
|
4
|
-
require 'trade-o-matic/adapters/base/raw_balance'
|
5
3
|
|
6
4
|
module Trader
|
7
|
-
class SurbtcBackend
|
5
|
+
class SurbtcBackend < BaseBackend
|
8
6
|
API_PREFIX = 'https://www.surbtc.com/api/v1'
|
9
7
|
|
10
8
|
TYPE_MAP = {
|
@@ -43,16 +41,12 @@ module Trader
|
|
43
41
|
attr_mapped(:limit?) { |r| r['price_type'] == 'limit' }
|
44
42
|
end
|
45
43
|
|
46
|
-
def
|
47
|
-
|
48
|
-
end
|
49
|
-
|
50
|
-
def fill_book(_book)
|
51
|
-
# TODO
|
44
|
+
def initialize
|
45
|
+
super :surbtc
|
52
46
|
end
|
53
47
|
|
54
|
-
def
|
55
|
-
|
48
|
+
def get_available_markets
|
49
|
+
[MAIN_MARKET]
|
56
50
|
end
|
57
51
|
|
58
52
|
def get_balance(_session, _currency)
|
@@ -74,8 +68,6 @@ module Trader
|
|
74
68
|
end
|
75
69
|
|
76
70
|
def create_order(_session, _pair, _volume, _price, _instruction)
|
77
|
-
raise 'market not supported' unless _pair == MAIN_MARKET
|
78
|
-
|
79
71
|
res = resource_for "markets/#{market_code_for(_pair)}/orders", _session
|
80
72
|
|
81
73
|
raw_order = postprocess res.post({
|
@@ -14,7 +14,7 @@ module Trader
|
|
14
14
|
|
15
15
|
proxy_market = find_exact_market _pair
|
16
16
|
proxy_market = find_compatible_market _pair if proxy_market.nil?
|
17
|
-
|
17
|
+
backend.not_supported _pair if proxy_market.nil?
|
18
18
|
|
19
19
|
proxy = AccountProxy.new self, proxy_market, _pair
|
20
20
|
|
@@ -59,7 +59,7 @@ module Trader
|
|
59
59
|
# TODO.
|
60
60
|
end
|
61
61
|
|
62
|
-
|
62
|
+
private
|
63
63
|
|
64
64
|
attr_reader :session
|
65
65
|
|
@@ -70,6 +70,5 @@ module Trader
|
|
70
70
|
def find_compatible_market(_pair)
|
71
71
|
available_markets.find { |p| p.compatible_with? _pair }
|
72
72
|
end
|
73
|
-
|
74
73
|
end
|
75
74
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module Trader
|
2
2
|
class AccountOrder
|
3
|
-
|
4
3
|
PENDING = :pending
|
5
4
|
OPEN = :open
|
6
5
|
CLOSED = :closed
|
@@ -81,7 +80,7 @@ module Trader
|
|
81
80
|
status == CLOSED or status == CANCELED
|
82
81
|
end
|
83
82
|
|
84
|
-
|
83
|
+
private
|
85
84
|
|
86
85
|
attr_reader :backend, :session, :forced_pair
|
87
86
|
|
@@ -94,6 +93,5 @@ module Trader
|
|
94
93
|
return _price if forced_pair.nil?
|
95
94
|
_price.convert_to forced_pair.quote
|
96
95
|
end
|
97
|
-
|
98
96
|
end
|
99
97
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module Trader
|
2
2
|
class Balance
|
3
|
-
|
4
3
|
def initialize(_backend, _session, _currency, _forced_currency=nil)
|
5
4
|
@backend = _backend
|
6
5
|
@session = _session
|
@@ -37,15 +36,31 @@ module Trader
|
|
37
36
|
end
|
38
37
|
|
39
38
|
def refresh!
|
40
|
-
self.raw = backend.get_balance
|
39
|
+
self.raw = backend.get_balance session, currency
|
41
40
|
self
|
42
41
|
end
|
43
42
|
|
44
|
-
|
43
|
+
def new_deposit_endpoint
|
44
|
+
backend.generate_endpoint session, original_currency
|
45
|
+
end
|
46
|
+
|
47
|
+
def withdraw(_amount, to: nil)
|
48
|
+
_amount = currency.pack _amount
|
49
|
+
_amount = _amount.convert_to original_currency
|
50
|
+
|
51
|
+
backend.withdraw_to_endpoint session, currency, _amount.amount, to
|
52
|
+
self
|
53
|
+
end
|
54
|
+
|
55
|
+
def transfer(_amount, to: nil)
|
56
|
+
withdraw _amount, to: to.new_deposit_endpoint
|
57
|
+
end
|
58
|
+
|
59
|
+
protected
|
45
60
|
|
46
61
|
attr_accessor :raw
|
47
62
|
|
48
|
-
|
63
|
+
private
|
49
64
|
|
50
65
|
attr_reader :backend, :session, :forced_currency
|
51
66
|
|
@@ -15,15 +15,16 @@ module Trader
|
|
15
15
|
@markets ||= backend.get_available_markets
|
16
16
|
end
|
17
17
|
|
18
|
-
|
18
|
+
private
|
19
19
|
|
20
20
|
def ensure_supported_market(_pair)
|
21
|
-
|
21
|
+
backend.not_supported _pair unless has_market_for? _pair
|
22
22
|
end
|
23
23
|
|
24
24
|
def ensure_supported_currency(_currency)
|
25
|
-
|
25
|
+
unless available_markets.any? { |m| m.quote == _currency || m.base == _currency }
|
26
|
+
backend.not_supported _currency
|
27
|
+
end
|
26
28
|
end
|
27
|
-
|
28
29
|
end
|
29
30
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Trader
|
2
|
+
class Error < StandardError; end
|
3
|
+
|
4
|
+
class AssertError < Error; end
|
5
|
+
|
6
|
+
class BackendError < Error
|
7
|
+
attr_reader :backend
|
8
|
+
|
9
|
+
def initialize(_backend, _message)
|
10
|
+
super "#{_backend}: #{_message}"
|
11
|
+
@backend = _backend
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class NotSupportedError < BackendError
|
16
|
+
attr_reader :feature
|
17
|
+
|
18
|
+
def initialize(_backend, _feature)
|
19
|
+
super _backend, "#{_feature} not supported"
|
20
|
+
@feature = _feature
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/trade-o-matic.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require "trade-o-matic/version"
|
2
2
|
require 'trade-o-matic/standard'
|
3
3
|
require 'trade-o-matic/command'
|
4
|
+
require 'trade-o-matic/errors'
|
4
5
|
|
5
6
|
require 'trade-o-matic/structs/currency'
|
6
7
|
require 'trade-o-matic/structs/currency_pair'
|
@@ -23,6 +24,11 @@ require 'trade-o-matic/core/account_proxy'
|
|
23
24
|
require 'trade-o-matic/core/account_order'
|
24
25
|
require 'trade-o-matic/core/balance'
|
25
26
|
|
27
|
+
require 'trade-o-matic/endpoints/base_endpoint'
|
28
|
+
require 'trade-o-matic/endpoints/bitcoin_address'
|
29
|
+
|
30
|
+
require 'trade-o-matic/adapters/base_backend'
|
31
|
+
|
26
32
|
require 'trade-o-matic/converters/fixed_converter'
|
27
33
|
require 'trade-o-matic/converters/sync_converter'
|
28
34
|
require 'trade-o-matic/converters/inverse_converter'
|
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.4.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-
|
11
|
+
date: 2016-05-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rest-client
|
@@ -253,6 +253,7 @@ files:
|
|
253
253
|
- lib/trade-o-matic/adapters/base/raw_account_order.rb
|
254
254
|
- lib/trade-o-matic/adapters/base/raw_balance.rb
|
255
255
|
- lib/trade-o-matic/adapters/base/raw_resource.rb
|
256
|
+
- lib/trade-o-matic/adapters/base_backend.rb
|
256
257
|
- lib/trade-o-matic/adapters/bitfinex_backend.rb
|
257
258
|
- lib/trade-o-matic/adapters/bitstamp_backend.rb
|
258
259
|
- lib/trade-o-matic/adapters/fake_backend.rb
|
@@ -279,6 +280,9 @@ files:
|
|
279
280
|
- lib/trade-o-matic/core/exchange.rb
|
280
281
|
- lib/trade-o-matic/core/market.rb
|
281
282
|
- lib/trade-o-matic/core/market_loader.rb
|
283
|
+
- lib/trade-o-matic/endpoints/base_endpoint.rb
|
284
|
+
- lib/trade-o-matic/endpoints/bitcoin_address.rb
|
285
|
+
- lib/trade-o-matic/errors.rb
|
282
286
|
- lib/trade-o-matic/services/backend_factory.rb
|
283
287
|
- lib/trade-o-matic/standard.rb
|
284
288
|
- lib/trade-o-matic/structs/ask_slope.rb
|