trade-o-matic 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: