excoin 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (62) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +32 -0
  3. data/Gemfile +13 -0
  4. data/LICENSE.txt +674 -0
  5. data/README.md +278 -0
  6. data/Rakefile +9 -0
  7. data/config/config.example.yml +16 -0
  8. data/excoin.gemspec +26 -0
  9. data/lib/account/account.rb +116 -0
  10. data/lib/account/deposit.rb +20 -0
  11. data/lib/account/order.rb +43 -0
  12. data/lib/account/orders.rb +138 -0
  13. data/lib/account/trade.rb +26 -0
  14. data/lib/account/trades.rb +59 -0
  15. data/lib/account/wallet.rb +72 -0
  16. data/lib/account/withdrawal.rb +27 -0
  17. data/lib/exchange/candlestick_chart.rb +33 -0
  18. data/lib/exchange/candlestick_data.rb +20 -0
  19. data/lib/exchange/exchange.rb +75 -0
  20. data/lib/exchange/market.rb +50 -0
  21. data/lib/exchange/order.rb +23 -0
  22. data/lib/exchange/order_depth_chart.rb +41 -0
  23. data/lib/exchange/order_depth_data.rb +23 -0
  24. data/lib/exchange/orders.rb +119 -0
  25. data/lib/exchange/trade.rb +26 -0
  26. data/lib/exchange/trades.rb +68 -0
  27. data/lib/excoin.rb +45 -0
  28. data/lib/excoin/api.rb +212 -0
  29. data/lib/excoin/version.rb +10 -0
  30. data/spec/fixtures/cassette_library/account_cancel_order_erb.yml +59 -0
  31. data/spec/fixtures/cassette_library/account_issue_order_erb.yml +59 -0
  32. data/spec/fixtures/cassette_library/account_view_order_erb.yml +59 -0
  33. data/spec/fixtures/cassette_library/exc_recent_trades.yml +157 -0
  34. data/spec/fixtures/cassette_library/exc_recent_trades_count.yml +62 -0
  35. data/spec/fixtures/cassette_library/exc_recent_trades_timestamp.yml +142 -0
  36. data/spec/fixtures/cassette_library/exchange_candlestick_chart_data.yml +58 -0
  37. data/spec/fixtures/cassette_library/exchange_candlestick_chart_data_duration.yml +58 -0
  38. data/spec/fixtures/cassette_library/exchange_open_orders.yml +58 -0
  39. data/spec/fixtures/cassette_library/exchange_open_orders_type.yml +58 -0
  40. data/spec/fixtures/cassette_library/exchange_order_depth_chart_data.yml +58 -0
  41. data/spec/fixtures/cassette_library/excoin_wallet_reserves.yml +59 -0
  42. data/spec/fixtures/cassette_library/excoin_wallets_summary.yml +65 -0
  43. data/spec/fixtures/cassette_library/excoin_wallets_summary_coin.yml +59 -0
  44. data/spec/fixtures/cassette_library/multi_exchange_summ.yml +58 -0
  45. data/spec/fixtures/cassette_library/multi_exchange_summ_currency.yml +58 -0
  46. data/spec/fixtures/cassette_library/single_exchange_summ.yml +58 -0
  47. data/spec/fixtures/cassette_library/single_exchange_summary.yml +58 -0
  48. data/spec/lib/account/account_spec.rb +136 -0
  49. data/spec/lib/account/orders_spec.rb +51 -0
  50. data/spec/lib/account/trades_spec.rb +52 -0
  51. data/spec/lib/account/wallet_spec.rb +67 -0
  52. data/spec/lib/exchange/candlestick_chart_spec.rb +23 -0
  53. data/spec/lib/exchange/exchange_spec.rb +38 -0
  54. data/spec/lib/exchange/market_spec.rb +23 -0
  55. data/spec/lib/exchange/order_depth_chart_spec.rb +20 -0
  56. data/spec/lib/exchange/orders_spec.rb +47 -0
  57. data/spec/lib/exchange/trades_spec.rb +50 -0
  58. data/spec/lib/excoin/api_spec.rb +228 -0
  59. data/spec/lib/excoin_spec.rb +28 -0
  60. data/spec/spec_helper.rb +46 -0
  61. data/spec/support/vcr.rb +21 -0
  62. 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
@@ -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