open_trade 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. data/.gitignore +17 -0
  2. data/Gemfile +5 -0
  3. data/LICENSE +22 -0
  4. data/README.md +29 -0
  5. data/Rakefile +2 -0
  6. data/bin/send_message.rb +7 -0
  7. data/lib/open_trade.rb +8 -0
  8. data/lib/open_trade/base.rb +4 -0
  9. data/lib/open_trade/base/constants.rb +3 -0
  10. data/lib/open_trade/base/message.rb +88 -0
  11. data/lib/open_trade/base/role.rb +144 -0
  12. data/lib/open_trade/messages/accumulator/calculation.rb +9 -0
  13. data/lib/open_trade/messages/common/acknowledge.rb +5 -0
  14. data/lib/open_trade/messages/common/error.rb +6 -0
  15. data/lib/open_trade/messages/common/heartbeat.rb +3 -0
  16. data/lib/open_trade/messages/common/log.rb +9 -0
  17. data/lib/open_trade/messages/common/start.rb +3 -0
  18. data/lib/open_trade/messages/common/status.rb +6 -0
  19. data/lib/open_trade/messages/common/stop.rb +3 -0
  20. data/lib/open_trade/messages/directory/process_activity.rb +9 -0
  21. data/lib/open_trade/messages/directory/process_list.rb +9 -0
  22. data/lib/open_trade/messages/executor/order_activity.rb +9 -0
  23. data/lib/open_trade/messages/market_data/depth.rb +9 -0
  24. data/lib/open_trade/messages/market_data/quote.rb +9 -0
  25. data/lib/open_trade/messages/market_data/tick.rb +9 -0
  26. data/lib/open_trade/messages/portfolio/account_status.rb +9 -0
  27. data/lib/open_trade/messages/portfolio/exit.rb +9 -0
  28. data/lib/open_trade/messages/portfolio/list_constraints.rb +9 -0
  29. data/lib/open_trade/messages/portfolio/order.rb +9 -0
  30. data/lib/open_trade/messages/portfolio/register_strategy.rb +9 -0
  31. data/lib/open_trade/messages/portfolio/set_constraint.rb +9 -0
  32. data/lib/open_trade/messages/strategy/signal.rb +9 -0
  33. data/lib/open_trade/version.rb +3 -0
  34. data/open_trade.gemspec +17 -0
  35. metadata +125 -0
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in open_trade.gemspec
4
+ gemspec
5
+ gem 'ffi-rzmq'
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Ian Roddis
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # OpenTrade
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'open_trade'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install open_trade
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'bundler/setup'
5
+ require 'open_trade'
6
+
7
+
data/lib/open_trade.rb ADDED
@@ -0,0 +1,8 @@
1
+ require "open_trade/version"
2
+ require 'ffi-rzmq'
3
+ require 'json'
4
+
5
+ module OpenTrade
6
+ require 'open_trade/base'
7
+ require 'open_trade/directory_service'
8
+ end
@@ -0,0 +1,4 @@
1
+ module OpenTrade
2
+ require 'open_trade/base/role'
3
+ require 'open_trade/base/message'
4
+ end
@@ -0,0 +1,3 @@
1
+ module OpenTrade
2
+ TIMESTAMP_FORMAT = '%Y/%m/%dT%H%M%S.%L' #2012/06/30T17:01:00.00
3
+ end
@@ -0,0 +1,88 @@
1
+ require 'json'
2
+ require 'date'
3
+ require 'securerandom'
4
+
5
+ class Hash
6
+ # Update only keys that exist in self with values that exist in param
7
+ def strict_update h={}
8
+ self.keys.each {|k| self[k] = h[k] if h.has_key? k}
9
+ self
10
+ end
11
+
12
+ def symbolize_keys
13
+ inject({}) do |options, (key, value)| options[(key.to_sym rescue key) || key] = value
14
+ options
15
+ end
16
+ end
17
+
18
+ def symbolize_keys! recurse=false
19
+ self.replace(self.symbolize_keys)
20
+ if recurse
21
+ self.values.each {|v| v.symbolize_keys! if v.class == self.class}
22
+ end
23
+ end
24
+ end
25
+
26
+ =begin
27
+ Messge types are an array of field descriptions as hashes:
28
+ [
29
+ {
30
+ :name => :some_name
31
+ :type => :string|:symbol|:number
32
+ :required => true/false
33
+ }, ...
34
+ ]
35
+ =end
36
+
37
+ module OpenTrade
38
+ module Base
39
+ class Message
40
+ @@message_templates = Hash.new
41
+ @@message_validations = Hash.new
42
+
43
+ def self.register_template name, fields, validation_proc=nil
44
+ raise "A message template of #{template} is already registered." if @@message.has_key? name
45
+ fields.each do |field, field_type|
46
+ if not [ :string, :symbol, :number ].contains? field_type
47
+ raise "Error while registering message template #{name}: field #{field} has invalid type #{field_type}"
48
+ end
49
+ end
50
+ fields.symbolize_keys! true
51
+ @@message_templates[name] = fields
52
+ @@message_validations[name] = validation_proc
53
+ end
54
+
55
+ def intialize template_name, field_data={}
56
+ if not @@message.has_key? template_name
57
+ raise "No message template named #{template_name} has been registered yet. Perhaps you forgot to include that gem?"
58
+ end
59
+
60
+ field_data.symbolize_keys! true
61
+
62
+ @type = template_name
63
+ @payload = Hash.new
64
+ @@message_templates[@type].keys.each {|k| @payload[k] = nil}
65
+ @payload.strict_update field_data
66
+ end
67
+
68
+ def to_s
69
+ verify
70
+ JSON.dump ({
71
+ :type => @type,
72
+ :created => Time.now.utc.strftime,
73
+ :uuid => SecureRandom.urlsafe_base64,
74
+ :data => @payload
75
+ })
76
+ end
77
+
78
+ def verify
79
+ @@message_templates[@type].each do |field|
80
+ raise "Required field #{field[:name]} is missing" if field[:required] and @payload[field[:name]] == nil
81
+ end
82
+
83
+ # Message specific validation
84
+ @@message_validations[@type].call(@data) unless @@message_validations[@type].nil?
85
+ end
86
+ end # Message
87
+ end # Module Base
88
+ end # Module OpenTrade
@@ -0,0 +1,144 @@
1
+ require 'socket'
2
+
3
+ module OpenTrade
4
+ module Base
5
+ class Role
6
+ attr_accessor :name, :type, :poll_interval, :request_timeout
7
+
8
+ # :name symbol Process name
9
+ # :type symbol Type of the process
10
+ # :options Hash
11
+ # :request_timeout Integer Time to wait for responses, in ms (default: 25)
12
+ # :poll_interval Integer Time to wait for new input, in ms (default: 25)
13
+ # :request_port Integer Port for requests. nil for no port, 0 for dynamic, and any other number for a static port
14
+ # :publish_port Integer Port for requests. nil for no port, 0 for dynamic, and any other number for a static port
15
+ def initialize name, type, options={}
16
+ defaults = {
17
+ :poll_interval=>25,
18
+ :request_timeout=>25,
19
+ :request_port => 0,
20
+ :publish_port => 0
21
+ }
22
+
23
+ options = defaults.merge options
24
+
25
+ @name = name
26
+ @type = type
27
+ @poll_interval = options[:poll_interval]
28
+ @request_timeout = options[:request_timeout]
29
+
30
+ # Internal stuff
31
+ @zmq_context = ZMQ::Context.new 1
32
+ @zmq_poller = ZMQ::Poller.new
33
+ @hostname = ::Socket.gethostname
34
+ @channels = Hash.new
35
+ @handlers = Hash.new
36
+ @running = false
37
+
38
+ # Set up the server channels
39
+ add_server_channel :request, ZMQ::REQ, options[:request_port]
40
+ add_server_channel :publish, ZMQ::PUB, options[:publish_port]
41
+
42
+ # Make sure to shutdown all the channels
43
+ ObjectSpace.define_finalizer self, method(:destroy)
44
+ end
45
+
46
+ # name symbol A unique name for the process
47
+ # zmq_type integer ZMQ::REP, ZMQ::PUB, etc
48
+ # port integer
49
+ def add_server_channel name, zmq_type, port
50
+ return if port == nil
51
+ @channels[name] = @zmq_context.socket zmq_type
52
+
53
+ if port > 0 # Static Port
54
+ @channels[name].bind "tcp://*:#{port}"
55
+ else # Dynamic port
56
+ port = rand(65000 - 1024) + 1024
57
+ begin
58
+ @channels[name].bind "tcp://*:#{port}"
59
+ rescue
60
+ port = rand(65000 - 1024) + 1024
61
+ retry
62
+ end
63
+ end
64
+
65
+ if zmq_type == ZMQ::REQ
66
+ @zmq_poller.register @channels[name], ZMQ::POLLIN
67
+ end
68
+ end
69
+
70
+ def delete_channel name
71
+ return unless @channels.has_key? name
72
+ @channels[name].close
73
+ @channels.delete name
74
+ end
75
+
76
+ # Register a new handler for each type of message
77
+ # message_type
78
+ def register_message_handler message_type, handler
79
+ @handlers[message_type] = handler
80
+ end
81
+
82
+ # Start
83
+ def start
84
+ @running = true
85
+
86
+ while @running do
87
+ @zmq_poller.poll @poll_interval
88
+ @zmq_poller.readables.each do |channel|
89
+ @channels.select {|channel_name, socket| socket === channel}.each do |channel,socket|
90
+ socket.recv_string(msg = '')
91
+ process_message msg
92
+ end
93
+ end
94
+
95
+ run_loop
96
+ end
97
+
98
+ #shutdown goes here
99
+ end
100
+
101
+ def process_message raw_message
102
+ begin
103
+ message = JSON.parse raw_message
104
+ rescue
105
+ log :error, "Invalid message: #{message}"
106
+ return
107
+ end
108
+
109
+ unless message.has_key? :type
110
+ log :error, "Invalid message: #{message}"
111
+ return
112
+ end
113
+
114
+ unless @handlers.has_key message[:type]
115
+ log :error, "No handler defined for message type #{message[:type]}"
116
+ return
117
+ end
118
+
119
+ @handlers[message[:type]].call message
120
+ end
121
+
122
+ # Run loop
123
+ # An empty process, overridden by the inheritors if needed
124
+ def run_loop
125
+ end
126
+
127
+ # Destroy, called on shutdown
128
+ def destroy
129
+ @channels.keys.each {|name| delete_channel name}
130
+ end
131
+
132
+ def log level, message
133
+ puts "[%s][%s]: %s" % [ Time.now, level, message ]
134
+ send :publish, Base::Message.new(:log, { :level => level, :message => message })
135
+ end
136
+
137
+ def send channel, message_obj
138
+ return unless @channels[channel]
139
+
140
+ @channels[channel].send_string message_obj.to_s
141
+ end
142
+ end # Role
143
+ end # Module Base
144
+ end # Module OpenTrade
@@ -0,0 +1,9 @@
1
+ module OpenTrade
2
+ OpenTrade::Message.register_template :calculation, [
3
+ { :name => "level", :type => :string, :required => true },
4
+ { :name => "message", :type => :string, :required => true },
5
+ ], Proc.new {|data|
6
+ valid_log_levels = [ :info, :debug, :warn, :crit ]
7
+ raise "Log message is not any kind of #{valid_log_levels.join(" ")}" unless valid_log_levels.include? data[:level]
8
+ }
9
+ end
@@ -0,0 +1,5 @@
1
+ module OpenTrade
2
+ OpenTrade::Message.register_template :acknowledge, [
3
+ { :name => "ack_uuid", :type => :string, :required => true }
4
+ ]
5
+ end
@@ -0,0 +1,6 @@
1
+ module OpenTrade
2
+ OpenTrade::Message.register_template :error, [
3
+ { :name => "ack_uuid", :type => :string, :required => true },
4
+ { :name => "error", :type => :string, :required => true },
5
+ ]
6
+ end
@@ -0,0 +1,3 @@
1
+ module OpenTrade
2
+ OpenTrade::Message.register_template :heartbeat, []
3
+ end
@@ -0,0 +1,9 @@
1
+ module OpenTrade
2
+ OpenTrade::Message.register_template :log, [
3
+ { :name => "level", :type => :string, :required => true },
4
+ { :name => "message", :type => :string, :required => true },
5
+ ], Proc.new {|data|
6
+ valid_log_levels = [ :info, :debug, :warn, :crit ]
7
+ raise "Log message is not any kind of #{valid_log_levels.join(" ")}" unless valid_log_levels.include? data[:level]
8
+ }
9
+ end
@@ -0,0 +1,3 @@
1
+ module OpenTrade
2
+ OpenTrade::Message.register_template :start, []
3
+ end
@@ -0,0 +1,6 @@
1
+ module OpenTrade
2
+ OpenTrade::Message.register_template :status, [
3
+ { :name => "mem", :type => :integer, :required => true },
4
+ { :name => "uptime", :type => :integer, :required => true }
5
+ ]
6
+ end
@@ -0,0 +1,3 @@
1
+ module OpenTrade
2
+ OpenTrade::Message.register_template :stop, []
3
+ end
@@ -0,0 +1,9 @@
1
+ module OpenTrade
2
+ OpenTrade::Message.register_template :log, [
3
+ { :name => "level", :type => :string, :required => true },
4
+ { :name => "message", :type => :string, :required => true },
5
+ ], Proc.new {|data|
6
+ valid_log_levels = [ :info, :debug, :warn, :crit ]
7
+ raise "Log message is not any kind of #{valid_log_levels.join(" ")}" unless valid_log_levels.include? data[:level]
8
+ }
9
+ end
@@ -0,0 +1,9 @@
1
+ module OpenTrade
2
+ OpenTrade::Message.register_template :log, [
3
+ { :name => "level", :type => :string, :required => true },
4
+ { :name => "message", :type => :string, :required => true },
5
+ ], Proc.new {|data|
6
+ valid_log_levels = [ :info, :debug, :warn, :crit ]
7
+ raise "Log message is not any kind of #{valid_log_levels.join(" ")}" unless valid_log_levels.include? data[:level]
8
+ }
9
+ end
@@ -0,0 +1,9 @@
1
+ module OpenTrade
2
+ OpenTrade::Message.register_template :log, [
3
+ { :name => "level", :type => :string, :required => true },
4
+ { :name => "message", :type => :string, :required => true },
5
+ ], Proc.new {|data|
6
+ valid_log_levels = [ :info, :debug, :warn, :crit ]
7
+ raise "Log message is not any kind of #{valid_log_levels.join(" ")}" unless valid_log_levels.include? data[:level]
8
+ }
9
+ end
@@ -0,0 +1,9 @@
1
+ module OpenTrade
2
+ OpenTrade::Message.register_template :log, [
3
+ { :name => "level", :type => :string, :required => true },
4
+ { :name => "message", :type => :string, :required => true },
5
+ ], Proc.new {|data|
6
+ valid_log_levels = [ :info, :debug, :warn, :crit ]
7
+ raise "Log message is not any kind of #{valid_log_levels.join(" ")}" unless valid_log_levels.include? data[:level]
8
+ }
9
+ end
@@ -0,0 +1,9 @@
1
+ module OpenTrade
2
+ OpenTrade::Message.register_template :log, [
3
+ { :name => "level", :type => :string, :required => true },
4
+ { :name => "message", :type => :string, :required => true },
5
+ ], Proc.new {|data|
6
+ valid_log_levels = [ :info, :debug, :warn, :crit ]
7
+ raise "Log message is not any kind of #{valid_log_levels.join(" ")}" unless valid_log_levels.include? data[:level]
8
+ }
9
+ end
@@ -0,0 +1,9 @@
1
+ module OpenTrade
2
+ OpenTrade::Message.register_template :log, [
3
+ { :name => "level", :type => :string, :required => true },
4
+ { :name => "message", :type => :string, :required => true },
5
+ ], Proc.new {|data|
6
+ valid_log_levels = [ :info, :debug, :warn, :crit ]
7
+ raise "Log message is not any kind of #{valid_log_levels.join(" ")}" unless valid_log_levels.include? data[:level]
8
+ }
9
+ end
@@ -0,0 +1,9 @@
1
+ module OpenTrade
2
+ OpenTrade::Message.register_template :log, [
3
+ { :name => "level", :type => :string, :required => true },
4
+ { :name => "message", :type => :string, :required => true },
5
+ ], Proc.new {|data|
6
+ valid_log_levels = [ :info, :debug, :warn, :crit ]
7
+ raise "Log message is not any kind of #{valid_log_levels.join(" ")}" unless valid_log_levels.include? data[:level]
8
+ }
9
+ end
@@ -0,0 +1,9 @@
1
+ module OpenTrade
2
+ OpenTrade::Message.register_template :log, [
3
+ { :name => "level", :type => :string, :required => true },
4
+ { :name => "message", :type => :string, :required => true },
5
+ ], Proc.new {|data|
6
+ valid_log_levels = [ :info, :debug, :warn, :crit ]
7
+ raise "Log message is not any kind of #{valid_log_levels.join(" ")}" unless valid_log_levels.include? data[:level]
8
+ }
9
+ end
@@ -0,0 +1,9 @@
1
+ module OpenTrade
2
+ OpenTrade::Message.register_template :log, [
3
+ { :name => "level", :type => :string, :required => true },
4
+ { :name => "message", :type => :string, :required => true },
5
+ ], Proc.new {|data|
6
+ valid_log_levels = [ :info, :debug, :warn, :crit ]
7
+ raise "Log message is not any kind of #{valid_log_levels.join(" ")}" unless valid_log_levels.include? data[:level]
8
+ }
9
+ end
@@ -0,0 +1,9 @@
1
+ module OpenTrade
2
+ OpenTrade::Message.register_template :log, [
3
+ { :name => "level", :type => :string, :required => true },
4
+ { :name => "message", :type => :string, :required => true },
5
+ ], Proc.new {|data|
6
+ valid_log_levels = [ :info, :debug, :warn, :crit ]
7
+ raise "Log message is not any kind of #{valid_log_levels.join(" ")}" unless valid_log_levels.include? data[:level]
8
+ }
9
+ end
@@ -0,0 +1,9 @@
1
+ module OpenTrade
2
+ OpenTrade::Message.register_template :log, [
3
+ { :name => "level", :type => :string, :required => true },
4
+ { :name => "message", :type => :string, :required => true },
5
+ ], Proc.new {|data|
6
+ valid_log_levels = [ :info, :debug, :warn, :crit ]
7
+ raise "Log message is not any kind of #{valid_log_levels.join(" ")}" unless valid_log_levels.include? data[:level]
8
+ }
9
+ end
@@ -0,0 +1,9 @@
1
+ module OpenTrade
2
+ OpenTrade::Message.register_template :log, [
3
+ { :name => "level", :type => :string, :required => true },
4
+ { :name => "message", :type => :string, :required => true },
5
+ ], Proc.new {|data|
6
+ valid_log_levels = [ :info, :debug, :warn, :crit ]
7
+ raise "Log message is not any kind of #{valid_log_levels.join(" ")}" unless valid_log_levels.include? data[:level]
8
+ }
9
+ end
@@ -0,0 +1,9 @@
1
+ module OpenTrade
2
+ OpenTrade::Message.register_template :log, [
3
+ { :name => "level", :type => :string, :required => true },
4
+ { :name => "message", :type => :string, :required => true },
5
+ ], Proc.new {|data|
6
+ valid_log_levels = [ :info, :debug, :warn, :crit ]
7
+ raise "Log message is not any kind of #{valid_log_levels.join(" ")}" unless valid_log_levels.include? data[:level]
8
+ }
9
+ end
@@ -0,0 +1,3 @@
1
+ module OpenTrade
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,17 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/open_trade/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Ian Roddis"]
6
+ gem.email = ["git@cactusgrove.net"]
7
+ gem.description = %q{All required message definitions, base classes, and some platform-agnostic tools.}
8
+ gem.summary = %q{The basic OpenTrade platform. You will still need to implement or install your own roles.}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "open_trade"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = OpenTrade::VERSION
17
+ end
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: open_trade
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ian Roddis
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-08-07 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: All required message definitions, base classes, and some platform-agnostic
15
+ tools.
16
+ email:
17
+ - git@cactusgrove.net
18
+ executables:
19
+ - !binary |-
20
+ c2VuZF9tZXNzYWdlLnJi
21
+ extensions: []
22
+ extra_rdoc_files: []
23
+ files:
24
+ - !binary |-
25
+ LmdpdGlnbm9yZQ==
26
+ - !binary |-
27
+ R2VtZmlsZQ==
28
+ - !binary |-
29
+ TElDRU5TRQ==
30
+ - !binary |-
31
+ UkVBRE1FLm1k
32
+ - !binary |-
33
+ UmFrZWZpbGU=
34
+ - !binary |-
35
+ YmluL3NlbmRfbWVzc2FnZS5yYg==
36
+ - !binary |-
37
+ bGliL29wZW5fdHJhZGUucmI=
38
+ - !binary |-
39
+ bGliL29wZW5fdHJhZGUvYmFzZS5yYg==
40
+ - !binary |-
41
+ bGliL29wZW5fdHJhZGUvYmFzZS9jb25zdGFudHMucmI=
42
+ - !binary |-
43
+ bGliL29wZW5fdHJhZGUvYmFzZS9tZXNzYWdlLnJi
44
+ - !binary |-
45
+ bGliL29wZW5fdHJhZGUvYmFzZS9yb2xlLnJi
46
+ - !binary |-
47
+ bGliL29wZW5fdHJhZGUvbWVzc2FnZXMvYWNjdW11bGF0b3IvY2FsY3VsYXRp
48
+ b24ucmI=
49
+ - !binary |-
50
+ bGliL29wZW5fdHJhZGUvbWVzc2FnZXMvY29tbW9uL2Fja25vd2xlZGdlLnJi
51
+ - !binary |-
52
+ bGliL29wZW5fdHJhZGUvbWVzc2FnZXMvY29tbW9uL2Vycm9yLnJi
53
+ - !binary |-
54
+ bGliL29wZW5fdHJhZGUvbWVzc2FnZXMvY29tbW9uL2hlYXJ0YmVhdC5yYg==
55
+ - !binary |-
56
+ bGliL29wZW5fdHJhZGUvbWVzc2FnZXMvY29tbW9uL2xvZy5yYg==
57
+ - !binary |-
58
+ bGliL29wZW5fdHJhZGUvbWVzc2FnZXMvY29tbW9uL3N0YXJ0LnJi
59
+ - !binary |-
60
+ bGliL29wZW5fdHJhZGUvbWVzc2FnZXMvY29tbW9uL3N0YXR1cy5yYg==
61
+ - !binary |-
62
+ bGliL29wZW5fdHJhZGUvbWVzc2FnZXMvY29tbW9uL3N0b3AucmI=
63
+ - !binary |-
64
+ bGliL29wZW5fdHJhZGUvbWVzc2FnZXMvZGlyZWN0b3J5L3Byb2Nlc3NfYWN0
65
+ aXZpdHkucmI=
66
+ - !binary |-
67
+ bGliL29wZW5fdHJhZGUvbWVzc2FnZXMvZGlyZWN0b3J5L3Byb2Nlc3NfbGlz
68
+ dC5yYg==
69
+ - !binary |-
70
+ bGliL29wZW5fdHJhZGUvbWVzc2FnZXMvZXhlY3V0b3Ivb3JkZXJfYWN0aXZp
71
+ dHkucmI=
72
+ - !binary |-
73
+ bGliL29wZW5fdHJhZGUvbWVzc2FnZXMvbWFya2V0X2RhdGEvZGVwdGgucmI=
74
+ - !binary |-
75
+ bGliL29wZW5fdHJhZGUvbWVzc2FnZXMvbWFya2V0X2RhdGEvcXVvdGUucmI=
76
+ - !binary |-
77
+ bGliL29wZW5fdHJhZGUvbWVzc2FnZXMvbWFya2V0X2RhdGEvdGljay5yYg==
78
+ - !binary |-
79
+ bGliL29wZW5fdHJhZGUvbWVzc2FnZXMvcG9ydGZvbGlvL2FjY291bnRfc3Rh
80
+ dHVzLnJi
81
+ - !binary |-
82
+ bGliL29wZW5fdHJhZGUvbWVzc2FnZXMvcG9ydGZvbGlvL2V4aXQucmI=
83
+ - !binary |-
84
+ bGliL29wZW5fdHJhZGUvbWVzc2FnZXMvcG9ydGZvbGlvL2xpc3RfY29uc3Ry
85
+ YWludHMucmI=
86
+ - !binary |-
87
+ bGliL29wZW5fdHJhZGUvbWVzc2FnZXMvcG9ydGZvbGlvL29yZGVyLnJi
88
+ - !binary |-
89
+ bGliL29wZW5fdHJhZGUvbWVzc2FnZXMvcG9ydGZvbGlvL3JlZ2lzdGVyX3N0
90
+ cmF0ZWd5LnJi
91
+ - !binary |-
92
+ bGliL29wZW5fdHJhZGUvbWVzc2FnZXMvcG9ydGZvbGlvL3NldF9jb25zdHJh
93
+ aW50LnJi
94
+ - !binary |-
95
+ bGliL29wZW5fdHJhZGUvbWVzc2FnZXMvc3RyYXRlZ3kvc2lnbmFsLnJi
96
+ - !binary |-
97
+ bGliL29wZW5fdHJhZGUvdmVyc2lvbi5yYg==
98
+ - !binary |-
99
+ b3Blbl90cmFkZS5nZW1zcGVj
100
+ homepage: ''
101
+ licenses: []
102
+ post_install_message:
103
+ rdoc_options: []
104
+ require_paths:
105
+ - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ! '>='
110
+ - !ruby/object:Gem::Version
111
+ version: '0'
112
+ required_rubygems_version: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ requirements: []
119
+ rubyforge_project:
120
+ rubygems_version: 1.8.17
121
+ signing_key:
122
+ specification_version: 3
123
+ summary: The basic OpenTrade platform. You will still need to implement or install
124
+ your own roles.
125
+ test_files: []