open_trade 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 (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: []