ib-ruby 0.7.8 → 0.7.9

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/HISTORY CHANGED
@@ -169,3 +169,7 @@
169
169
  == 0.7.8 / 2012-04-23
170
170
 
171
171
  * Models are now fully DB-backed
172
+
173
+ == 0.7.9 / 2012-04-24
174
+
175
+ * Order and OrderState API extended
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.8
1
+ 0.7.9
@@ -27,11 +27,20 @@ module IB
27
27
  # Comparison support
28
28
  def content_attributes
29
29
  HashWithIndifferentAccess[attributes.reject do |(attr, _)|
30
- attr.to_s =~ /(_id|_count)$/ ||
31
- [:created_at, :updated_at, :type, :id].include?(attr.to_sym)
30
+ attr.to_s =~ /(_count)$/ ||
31
+ [:created_at, :updated_at, :type,
32
+ :id, :order_id, :contract_id].include?(attr.to_sym)
32
33
  end]
33
34
  end
34
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
+
35
44
  # Default Model comparison
36
45
  def == other
37
46
  content_attributes.inject(true) { |res, (attr, value)| res && other.send(attr) == value } &&
@@ -73,58 +82,58 @@ module IB
73
82
  def self.define_property_methods name, body={}
74
83
  #p name, body
75
84
  case body
76
- when '' # default getter and setter
77
- define_property_methods name
78
-
79
- when Array # [setter, getter, validators]
80
- define_property_methods name,
81
- :get => body[0],
82
- :set => body[1],
83
- :validate => body[2]
84
-
85
- when Hash # recursion base case
86
- getter = case # Define getter
87
- when body[:get].respond_to?(:call)
88
- body[:get]
89
- when body[:get]
90
- proc { self[name].send "to_#{body[:get]}" }
91
- when VALUES[name] # property is encoded
92
- proc { VALUES[name][self[name]] }
93
- #when respond_to?(:column_names) && column_names.include?(name.to_s)
94
- # # noop, ActiveRecord will take care of it...
95
- # p "#{name} => get noop"
96
- # p respond_to?(:column_names) && column_names
97
- else
98
- proc { self[name] }
99
- end
100
- define_method name, &getter if getter
101
-
102
- setter = case # Define setter
103
- when body[:set].respond_to?(:call)
104
- body[:set]
105
- when body[:set]
106
- proc { |value| self[name] = value.send "to_#{body[:set]}" }
107
- when CODES[name] # property is encoded
108
- proc { |value| self[name] = CODES[name][value] || value }
109
- else
110
- proc { |value| self[name] = value } # p name, value;
111
- end
112
- define_method "#{name}=", &setter if setter
113
-
114
- # Define validator(s)
115
- [body[:validate]].flatten.compact.each do |validator|
116
- case validator
117
- when Proc
118
- validates_each name, &validator
119
- when Hash
120
- validates name, validator.dup
121
- end
85
+ when '' # default getter and setter
86
+ define_property_methods name
87
+
88
+ when Array # [setter, getter, validators]
89
+ define_property_methods name,
90
+ :get => body[0],
91
+ :set => body[1],
92
+ :validate => body[2]
93
+
94
+ when Hash # recursion base case
95
+ getter = case # Define getter
96
+ when body[:get].respond_to?(:call)
97
+ body[:get]
98
+ when body[:get]
99
+ proc { self[name].send "to_#{body[:get]}" }
100
+ when VALUES[name] # property is encoded
101
+ proc { VALUES[name][self[name]] }
102
+ #when respond_to?(:column_names) && column_names.include?(name.to_s)
103
+ # # noop, ActiveRecord will take care of it...
104
+ # p "#{name} => get noop"
105
+ # p respond_to?(:column_names) && column_names
106
+ else
107
+ proc { self[name] }
108
+ end
109
+ define_method name, &getter if getter
110
+
111
+ setter = case # Define setter
112
+ when body[:set].respond_to?(:call)
113
+ body[:set]
114
+ when body[:set]
115
+ proc { |value| self[name] = value.send "to_#{body[:set]}" }
116
+ when CODES[name] # property is encoded
117
+ proc { |value| self[name] = CODES[name][value] || value }
118
+ else
119
+ proc { |value| self[name] = value } # p name, value;
120
+ end
121
+ define_method "#{name}=", &setter if setter
122
+
123
+ # Define validator(s)
124
+ [body[:validate]].flatten.compact.each do |validator|
125
+ case validator
126
+ when Proc
127
+ validates_each name, &validator
128
+ when Hash
129
+ validates name, validator.dup
122
130
  end
131
+ end
123
132
 
124
133
  # TODO define self[:name] accessors for :virtual and :flag properties
125
134
 
126
- else # setter given
127
- define_property_methods name, :set => body, :get => body
135
+ else # setter given
136
+ define_property_methods name, :set => body, :get => body
128
137
  end
129
138
  end
130
139
 
@@ -264,7 +264,13 @@ module IB
264
264
  :last_fill_price, # double
265
265
  :average_price, # double
266
266
  :average_fill_price, # double
267
- :why_held # String: comma-separated list of reasons for order to be held.
267
+ :why_held, # String: comma-separated list of reasons for order to be held.
268
+ # Testing Order state:
269
+ :new?,
270
+ :pending?,
271
+ :active?,
272
+ :inactive?,
273
+ :complete_fill?,
268
274
  ].each { |property| define_method(property) { order_state.send(property) } }
269
275
 
270
276
  # Order is not valid without correct :local_id (:order_id)
@@ -63,6 +63,31 @@ module IB
63
63
  validates_numericality_of :local_id, :perm_id, :client_id, :parent_id, :filled,
64
64
  :remaining, :only_integer => true, :allow_nil => true
65
65
 
66
+ ## Testing Order state:
67
+
68
+ def new?
69
+ status.empty? || status == 'New'
70
+ end
71
+
72
+ # Order is in a valid, working state on TWS side
73
+ def pending?
74
+ status == 'PendingSubmit' || status == 'PreSubmitted' || status == 'Submitted'
75
+ end
76
+
77
+ # Order is in invalid state
78
+ def active?
79
+ new? || pending?
80
+ end
81
+
82
+ # Order is in invalid state
83
+ def inactive?
84
+ !active? # status == 'Inactive'
85
+ end
86
+
87
+ def complete_fill?
88
+ status == 'Filled' && remaining == 0 # filled >= total_quantity # Manually corrected
89
+ end
90
+
66
91
  # Comparison
67
92
  def == other
68
93
  other && other.is_a?(OrderState) &&
@@ -117,7 +117,30 @@ describe IB::Models::Order do
117
117
 
118
118
  it 'has extra accessors to OrderState properties' do
119
119
  subject.order_state.should_not be_nil
120
+
120
121
  subject.status.should == 'New'
122
+ subject.commission.should be_nil
123
+ subject.commission_currency.should be_nil
124
+ subject.min_commission.should be_nil
125
+ subject.max_commission.should be_nil
126
+ subject.warning_text.should be_nil
127
+ subject.init_margin.should be_nil
128
+ subject.maint_margin.should be_nil
129
+ subject.equity_with_loan.should be_nil
130
+ # Properties arriving via OrderStatus messagesubject.
131
+ subject.filled.should be_nil
132
+ subject.remaining.should be_nil
133
+ subject.price.should be_nil
134
+ subject.last_fill_price.should be_nil
135
+ subject.average_price.should be_nil
136
+ subject.average_fill_price.should be_nil
137
+ subject.why_held.should be_nil
138
+ # Testing Order statesubject.
139
+ subject.should be_new
140
+ subject.should_not be_pending
141
+ subject.should be_active
142
+ subject.should_not be_inactive
143
+ subject.should_not be_complete_fill
121
144
  end
122
145
 
123
146
  context 'update Order state by ' do
@@ -38,7 +38,7 @@ describe IB::Models::OrderState do
38
38
  let(:assigns) do
39
39
  {[:status] =>
40
40
  {[nil, ''] => /must not be empty/,
41
- ['Zorro', :Zorro] => 'Zorro' }
41
+ ['Zorro', :Zorro] => 'Zorro'}
42
42
  }
43
43
  end
44
44
 
@@ -52,4 +52,64 @@ describe IB::Models::OrderState do
52
52
  it_behaves_like 'Model'
53
53
  it_behaves_like 'Self-equal Model'
54
54
 
55
+ context '#update_missing' do
56
+ context 'updating with Hash' do
57
+
58
+ subject { IB::OrderState.new.update_missing(props) }
59
+
60
+ it_behaves_like 'Model instantiated with properties'
61
+
62
+ end
63
+
64
+ context 'updating with Model' do
65
+
66
+ subject { IB::OrderState.new.update_missing(IB::OrderState.new(props)) }
67
+
68
+ it_behaves_like 'Model instantiated with properties'
69
+
70
+ end
71
+
72
+ end
73
+
74
+ it 'has extra test methods' do
75
+ empty_state = IB::OrderState.new
76
+ empty_state.should be_new
77
+ empty_state.should be_active
78
+ empty_state.should_not be_inactive
79
+ empty_state.should_not be_complete_fill
80
+
81
+ state = IB::OrderState.new(props)
82
+ ['PendingSubmit', 'PreSubmitted', 'Submitted'].each do |status|
83
+ state.status = status
84
+ state.should_not be_new
85
+ state.should be_active
86
+ state.should_not be_inactive
87
+ state.should_not be_complete_fill
88
+ state.should be_pending
89
+ end
90
+
91
+ ['PendingCancel', 'Cancelled', 'ApiCancelled', 'Inactive'].each do |status|
92
+ state.status = status
93
+ state.should_not be_new
94
+ state.should_not be_active
95
+ state.should be_inactive
96
+ state.should_not be_complete_fill
97
+ state.should_not be_pending
98
+ end
99
+
100
+ state.status = 'Filled'
101
+ state.should_not be_new
102
+ state.should_not be_active
103
+ state.should be_inactive
104
+ state.should_not be_complete_fill
105
+ state.should_not be_pending
106
+
107
+ state.remaining = 0
108
+ state.should_not be_new
109
+ state.should_not be_active
110
+ state.should be_inactive
111
+ state.should be_complete_fill
112
+ state.should_not be_pending
113
+ end
114
+
55
115
  end # describe IB::Order
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: ib-ruby
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.7.8
5
+ version: 0.7.9
6
6
  platform: ruby
7
7
  authors:
8
8
  - Paul Legato
@@ -11,7 +11,7 @@ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
13
 
14
- date: 2012-04-23 00:00:00 Z
14
+ date: 2012-04-24 00:00:00 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler