ib-extensions 1.0 → 1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|