trade-o-matic 0.1.0

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9300715275fb3f78ca15a6d534d493f61c75ea7e
4
+ data.tar.gz: b3f66fd9b2f31736c86260f45c817ea8dc85dc01
5
+ SHA512:
6
+ metadata.gz: 5208ae28f7c8d4da98d1a65bfdef0f1f9b2b1a09e4744ee79b87c32f104a6c9e71ceca7ea4045af8cba160c7b4ffca7f2b338b694cb514310957791e3fd24897
7
+ data.tar.gz: 4efe51fef441d0a483e38a766743268f87bf4fb9a968496763c85befd879aa6e05902b5732e24e6e525199e83c4e2435019ca16130341f5ed25f9e18cd7e0b5a
data/bin/trader ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'trade-o-matic'
4
+ require 'trade-o-matic/cli'
@@ -0,0 +1,63 @@
1
+ require 'rest-client'
2
+ require 'json'
3
+
4
+ module Trader
5
+
6
+ # TODO: separate market information from account
7
+
8
+ class BitstampAccount
9
+
10
+ def initialize
11
+ end
12
+
13
+ def market_snapshot
14
+ market = Market.new :BTC, :Bitstamp_USD
15
+ unpack_order_book market, fetch_raw_order_book
16
+ unpack_transactions market, fetch_raw_transactions
17
+ market
18
+ end
19
+
20
+ def refresh
21
+ end
22
+
23
+ def base_balance # XBT in an XBT/USD pair
24
+ Price.new :BTC, 0.0
25
+ end
26
+
27
+ def quote_balance # USD in an XBT/USD pair
28
+ Price.new :Bitstamp_USD, 20000.0
29
+ end
30
+
31
+ def create_order
32
+ end
33
+
34
+ def cancel_order
35
+ end
36
+
37
+ def orders
38
+ end
39
+
40
+ private
41
+
42
+ def fetch_raw_order_book
43
+ JSON.parse(RestClient.get "https://www.bitstamp.net/api/order_book/")
44
+ end
45
+
46
+ def fetch_raw_transactions
47
+ JSON.parse(RestClient.get "https://www.bitstamp.net/api/transactions/")
48
+ end
49
+
50
+ def unpack_order_book(_market, _ob)
51
+ _ob['bids'].each { |o| _market.add_bid(o[0].to_f, o[1].to_f) }
52
+ _ob['asks'].each { |o| _market.add_ask(o[0].to_f, o[1].to_f) }
53
+ end
54
+
55
+ def unpack_transactions(_market, _tx)
56
+ _tx.each do |t|
57
+ time = Time.at(t['date'].to_i)
58
+ market.add_buy(t['price'].to_f, t['amount'].to_f, time) if ['type'] == 0
59
+ market.add_sell(t['price'].to_f, t['amount'].to_f, time) if ['type'] == 1
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,49 @@
1
+ require 'gli'
2
+
3
+ module Trader
4
+ class CLI
5
+ extend GLI::App
6
+
7
+ program_desc 'Trader command line interface'
8
+
9
+ desc "Executes trade-o-matic using provided settings"
10
+ command [:run, :r] do |c|
11
+
12
+ c.desc "Specifies the configuration file"
13
+ c.flag [:c, :config]
14
+
15
+ c.desc "Start the server in verbose mode"
16
+ c.switch :dry, :default_value => false
17
+
18
+ c.action do |global_options,options,args|
19
+
20
+ require 'trade-o-matic/adapters/bitstamp_account'
21
+ require 'trade-o-matic/generators/linear_generator'
22
+ require 'trade-o-matic/flows/ask_replicator_flow'
23
+
24
+ Currency.register_conversion(:CLP, :Bitstamp_USD, 1.0/710.0)
25
+
26
+ source = Trader::BitstampAccount.new
27
+ target = nil
28
+ generator = LinearGenerator.new(spread: Price.new(:CLP, 10000.0), step: Price.new(:CLP, 1000.0))
29
+
30
+ flow = Trader::AskReplicatorFlow.new source, target, generator
31
+
32
+ puts 'Running ask replicator'
33
+ orders = flow.run options[:dry]
34
+
35
+ puts 'Generated the following orders :'
36
+ orders.each { |o| puts "#{o.price} [#{o.volume}]" }
37
+ end
38
+ end
39
+
40
+ on_error do |exc|
41
+ puts exc.to_s
42
+ puts exc.backtrace
43
+
44
+ false
45
+ end
46
+
47
+ exit run(ARGV)
48
+ end
49
+ end
@@ -0,0 +1,16 @@
1
+ module Trader
2
+
3
+ class FixedConverter < Converter
4
+
5
+ attr_accessor :rate
6
+
7
+ def initialize(_rate)
8
+ @rate = _rate
9
+ end
10
+
11
+ def convert(_value, _from, _to)
12
+ _value * rate
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,33 @@
1
+ module Trader
2
+
3
+ class SyncConverter < Converter
4
+
5
+ attr_reader :ttl
6
+
7
+ def initialize(_ttl, &_block)
8
+ @ttl = _ttl
9
+ @block = _block
10
+ end
11
+
12
+ def expired?
13
+ @last_sync < Time.new - @ttl
14
+ end
15
+
16
+ def convert(_value, _from, _to)
17
+ rate = sync_rate
18
+ _value * rate
19
+ end
20
+
21
+ private
22
+
23
+ def sync_rate
24
+ if @last_sync.nil? or expired?
25
+ @rate = @block.call
26
+ @last_sync = Time.now
27
+ end
28
+
29
+ @rate
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,50 @@
1
+ module Trader
2
+
3
+ class AskReplicatorFlow
4
+
5
+ def initialize(_source, _target, _generator)
6
+ @source = _source
7
+ @target = _target
8
+ @generator = _generator
9
+ end
10
+
11
+ def run(_dry)
12
+
13
+ # TODO: assert that both source and target base currencies are the same.
14
+
15
+ market = source.market_snapshot
16
+
17
+ skip_volume = market.ask_slope.volume 60
18
+
19
+ start_price = market.ask_slope.price skip_volume
20
+
21
+ available_volume = market.ask_slope.assess source.quote_balance, skip_volume # TODO: check
22
+
23
+ # available_volume = target.base_balance if target.base_balance < available_volume
24
+
25
+ orders = generator.ask start_price, available_volume
26
+
27
+ orders = adjust_orders_to_slope orders, market.ask_slope
28
+
29
+ # orders.each { |o| o.price.convert(target.quote_currency) }
30
+
31
+ # executed = target_position.sync orders
32
+ # executed.each do |order|
33
+
34
+ # end
35
+
36
+ # TODO: transform orders price to target currency
37
+
38
+ # TODO: sync orders
39
+
40
+ end
41
+
42
+ private
43
+
44
+ attr_reader :source, :target, :generator
45
+
46
+ def adjust_orders_to_slope(_orders, _slope)
47
+ _orders
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,37 @@
1
+ module Trader
2
+ class LinearGenerator
3
+
4
+ def initialize(_options)
5
+ @price_spread = _options[:spread]
6
+ @price_step = _options[:step]
7
+ end
8
+
9
+ def bid(_start_price, _volume)
10
+ generate _start_price, _volume, -1
11
+ end
12
+
13
+ def ask(_start_price, _volume)
14
+ generate _start_price, _volume, 1
15
+ end
16
+
17
+ private
18
+
19
+ def generate(_start_price, _volume, _mult)
20
+ buckets = (@price_spread.amount / @price_step.amount).floor
21
+
22
+ # make sure price step is using the same currency as generated prices
23
+ conv_price_step = @price_step.convert(_start_price.currency).amount
24
+
25
+ buckets.floor.times.map do |i|
26
+ price = _start_price.amount + _mult * conv_price_step * i
27
+ volume = _volume.amount / buckets
28
+
29
+ Order.new(
30
+ Price.new(_start_price.currency, price),
31
+ Price.new(_volume.currency, volume)
32
+ )
33
+ end
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,10 @@
1
+ module Trader
2
+ class AskSlope < Slope
3
+
4
+ private
5
+
6
+ def compare(_price_a, _price_b)
7
+ _price_a <=> _price_b
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Trader
2
+ class BidSlope < Slope
3
+
4
+ private
5
+
6
+ def compare(_price_a, _price_b)
7
+ _price_b <=> _price_a
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,8 @@
1
+ module Trader
2
+ class Converter
3
+
4
+ def convert(_value, _from, _to)
5
+ raise NotImplementedError, 'convert method not implemented'
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,63 @@
1
+ module Trader
2
+ class Currency
3
+
4
+ def self.register_conversion(_to, _from, _converter=nil, &_block)
5
+ _to = _to.code if _to.is_a? Currency
6
+ _from = _from.code if _from.is_a? Currency
7
+
8
+ if !_block.nil?
9
+ _converter = SyncConverter.new(300, &_block)
10
+ elsif _converter.is_a? Integer or _converter.is_a? Float
11
+ _converter = FixedConverter.new(_converter)
12
+ end
13
+
14
+ converters["#{_to}-#{_from}"] = _converter
15
+ end
16
+
17
+ def self.for_code(_code)
18
+ registry[_code]
19
+ end
20
+
21
+ attr_reader :code
22
+
23
+ def initialize(_code)
24
+ @code = _code
25
+ end
26
+
27
+ def convert(_value, _currency)
28
+ _currency = _currency.code if _currency.is_a? Currency
29
+ converter_for(code, _currency).convert(_value, code, _currency)
30
+ end
31
+
32
+ def unpack(_value, _options={})
33
+ _options = { default: _options } unless _options.is_a? Hash
34
+
35
+ if _value.is_a? Price
36
+ raise StandardError, "Expected value currency to be #{code} (was #{_value.currency.code})" if _value.currency != self
37
+ _value.amount
38
+ elsif _value.nil?
39
+ _options[:default]
40
+ elsif _options.fetch(:strict, true)
41
+ raise StandardError, "Must provide a currency bound price"
42
+ else
43
+ _value
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def self.registry
50
+ @@registry ||= Hash.new { |h,k| h[k] = self.new(k.to_sym) }
51
+ end
52
+
53
+ def self.converters
54
+ @@converters ||= Hash.new
55
+ end
56
+
57
+ def converter_for(_from, _to)
58
+ cv = self.class.converters["#{_from}-#{_to}"]
59
+ raise StandardError, "No converter registered for #{_from}/#{_to}" if cv.nil?
60
+ cv
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,14 @@
1
+ module Trader
2
+ class CurrencyPair
3
+
4
+ attr_reader :base, :quote
5
+
6
+ def initialize(_base, _quote)
7
+ _base = Currency.for_code _base unless _base.is_a? Currency
8
+ _quote = Currency.for_code _quote unless _quote.is_a? Currency
9
+
10
+ @base = _base
11
+ @quote = _quote
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,28 @@
1
+ module Trader
2
+ class Market
3
+
4
+ attr_reader :pair, :ask_slope, :bid_slope
5
+
6
+ def initialize(_base, _quote)
7
+ @pair = CurrencyPair.new _base, _quote
8
+ @ask_slope = AskSlope.new @pair
9
+ @bid_slope = BidSlope.new @pair
10
+ end
11
+
12
+ def add_bid(_price, _volume)
13
+ @bid_slope.add_order(_price, _volume)
14
+ end
15
+
16
+ def add_ask(_price, _volume)
17
+ @ask_slope.add_order(_price, _volume)
18
+ end
19
+
20
+ def add_sell(_price, _volume, _time)
21
+ @bid_slope.add_transaction(_price, _volume, _time)
22
+ end
23
+
24
+ def add_buy(_price, _volume, _time)
25
+ @bid_slope.add_transaction(_price, _volume, _time)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,3 @@
1
+ module Trader
2
+ class Order < Struct.new(:price, :volume); end
3
+ end
@@ -0,0 +1,41 @@
1
+ module Trader
2
+ class Price
3
+
4
+ attr_reader :currency, :amount
5
+
6
+ def initialize(_currency, _amount)
7
+ _currency = Currency.for_code(_currency) unless _currency.is_a? Currency
8
+
9
+ @currency = _currency
10
+ @amount = _amount
11
+ end
12
+
13
+ def convert(_other_currency)
14
+ _other_currency = Currency.for _other_currency unless _other_currency.is_a? Currency
15
+
16
+ return self if _other_currency == currency
17
+
18
+ new_amount = @currency.convert amount, _other_currency
19
+ Price.new _other_currency, new_amount
20
+ end
21
+
22
+ def to_s
23
+ "#{amount} #{currency.code}"
24
+ end
25
+
26
+ [:<, :<=, :>=, :>, :==, '<=>'].each do |op|
27
+ define_method(op) do |_other|
28
+ _other = currency.unpack(_other)
29
+ amount.public_send(op, _other)
30
+ end
31
+ end
32
+
33
+ [:+, :-, :*, :/].each do |op|
34
+ define_method(op) do |_other|
35
+ _other = currency.unpack(_other)
36
+ Price.new currency, amount.public_send(op, _other)
37
+ end
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,147 @@
1
+ module Trader
2
+ class Slope
3
+
4
+ attr_reader :pair
5
+
6
+ def initialize(_pair, _ref_time=nil)
7
+ @pair = _pair
8
+ @orders = []
9
+ @transactions = []
10
+ @orders_sorted = false
11
+ @ref_time = _ref_time || Time.now
12
+ end
13
+
14
+ def add_order(_price, _volume)
15
+ @orders_sorted = false
16
+ @orders << Order.new(
17
+ Price.new(pair.quote, _price),
18
+ Price.new(pair.base, _volume),
19
+ )
20
+ nil
21
+ end
22
+
23
+ def add_transaction(_price, _volume, _time)
24
+ @transactions << Transaction.new(
25
+ Price.new(pair.quote, _price),
26
+ Price.new(pair.base, _volume),
27
+ _time
28
+ )
29
+ nil
30
+ end
31
+
32
+ def volume(_period_seconds)
33
+ ref_time = @ref_time - _period_seconds
34
+ amount = @transactions.inject(0.0) do |r, trx|
35
+ if trx.time >= ref_time
36
+ r + trx.volume.amount
37
+ else
38
+ r
39
+ end
40
+ end
41
+
42
+ Price.new pair.base, amount
43
+ end
44
+
45
+ def price(_skip_volume=nil)
46
+ _skip_volume = pair.base.unpack _skip_volume, 0.0
47
+
48
+ slice(_skip_volume).first[0].price
49
+ end
50
+
51
+ def volume_for_price(_price, _skip_volume=nil)
52
+ _price = pair.quote.unpack _price
53
+ _skip_volume = pair.base.unpack _skip_volume, 0.0
54
+
55
+ wt_price = 0.0
56
+ r_volume = 0.0
57
+
58
+ slice(_skip_volume).each do |order, volume|
59
+ if compare(order.price.amount, _price) == -1
60
+ x = (_price - wt_price) * r_volume / (order.price.amount - _price)
61
+ if x < volume
62
+ volume = x
63
+ end
64
+ end
65
+
66
+ wt_price = (wt_price * r_volume + order.price.amount * volume) / (r_volume + volume)
67
+ r_volume += volume
68
+ end
69
+
70
+ Price.new pair.base, r_volume
71
+ end
72
+
73
+ def quote(_volume, _skip_volume=nil)
74
+ _volume = pair.base.unpack _volume, 0.0
75
+ _skip_volume = pair.base.unpack _skip_volume, 0.0
76
+
77
+ total_price = 0.0
78
+ slice(_skip_volume, _volume).each do |order, order_volume|
79
+ total_price += order_volume * order.price.amount
80
+ end
81
+
82
+ Price.new pair.quote, total_price
83
+ end
84
+
85
+ def assess(_amount, _skip_volume=nil)
86
+ _amount = pair.quote.unpack _amount
87
+ _skip_volume = pair.base.unpack _skip_volume, 0.0
88
+
89
+ total_volume = 0.0
90
+ slice(_skip_volume).each do |order, volume|
91
+ order_quote = order.price.amount * volume
92
+ if order_quote > _amount
93
+ total_volume += _amount / order.price.amount
94
+ break
95
+ else
96
+ total_volume += volume
97
+ _amount -= order_quote
98
+ end
99
+ end
100
+
101
+ Price.new pair.base, total_volume
102
+ end
103
+
104
+ private
105
+
106
+ attr_reader :transactions
107
+
108
+ def orders
109
+ unless @orders_sorted
110
+ sort_by_relevance @orders
111
+ @orders_sorted = true
112
+ end
113
+
114
+ @orders
115
+ end
116
+
117
+ def slice(_skip_volume, _volume=nil)
118
+ return to_enum(:slice, _skip_volume, _volume) unless block_given?
119
+
120
+ orders.each do |order|
121
+ if order.volume.amount >= _skip_volume
122
+ volume = order.volume.amount - _skip_volume
123
+
124
+ unless _volume.nil?
125
+ volume = _volume if _volume < volume
126
+ _volume -= volume
127
+ end
128
+
129
+ yield order, volume
130
+ break if _volume == 0.0
131
+ _skip_volume = 0.0
132
+ else
133
+ _skip_volume -= order.volume.amount
134
+ end
135
+ end
136
+ end
137
+
138
+ def sort_by_relevance(_orders)
139
+ _orders.sort! { |a, b| compare a.price.amount, b.price.amount }
140
+ end
141
+
142
+ def compare(_price_a, _price_b)
143
+ # abstract
144
+ end
145
+
146
+ end
147
+ end
@@ -0,0 +1,3 @@
1
+ module Trader
2
+ class Transaction < Struct.new(:price, :volume, :time); end
3
+ end
@@ -0,0 +1,3 @@
1
+ module Trader
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,19 @@
1
+ require "trade-o-matic/version"
2
+
3
+ require 'trade-o-matic/structs/currency'
4
+ require 'trade-o-matic/structs/currency_pair'
5
+ require 'trade-o-matic/structs/converter'
6
+ require 'trade-o-matic/structs/price'
7
+ require 'trade-o-matic/structs/order'
8
+ require 'trade-o-matic/structs/transaction'
9
+ require 'trade-o-matic/structs/market'
10
+ require 'trade-o-matic/structs/slope'
11
+ require 'trade-o-matic/structs/ask_slope'
12
+ require 'trade-o-matic/structs/bid_slope'
13
+
14
+ require 'trade-o-matic/converters/fixed_converter'
15
+ require 'trade-o-matic/converters/sync_converter'
16
+
17
+ module Trader
18
+
19
+ end
metadata ADDED
@@ -0,0 +1,281 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: trade-o-matic
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ignacio Baixas
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-12-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: gli
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '2.12'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '2.12'
27
+ - !ruby/object:Gem::Dependency
28
+ name: inquirer
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '0.2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '0.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rainbow
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '2.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '2.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry-byebug
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '3.2'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '3.2'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rest-client
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: bundler
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: '1.6'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: '1.6'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ version: '10.4'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: '10.4'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: '3.1'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ~>
123
+ - !ruby/object:Gem::Version
124
+ version: '3.1'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rspec-nc
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ~>
130
+ - !ruby/object:Gem::Version
131
+ version: '0.2'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ~>
137
+ - !ruby/object:Gem::Version
138
+ version: '0.2'
139
+ - !ruby/object:Gem::Dependency
140
+ name: guard
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ~>
144
+ - !ruby/object:Gem::Version
145
+ version: '2.11'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ~>
151
+ - !ruby/object:Gem::Version
152
+ version: '2.11'
153
+ - !ruby/object:Gem::Dependency
154
+ name: guard-rspec
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ~>
158
+ - !ruby/object:Gem::Version
159
+ version: '4.5'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ~>
165
+ - !ruby/object:Gem::Version
166
+ version: '4.5'
167
+ - !ruby/object:Gem::Dependency
168
+ name: terminal-notifier-guard
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ~>
172
+ - !ruby/object:Gem::Version
173
+ version: '1.6'
174
+ - - '>='
175
+ - !ruby/object:Gem::Version
176
+ version: 1.6.1
177
+ type: :development
178
+ prerelease: false
179
+ version_requirements: !ruby/object:Gem::Requirement
180
+ requirements:
181
+ - - ~>
182
+ - !ruby/object:Gem::Version
183
+ version: '1.6'
184
+ - - '>='
185
+ - !ruby/object:Gem::Version
186
+ version: 1.6.1
187
+ - !ruby/object:Gem::Dependency
188
+ name: pry
189
+ requirement: !ruby/object:Gem::Requirement
190
+ requirements:
191
+ - - ~>
192
+ - !ruby/object:Gem::Version
193
+ version: '0.10'
194
+ type: :development
195
+ prerelease: false
196
+ version_requirements: !ruby/object:Gem::Requirement
197
+ requirements:
198
+ - - ~>
199
+ - !ruby/object:Gem::Version
200
+ version: '0.10'
201
+ - !ruby/object:Gem::Dependency
202
+ name: pry-remote
203
+ requirement: !ruby/object:Gem::Requirement
204
+ requirements:
205
+ - - ~>
206
+ - !ruby/object:Gem::Version
207
+ version: '0.1'
208
+ type: :development
209
+ prerelease: false
210
+ version_requirements: !ruby/object:Gem::Requirement
211
+ requirements:
212
+ - - ~>
213
+ - !ruby/object:Gem::Version
214
+ version: '0.1'
215
+ - !ruby/object:Gem::Dependency
216
+ name: pry-nav
217
+ requirement: !ruby/object:Gem::Requirement
218
+ requirements:
219
+ - - ~>
220
+ - !ruby/object:Gem::Version
221
+ version: '0.2'
222
+ type: :development
223
+ prerelease: false
224
+ version_requirements: !ruby/object:Gem::Requirement
225
+ requirements:
226
+ - - ~>
227
+ - !ruby/object:Gem::Version
228
+ version: '0.2'
229
+ description: Yep
230
+ email:
231
+ - ignacio@platan.us
232
+ executables:
233
+ - trader
234
+ extensions: []
235
+ extra_rdoc_files: []
236
+ files:
237
+ - bin/trader
238
+ - lib/trade-o-matic.rb
239
+ - lib/trade-o-matic/adapters/bitstamp_account.rb
240
+ - lib/trade-o-matic/cli.rb
241
+ - lib/trade-o-matic/converters/fixed_converter.rb
242
+ - lib/trade-o-matic/converters/sync_converter.rb
243
+ - lib/trade-o-matic/flows/ask_replicator_flow.rb
244
+ - lib/trade-o-matic/generators/linear_generator.rb
245
+ - lib/trade-o-matic/structs/ask_slope.rb
246
+ - lib/trade-o-matic/structs/bid_slope.rb
247
+ - lib/trade-o-matic/structs/converter.rb
248
+ - lib/trade-o-matic/structs/currency.rb
249
+ - lib/trade-o-matic/structs/currency_pair.rb
250
+ - lib/trade-o-matic/structs/market.rb
251
+ - lib/trade-o-matic/structs/order.rb
252
+ - lib/trade-o-matic/structs/price.rb
253
+ - lib/trade-o-matic/structs/slope.rb
254
+ - lib/trade-o-matic/structs/transaction.rb
255
+ - lib/trade-o-matic/version.rb
256
+ homepage: https://github.com/surbtc/trade-o-matic
257
+ licenses:
258
+ - MIT
259
+ metadata: {}
260
+ post_install_message:
261
+ rdoc_options: []
262
+ require_paths:
263
+ - lib
264
+ required_ruby_version: !ruby/object:Gem::Requirement
265
+ requirements:
266
+ - - '>='
267
+ - !ruby/object:Gem::Version
268
+ version: '0'
269
+ required_rubygems_version: !ruby/object:Gem::Requirement
270
+ requirements:
271
+ - - '>='
272
+ - !ruby/object:Gem::Version
273
+ version: '0'
274
+ requirements: []
275
+ rubyforge_project:
276
+ rubygems_version: 2.4.8
277
+ signing_key:
278
+ specification_version: 4
279
+ summary: Trade-O-Matic is a trade automation framework
280
+ test_files: []
281
+ has_rdoc: