excoin 0.0.1

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.
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