ib-ruby 0.8.1 → 0.8.3
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.
- data/.gitignore +0 -1
- data/HISTORY +5 -0
- data/README.md +47 -53
- data/Rakefile +2 -1
- data/VERSION +1 -1
- data/app/assets/javascripts/ib/application.js +15 -0
- data/app/assets/javascripts/ib/underlyings.js +2 -0
- data/app/assets/stylesheets/ib/application.css +13 -0
- data/app/assets/stylesheets/ib/underlyings.css +4 -0
- data/app/assets/stylesheets/scaffold.css +56 -0
- data/app/controllers/ib/application_controller.rb +5 -0
- data/app/controllers/ib/underlyings_controller.rb +87 -0
- data/app/helpers/ib/application_helper.rb +4 -0
- data/app/helpers/ib/underlyings_helper.rb +4 -0
- data/app/models/ib/underlying.rb +5 -0
- data/app/views/ib/underlyings/_form.html.erb +33 -0
- data/app/views/ib/underlyings/edit.html.erb +6 -0
- data/app/views/ib/underlyings/index.html.erb +29 -0
- data/app/views/ib/underlyings/new.html.erb +5 -0
- data/app/views/ib/underlyings/show.html.erb +25 -0
- data/app/views/layouts/ib/application.html.erb +14 -0
- data/config/routes.rb +6 -0
- data/db/config.yml +19 -0
- data/db/migrate/{101_add_executions.rb → 101_add_ib_executions.rb} +2 -2
- data/db/migrate/{111_add_bars.rb → 111_add_ib_bars.rb} +2 -2
- data/db/migrate/{121_add_order_states.rb → 121_add_ib_order_states.rb} +2 -2
- data/db/migrate/{131_add_orders.rb → 131_add_ib_orders.rb} +2 -2
- data/db/migrate/{141_add_combo_legs.rb → 141_add_ib_combo_legs.rb} +2 -2
- data/db/migrate/{151_add_underlyings.rb → 151_add_ib_underlyings.rb} +2 -2
- data/db/migrate/{161_add_contract_details.rb → 161_add_ib_contract_details.rb} +2 -2
- data/db/migrate/{171_add_contracts.rb → 171_add_ib_contracts.rb} +2 -2
- data/db/schema.rb +245 -0
- data/lib/ib/base.rb +97 -0
- data/lib/ib/base_properties.rb +140 -0
- data/lib/{ib-ruby → ib}/connection.rb +2 -2
- data/lib/{ib-ruby → ib}/constants.rb +0 -0
- data/lib/{ib-ruby → ib}/db.rb +9 -5
- data/lib/ib/engine.rb +35 -0
- data/lib/{ib-ruby → ib}/errors.rb +0 -0
- data/lib/{ib-ruby → ib}/extensions.rb +2 -2
- data/lib/{ib-ruby → ib}/logger.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/abstract_message.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/incoming/abstract_message.rb +1 -1
- data/lib/{ib-ruby → ib}/messages/incoming/alert.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/incoming/contract_data.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/incoming/delta_neutral_validation.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/incoming/execution_data.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/incoming/historical_data.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/incoming/market_depths.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/incoming/next_valid_id.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/incoming/open_order.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/incoming/order_status.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/incoming/portfolio_value.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/incoming/real_time_bar.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/incoming/scanner_data.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/incoming/ticks.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/incoming.rb +14 -14
- data/lib/{ib-ruby → ib}/messages/outgoing/abstract_message.rb +1 -1
- data/lib/{ib-ruby → ib}/messages/outgoing/bar_requests.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/outgoing/place_order.rb +0 -0
- data/lib/{ib-ruby → ib}/messages/outgoing.rb +5 -5
- data/lib/ib/messages.rb +8 -0
- data/lib/ib/model.rb +8 -0
- data/lib/ib/models.rb +10 -0
- data/lib/ib/requires.rb +9 -0
- data/lib/{ib-ruby → ib}/socket.rb +0 -0
- data/lib/{ib-ruby → ib}/symbols/forex.rb +1 -1
- data/lib/{ib-ruby → ib}/symbols/futures.rb +2 -2
- data/lib/{ib-ruby → ib}/symbols/options.rb +1 -1
- data/lib/{ib-ruby → ib}/symbols/stocks.rb +1 -1
- data/lib/ib/symbols.rb +9 -0
- data/lib/{ib-ruby → ib}/version.rb +0 -0
- data/lib/ib-ruby.rb +2 -24
- data/lib/ib.rb +23 -0
- data/lib/models/ib/bag.rb +51 -0
- data/lib/models/ib/bar.rb +41 -0
- data/lib/models/ib/combo_leg.rb +102 -0
- data/lib/models/ib/contract.rb +287 -0
- data/lib/models/ib/contract_detail.rb +68 -0
- data/lib/models/ib/execution.rb +62 -0
- data/lib/models/ib/option.rb +60 -0
- data/lib/models/ib/order.rb +389 -0
- data/lib/models/ib/order_state.rb +126 -0
- data/lib/models/ib/underlying.rb +35 -0
- data/spec/README.md +34 -2
- data/spec/TODO +5 -1
- data/spec/comb.rb +13 -0
- data/spec/db.rb +1 -1
- data/spec/db_helper.rb +3 -3
- data/spec/dummy.rb +13 -0
- data/spec/gw.rb +4 -0
- data/spec/{ib-ruby → ib}/connection_spec.rb +0 -0
- data/spec/{ib-ruby → ib}/messages/incoming/alert_spec.rb +0 -0
- data/spec/{ib-ruby → ib}/messages/incoming/open_order_spec.rb +0 -0
- data/spec/{ib-ruby → ib}/messages/incoming/order_status_spec.rb +16 -17
- data/spec/{ib-ruby → ib}/messages/outgoing/account_data_spec.rb +0 -0
- data/spec/{ib-ruby → ib}/messages/outgoing/market_data_type_spec.rb +0 -0
- data/spec/integration/historic_data_spec.rb +3 -3
- data/spec/integration/orders/trades_spec.rb +1 -1
- data/spec/{ib-ruby/models → models/ib}/bag_spec.rb +2 -7
- data/spec/{ib-ruby/models → models/ib}/bar_spec.rb +1 -6
- data/spec/{ib-ruby/models → models/ib}/combo_leg_spec.rb +2 -12
- data/spec/{ib-ruby/models → models/ib}/contract_detail_spec.rb +3 -8
- data/spec/{ib-ruby/models → models/ib}/contract_spec.rb +4 -12
- data/spec/{ib-ruby/models → models/ib}/execution_spec.rb +2 -7
- data/spec/{ib-ruby/models → models/ib}/option_spec.rb +1 -6
- data/spec/{ib-ruby/models → models/ib}/order_spec.rb +5 -10
- data/spec/{ib-ruby/models → models/ib}/order_state_spec.rb +2 -7
- data/spec/{ib-ruby/models → models/ib}/underlying_spec.rb +3 -7
- data/spec/my.rb +5 -0
- data/spec/spec_helper.rb +62 -36
- metadata +417 -544
- data/lib/ib-ruby/messages.rb +0 -8
- data/lib/ib-ruby/models/bag.rb +0 -54
- data/lib/ib-ruby/models/bar.rb +0 -43
- data/lib/ib-ruby/models/combo_leg.rb +0 -104
- data/lib/ib-ruby/models/contract.rb +0 -287
- data/lib/ib-ruby/models/contract_detail.rb +0 -70
- data/lib/ib-ruby/models/execution.rb +0 -64
- data/lib/ib-ruby/models/model.rb +0 -105
- data/lib/ib-ruby/models/model_properties.rb +0 -146
- data/lib/ib-ruby/models/option.rb +0 -62
- data/lib/ib-ruby/models/order.rb +0 -389
- data/lib/ib-ruby/models/order_state.rb +0 -128
- data/lib/ib-ruby/models/underlying.rb +0 -36
- data/lib/ib-ruby/models.rb +0 -15
- data/lib/ib-ruby/symbols.rb +0 -9
- data/spec/test.rb +0 -61
data/lib/ib-ruby/models/model.rb
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
module IB
|
|
2
|
-
module Models
|
|
3
|
-
|
|
4
|
-
# Base class for tableless IB data Models extends ActiveModel API
|
|
5
|
-
class Model
|
|
6
|
-
extend ActiveModel::Naming
|
|
7
|
-
extend ActiveModel::Callbacks
|
|
8
|
-
include ActiveModel::Validations
|
|
9
|
-
include ActiveModel::Serialization
|
|
10
|
-
include ActiveModel::Serializers::Xml
|
|
11
|
-
include ActiveModel::Serializers::JSON
|
|
12
|
-
|
|
13
|
-
# IB Models can be either database-backed, or not
|
|
14
|
-
# require 'ib-ruby/db' # to make all IB models database-backed
|
|
15
|
-
# If you plan to persist only specific Models, select those subclasses here:
|
|
16
|
-
def self.for subclass
|
|
17
|
-
if DB # && [:contract, :order, :order_state].include? subclass
|
|
18
|
-
ActiveRecord::Base
|
|
19
|
-
else
|
|
20
|
-
Model
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
#attr_accessor :attributes
|
|
25
|
-
|
|
26
|
-
# If a opts hash is given, keys are taken as attribute names, values as data.
|
|
27
|
-
# The model instance fields are then set automatically from the opts Hash.
|
|
28
|
-
def initialize attributes={}, opts={}
|
|
29
|
-
run_callbacks :initialize do
|
|
30
|
-
error "Argument must be a Hash", :args unless attributes.is_a?(Hash)
|
|
31
|
-
|
|
32
|
-
self.attributes = default_attributes.merge(attributes)
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# ActiveModel API (for serialization)
|
|
37
|
-
|
|
38
|
-
def attributes
|
|
39
|
-
@attributes ||= HashWithIndifferentAccess.new
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def attributes= attrs
|
|
43
|
-
attrs.keys.each { |key| self.send("#{key}=", attrs[key]) }
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
# ActiveModel-style read/write_attribute accessors
|
|
47
|
-
def [] key
|
|
48
|
-
attributes[key.to_sym]
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def []= key, val
|
|
52
|
-
# p key, val
|
|
53
|
-
attributes[key.to_sym] = val
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def to_model
|
|
57
|
-
self
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def new_record?
|
|
61
|
-
true
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
def save
|
|
65
|
-
valid?
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
alias save! save
|
|
69
|
-
|
|
70
|
-
### ActiveRecord::Base association API mocks
|
|
71
|
-
|
|
72
|
-
def self.belongs_to model, *args
|
|
73
|
-
attr_accessor model
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def self.has_one model, *args
|
|
77
|
-
attr_accessor model
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def self.has_many models, *args
|
|
81
|
-
attr_accessor models
|
|
82
|
-
|
|
83
|
-
define_method(models) do
|
|
84
|
-
self.instance_variable_get("@#{models}") ||
|
|
85
|
-
self.instance_variable_set("@#{models}", [])
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
def self.find *args
|
|
90
|
-
[]
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
### ActiveRecord::Base callback API mocks
|
|
94
|
-
|
|
95
|
-
define_model_callbacks :initialize, :only => :after
|
|
96
|
-
|
|
97
|
-
### ActiveRecord::Base misc
|
|
98
|
-
|
|
99
|
-
def self.serialize *properties
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
end # Model
|
|
104
|
-
end # module Models
|
|
105
|
-
end # module IB
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
require 'active_model'
|
|
2
|
-
require 'active_support/concern'
|
|
3
|
-
require 'active_support/hash_with_indifferent_access'
|
|
4
|
-
|
|
5
|
-
module IB
|
|
6
|
-
module Models
|
|
7
|
-
|
|
8
|
-
# Module adds prop Macro and
|
|
9
|
-
module ModelProperties
|
|
10
|
-
extend ActiveSupport::Concern
|
|
11
|
-
|
|
12
|
-
def default_attributes
|
|
13
|
-
{:created_at => Time.now,
|
|
14
|
-
:updated_at => Time.now,
|
|
15
|
-
}
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
### Instance methods
|
|
19
|
-
|
|
20
|
-
# Default presentation
|
|
21
|
-
def to_human
|
|
22
|
-
"<#{self.class.to_s.demodulize}: " + attributes.map do |attr, value|
|
|
23
|
-
"#{attr}: #{value}" unless value.nil?
|
|
24
|
-
end.compact.sort.join(' ') + ">"
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
# Comparison support
|
|
28
|
-
def content_attributes
|
|
29
|
-
HashWithIndifferentAccess[attributes.reject do |(attr, _)|
|
|
30
|
-
attr.to_s =~ /(_count)$/ ||
|
|
31
|
-
[:created_at, :updated_at, :type,
|
|
32
|
-
:id, :order_id, :contract_id].include?(attr.to_sym)
|
|
33
|
-
end]
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# Update nil attributes from given Hash or model
|
|
37
|
-
def update_missing attrs
|
|
38
|
-
attrs = attrs.content_attributes unless attrs.kind_of?(Hash)
|
|
39
|
-
|
|
40
|
-
attrs.each { |attr, val| send "#{attr}=", val if send(attr).blank? }
|
|
41
|
-
self # for chaining
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
# Default Model comparison
|
|
45
|
-
def == other
|
|
46
|
-
content_attributes.inject(true) { |res, (attr, value)| res && other.send(attr) == value } &&
|
|
47
|
-
other.content_attributes.inject(true) { |res, (attr, value)| res && send(attr) == value }
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
included do
|
|
51
|
-
|
|
52
|
-
### Class macros
|
|
53
|
-
|
|
54
|
-
def self.prop *properties
|
|
55
|
-
prop_hash = properties.last.is_a?(Hash) ? properties.pop : {}
|
|
56
|
-
|
|
57
|
-
properties.each { |names| define_property names, nil }
|
|
58
|
-
prop_hash.each { |names, type| define_property names, type }
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def self.define_property names, body
|
|
62
|
-
aliases = [names].flatten
|
|
63
|
-
name = aliases.shift
|
|
64
|
-
instance_eval do
|
|
65
|
-
|
|
66
|
-
define_property_methods name, body
|
|
67
|
-
|
|
68
|
-
aliases.each do |ali|
|
|
69
|
-
alias_method "#{ali}", name
|
|
70
|
-
alias_method "#{ali}=", "#{name}="
|
|
71
|
-
end
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def self.define_property_methods name, body={}
|
|
76
|
-
#p name, body
|
|
77
|
-
case body
|
|
78
|
-
when '' # default getter and setter
|
|
79
|
-
define_property_methods name
|
|
80
|
-
|
|
81
|
-
when Array # [setter, getter, validators]
|
|
82
|
-
define_property_methods name,
|
|
83
|
-
:get => body[0],
|
|
84
|
-
:set => body[1],
|
|
85
|
-
:validate => body[2]
|
|
86
|
-
|
|
87
|
-
when Hash # recursion base case
|
|
88
|
-
getter = case # Define getter
|
|
89
|
-
when body[:get].respond_to?(:call)
|
|
90
|
-
body[:get]
|
|
91
|
-
when body[:get]
|
|
92
|
-
proc { self[name].send "to_#{body[:get]}" }
|
|
93
|
-
when VALUES[name] # property is encoded
|
|
94
|
-
proc { VALUES[name][self[name]] }
|
|
95
|
-
#when respond_to?(:column_names) && column_names.include?(name.to_s)
|
|
96
|
-
# # noop, ActiveRecord will take care of it...
|
|
97
|
-
# p "#{name} => get noop"
|
|
98
|
-
# p respond_to?(:column_names) && column_names
|
|
99
|
-
else
|
|
100
|
-
proc { self[name] }
|
|
101
|
-
end
|
|
102
|
-
define_method name, &getter if getter
|
|
103
|
-
|
|
104
|
-
setter = case # Define setter
|
|
105
|
-
when body[:set].respond_to?(:call)
|
|
106
|
-
body[:set]
|
|
107
|
-
when body[:set]
|
|
108
|
-
proc { |value| self[name] = value.send "to_#{body[:set]}" }
|
|
109
|
-
when CODES[name] # property is encoded
|
|
110
|
-
proc { |value| self[name] = CODES[name][value] || value }
|
|
111
|
-
else
|
|
112
|
-
proc { |value| self[name] = value } # p name, value;
|
|
113
|
-
end
|
|
114
|
-
define_method "#{name}=", &setter if setter
|
|
115
|
-
|
|
116
|
-
# Define validator(s)
|
|
117
|
-
[body[:validate]].flatten.compact.each do |validator|
|
|
118
|
-
case validator
|
|
119
|
-
when Proc
|
|
120
|
-
validates_each name, &validator
|
|
121
|
-
when Hash
|
|
122
|
-
validates name, validator.dup
|
|
123
|
-
end
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
# TODO define self[:name] accessors for :virtual and :flag properties
|
|
127
|
-
|
|
128
|
-
else # setter given
|
|
129
|
-
define_property_methods name, :set => body, :get => body
|
|
130
|
-
end
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
# Extending AR-backed Model class with attribute defaults
|
|
134
|
-
if defined?(ActiveRecord::Base) && ancestors.include?(ActiveRecord::Base)
|
|
135
|
-
def initialize attributes={}, opts={}
|
|
136
|
-
super default_attributes.merge(attributes), opts
|
|
137
|
-
end
|
|
138
|
-
else
|
|
139
|
-
# Timestamps
|
|
140
|
-
prop :created_at, :updated_at
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
end # included
|
|
144
|
-
end # module ModelProperties
|
|
145
|
-
end # module Models
|
|
146
|
-
end
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
require 'ib-ruby/models/contract'
|
|
2
|
-
|
|
3
|
-
module IB
|
|
4
|
-
module Models
|
|
5
|
-
class Option < Contract
|
|
6
|
-
|
|
7
|
-
validates_numericality_of :strike, :greater_than => 0
|
|
8
|
-
validates_format_of :sec_type, :with => /^option$/,
|
|
9
|
-
:message => "should be an option"
|
|
10
|
-
validates_format_of :local_symbol, :with => /^\w+\s*\d{6}[pcPC]\d{8}$|^$/,
|
|
11
|
-
:message => "invalid OSI code"
|
|
12
|
-
validates_format_of :right, :with => /^put$|^call$/,
|
|
13
|
-
:message => "should be put or call"
|
|
14
|
-
|
|
15
|
-
# For Options, this is contract's OSI (Option Symbology Initiative) name/code
|
|
16
|
-
alias osi local_symbol
|
|
17
|
-
|
|
18
|
-
def osi= value
|
|
19
|
-
# Normalize to 21 char
|
|
20
|
-
self.local_symbol = value.sub(/ /, ' '*(22-value.size))
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
# Make valid IB Contract definition from OSI (Option Symbology Initiative) code.
|
|
24
|
-
# NB: Simply making a new Contract with *local_symbol* (osi) property set to a
|
|
25
|
-
# valid OSI code works just as well, just do NOT set *expiry*, *right* or
|
|
26
|
-
# *strike* properties in this case.
|
|
27
|
-
# This class method provided as a backup and shows how to analyse OSI codes.
|
|
28
|
-
def self.from_osi osi
|
|
29
|
-
|
|
30
|
-
# Parse contract's OSI (OCC Option Symbology Initiative) code
|
|
31
|
-
args = osi.match(/(\w+)\s?(\d\d)(\d\d)(\d\d)([pcPC])(\d+)/).to_a.drop(1)
|
|
32
|
-
symbol = args.shift
|
|
33
|
-
year = 2000 + args.shift.to_i
|
|
34
|
-
month = args.shift.to_i
|
|
35
|
-
day = args.shift.to_i
|
|
36
|
-
right = args.shift.upcase
|
|
37
|
-
strike = args.shift.to_i/1000.0
|
|
38
|
-
|
|
39
|
-
# Set correct expiry date - IB expiry date differs from OSI if expiry date
|
|
40
|
-
# falls on Saturday (see https://github.com/arvicco/option_mower/issues/4)
|
|
41
|
-
expiry_date = Time.utc(year, month, day)
|
|
42
|
-
expiry_date = Time.utc(year, month, day-1) if expiry_date.wday == 6
|
|
43
|
-
|
|
44
|
-
new :symbol => symbol,
|
|
45
|
-
:exchange => "SMART",
|
|
46
|
-
:expiry => expiry_date.to_ib[2..7], # YYMMDD
|
|
47
|
-
:right => right,
|
|
48
|
-
:strike => strike
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def default_attributes
|
|
52
|
-
super.merge :sec_type => :option
|
|
53
|
-
#self[:description] ||= osi ? osi : "#{symbol} #{strike} #{right} #{expiry}"
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def to_human
|
|
57
|
-
"<Option: " + [symbol, expiry, right, strike, exchange, currency].join(" ") + ">"
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
end # class Option
|
|
61
|
-
end # module Models
|
|
62
|
-
end # module IB
|