ib-extensions 1.0 → 1.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.
- checksums.yaml +4 -4
- data/Gemfile +2 -1
- data/Gemfile.lock +33 -34
- data/README.md +12 -7
- data/bin/console +3 -5
- data/bin/{gateway.rb → gateway} +13 -4
- data/changelog.md +6 -0
- data/ib-extensions.gemspec +1 -0
- data/lib/ib/alerts/base-alert.rb +3 -1
- data/lib/ib/alerts/order-alerts.rb +5 -0
- data/lib/ib/eod.rb +19 -23
- data/lib/ib/extensions.rb +1 -0
- data/lib/ib/extensions/version.rb +1 -1
- data/lib/ib/gateway.rb +77 -63
- data/lib/ib/gateway/account-infos.rb +1 -2
- data/lib/ib/gateway/order-handling.rb +121 -126
- data/lib/ib/market-price.rb +2 -2
- data/lib/ib/models/account.rb +63 -56
- data/lib/ib/models/option.rb +20 -0
- data/lib/ib/option-chain.rb +180 -182
- data/lib/ib/order-prototypes.rb +1 -1
- data/lib/ib/spread-prototypes.rb +2 -2
- data/lib/ib/spread_prototypes/stock-spread.rb +1 -1
- data/lib/ib/verify.rb +192 -222
- metadata +19 -18
- data/examples/cancel_orders +0 -74
- data/examples/eod +0 -35
- data/examples/input.rb +0 -475
- data/examples/market_price +0 -57
- data/examples/option_chain +0 -67
- data/examples/place_and_modify_order +0 -162
- data/examples/place_bracket_order +0 -62
- data/examples/place_butterfly_order +0 -104
- data/examples/place_combo_order +0 -70
- data/examples/place_limit_order +0 -82
- data/examples/place_the_limit_order +0 -145
- data/examples/volatility_research +0 -139
- data/examples/what_if_order +0 -90
- data/lib/ib/models/spread.rb +0 -159
@@ -30,7 +30,6 @@ raises an IB::Error if less then 100 items are recieved-
|
|
30
30
|
=end
|
31
31
|
def get_account_data *accounts, watchlists: []
|
32
32
|
|
33
|
-
logger.progname = 'Gateway#get_account_data'
|
34
33
|
|
35
34
|
@account_data_subscription ||= subscribe_account_updates
|
36
35
|
|
@@ -106,7 +105,7 @@ raises an IB::Error if less then 100 items are recieved-
|
|
106
105
|
# .portfolio_values
|
107
106
|
# .update_or_create( msg.portfolio_value ) { :account }
|
108
107
|
logger.debug { "#{ account.account } :: #{ msg.contract.to_human }" }
|
109
|
-
|
108
|
+
end # case
|
110
109
|
end # account_data
|
111
110
|
end # subscribe
|
112
111
|
end # def
|
@@ -4,109 +4,105 @@ module OrderHandling
|
|
4
4
|
UpdateOrderDependingObject
|
5
5
|
|
6
6
|
Generic method which enables operations on the order-Object,
|
7
|
-
which is associated to OrderState-, Execution-, CommissionReport-
|
7
|
+
which is associated to OrderState-, Execution-, CommissionReport-
|
8
8
|
events fired by the tws.
|
9
9
|
The order is identified by local_id and perm_id
|
10
10
|
|
11
11
|
Everything is carried out in a mutex-synchonized environment
|
12
12
|
=end
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
#
|
92
|
-
#
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
tws.unsubscribe subscription
|
107
|
-
end
|
108
|
-
|
109
|
-
alias update_orders request_open_orders
|
13
|
+
def update_order_dependent_object order_dependent_object # :nodoc:
|
14
|
+
account_data do | a |
|
15
|
+
order = if order_dependent_object.local_id.present?
|
16
|
+
a.locate_order( :local_id => order_dependent_object.local_id)
|
17
|
+
else
|
18
|
+
a.locate_order( :perm_id => order_dependent_object.perm_id)
|
19
|
+
end
|
20
|
+
yield order if order.present?
|
21
|
+
end
|
22
|
+
end
|
23
|
+
def initialize_order_handling
|
24
|
+
tws.subscribe( :CommissionReport, :ExecutionData, :OrderStatus, :OpenOrder, :OpenOrderEnd, :NextValidId ) do |msg|
|
25
|
+
case msg
|
26
|
+
|
27
|
+
when IB::Messages::Incoming::CommissionReport
|
28
|
+
# Commission-Reports are not assigned to a order -
|
29
|
+
logger.info "CommissionReport -------#{msg.exec_id} :...:C: #{msg.commission} :...:P/L: #{msg.realized_pnl}-"
|
30
|
+
when IB::Messages::Incoming::OrderStatus
|
31
|
+
|
32
|
+
# The order-state only links via local_id and perm_id to orders.
|
33
|
+
# There is no reference to a contract or an account
|
34
|
+
|
35
|
+
success = update_order_dependent_object( msg.order_state) do |o|
|
36
|
+
o.order_states.update_or_create msg.order_state, :status
|
37
|
+
end
|
38
|
+
|
39
|
+
logger.info { "Order State not assigned-- #{msg.order_state.to_human} ----------" } if success.nil?
|
40
|
+
|
41
|
+
when IB::Messages::Incoming::OpenOrder
|
42
|
+
## todo --> handling of bags --> no con_id
|
43
|
+
account_data(msg.order.account) do | this_account |
|
44
|
+
# first update the contracts
|
45
|
+
# make open order equal to IB::Spreads (include negativ con_id)
|
46
|
+
msg.contract[:con_id] = -msg.contract.combo_legs.map{|y| y.con_id}.sum if msg.contract.is_a? IB::Bag
|
47
|
+
msg.contract.orders.update_or_create msg.order, :local_id
|
48
|
+
this_account.contracts.first_or_create msg.contract, :con_id
|
49
|
+
# now save the order-record
|
50
|
+
msg.order.contract = msg.contract
|
51
|
+
this_account.orders.update_or_create msg.order, :local_id
|
52
|
+
end
|
53
|
+
|
54
|
+
# update_ib_order msg ## aus support
|
55
|
+
when IB::Messages::Incoming::OpenOrderEnd
|
56
|
+
# exitcondition=true
|
57
|
+
logger.debug { "OpenOrderEnd" }
|
58
|
+
|
59
|
+
when IB::Messages::Incoming::ExecutionData
|
60
|
+
# Excution-Data are fired independly from order-states.
|
61
|
+
# The Objects are stored at the associated order
|
62
|
+
success = update_order_dependent_object( msg.execution) do |o|
|
63
|
+
o.executions << msg.execution
|
64
|
+
if msg.execution.cumulative_quantity.to_i == o.total_quantity.abs
|
65
|
+
logger.info{ "#{o.account} --> #{o.contract.symbol}: Execution completed" }
|
66
|
+
o.order_states.first_or_create( IB::OrderState.new( perm_id: o.perm_id, local_id: o.local_id,
|
67
|
+
|
68
|
+
status: 'Filled' ), :status )
|
69
|
+
# update portfoliovalue
|
70
|
+
a = @accounts.detect{ | x | x.account == o.account } # we are in a mutex controlled environment
|
71
|
+
pv = a.portfolio_values.detect{ | y | y.contract.con_id == o.contract.con_id}
|
72
|
+
change = o.action == :sell ? -o.total_quantity : o.total_quantity
|
73
|
+
if pv.present?
|
74
|
+
pv.update_attribute :position, pv.position + change
|
75
|
+
else
|
76
|
+
a.portfolio_values << IB::PortfolioValue.new( position: change, contract: o.contract )
|
77
|
+
end
|
78
|
+
else
|
79
|
+
logger.debug{ "#{o.account} --> #{o.contract.symbol}: Execution not completed (#{msg.execution.cumulative_quantity.to_i}/#{o.total_quantity.abs})" }
|
80
|
+
end # branch
|
81
|
+
end # block
|
82
|
+
|
83
|
+
logger.error { "Execution-Record not assigned-- #{msg.execution.to_human} ----------" } if success.nil?
|
84
|
+
|
85
|
+
end # case msg.code
|
86
|
+
end # do
|
87
|
+
end # def subscribe
|
88
|
+
|
89
|
+
# Resets the order-array for each account first.
|
90
|
+
# Requests all open (eg. pending) orders from the tws
|
91
|
+
#
|
92
|
+
# Waits until the OpenOrderEnd-Message is recieved
|
93
|
+
|
94
|
+
|
95
|
+
def request_open_orders
|
96
|
+
|
97
|
+
exit_condition = false
|
98
|
+
subscription = tws.subscribe( :OpenOrderEnd ) { exit_condition = true }
|
99
|
+
account_data{| account | account.orders = [] }
|
100
|
+
send_message :RequestAllOpenOrders
|
101
|
+
i=0; loop{ i+=1; sleep 0.01; break if i > 1000 || exit_condition }
|
102
|
+
tws.unsubscribe subscription
|
103
|
+
end
|
104
|
+
|
105
|
+
alias update_orders request_open_orders
|
110
106
|
|
111
107
|
|
112
108
|
|
@@ -119,32 +115,31 @@ end # module
|
|
119
115
|
|
120
116
|
module IB
|
121
117
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
end # class Order
|
118
|
+
class Order
|
119
|
+
def auto_adjust
|
120
|
+
# lambda to perform the calculation
|
121
|
+
adjust_price = ->(a,b) do
|
122
|
+
a = BigDecimal( a, 5 )
|
123
|
+
b = BigDecimal( b, 5 )
|
124
|
+
_,o = a.divmod(b)
|
125
|
+
a - o
|
126
|
+
end
|
127
|
+
# adjust_price[2.6896, 0.1].to_f => 2.6
|
128
|
+
# adjust_price[2.0896, 0.05].to_f => 2.05
|
129
|
+
# adjust_price[2.0896, 0.002].to_f => 2.088
|
130
|
+
|
131
|
+
|
132
|
+
error "No Contract provided to Auto adjust" unless contract.is_a? IB::Contract
|
133
|
+
|
134
|
+
unless contract.is_a? IB::Bag
|
135
|
+
# ensure that contract_details are present
|
136
|
+
|
137
|
+
the_details = contract.contract_detail.present? ? contract.contract_detail : contract.verify.first.contract_detail
|
138
|
+
# there are two attributes to consider: limit_price and aux_price
|
139
|
+
# limit_price + aux_price may be nil or an empty string. Then ".to_f.zero?" becomes true
|
140
|
+
self.limit_price= adjust_price.call(limit_price.to_f, the_details.min_tick) unless limit_price.to_f.zero?
|
141
|
+
self.aux_price= adjust_price.call(aux_price.to_f, the_details.min_tick) unless aux_price.to_f.zero?
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end # class Order
|
150
145
|
end # module
|
data/lib/ib/market-price.rb
CHANGED
@@ -65,7 +65,7 @@ module IB
|
|
65
65
|
#and cancel subscriptions to the message handler
|
66
66
|
# method returns the (running) thread
|
67
67
|
th = Thread.new do
|
68
|
-
|
68
|
+
finalize, raise_delay_alert = false, false
|
69
69
|
s_id = tws.subscribe(:TickSnapshotEnd){|x| finalize = true if x.ticker_id == the_id }
|
70
70
|
|
71
71
|
e_id = tws.subscribe(:Alert){|x| raise_delay_alert = true if x.code == 354 && x.error_id == the_id }
|
@@ -77,7 +77,7 @@ module IB
|
|
77
77
|
[last,close,bid,ask].each do |x|
|
78
78
|
tickdata[x] = msg.the_data[:price] if x.include?( IB::TICK_TYPES[ msg.the_data[:tick_type]])
|
79
79
|
# fast exit condition
|
80
|
-
finalize = true if tickdata.size
|
80
|
+
finalize = true if tickdata.size >= 4 || ( tickdata[bid].present? && tickdata[ask].present? )
|
81
81
|
end if msg.ticker_id == the_id
|
82
82
|
end
|
83
83
|
# initialize »the_id« that is used to identify the received tick messages
|
data/lib/ib/models/account.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
module IB
|
2
2
|
|
3
|
-
class Account
|
3
|
+
class Account
|
4
4
|
|
5
5
|
|
6
6
|
def account_data_scan search_key, search_currency=nil
|
7
7
|
if account_values.is_a? Array
|
8
|
-
if search_currency.present?
|
8
|
+
if search_currency.present?
|
9
9
|
account_values.find_all{|x| x.key.match( search_key ) && x.currency == search_currency.upcase }
|
10
10
|
else
|
11
11
|
account_values.find_all{|x| x.key.match( search_key ) }
|
@@ -24,8 +24,8 @@ module IB
|
|
24
24
|
|
25
25
|
=begin rdoc
|
26
26
|
given any key of local_id, perm_id or order_ref
|
27
|
-
and an optional status, which can be a string or a
|
28
|
-
regexp ( status: /mitted/ matches Submitted and Presubmitted)
|
27
|
+
and an optional status, which can be a string or a
|
28
|
+
regexp ( status: /mitted/ matches Submitted and Presubmitted)
|
29
29
|
the last associated Orderrecord is returned.
|
30
30
|
|
31
31
|
Thus if several Orders are placed with the same order_ref, the active one is returned
|
@@ -33,16 +33,23 @@ Thus if several Orders are placed with the same order_ref, the active one is ret
|
|
33
33
|
(If multible keys are specified, local_id preceeds perm_id)
|
34
34
|
|
35
35
|
=end
|
36
|
-
def locate_order local_id: nil, perm_id: nil, order_ref: nil, status: /ubmitted/, con_id: nil
|
36
|
+
def locate_order local_id: nil, perm_id: nil, order_ref: nil, status: /ubmitted/, contract: nil, con_id: nil
|
37
37
|
search_option= [ local_id.present? ? [:local_id , local_id] : nil ,
|
38
38
|
perm_id.present? ? [:perm_id, perm_id] : nil,
|
39
39
|
order_ref.present? ? [:order_ref , order_ref ] : nil ].compact.first
|
40
|
-
matched_items = if search_option.nil?
|
41
|
-
orders
|
42
|
-
else
|
40
|
+
matched_items = if search_option.nil?
|
41
|
+
orders
|
42
|
+
else
|
43
43
|
orders.find_all{|x| x[search_option.first].to_i == search_option.last.to_i }
|
44
44
|
end
|
45
|
-
|
45
|
+
if contract.present?
|
46
|
+
if contract.con_id.nil? || contract.con_id =="" || contract.con_id.zero?
|
47
|
+
contract = contract.verify.first unless contract.is_a? IB::Bag
|
48
|
+
end
|
49
|
+
matched_items = matched_items.find_all{|o| o.contract.essential == contract.essential }
|
50
|
+
elsif con_id.present?
|
51
|
+
matched_items = matched_items.find_all{|o| o.contract.con_id == con_id }
|
52
|
+
end
|
46
53
|
|
47
54
|
if status.present?
|
48
55
|
status = Regexp.new(status) unless status.is_a? Regexp
|
@@ -53,8 +60,8 @@ Thus if several Orders are placed with the same order_ref, the active one is ret
|
|
53
60
|
end
|
54
61
|
|
55
62
|
|
56
|
-
=begin rdoc
|
57
|
-
requires an IB::Order as parameter.
|
63
|
+
=begin rdoc
|
64
|
+
requires an IB::Order as parameter.
|
58
65
|
|
59
66
|
If attached, the associated IB::Contract is used to specify the tws-command
|
60
67
|
|
@@ -65,9 +72,9 @@ auto_adjust: Limit- and Aux-Prices are adjusted to Min-Tick
|
|
65
72
|
convert_size: The action-attribute (:buy :sell) is associated according the content of :total_quantity.
|
66
73
|
|
67
74
|
|
68
|
-
The parameter «order» is modified!
|
75
|
+
The parameter «order» is modified!
|
69
76
|
|
70
|
-
It can be used to modify and eventually cancel
|
77
|
+
It can be used to modify and eventually cancel
|
71
78
|
|
72
79
|
The method raises an IB::TransmissionError if the transmitted order ist not acknowledged by the tws after
|
73
80
|
one second.
|
@@ -79,23 +86,23 @@ Example
|
|
79
86
|
g = IB::Gateway.current.clients.last
|
80
87
|
|
81
88
|
g.preview contract: j36, order: order
|
82
|
-
=> {:init_margin=>0.10864874e6,
|
83
|
-
:maint_margin=>0.9704137e5,
|
84
|
-
:equity_with_loan=>0.97877973e6,
|
85
|
-
:commission=>0.524e1,
|
86
|
-
:commission_currency=>"USD",
|
89
|
+
=> {:init_margin=>0.10864874e6,
|
90
|
+
:maint_margin=>0.9704137e5,
|
91
|
+
:equity_with_loan=>0.97877973e6,
|
92
|
+
:commission=>0.524e1,
|
93
|
+
:commission_currency=>"USD",
|
87
94
|
:warning=>""}
|
88
95
|
|
89
96
|
the_local_id = g.place order: order
|
90
97
|
=> 67 # returns local_id
|
91
|
-
order.contract # updated contract-record
|
92
|
-
=> #<IB::Contract:0x00000000013c94b0 @attributes={:con_id=>95346693,
|
93
|
-
:exchange=>"SGX",
|
94
|
-
:right=>"",
|
95
|
-
:include_expired=>false}>
|
98
|
+
order.contract # updated contract-record
|
99
|
+
=> #<IB::Contract:0x00000000013c94b0 @attributes={:con_id=>95346693,
|
100
|
+
:exchange=>"SGX",
|
101
|
+
:right=>"",
|
102
|
+
:include_expired=>false}>
|
96
103
|
|
97
104
|
order.limit_price = 65 # set new price
|
98
|
-
g.modify order: order # and transmit
|
105
|
+
g.modify order: order # and transmit
|
99
106
|
=> 67 # returns local_id
|
100
107
|
|
101
108
|
g.locate_order( local_id: the_local_id )
|
@@ -103,18 +110,24 @@ Example
|
|
103
110
|
|
104
111
|
g.cancel order: order
|
105
112
|
# logger output: 05:17:11 Cancelling 65 New #250/ from 3000/DU167349>
|
106
|
-
|
107
113
|
=end
|
108
114
|
|
109
|
-
def place_order order:, contract: nil, auto_adjust: true, convert_size: false
|
115
|
+
def place_order order:, contract: nil, auto_adjust: true, convert_size: false, enable_error: false
|
110
116
|
# adjust the orderprice to min-tick
|
111
|
-
logger.progname = 'Account#PlaceOrder'
|
112
117
|
result = ->(l){ orders.detect{|x| x.local_id == l && x.submitted? } }
|
113
118
|
#·IB::Symbols are always qualified. They carry a description-field
|
114
|
-
|
115
|
-
|
116
|
-
order.contract
|
117
|
-
|
119
|
+
qualified_contract = ->(c) { c.is_a?(IB::Contract) && ( c.description.present? || (c.con_id.present? && !c.con_id.to_i.zero?) || (c.con_id.to_i <0 && c.sec_type == :bag )) }
|
120
|
+
|
121
|
+
order.contract ||= if qualified_contract[ contract ]
|
122
|
+
contract
|
123
|
+
else
|
124
|
+
contract.verify.first
|
125
|
+
end
|
126
|
+
|
127
|
+
if order.contract.nil?
|
128
|
+
error "No valid contract given" if enable_error
|
129
|
+
return 0
|
130
|
+
end
|
118
131
|
## sending of plain vanilla IB::Bags will fail using account.place, unless a (negative) con-id is provided!
|
119
132
|
# error "place order: ContractVerification failed. No con_id assigned" unless qualified_contract[order.contract]
|
120
133
|
ib = IB::Connection.current
|
@@ -122,46 +135,41 @@ Example
|
|
122
135
|
the_local_id = nil
|
123
136
|
|
124
137
|
### Handle Error messages
|
125
|
-
### Default action:
|
138
|
+
### Default action: raise IB::Transmission Error
|
126
139
|
sa = ib.subscribe( :Alert ) do | msg |
|
140
|
+
# puts "local_id: #{the_local_id}"
|
127
141
|
if msg.error_id == the_local_id
|
128
|
-
if [ 110, # The price does not
|
142
|
+
if [ 110, # The price does not confirm to the minimum price variation for this contract
|
129
143
|
388, # Order size x is smaller than the minimum required size of yy.
|
130
144
|
].include? msg.code
|
131
|
-
|
145
|
+
error msg.message if enable_error
|
146
|
+
wrong_order = msg.error_id.to_i
|
132
147
|
ib.logger.error msg.message
|
133
148
|
end
|
134
149
|
end
|
135
150
|
end
|
136
151
|
order.account = account # assign the account_id to the account-field of IB::Order
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
order.action = order.total_quantity.to_i > 0 ? :buy : :sell
|
152
|
+
self.orders.update_or_create order, :order_ref
|
153
|
+
order.auto_adjust # if auto_adjust /defined in lib/order_handling
|
154
|
+
if convert_size
|
155
|
+
order.action = order.total_quantity.to_i > 0 ? :buy : :sell
|
156
|
+
logger.info{ "Converted ordesize to #{order.total_quantity} and triggered a #{order.action} order"} if order.total_quantity.to_i < 0
|
143
157
|
order.total_quantity = order.total_quantity.to_i.abs
|
144
158
|
end
|
145
159
|
# apply non_guarenteed and other stuff bound to the contract to order.
|
146
160
|
order.attributes.merge! order.contract.order_requirements unless order.contract.order_requirements.blank?
|
147
161
|
# con_id and exchange fully qualify a contract, no need to transmit other data
|
148
|
-
the_contract = order.contract.con_id >0 ? Contract.new( con_id: order.contract.con_id, exchange: order.contract.exchange) : nil
|
162
|
+
the_contract = order.contract.con_id >0 ? Contract.new( con_id: order.contract.con_id, exchange: order.contract.exchange) : nil
|
149
163
|
the_local_id = order.place the_contract # return the local_id
|
150
|
-
|
151
|
-
loop{ sleep(0.001); break if locate_order( local_id: the_local_id, status: nil ).present? }
|
152
|
-
end
|
164
|
+
i=0; loop{i+=1; sleep(0.01); break if locate_order( local_id: the_local_id, status: nil ).present? || i> 1000 }
|
153
165
|
|
154
166
|
ib.unsubscribe sa
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
else
|
159
|
-
nil
|
160
|
-
end
|
161
|
-
end # place
|
167
|
+
raise IB::TransmissionError," #{order.to_human} is not transmitted properly" if i >=1000
|
168
|
+
the_local_id # return_value
|
169
|
+
end # place
|
162
170
|
|
163
171
|
# shortcut to enable
|
164
|
-
# account.place order: {} , contract: {}
|
172
|
+
# account.place order: {} , contract: {}
|
165
173
|
# account.preview order: {} , contract: {}
|
166
174
|
# account.modify order: {}
|
167
175
|
alias place place_order
|
@@ -171,7 +179,7 @@ Account#ModifyOrder operates in two modi:
|
|
171
179
|
|
172
180
|
First: The order is specified via local_id, perm_id or order_ref.
|
173
181
|
It is checked, whether the order is still modificable.
|
174
|
-
Then the Order ist provided through the block. Any modification is done there.
|
182
|
+
Then the Order ist provided through the block. Any modification is done there.
|
175
183
|
Important: The Block has to return the modified IB::Order
|
176
184
|
|
177
185
|
Second: The order can be provided as parameter as well. This will be used
|
@@ -185,7 +193,6 @@ This has to be done manualy in the provided block
|
|
185
193
|
def modify_order local_id: nil, order_ref: nil, order:nil
|
186
194
|
|
187
195
|
result = ->(l){ orders.detect{|x| x.local_id == l && x.submitted? } }
|
188
|
-
logger.tap{ |l| l.progname = "Account #{account}#modify_order"}
|
189
196
|
order ||= locate_order( local_id: local_id,
|
190
197
|
status: /ubmitted/ ,
|
191
198
|
order_ref: order_ref )
|
@@ -214,9 +221,9 @@ This has to be done manualy in the provided block
|
|
214
221
|
order.what_if = true
|
215
222
|
the_local_id = place_order order: order, contract: contract
|
216
223
|
i=0; loop{ i= i+1; break if result[the_local_id] || i > 1000; sleep 0.01 }
|
217
|
-
|
224
|
+
raise IB::TransmissionError,"(Preview-) #{order.to_human} is not transmitted properly" if i >=1000
|
218
225
|
order.what_if = false # reset what_if flag
|
219
|
-
order.local_id = nil # reset local_id to enable
|
226
|
+
order.local_id = nil # reset local_id to enable re-using the order-object for placing
|
220
227
|
result[the_local_id].order_state.forcast # return_value
|
221
228
|
end
|
222
229
|
|