excoin 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +32 -0
- data/Gemfile +13 -0
- data/LICENSE.txt +674 -0
- data/README.md +278 -0
- data/Rakefile +9 -0
- data/config/config.example.yml +16 -0
- data/excoin.gemspec +26 -0
- data/lib/account/account.rb +116 -0
- data/lib/account/deposit.rb +20 -0
- data/lib/account/order.rb +43 -0
- data/lib/account/orders.rb +138 -0
- data/lib/account/trade.rb +26 -0
- data/lib/account/trades.rb +59 -0
- data/lib/account/wallet.rb +72 -0
- data/lib/account/withdrawal.rb +27 -0
- data/lib/exchange/candlestick_chart.rb +33 -0
- data/lib/exchange/candlestick_data.rb +20 -0
- data/lib/exchange/exchange.rb +75 -0
- data/lib/exchange/market.rb +50 -0
- data/lib/exchange/order.rb +23 -0
- data/lib/exchange/order_depth_chart.rb +41 -0
- data/lib/exchange/order_depth_data.rb +23 -0
- data/lib/exchange/orders.rb +119 -0
- data/lib/exchange/trade.rb +26 -0
- data/lib/exchange/trades.rb +68 -0
- data/lib/excoin.rb +45 -0
- data/lib/excoin/api.rb +212 -0
- data/lib/excoin/version.rb +10 -0
- data/spec/fixtures/cassette_library/account_cancel_order_erb.yml +59 -0
- data/spec/fixtures/cassette_library/account_issue_order_erb.yml +59 -0
- data/spec/fixtures/cassette_library/account_view_order_erb.yml +59 -0
- data/spec/fixtures/cassette_library/exc_recent_trades.yml +157 -0
- data/spec/fixtures/cassette_library/exc_recent_trades_count.yml +62 -0
- data/spec/fixtures/cassette_library/exc_recent_trades_timestamp.yml +142 -0
- data/spec/fixtures/cassette_library/exchange_candlestick_chart_data.yml +58 -0
- data/spec/fixtures/cassette_library/exchange_candlestick_chart_data_duration.yml +58 -0
- data/spec/fixtures/cassette_library/exchange_open_orders.yml +58 -0
- data/spec/fixtures/cassette_library/exchange_open_orders_type.yml +58 -0
- data/spec/fixtures/cassette_library/exchange_order_depth_chart_data.yml +58 -0
- data/spec/fixtures/cassette_library/excoin_wallet_reserves.yml +59 -0
- data/spec/fixtures/cassette_library/excoin_wallets_summary.yml +65 -0
- data/spec/fixtures/cassette_library/excoin_wallets_summary_coin.yml +59 -0
- data/spec/fixtures/cassette_library/multi_exchange_summ.yml +58 -0
- data/spec/fixtures/cassette_library/multi_exchange_summ_currency.yml +58 -0
- data/spec/fixtures/cassette_library/single_exchange_summ.yml +58 -0
- data/spec/fixtures/cassette_library/single_exchange_summary.yml +58 -0
- data/spec/lib/account/account_spec.rb +136 -0
- data/spec/lib/account/orders_spec.rb +51 -0
- data/spec/lib/account/trades_spec.rb +52 -0
- data/spec/lib/account/wallet_spec.rb +67 -0
- data/spec/lib/exchange/candlestick_chart_spec.rb +23 -0
- data/spec/lib/exchange/exchange_spec.rb +38 -0
- data/spec/lib/exchange/market_spec.rb +23 -0
- data/spec/lib/exchange/order_depth_chart_spec.rb +20 -0
- data/spec/lib/exchange/orders_spec.rb +47 -0
- data/spec/lib/exchange/trades_spec.rb +50 -0
- data/spec/lib/excoin/api_spec.rb +228 -0
- data/spec/lib/excoin_spec.rb +28 -0
- data/spec/spec_helper.rb +46 -0
- data/spec/support/vcr.rb +21 -0
- metadata +209 -0
@@ -0,0 +1,75 @@
|
|
1
|
+
class Excoin::Market::Exchange
|
2
|
+
attr_reader :name, :currency, :commodity, :last_price, :daily_high,
|
3
|
+
:daily_low, :daily_volume, :top_bid, :lowest_ask, :orders,
|
4
|
+
:trades, :spread
|
5
|
+
|
6
|
+
def initialize(exchange_data)
|
7
|
+
begin
|
8
|
+
@name = exchange_data['currency'] + exchange_data['commodity']
|
9
|
+
@currency = exchange_data['currency']
|
10
|
+
@commodity = exchange_data['commodity']
|
11
|
+
|
12
|
+
self.update_summary(exchange_data)
|
13
|
+
@orders = Orders.new(self)
|
14
|
+
@trades = Trades.new(self)
|
15
|
+
rescue
|
16
|
+
puts "Error in Excoin::Market::Exchange.initialize"
|
17
|
+
puts exchange_data
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def update_summary(exchange_data = nil)
|
22
|
+
begin
|
23
|
+
exchange_data ||= self.get_summary
|
24
|
+
|
25
|
+
@last_price = BigDecimal.new(exchange_data['last_price'])
|
26
|
+
@daily_high = BigDecimal.new(exchange_data['high'])
|
27
|
+
@daily_low = BigDecimal.new(exchange_data['low'])
|
28
|
+
@daily_volume = BigDecimal.new(exchange_data['volume'])
|
29
|
+
@top_bid = BigDecimal.new(exchange_data['top_bid'])
|
30
|
+
@lowest_ask = BigDecimal.new(exchange_data['lowest_ask'])
|
31
|
+
spread = self.top_bid - self.lowest_ask
|
32
|
+
@spread = (spread > 0 ? spread : (spread * -1))
|
33
|
+
rescue
|
34
|
+
puts "Error in Excoin::Market::Exchange.update_summary"
|
35
|
+
puts exchange_data
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def update(exchange_data = nil)
|
40
|
+
self.update_summary(exchange_data)
|
41
|
+
@orders.update
|
42
|
+
@trades.update
|
43
|
+
end
|
44
|
+
|
45
|
+
def issue_order(type, amount, price)
|
46
|
+
decimal_amount = amount
|
47
|
+
if amount.class == String
|
48
|
+
decimal_amount = BigDecimal.new(amount)
|
49
|
+
end
|
50
|
+
if type.upcase == "BID" and (Excoin.account.wallet(self.currency).status == "inactive" or Excoin.account.wallet(self.currency).available_balance < decimal_amount)
|
51
|
+
return "Insufficient funds for this order (#{self.currency})"
|
52
|
+
elsif type.upcase == "ASK" and (Excoin.account.wallet(self.commodity).status == "inactive" or Excoin.account.wallet(self.commodity).available_balance < decimal_amount)
|
53
|
+
return "Insufficient funds for this order (#{self.commodity})"
|
54
|
+
else
|
55
|
+
begin
|
56
|
+
order = Excoin.api.account_issue_order(self.currency, self.commodity, type, amount, price)
|
57
|
+
order.merge!({"currency" => self.currency, "commodity" => self.commodity})
|
58
|
+
exchange_order = Excoin::Market::Exchange::Order.new(order)
|
59
|
+
account_order = Excoin::Account::Order.new(order)
|
60
|
+
self.orders.add(exchange_order)
|
61
|
+
Excoin.account.orders.add(account_order)
|
62
|
+
return account_order.id
|
63
|
+
rescue
|
64
|
+
puts "Error in Excoin::Market::Exchange.issue_order"
|
65
|
+
puts order
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
protected
|
71
|
+
def get_summary
|
72
|
+
Excoin.api(@api_key).exchange_summary(@currency, @commodity)
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
class Excoin::Market < Array
|
2
|
+
|
3
|
+
def initialize
|
4
|
+
self.refresh_all_data
|
5
|
+
end
|
6
|
+
|
7
|
+
def exchanges(currency)
|
8
|
+
return self.select{ |e| e.currency == currency }
|
9
|
+
end
|
10
|
+
|
11
|
+
def exchange(exchange_name)
|
12
|
+
return self.select{ |e| e.name == exchange_name }[0]
|
13
|
+
end
|
14
|
+
|
15
|
+
def update
|
16
|
+
exchanges_data = self.get_summary
|
17
|
+
begin
|
18
|
+
exchanges_data.each do |exchange_data|
|
19
|
+
if self.select{|e| e.exchange_name == exchange_data['currency'] + exchange_data['commodity']}.empty?
|
20
|
+
self.push(Exchange.new(exchange_data))
|
21
|
+
else
|
22
|
+
exchange.update(exchange_data)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
rescue
|
26
|
+
puts "Error in Excoin::Market.update"
|
27
|
+
puts exchanges_data
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def update_orders
|
32
|
+
self.each do |exchange|
|
33
|
+
exchange.orders.update
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def refresh_all_data
|
38
|
+
self.clear
|
39
|
+
exchanges_data = self.get_summary
|
40
|
+
exchanges_data.each do |e|
|
41
|
+
self.push(Exchange.new(e))
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
protected
|
46
|
+
def get_summary
|
47
|
+
Excoin.api(@api_key).multiple_exchange_summary
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class Excoin::Market::Exchange::Order
|
2
|
+
attr_reader :currency, :commodity, :type, :price,
|
3
|
+
:commodity_amount, :currency_amount
|
4
|
+
|
5
|
+
def initialize(order_data)
|
6
|
+
begin
|
7
|
+
@currency = order_data['currency']
|
8
|
+
@commodity = order_data['commodity']
|
9
|
+
@type = order_data['type']
|
10
|
+
@price = BigDecimal.new(order_data['price'])
|
11
|
+
@commodity_amount = BigDecimal.new(order_data['commodity_amount'])
|
12
|
+
@currency_amount = BigDecimal.new(order_data['currency_amount'])
|
13
|
+
rescue
|
14
|
+
puts "Error in Excoin::Market::Exchange::Order.initialize"
|
15
|
+
puts order_data
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def exchange
|
20
|
+
return Excoin.market.exchange(@currency + @commodity)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class Excoin::Market::Exchange::OrderDepthChart
|
2
|
+
attr_reader :currency, :commodity, :bid_orders, :ask_orders
|
3
|
+
|
4
|
+
def initialize(exchange_name)
|
5
|
+
@exchange_name = exchange_name
|
6
|
+
exchange = self.exchange
|
7
|
+
|
8
|
+
@currency = exchange.currency
|
9
|
+
@commodity = exchange.commodity
|
10
|
+
self.update
|
11
|
+
end
|
12
|
+
|
13
|
+
def update
|
14
|
+
@bid_orders = Array.new
|
15
|
+
@ask_orders = Array.new
|
16
|
+
self.populate_orders
|
17
|
+
end
|
18
|
+
|
19
|
+
def exchange
|
20
|
+
return Excoin.market.exchange(@exchange_name)
|
21
|
+
end
|
22
|
+
|
23
|
+
protected
|
24
|
+
|
25
|
+
def populate_orders
|
26
|
+
data = self.get
|
27
|
+
data.each do |order_data|
|
28
|
+
order = DataPoint.new(order_data)
|
29
|
+
if order.type == "BID"
|
30
|
+
@bid_orders << order
|
31
|
+
elsif order.type == "ASK"
|
32
|
+
@ask_orders << order
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def get
|
38
|
+
Excoin.api.exchange_order_depth_chart_data(@currency, @commodity)
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class Excoin::Market::Exchange::OrderDepthChart::DataPoint
|
2
|
+
attr_reader :type, :currency_amount, :price
|
3
|
+
|
4
|
+
def initialize(order_data)
|
5
|
+
update(order_data)
|
6
|
+
end
|
7
|
+
|
8
|
+
protected
|
9
|
+
|
10
|
+
def update(order_data)
|
11
|
+
begin
|
12
|
+
type_array = order_data.select{|h| h != "price"}.to_a.flatten
|
13
|
+
@type = type_array[0]
|
14
|
+
@currency_amount = type_array[1]
|
15
|
+
@price = BigDecimal.new(order_data['price'])
|
16
|
+
rescue
|
17
|
+
puts "Error in Excoin::Market::Exchange::OrderDepthChart::DataPoint.update"
|
18
|
+
puts order_data
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,119 @@
|
|
1
|
+
class Excoin::Market::Exchange::Orders
|
2
|
+
attr_reader :bids, :asks, :all, :orders
|
3
|
+
|
4
|
+
def initialize(exchange)
|
5
|
+
@currency = exchange.currency
|
6
|
+
@commodity = exchange.commodity
|
7
|
+
self.update
|
8
|
+
end
|
9
|
+
|
10
|
+
def update(type = nil)
|
11
|
+
unless type
|
12
|
+
order_data = self.get
|
13
|
+
begin
|
14
|
+
@orders = self.process_orders(order_data)
|
15
|
+
@bids = @orders['bid_orders']
|
16
|
+
@asks = @orders['ask_orders']
|
17
|
+
@all = self.populate_all
|
18
|
+
rescue
|
19
|
+
puts "Error in Excoin::Market::Exchange::Orders.update (unless type)"
|
20
|
+
puts order_data
|
21
|
+
end
|
22
|
+
else
|
23
|
+
order_data = self.get(type)
|
24
|
+
begin
|
25
|
+
orders_by_type = self.process_by_type(order_data)
|
26
|
+
@orders.merge!(orders_by_type)
|
27
|
+
self.set_order_arrays(type)
|
28
|
+
rescue
|
29
|
+
puts "Error in Excoin::Market::Exchange::Orders.update (else)"
|
30
|
+
puts order_data
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def add(new_order)
|
36
|
+
begin
|
37
|
+
type = new_order.type.downcase
|
38
|
+
@orders.select{|k,v| k =~ Regexp.new(type)}[type + "_orders"] << new_order
|
39
|
+
if type == "BID"
|
40
|
+
@orders.select{|k,v| k =~ Regexp.new(type)}[type + "_orders"].sort_by{|order| order.price}.reverse!
|
41
|
+
elsif type == "ASK"
|
42
|
+
@orders.select{|k,v| k =~ Regexp.new(type)}[type + "_orders"].sort_by{|order| order.price}
|
43
|
+
end
|
44
|
+
self.set_order_arrays(new_order.type)
|
45
|
+
rescue
|
46
|
+
puts "Error in Excoin::Market::Exchange::Orders.add"
|
47
|
+
puts new_order
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def remove(order_data)
|
52
|
+
begin
|
53
|
+
type = order_data['type'].downcase
|
54
|
+
@orders.select{|k,v| k =~ Regexp.new(type)}[type + "_orders"].delete_at(@orders.select{|k,v| k =~ Regexp.new(type)}[type + "_orders"].find_index{|order| order.price == BigDecimal.new(order_data['price']) and order.currency_amount == BigDecimal.new(order_data['currency_amount']) and order.commodity_amount == BigDecimal.new(order_data['commodity_amount'])})
|
55
|
+
self.set_order_arrays(order_data['type'])
|
56
|
+
rescue
|
57
|
+
puts "Error in Excoin::Market::Exchange::Orders.remove"
|
58
|
+
puts order_data
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def filter(attr, value, operator = :==)
|
63
|
+
attr = attr.to_sym
|
64
|
+
if attr == :price or attr == :commodity_amount or attr == :currency_amount
|
65
|
+
value = BigDecimal.new(value)
|
66
|
+
end
|
67
|
+
return @all.select{|order| order.send(attr).send(operator, value)}
|
68
|
+
end
|
69
|
+
|
70
|
+
def count(attr, value, operator = :==)
|
71
|
+
return filter(attr, value, operator).size
|
72
|
+
end
|
73
|
+
|
74
|
+
protected
|
75
|
+
|
76
|
+
def get(type = nil)
|
77
|
+
Excoin.api.exchange_open_orders(@currency, @commodity, type)
|
78
|
+
end
|
79
|
+
|
80
|
+
def process_orders(exchange_order_data)
|
81
|
+
exchange_orders = Hash.new
|
82
|
+
exchange_order_data.each do |hash_by_type|
|
83
|
+
exchange_orders.merge!(process_by_type(hash_by_type))
|
84
|
+
end
|
85
|
+
return exchange_orders
|
86
|
+
end
|
87
|
+
|
88
|
+
def process_by_type(hash_by_type)
|
89
|
+
orders_by_type = Array.new
|
90
|
+
type = hash_by_type.select{|k,v| k == 'type'}
|
91
|
+
hash_by_type['orders'].each do |o|
|
92
|
+
o.merge!(type).merge!({"currency" => @currency, "commodity" => @commodity})
|
93
|
+
order = Excoin::Market::Exchange::Order.new(o)
|
94
|
+
orders_by_type << order
|
95
|
+
end
|
96
|
+
return { "#{type['type'].downcase}_orders" => orders_by_type }
|
97
|
+
end
|
98
|
+
|
99
|
+
def set_order_arrays(type)
|
100
|
+
if type.downcase == "bid"
|
101
|
+
@bids = @orders[type.downcase + "_orders"]
|
102
|
+
elsif type.downcase == "ask"
|
103
|
+
@asks = @orders[type.downcase + "_orders"]
|
104
|
+
end
|
105
|
+
@all = self.populate_all
|
106
|
+
end
|
107
|
+
|
108
|
+
def populate_all
|
109
|
+
all = Array.new
|
110
|
+
@bids.each do |o|
|
111
|
+
all << o
|
112
|
+
end
|
113
|
+
@asks.each do |o|
|
114
|
+
all << o
|
115
|
+
end
|
116
|
+
return all
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class Excoin::Market::Exchange::Trade
|
2
|
+
attr_reader :timestamp, :currency, :commodity, :type, :price,
|
3
|
+
:commodity_amount, :currency_amount
|
4
|
+
|
5
|
+
|
6
|
+
def initialize(trade_data)
|
7
|
+
begin
|
8
|
+
@timestamp = Time.parse(trade_data['timestamp'])
|
9
|
+
@currency = trade_data['currency']
|
10
|
+
@commodity = trade_data['commodity']
|
11
|
+
@type = trade_data['type']
|
12
|
+
@price = BigDecimal.new(trade_data['price'])
|
13
|
+
@commodity_amount = BigDecimal.new(trade_data['commodity_amount'])
|
14
|
+
@currency_amount = BigDecimal.new(trade_data['currency_amount'])
|
15
|
+
rescue
|
16
|
+
puts "Error in Excoin::Market::Exchange::Trade.initialize"
|
17
|
+
puts trade_data
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def exchange
|
22
|
+
Excoin.market.exchange(@currency + @commodity)
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
class Excoin::Market::Exchange::Trades < Array
|
2
|
+
|
3
|
+
def initialize(exchange)
|
4
|
+
@currency = exchange.currency
|
5
|
+
@commodity = exchange.commodity
|
6
|
+
self.update
|
7
|
+
end
|
8
|
+
|
9
|
+
def update(limit_type = "count", limit = 100)
|
10
|
+
self.clear
|
11
|
+
trade_data = self.get_recent(@currency, @commodity, limit_type, limit)
|
12
|
+
begin
|
13
|
+
trade_data['trades'].each do |trade|
|
14
|
+
self.push(Excoin::Market::Exchange::Trade.new(trade))
|
15
|
+
end
|
16
|
+
rescue
|
17
|
+
puts "Error in Excoin::Market::Exchange::Trades.update"
|
18
|
+
puts trade_data
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def buys
|
23
|
+
self.select{|trade| trade.type == "BUY"}
|
24
|
+
end
|
25
|
+
|
26
|
+
def sells
|
27
|
+
self.select{|trade| trade.type == "SELL"}
|
28
|
+
end
|
29
|
+
|
30
|
+
def highest(type = nil)
|
31
|
+
unless type
|
32
|
+
self.max_by{|trade| trade.price}
|
33
|
+
else
|
34
|
+
self.select{|trade| trade.type == type.upcase}.max_by{|trade| trade.price}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def lowest(type = nil)
|
39
|
+
unless type
|
40
|
+
self.min_by{|trade| trade.price}
|
41
|
+
else
|
42
|
+
self.select{|trade| trade.type == type.upcase}.min_by{|trade| trade.price}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def add(trade_data)
|
47
|
+
begin
|
48
|
+
unless trade_data.has_key?("currency")
|
49
|
+
trade_data.merge!({"currency" => @currency, "commodity" => @commodity})
|
50
|
+
end
|
51
|
+
self.insert(0, Excoin::Market::Exchange::Trade.new(trade_data))
|
52
|
+
rescue
|
53
|
+
puts "Error in Excoin::Market::Exchange::Trades.add"
|
54
|
+
puts trade_data
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def trim(number)
|
59
|
+
self.pop(number)
|
60
|
+
end
|
61
|
+
|
62
|
+
protected
|
63
|
+
|
64
|
+
def get_recent(currency, commodity, limit_type = "count", limit = 100)
|
65
|
+
Excoin.api.exchange_recent_trades(currency, commodity, limit_type, limit)
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
data/lib/excoin.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
module Excoin
|
2
|
+
require "time"
|
3
|
+
require "bigdecimal"
|
4
|
+
require "bigdecimal/util"
|
5
|
+
require "excoin/api"
|
6
|
+
require "account/account"
|
7
|
+
require "account/wallet"
|
8
|
+
require "account/deposit"
|
9
|
+
require "account/withdrawal"
|
10
|
+
require "account/orders"
|
11
|
+
require "account/order"
|
12
|
+
require "account/trades"
|
13
|
+
require "account/trade"
|
14
|
+
require "exchange/market"
|
15
|
+
require "exchange/exchange"
|
16
|
+
require "exchange/orders"
|
17
|
+
require "exchange/order"
|
18
|
+
require "exchange/trades"
|
19
|
+
require "exchange/trade"
|
20
|
+
require "exchange/order_depth_chart"
|
21
|
+
require "exchange/order_depth_data"
|
22
|
+
require "exchange/candlestick_chart"
|
23
|
+
require "exchange/candlestick_data"
|
24
|
+
|
25
|
+
|
26
|
+
def self.account
|
27
|
+
self.api if @api.nil?
|
28
|
+
@account ||= Account.new
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.exchange(exchange_name)
|
32
|
+
self.api if @api.nil?
|
33
|
+
@exchange ||= self.market.exchange(exchange_name)
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.market
|
37
|
+
self.api if @api.nil?
|
38
|
+
@market ||= Market.new
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.api(api_key = nil, api_secret = nil, replay_strategy = nil, strategy_parameter = nil)
|
42
|
+
@api ||= API.new(api_key, api_secret, replay_strategy, strategy_parameter)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|