ib-api 972.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +50 -0
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +105 -0
- data/Guardfile +24 -0
- data/LICENSE +674 -0
- data/README.md +65 -0
- data/Rakefile +11 -0
- data/VERSION +1 -0
- data/api.gemspec +43 -0
- data/bin/console +95 -0
- data/bin/console.yml +3 -0
- data/bin/setup +8 -0
- data/changelog.md +7 -0
- data/example/README.md +76 -0
- data/example/account_info +54 -0
- data/example/account_positions +30 -0
- data/example/account_summary +88 -0
- data/example/cancel_orders +74 -0
- data/example/fa_accounts +25 -0
- data/example/fundamental_data +40 -0
- data/example/historic_data_cli +186 -0
- data/example/list_orders +45 -0
- data/example/portfolio_csv +81 -0
- data/example/scanner_data +62 -0
- data/example/template +19 -0
- data/example/tick_data +28 -0
- data/lib/extensions/class-extensions.rb +87 -0
- data/lib/ib-api.rb +7 -0
- data/lib/ib/base.rb +103 -0
- data/lib/ib/base_properties.rb +160 -0
- data/lib/ib/connection.rb +450 -0
- data/lib/ib/constants.rb +393 -0
- data/lib/ib/errors.rb +44 -0
- data/lib/ib/logger.rb +26 -0
- data/lib/ib/messages.rb +99 -0
- data/lib/ib/messages/abstract_message.rb +101 -0
- data/lib/ib/messages/incoming.rb +251 -0
- data/lib/ib/messages/incoming/abstract_message.rb +116 -0
- data/lib/ib/messages/incoming/account_value.rb +78 -0
- data/lib/ib/messages/incoming/alert.rb +34 -0
- data/lib/ib/messages/incoming/contract_data.rb +102 -0
- data/lib/ib/messages/incoming/delta_neutral_validation.rb +23 -0
- data/lib/ib/messages/incoming/execution_data.rb +50 -0
- data/lib/ib/messages/incoming/historical_data.rb +84 -0
- data/lib/ib/messages/incoming/market_depths.rb +44 -0
- data/lib/ib/messages/incoming/next_valid_id.rb +18 -0
- data/lib/ib/messages/incoming/open_order.rb +277 -0
- data/lib/ib/messages/incoming/order_status.rb +85 -0
- data/lib/ib/messages/incoming/portfolio_value.rb +78 -0
- data/lib/ib/messages/incoming/real_time_bar.rb +32 -0
- data/lib/ib/messages/incoming/scanner_data.rb +54 -0
- data/lib/ib/messages/incoming/ticks.rb +268 -0
- data/lib/ib/messages/outgoing.rb +437 -0
- data/lib/ib/messages/outgoing/abstract_message.rb +88 -0
- data/lib/ib/messages/outgoing/account_requests.rb +112 -0
- data/lib/ib/messages/outgoing/bar_requests.rb +250 -0
- data/lib/ib/messages/outgoing/place_order.rb +209 -0
- data/lib/ib/messages/outgoing/request_marketdata.rb +99 -0
- data/lib/ib/messages/outgoing/request_tick_data.rb +21 -0
- data/lib/ib/model.rb +4 -0
- data/lib/ib/models.rb +14 -0
- data/lib/ib/server_versions.rb +114 -0
- data/lib/ib/socket.rb +185 -0
- data/lib/ib/support.rb +160 -0
- data/lib/ib/version.rb +6 -0
- data/lib/models/ib/account.rb +85 -0
- data/lib/models/ib/account_value.rb +33 -0
- data/lib/models/ib/bag.rb +55 -0
- data/lib/models/ib/bar.rb +31 -0
- data/lib/models/ib/combo_leg.rb +105 -0
- data/lib/models/ib/condition.rb +245 -0
- data/lib/models/ib/contract.rb +415 -0
- data/lib/models/ib/contract_detail.rb +108 -0
- data/lib/models/ib/execution.rb +67 -0
- data/lib/models/ib/forex.rb +13 -0
- data/lib/models/ib/future.rb +15 -0
- data/lib/models/ib/index.rb +15 -0
- data/lib/models/ib/option.rb +78 -0
- data/lib/models/ib/option_detail.rb +55 -0
- data/lib/models/ib/order.rb +519 -0
- data/lib/models/ib/order_state.rb +152 -0
- data/lib/models/ib/portfolio_value.rb +64 -0
- data/lib/models/ib/stock.rb +16 -0
- data/lib/models/ib/underlying.rb +34 -0
- data/lib/models/ib/vertical.rb +96 -0
- data/lib/requires.rb +12 -0
- metadata +203 -0
@@ -0,0 +1,108 @@
|
|
1
|
+
module IB
|
2
|
+
|
3
|
+
# Additional Contract properties (volatile, therefore extracted)
|
4
|
+
class ContractDetail < IB::Model
|
5
|
+
include BaseProperties
|
6
|
+
|
7
|
+
# All fields Strings, unless specified otherwise:
|
8
|
+
prop :market_name, # The market name for this contract.
|
9
|
+
:trading_class, # The trading class name for this contract.
|
10
|
+
:min_tick, # double: The minimum price tick.
|
11
|
+
:price_magnifier, # int: Allows execution and strike prices to be reported
|
12
|
+
# consistently with market data, historical data and the
|
13
|
+
# order price: Z on LIFFE is reported in index points, not GBP.
|
14
|
+
|
15
|
+
:order_types, # The list of valid order types for this contract.
|
16
|
+
:valid_exchanges, # The list of exchanges this contract is traded on.
|
17
|
+
:under_con_id, # int: The underlying contract ID.
|
18
|
+
:long_name, # Descriptive name of the asset.
|
19
|
+
:contract_month, # The contract month of the underlying futures contract.
|
20
|
+
|
21
|
+
:agg_group,
|
22
|
+
:under_symbol,
|
23
|
+
:under_sec_type,
|
24
|
+
:market_rule_ids,
|
25
|
+
:real_expiration_date,
|
26
|
+
|
27
|
+
|
28
|
+
# For Bonds only
|
29
|
+
:valid_next_option_date,
|
30
|
+
:valid_next_option_type,
|
31
|
+
:valid_next_option_partial,
|
32
|
+
|
33
|
+
# The industry classification of the underlying/product:
|
34
|
+
:industry, # Wide industry. For example, Financial.
|
35
|
+
:category, # Industry category. For example, InvestmentSvc.
|
36
|
+
:subcategory, # Subcategory. For example, Brokerage.
|
37
|
+
[:time_zone, :time_zone_id], # Time zone for the trading hours (e.g. EST)
|
38
|
+
:trading_hours, # The trading hours of the product. For example:
|
39
|
+
# 20090507:0700-1830,1830-2330;20090508:CLOSED.
|
40
|
+
:liquid_hours, # The liquid trading hours of the product. For example,
|
41
|
+
# 20090507:0930-1600;20090508:CLOSED.
|
42
|
+
|
43
|
+
# To support products in Australia which trade in non-currency units, the following
|
44
|
+
# attributes have been added to Execution and Contract Details objects:
|
45
|
+
:ev_rule, # evRule - String contains the Economic Value Rule name and optional argument,
|
46
|
+
# separated by a colon. Examle: aussieBond:YearsToExpiration=3.
|
47
|
+
# When the optional argument not present, the value will be followed by a colon.
|
48
|
+
[:ev_multiplier, :ev_multipler], # evMultiplier - double, tells you approximately
|
49
|
+
# how much the market value of a contract would change if the price were
|
50
|
+
# to change by 1. It cannot be used to get market value by multiplying
|
51
|
+
# the price by the approximate multiplier.
|
52
|
+
|
53
|
+
:sec_id_list, # Array with multiple Security ids
|
54
|
+
# MD Size Multiplier. Returns the size multiplier for values returned to tickSize from a market data request. Generally 100 for US stocks and 1 for other instruments.
|
55
|
+
:md_size_multiplier,
|
56
|
+
#
|
57
|
+
# BOND values:
|
58
|
+
:cusip, # The nine-character bond CUSIP or the 12-character SEDOL.
|
59
|
+
:ratings, # Credit rating of the issuer. Higher rating is less risky investment.
|
60
|
+
# Bond ratings are from Moody's and S&P respectively.
|
61
|
+
:desc_append, # Additional descriptive information about the bond.
|
62
|
+
:bond_type, # The type of bond, such as "CORP."
|
63
|
+
:coupon_type, # The type of bond coupon.
|
64
|
+
:coupon, # double: The interest rate used to calculate the amount you
|
65
|
+
# will receive in interest payments over the year. default 0
|
66
|
+
:maturity, # The date on which the issuer must repay bond face value
|
67
|
+
:issue_date, # The date the bond was issued.
|
68
|
+
:next_option_date, # only if bond has embedded options.
|
69
|
+
:next_option_type, # only if bond has embedded options.
|
70
|
+
:notes, # Additional notes, if populated for the bond in IB's database
|
71
|
+
:callable => :bool, # Can be called by the issuer under certain conditions.
|
72
|
+
:puttable => :bool, # Can be sold back to the issuer under certain conditions
|
73
|
+
:convertible => :bool, # Can be converted to stock under certain conditions.
|
74
|
+
:next_option_partial => :bool # # only if bond has embedded options.
|
75
|
+
|
76
|
+
# Extra validations
|
77
|
+
validates_format_of :time_zone, :with => /\A\w{3}\z/, :message => 'should be XXX'
|
78
|
+
|
79
|
+
serialize :sec_id_list, Hash
|
80
|
+
|
81
|
+
belongs_to :contract
|
82
|
+
alias summary contract
|
83
|
+
alias summary= contract=
|
84
|
+
|
85
|
+
def default_attributes
|
86
|
+
super.merge :coupon => 0.0,
|
87
|
+
:under_con_id => 0,
|
88
|
+
:min_tick => 0,
|
89
|
+
:ev_multipler => 0,
|
90
|
+
:sec_id_list => Hash.new,
|
91
|
+
:callable => false,
|
92
|
+
:puttable => false,
|
93
|
+
:convertible => false,
|
94
|
+
:next_option_partial => false
|
95
|
+
end
|
96
|
+
|
97
|
+
def to_human
|
98
|
+
ret = "<ContractDetails #{long_name}, market-name:#{market_name}, "
|
99
|
+
ret << "category:#{category}, industry:#{industry} / #{subcategory}, " if category.present?
|
100
|
+
ret << "underlying: con_id:#{under_con_id} , sec_type:#{under_sec_type}, symbol:#{under_symbol} " unless under_con_id.zero?
|
101
|
+
ret << "ev_multiplier:#{ev_multiplier}, convertible:#{convertible}, cupon:#{coupon}, "
|
102
|
+
ret << "md_size_multiplier:#{md_size_multiplier}, min_tick:#{min_tick}, next_option_partial:#{next_option_partial} "
|
103
|
+
ret <<"price_magnifier:#{price_magnifier}, puttable:#{puttable}, sec_id-list:#{sec_id_list}, "
|
104
|
+
ret <<"valid exchanges: #{ valid_exchanges}, order types: #{order_types} >"
|
105
|
+
end
|
106
|
+
|
107
|
+
end # class ContractDetail
|
108
|
+
end # module IB
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module IB
|
2
|
+
|
3
|
+
# This is IB Order execution report.
|
4
|
+
class Execution < IB::Model
|
5
|
+
include BaseProperties
|
6
|
+
|
7
|
+
belongs_to :order
|
8
|
+
|
9
|
+
prop :local_id, # int: order id. TWS orders have a fixed order id of 0.
|
10
|
+
:client_id, # int: client id. TWS orders have a fixed client id of 0.
|
11
|
+
:perm_id, # int: TWS id used to identify orders over TWS sessions
|
12
|
+
:exec_id, # String: Unique order execution id over TWS sessions.
|
13
|
+
:time, # # TODO: convert into Time object?
|
14
|
+
# String: The order execution time.
|
15
|
+
:exchange, # String: Exchange that executed the order.
|
16
|
+
:order_ref, # String: Same order_ref as in corresponding Order
|
17
|
+
:price, # double: The order execution price.
|
18
|
+
:average_price, # double: Used in regular trades, combo trades and legs of the combo.
|
19
|
+
:ev_rule, # String: Australian products only
|
20
|
+
:ev_multiplier, # double: Australian products onlyA
|
21
|
+
:model_code,
|
22
|
+
:last_liquidity,
|
23
|
+
|
24
|
+
[:quantity, :shares], # int: The number of shares filled.
|
25
|
+
:cumulative_quantity, # int: Used in regular trades, combo trades and legs of combo
|
26
|
+
:liquidation => :bool, # This position is liquidated last should the need arise.
|
27
|
+
[:account_name, :account_number] => :s, # The customer account number.
|
28
|
+
[:side, :action] => PROPS[:side] # Was the transaction a buy or a sale: BOT|SLD
|
29
|
+
|
30
|
+
# Extra validations
|
31
|
+
validates_numericality_of :quantity, :cumulative_quantity, :price, :average_price
|
32
|
+
validates_numericality_of :local_id, :client_id, :perm_id, :only_integer => true
|
33
|
+
|
34
|
+
def default_attributes
|
35
|
+
super.merge :local_id => 0,
|
36
|
+
:client_id => 0,
|
37
|
+
:quantity => 0,
|
38
|
+
:price => 0,
|
39
|
+
:perm_id => 0,
|
40
|
+
:liquidation => false
|
41
|
+
end
|
42
|
+
|
43
|
+
# Comparison
|
44
|
+
def == other
|
45
|
+
super(other) ||
|
46
|
+
other.is_a?(self.class) &&
|
47
|
+
perm_id == other.perm_id &&
|
48
|
+
local_id == other.local_id && # ((p __LINE__)||true) &&
|
49
|
+
client_id == other.client_id &&
|
50
|
+
exec_id == other.exec_id &&
|
51
|
+
time == other.time &&
|
52
|
+
exchange == other.exchange &&
|
53
|
+
order_ref == other.order_ref &&
|
54
|
+
side == other.side
|
55
|
+
# TODO: || compare all attributes!
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_human
|
59
|
+
"<Execution: #{time} #{side} #{quantity} at #{price} on #{exchange}, " +
|
60
|
+
"cumulative #{cumulative_quantity} at #{average_price}, " +
|
61
|
+
"ids #{local_id}/#{perm_id}/#{exec_id}>"
|
62
|
+
end
|
63
|
+
|
64
|
+
alias to_s to_human
|
65
|
+
|
66
|
+
end # Execution
|
67
|
+
end # module IB
|
@@ -0,0 +1,13 @@
|
|
1
|
+
#require 'models/ib/contract'
|
2
|
+
module IB
|
3
|
+
class Forex < IB::Contract
|
4
|
+
validates_format_of :sec_type, :with => /\Aforex\z/,
|
5
|
+
:message => "should be a Currency-Pair"
|
6
|
+
def default_attributes
|
7
|
+
# Base-currency: USD
|
8
|
+
super.merge :sec_type => :forex, currency:'USD', exchange:'IDEALPRO'
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#require 'models/ib/contract'
|
2
|
+
module IB
|
3
|
+
class Future < Contract
|
4
|
+
validates_format_of :sec_type, :with => /\Afuture\z/,
|
5
|
+
:message => "should be a Future"
|
6
|
+
def default_attributes
|
7
|
+
super.merge :sec_type => :future, currency:'USD'
|
8
|
+
end
|
9
|
+
def to_human
|
10
|
+
"<Future: " + [symbol, expiry, currency].join(" ") + ">"
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#require 'models/ib/contract'
|
2
|
+
module IB
|
3
|
+
class Index < Contract
|
4
|
+
validates_format_of :sec_type, :with => /\Aind\z/,
|
5
|
+
:message => "should be a Index"
|
6
|
+
def default_attributes
|
7
|
+
super.merge :sec_type => :ind
|
8
|
+
end
|
9
|
+
def to_human
|
10
|
+
"<Index: " + [symbol, currency].join(" ") + ">"
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'models/ib/contract'
|
2
|
+
require 'models/ib/option_detail'
|
3
|
+
|
4
|
+
module IB
|
5
|
+
class Option < Contract
|
6
|
+
|
7
|
+
validates_numericality_of :strike, :greater_than => 0
|
8
|
+
validates_format_of :sec_type, :with => /\Aoption\z/,
|
9
|
+
:message => "should be an option"
|
10
|
+
validates_format_of :local_symbol, :with => /\A\w+\s*\d{6}[pcPC]\d{8}$|\A\z/,
|
11
|
+
:message => "invalid OSI code"
|
12
|
+
validates_format_of :right, :with => /\Aput$|^call\z/,
|
13
|
+
:message => "should be put or call"
|
14
|
+
|
15
|
+
|
16
|
+
# introduce Option.greek with reference to IB::OptionDetail-dataset
|
17
|
+
#
|
18
|
+
has_one :greek , as: :option_detail
|
19
|
+
# For Options, this is contract's OSI (Option Symbology Initiative) name/code
|
20
|
+
alias osi local_symbol
|
21
|
+
|
22
|
+
def osi= value
|
23
|
+
# Normalize to 21 char
|
24
|
+
self.local_symbol = value.sub(/ /, ' '*(22-value.size))
|
25
|
+
end
|
26
|
+
|
27
|
+
# Make valid IB Contract definition from OSI (Option Symbology Initiative) code.
|
28
|
+
# NB: Simply making a new Contract with *local_symbol* (osi) property set to a
|
29
|
+
# valid OSI code works just as well, just do NOT set *expiry*, *right* or
|
30
|
+
# *strike* properties in this case.
|
31
|
+
# This class method provided as a backup and shows how to analyse OSI codes.
|
32
|
+
def self.from_osi osi
|
33
|
+
|
34
|
+
# Parse contract's OSI (OCC Option Symbology Initiative) code
|
35
|
+
args = osi.match(/(\w+)\s?(\d\d)(\d\d)(\d\d)([pcPC])(\d+)/).to_a.drop(1)
|
36
|
+
symbol = args.shift
|
37
|
+
year = 2000 + args.shift.to_i
|
38
|
+
month = args.shift.to_i
|
39
|
+
day = args.shift.to_i
|
40
|
+
right = args.shift.upcase
|
41
|
+
strike = args.shift.to_i/1000.0
|
42
|
+
|
43
|
+
# Set correct expiry date - IB expiry date differs from OSI if expiry date
|
44
|
+
# falls on Saturday (see https://github.com/arvicco/option_mower/issues/4)
|
45
|
+
expiry_date = Time.utc(year, month, day)
|
46
|
+
expiry_date = Time.utc(year, month, day-1) if expiry_date.wday == 6
|
47
|
+
|
48
|
+
new :symbol => symbol,
|
49
|
+
:exchange => "SMART",
|
50
|
+
:expiry => expiry_date.to_ib[2..7], # YYMMDD
|
51
|
+
:right => right,
|
52
|
+
:strike => strike
|
53
|
+
end
|
54
|
+
|
55
|
+
def default_attributes
|
56
|
+
super.merge :sec_type => :option
|
57
|
+
#self[:description] ||= osi ? osi : "#{symbol} #{strike} #{right} #{expiry}"
|
58
|
+
end
|
59
|
+
def == other
|
60
|
+
super(other) || ( # finish positive, if contract#== is true
|
61
|
+
# otherwise, we most probably compare the response from IB with our selfmade input
|
62
|
+
exchange == other.exchange &&
|
63
|
+
include_expired == other.include_expired &&
|
64
|
+
sec_type == other.sec_type &&
|
65
|
+
multiplier == other.multiplier &&
|
66
|
+
strike == other.strike &&
|
67
|
+
right == other.right &&
|
68
|
+
multiplier == other.multiplier &&
|
69
|
+
expiry == other.expiry )
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
def to_human
|
74
|
+
"<Option: " + [symbol, expiry, right, strike, exchange, currency].join(" ") + ">"
|
75
|
+
end
|
76
|
+
|
77
|
+
end # class Option
|
78
|
+
end # module IB
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module IB
|
2
|
+
|
3
|
+
# Additional Option properties and Option-Calculations
|
4
|
+
class OptionDetail < IB::Model
|
5
|
+
include BaseProperties
|
6
|
+
|
7
|
+
prop :delta, :gamma, :vega, :theta, # greeks
|
8
|
+
:implied_volatility,
|
9
|
+
:pv_dividend, # anticipated Dividend
|
10
|
+
:under_price, # price of the Underlying
|
11
|
+
:option_price,
|
12
|
+
:close_price,
|
13
|
+
:open_tick,
|
14
|
+
:bid_price,
|
15
|
+
:ask_price,
|
16
|
+
:prev_strike,
|
17
|
+
:next_strike,
|
18
|
+
:prev_expiry,
|
19
|
+
:next_expiry,
|
20
|
+
:option_price
|
21
|
+
belongs_to :option
|
22
|
+
|
23
|
+
# returns true if all datafields are filled with reasonal data
|
24
|
+
def complete?
|
25
|
+
fields= [ :delta, :gamma, :vega, :theta,
|
26
|
+
:implied_volatility, :pv_dividend, :open_tick,
|
27
|
+
:under_price, :option_price, :close_price, :bid_price, :ask_price]
|
28
|
+
|
29
|
+
!fields.detect{|y| self.send(y).nil?}
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
def greeks?
|
34
|
+
fields= [ :delta, :gamma, :vega, :theta,
|
35
|
+
:implied_volatility, :pv_dividend]
|
36
|
+
|
37
|
+
!fields.detect{|y| self.send(y).nil?}
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_human
|
42
|
+
outstr= ->( item ) { if item.nil? then "--" else sprintf("%g" , item) end }
|
43
|
+
att = " optionPrice: #{ outstr[ option_price ]}, UnderlyingPrice: #{ outstr[ under_price] } impl.Vola: #{ outstr[ implied_volatility ]} ; dividend: #{ outstr[ pv_dividend ]}; "
|
44
|
+
greeks = "Greeks:: delta: #{ outstr[ delta ] }; gamma: #{ outstr[ gamma ]}, vega: #{ outstr[ vega ] }; theta: #{ outstr[ theta ]}"
|
45
|
+
prices= " close: #{ outstr[ close_price ]}; bid: #{ outstr[ bid_price ]}; ask: #{ outstr[ ask_price ]} "
|
46
|
+
if complete?
|
47
|
+
"< "+ prices + "\n" + att + "\n" + greeks + " >"
|
48
|
+
else
|
49
|
+
"< " + greeks + " >"
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end # class
|
55
|
+
end # module
|
@@ -0,0 +1,519 @@
|
|
1
|
+
require 'models/ib/order_state'
|
2
|
+
|
3
|
+
module IB
|
4
|
+
class Order < IB::Model
|
5
|
+
include BaseProperties
|
6
|
+
|
7
|
+
# General Notes:
|
8
|
+
# 1. Placing Orders by con_id - When you place an order by con_id, you must
|
9
|
+
# provide the con_id AND the exchange. If you provide extra fields when placing
|
10
|
+
# an order by conid, the order may not work.
|
11
|
+
|
12
|
+
# 2. Order IDs - Each order you place must have a unique Order ID. Increment
|
13
|
+
# your own Order IDs to avoid conflicts between orders placed from your API application.
|
14
|
+
|
15
|
+
# Main order fields
|
16
|
+
prop :local_id, # int: Order id associated with client (volatile).
|
17
|
+
:client_id, # int: The id of the client that placed this order.
|
18
|
+
:perm_id, # int: TWS permanent id, remains the same over TWS sessions.
|
19
|
+
:quantity, :total_quantity, # int: The order quantity.
|
20
|
+
|
21
|
+
:order_type, # String: Order type.
|
22
|
+
# Limit Risk: MTL / MKT PRT / QUOTE / STP / STP LMT / TRAIL / TRAIL LIMIT / TRAIL LIT / TRAIL MIT
|
23
|
+
# Speed of Execution: MKT / MIT / MOC / MOO / PEG MKT / REL
|
24
|
+
# Price Improvement: BOX TOP / LOC / LOO / LIT / PEG MID / VWAP
|
25
|
+
# Advanced Trading: OCA / VOL / SCALE
|
26
|
+
# Other (no abbreviation): Bracket, Auction, Discretionary, Sweep-to-Fill,
|
27
|
+
# Price Improvement Auction, Block, Hidden, Iceberg/Reserve, All-or-None, Fill-or-Kill
|
28
|
+
# See 'ib/constants.rb' ORDER_TYPES for a complete list of valid values.
|
29
|
+
|
30
|
+
:limit_price, # double: LIMIT price, used for limit, stop-limit and relative
|
31
|
+
# orders. In all other cases specify zero. For relative
|
32
|
+
# orders with no limit price, also specify zero.
|
33
|
+
:aux_price, # => 0.0, default set to "" (as implemented in python code)
|
34
|
+
#:aux_price, # double: STOP price for stop-limit orders, and the OFFSET amount
|
35
|
+
# for relative orders. In all other cases, specify zero.
|
36
|
+
|
37
|
+
:oca_group, # String: Identifies a member of a one-cancels-all group.
|
38
|
+
:oca_type, # int: Tells how to handle remaining orders in an OCA group
|
39
|
+
# when one order or part of an order executes. Valid values:
|
40
|
+
# - 1 = Cancel all remaining orders with block
|
41
|
+
# - 2 = Remaining orders are reduced in size with block
|
42
|
+
# - 3 = Remaining orders are reduced in size with no block
|
43
|
+
# If you use a value "with block" your order has
|
44
|
+
# overfill protection. This means that only one order in
|
45
|
+
# the group will be routed at a time to remove the
|
46
|
+
# possibility of an overfill.
|
47
|
+
:parent_id, # int: The order ID of the parent (original) order, used
|
48
|
+
# for bracket (STP) and auto trailing stop (TRAIL) orders.
|
49
|
+
:display_size, # int: publicly disclosed order size for Iceberg orders.
|
50
|
+
|
51
|
+
:trigger_method, # Specifies how Simulated Stop, Stop-Limit and Trailing
|
52
|
+
# Stop orders are triggered. Valid values are:
|
53
|
+
# 0 - Default, "double bid/ask" for OTC/US options, "last" otherswise.
|
54
|
+
# 1 - "double bid/ask" method, stop orders are triggered based on
|
55
|
+
# two consecutive bid or ask prices.
|
56
|
+
# 2 - "last" method, stops are triggered based on the last price.
|
57
|
+
# 3 - double last method.
|
58
|
+
# 4 - bid/ask method. For a buy order, a single occurrence of the
|
59
|
+
# bid price must be at or above the trigger price. For a sell
|
60
|
+
# order, a single occurrence of the ask price must be at or
|
61
|
+
# below the trigger price.
|
62
|
+
# 7 - last or bid/ask method. For a buy order, a single bid price
|
63
|
+
# or the last price must be at or above the trigger price.
|
64
|
+
# For a sell order, a single ask price or the last price
|
65
|
+
# must be at or below the trigger price.
|
66
|
+
# 8 - mid-point method, where the midpoint must be at or above
|
67
|
+
# (for a buy) or at or below (for a sell) the trigger price,
|
68
|
+
# and the spread between the bid and ask must be less than
|
69
|
+
# 0.1% of the midpoint
|
70
|
+
|
71
|
+
:good_after_time, # Indicates that the trade should be submitted after the
|
72
|
+
# time and date set, format YYYYMMDD HH:MM:SS (seconds are optional).
|
73
|
+
:good_till_date, # Indicates that the trade should remain working until the
|
74
|
+
# time and date set, format YYYYMMDD HH:MM:SS (seconds are optional).
|
75
|
+
# You must set the :tif to GTD when using this string.
|
76
|
+
# Use an empty String if not applicable.
|
77
|
+
|
78
|
+
:rule_80a, # Individual = 'I', Agency = 'A', AgentOtherMember = 'W',
|
79
|
+
# IndividualPTIA = 'J', AgencyPTIA = 'U', AgentOtherMemberPTIA = 'M',
|
80
|
+
# IndividualPT = 'K', AgencyPT = 'Y', AgentOtherMemberPT = 'N'
|
81
|
+
:min_quantity, # int: Identifies a minimum quantity order type.
|
82
|
+
:percent_offset, # double: percent offset amount for relative (REL)orders only
|
83
|
+
:trail_stop_price, # double: for TRAILLIMIT orders only
|
84
|
+
# As of client v.56, we receive trailing_percent in openOrder
|
85
|
+
:trailing_percent,
|
86
|
+
|
87
|
+
# Financial advisors only - use an empty String if not applicable.
|
88
|
+
:fa_group, :fa_profile, :fa_method, :fa_percentage,
|
89
|
+
:model_code , # string, no further reference in docs.
|
90
|
+
# Institutional orders only!
|
91
|
+
:origin, # 0=Customer, 1=Firm
|
92
|
+
:order_ref, # String: Order reference. Customer defined order ID tag.
|
93
|
+
:short_sale_slot, # 1 - you hold the shares,
|
94
|
+
# 2 - they will be delivered from elsewhere.
|
95
|
+
# Only for Action="SSHORT
|
96
|
+
:designated_location, # String: set when slot==2 only
|
97
|
+
:exempt_code, # int
|
98
|
+
|
99
|
+
# Clearing info
|
100
|
+
:account, # String: The account number (Uxxx). For institutional customers only.
|
101
|
+
:settling_firm, # String: Institutional only
|
102
|
+
:clearing_account, # String: For IBExecution customers: Specifies the
|
103
|
+
# true beneficiary of the order. This value is required
|
104
|
+
# for FUT/FOP orders for reporting to the exchange.
|
105
|
+
:clearing_intent, # IBExecution customers: "", IB, Away, PTA (post trade allocation).
|
106
|
+
|
107
|
+
# SMART routing only
|
108
|
+
:discretionary_amount, # double: The amount off the limit price
|
109
|
+
# allowed for discretionary orders.
|
110
|
+
:nbbo_price_cap, # double: Maximum Smart order distance from the NBBO.
|
111
|
+
|
112
|
+
# BOX or VOL ORDERS ONLY
|
113
|
+
:auction_strategy, # For BOX exchange only. Valid values:
|
114
|
+
# 1=AUCTION_MATCH, 2=AUCTION_IMPROVEMENT, 3=AUCTION_TRANSPARENT
|
115
|
+
:starting_price, # double: Starting price. Valid on BOX orders only.
|
116
|
+
:stock_ref_price, # double: The stock reference price, used for VOL
|
117
|
+
# orders to compute the limit price sent to an exchange (whether or not
|
118
|
+
# Continuous Update is selected), and for price range monitoring.
|
119
|
+
:delta, # double: Stock delta. Valid on BOX orders only.
|
120
|
+
|
121
|
+
# Pegged to stock or VOL orders. For price improvement option orders
|
122
|
+
# on BOX and VOL orders with dynamic management:
|
123
|
+
:stock_range_lower, # double: The lower value for the acceptable
|
124
|
+
# underlying stock price range.
|
125
|
+
:stock_range_upper, # double The upper value for the acceptable
|
126
|
+
# underlying stock price range.
|
127
|
+
|
128
|
+
# VOLATILITY ORDERS ONLY:
|
129
|
+
# http://www.interactivebrokers.com/en/general/education/pdfnotes/PDF-VolTrader.php
|
130
|
+
:volatility, # double: What the price is, computed via TWSs Options
|
131
|
+
# Analytics. For VOL orders, the limit price sent to an
|
132
|
+
# exchange is not editable, as it is the output of a
|
133
|
+
# function. Volatility is expressed as a percentage.
|
134
|
+
:volatility_type, # int: How the volatility is calculated: 1=daily, 2=annual
|
135
|
+
:reference_price_type, # int: For dynamic management of volatility orders:
|
136
|
+
# - 1 = Average of National Best Bid or Ask,
|
137
|
+
# - 2 = National Best Bid when buying a call or selling a put;
|
138
|
+
# and National Best Ask when selling a call or buying a put.
|
139
|
+
:continuous_update, # int: Used for dynamic management of volatility orders.
|
140
|
+
# Determines whether TWS is supposed to update the order price as the underlying
|
141
|
+
# moves. If selected, the limit price sent to an exchange is modified by TWS
|
142
|
+
# if the computed price of the option changes enough to warrant doing so. This
|
143
|
+
# is helpful in keeping the limit price up to date as the underlying price changes.
|
144
|
+
:delta_neutral_order_type, # String: Enter an order type to instruct TWS
|
145
|
+
# to submit a delta neutral trade on full or partial execution of the
|
146
|
+
# VOL order. For no hedge delta order to be sent, specify NONE.
|
147
|
+
# Valid values - LMT, MKT, MTL, REL, MOC
|
148
|
+
:delta_neutral_aux_price, # double: Use this field to enter a value if
|
149
|
+
# the value in the deltaNeutralOrderType field is an order
|
150
|
+
# type that requires an Aux price, such as a REL order.
|
151
|
+
|
152
|
+
# As of client v.52, we also receive delta... params in openOrder
|
153
|
+
:delta_neutral_designated_location,
|
154
|
+
:delta_neutral_con_id,
|
155
|
+
:delta_neutral_settling_firm,
|
156
|
+
:delta_neutral_clearing_account,
|
157
|
+
:delta_neutral_clearing_intent,
|
158
|
+
# Used when the hedge involves a stock and indicates whether or not it is sold short.
|
159
|
+
:delta_neutral_short_sale,
|
160
|
+
# Has a value of 1 (the clearing broker holds shares) or 2 (delivered from a third party).
|
161
|
+
# If you use 2, then you must specify a deltaNeutralDesignatedLocation.
|
162
|
+
:delta_neutral_short_sale_slot,
|
163
|
+
# Specifies whether the order is an Open or a Close order and is used
|
164
|
+
# when the hedge involves a CFD and and the order is clearing away.
|
165
|
+
:delta_neutral_open_close,
|
166
|
+
|
167
|
+
# HEDGE ORDERS ONLY:
|
168
|
+
# As of client v.49/50, we can now add hedge orders using the API.
|
169
|
+
# Hedge orders are child orders that take additional fields. There are four
|
170
|
+
# types of hedging orders supported by the API: Delta, Beta, FX, Pair.
|
171
|
+
# All hedge orders must have a parent order submitted first. The hedge order
|
172
|
+
# should set its :parent_id. If the hedgeType is Beta, the beta sent in the
|
173
|
+
# hedgeParm can be zero, which means it is not used. Delta is only valid
|
174
|
+
# if the parent order is an option and the child order is a stock.
|
175
|
+
|
176
|
+
:hedge_type, # String: D = Delta, B = Beta, F = FX or P = Pair
|
177
|
+
:hedge_param, # String; value depends on the hedgeType; sent from the API
|
178
|
+
# only if hedge_type is NOT null. It is required for Pair hedge order,
|
179
|
+
# optional for Beta hedge orders, and ignored for Delta and FX hedge orders.
|
180
|
+
|
181
|
+
# COMBO ORDERS ONLY:
|
182
|
+
:basis_points, # double: EFP orders only
|
183
|
+
:basis_points_type, # double: EFP orders only
|
184
|
+
|
185
|
+
# ALGO ORDERS ONLY:
|
186
|
+
:algo_strategy, # String
|
187
|
+
:algo_params, # public Vector<TagValue> m_algoParams; ?!
|
188
|
+
:algo_id, # since Vers. 71
|
189
|
+
# SCALE ORDERS ONLY:
|
190
|
+
:scale_init_level_size, # int: Size of the first (initial) order component.
|
191
|
+
:scale_subs_level_size, # int: Order size of the subsequent scale order
|
192
|
+
# components. Used in conjunction with scaleInitLevelSize().
|
193
|
+
:scale_price_increment, # double: Price increment between scale components.
|
194
|
+
# This field is required for Scale orders.
|
195
|
+
|
196
|
+
# As of client v.54, we can receive additional scale order fields:
|
197
|
+
:scale_price_adjust_value,
|
198
|
+
:scale_price_adjust_interval,
|
199
|
+
:scale_profit_offset,
|
200
|
+
:scale_init_position,
|
201
|
+
:scale_init_fill_qty,
|
202
|
+
:scale_table, # Vers 69
|
203
|
+
:active_start_time, # Vers 69
|
204
|
+
:active_stop_time, # Vers 69
|
205
|
+
# pegged to benchmark
|
206
|
+
:reference_contract_id,
|
207
|
+
:is_pegged_change_amount_decrease,
|
208
|
+
:pegged_change_amount,
|
209
|
+
:reference_change_amount,
|
210
|
+
:reference_exchange_id ,
|
211
|
+
|
212
|
+
:conditions, # Conditions determining when the order will be activated or canceled.
|
213
|
+
### http://xavierib.github.io/twsapidocs/order_conditions.html
|
214
|
+
:conditions_ignore_rth, # bool: Indicates whether or not conditions will also be valid outside Regular Trading Hours
|
215
|
+
:conditions_cancel_order,# bool: Conditions can determine if an order should become active or canceled.
|
216
|
+
:adjusted_order_type,
|
217
|
+
:trigger_price,
|
218
|
+
:limit_price_offset, # used in trailing stop limit + trailing limit orders
|
219
|
+
:adjusted_stop_price,
|
220
|
+
:adjusted_stop_limit_price,
|
221
|
+
:adjusted_trailing_amount,
|
222
|
+
|
223
|
+
:adjustable_trailing_unit,
|
224
|
+
:ext_operator , # 105: MIN_SERVER_VER_EXT_OPERATOR
|
225
|
+
# This is a regulartory attribute that applies
|
226
|
+
# to all US Commodity (Futures) Exchanges, provided
|
227
|
+
# to allow client to comply with CFTC Tag 50 Rules.
|
228
|
+
:soft_dollar_tier_name, # 106: MIN_SERVER_VER_SOFT_DOLLAR_TIER
|
229
|
+
:soft_dollar_tier_value,
|
230
|
+
:soft_dollar_tier_display_name,
|
231
|
+
# Define the Soft Dollar Tier used for the order.
|
232
|
+
# Only provided for registered professional advisors and hedge and mutual funds.
|
233
|
+
# format: "#{name}=#{value},#{display_name}", name and value are used in the
|
234
|
+
# order-specification. Its included as ["#{name}","#{value}"] pair
|
235
|
+
|
236
|
+
:cash_qty, # 111: MIN_SERVER_VER_CASH_QTY
|
237
|
+
# decimal : The native cash quantity
|
238
|
+
:mifid_2_decision_maker,
|
239
|
+
:mifid_2_decision_algo,
|
240
|
+
:mifid_2_execution_maker,
|
241
|
+
:mifid_2_execution_algo,
|
242
|
+
:dont_use_auto_price_for_hedge,
|
243
|
+
:discretionary_up_to_limit_price
|
244
|
+
|
245
|
+
# Properties with complex processing logics
|
246
|
+
prop :tif, # String: Time in Force (time to market): DAY/GAT/GTD/GTC/IOC
|
247
|
+
:random_size => :bool, # Vers 76
|
248
|
+
:random_price => :bool, # Vers 76
|
249
|
+
:scale_auto_reset => :bool,
|
250
|
+
:scale_random_percent => :bool,
|
251
|
+
:solicided => :bool, # Vers 73
|
252
|
+
:what_if => :bool, # Only return pre-trade commissions and margin info, do not place
|
253
|
+
:not_held => :bool, # Not Held
|
254
|
+
:outside_rth => :bool, # Order may trigger or fill outside of regular hours. (WAS: ignore_rth)
|
255
|
+
:hidden => :bool, # Order will not be visible in market depth. ISLAND only.
|
256
|
+
:transmit => :bool, # If false, order will be created but not transmitted.
|
257
|
+
:block_order => :bool, # This is an ISE Block order.
|
258
|
+
:sweep_to_fill => :bool, # This is a Sweep-to-Fill order.
|
259
|
+
:override_percentage_constraints => :bool,
|
260
|
+
# TWS Presets page constraints ensure that your price and size order values
|
261
|
+
# are reasonable. Orders sent from the API are also validated against these
|
262
|
+
# safety constraints, unless this parameter is set to True.
|
263
|
+
:all_or_none => :bool, # AON
|
264
|
+
:etrade_only => :bool, # Trade with electronic quotes.
|
265
|
+
:firm_quote_only => :bool, # Trade with firm quotes.
|
266
|
+
:opt_out_smart_routing => :bool, # Australian exchange only, default false
|
267
|
+
:open_close => PROPS[:open_close], # Originally String: O=Open, C=Close ()
|
268
|
+
# for ComboLeg compatibility: SAME = 0; OPEN = 1; CLOSE = 2; UNKNOWN = 3;
|
269
|
+
[:side, :action] => PROPS[:side], # String: Action/side: BUY/SELL/SSHORT/SSHORTX
|
270
|
+
:is_O_ms_container => :bool
|
271
|
+
|
272
|
+
prop :placed_at,
|
273
|
+
:modified_at,
|
274
|
+
:leg_prices,
|
275
|
+
:algo_params,
|
276
|
+
:combo_params # Valid tags are LeginPrio, MaxSegSize, DontLeginNext, ChangeToMktTime1,
|
277
|
+
# ChangeToMktTime2, ChangeToMktOffset, DiscretionaryPct, NonGuaranteed,
|
278
|
+
# CondPriceMin, CondPriceMax, and PriceCondConid.
|
279
|
+
# to set an execuction-range of a security:
|
280
|
+
# PriceCondConid, 10375; -- conid of the combo-leg
|
281
|
+
# CondPriceMax, 62.0; -- max and min-price
|
282
|
+
# CondPriceMin.;60.0
|
283
|
+
|
284
|
+
|
285
|
+
# prop :misc1, :misc2, :misc3, :misc4, :misc5, :misc6, :misc7, :misc8 # just 4 debugging
|
286
|
+
|
287
|
+
alias order_combo_legs leg_prices
|
288
|
+
alias smart_combo_routing_params combo_params
|
289
|
+
|
290
|
+
# serialize is included for active_record compatibility
|
291
|
+
# serialize :leg_prices
|
292
|
+
# serialize :conditions
|
293
|
+
# serialize :algo_params, Hash
|
294
|
+
# serialize :combo_params
|
295
|
+
# serialize :soft_dollar_tier_params, HashWithIndifferentAccess
|
296
|
+
serialize :mics_options, Hash
|
297
|
+
|
298
|
+
# Order is always placed for a contract. Here, we explicitly set this link.
|
299
|
+
belongs_to :contract
|
300
|
+
|
301
|
+
# Order has a collection of Executions if it was filled
|
302
|
+
has_many :executions
|
303
|
+
|
304
|
+
# Order has a collection of OrderStates, last one is always current
|
305
|
+
has_many :order_states
|
306
|
+
# Order can have multible conditions
|
307
|
+
has_many :conditions
|
308
|
+
|
309
|
+
def order_state
|
310
|
+
order_states.last
|
311
|
+
end
|
312
|
+
|
313
|
+
def order_state= state
|
314
|
+
self.order_states.push case state
|
315
|
+
when IB::OrderState
|
316
|
+
state
|
317
|
+
when Symbol, String
|
318
|
+
IB::OrderState.new :status => state
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
# Some properties received from IB are separated into OrderState object,
|
323
|
+
# but they are still readable as Order properties through delegation:
|
324
|
+
# Properties arriving via OpenOrder message:
|
325
|
+
[:commission, # double: Shows the commission amount on the order.
|
326
|
+
:commission_currency, # String: Shows the currency of the commission.
|
327
|
+
:min_commission, # The possible min range of the actual order commission.
|
328
|
+
:max_commission, # The possible max range of the actual order commission.
|
329
|
+
:warning_text, # String: Displays a warning message if warranted.
|
330
|
+
:init_margin, # Float: The impact the order would have on your initial margin.
|
331
|
+
:maint_margin, # Float: The impact the order would have on your maintenance margin.
|
332
|
+
:equity_with_loan, # Float: The impact the order would have on your equity
|
333
|
+
:status, # String: Displays the order status. See OrderState for values
|
334
|
+
# Properties arriving via OrderStatus message:
|
335
|
+
:filled, # int
|
336
|
+
:remaining, # int
|
337
|
+
:price, # double
|
338
|
+
:last_fill_price, # double
|
339
|
+
:average_price, # double
|
340
|
+
:average_fill_price, # double
|
341
|
+
:why_held, # String: comma-separated list of reasons for order to be held.
|
342
|
+
# Testing Order state:
|
343
|
+
:new?,
|
344
|
+
:submitted?,
|
345
|
+
:pending?,
|
346
|
+
:active?,
|
347
|
+
:inactive?,
|
348
|
+
:complete_fill?
|
349
|
+
].each { |property| define_method(property) { order_state.send(property) } }
|
350
|
+
|
351
|
+
# Order is not valid without correct :local_id
|
352
|
+
validates_numericality_of :local_id, :perm_id, :client_id, :parent_id,
|
353
|
+
:total_quantity, :min_quantity, :display_size,
|
354
|
+
:only_integer => true, :allow_nil => true
|
355
|
+
|
356
|
+
validates_numericality_of :limit_price, :aux_price, :allow_nil => true
|
357
|
+
|
358
|
+
|
359
|
+
def default_attributes # default valus are taken from order.java
|
360
|
+
# public Order() { }
|
361
|
+
super.merge(
|
362
|
+
:active_start_time => "", # order.java # 470 # Vers 69
|
363
|
+
:active_stop_time => "", #order.java # 471 # Vers 69
|
364
|
+
:algo_strategy => '',
|
365
|
+
:algo_id => '' , # order.java # 495
|
366
|
+
:auction_strategy => :none,
|
367
|
+
:conditions => [],
|
368
|
+
:continuous_update => 0,
|
369
|
+
:designated_location => '', # order.java # 487
|
370
|
+
:display_size => 0,
|
371
|
+
:discretionary_amount => 0,
|
372
|
+
:etrade_only => true, # stolen from python client
|
373
|
+
:exempt_code => -1,
|
374
|
+
:ext_operator => '' , # order.java # 499
|
375
|
+
:firm_quote_only => true, # stolen from python client
|
376
|
+
:not_held => false, # order.java # 494
|
377
|
+
:oca_type => :none,
|
378
|
+
:order_type => :limit,
|
379
|
+
:open_close => :open, # order.java #
|
380
|
+
:opt_out_smart_routing => false,
|
381
|
+
:origin => :customer,
|
382
|
+
:outside_rth => false, # order.java # 472
|
383
|
+
:parent_id => 0,
|
384
|
+
:random_size => false, #oder.java 497 # Vers 76
|
385
|
+
:random_price => false, # order.java # 498 # Vers 76
|
386
|
+
:scale_auto_reset => false, # order.java # 490
|
387
|
+
:scale_random_percent => false, # order.java # 491
|
388
|
+
:scale_table => "", # order.java # 492
|
389
|
+
:short_sale_slot => :default,
|
390
|
+
:solicided => false, # order.java # 496
|
391
|
+
:tif => :day,
|
392
|
+
:transmit => true,
|
393
|
+
:trigger_method => :default,
|
394
|
+
:what_if => false, # order.java # 493
|
395
|
+
:leg_prices => [],
|
396
|
+
:algo_params => Hash.new, #{},
|
397
|
+
:combo_params =>[], #{},
|
398
|
+
# :soft_dollar_tier_params => HashWithIndifferentAccess.new(
|
399
|
+
# :name => "",
|
400
|
+
# :val => "",
|
401
|
+
# :display_name => ''),
|
402
|
+
:order_state => IB::OrderState.new(:status => 'New',
|
403
|
+
:filled => 0,
|
404
|
+
:remaining => 0,
|
405
|
+
:price => 0,
|
406
|
+
:average_price => 0)
|
407
|
+
) # closing of merge
|
408
|
+
end
|
409
|
+
|
410
|
+
|
411
|
+
=begin rdoc
|
412
|
+
Format of serialisation
|
413
|
+
|
414
|
+
count of records
|
415
|
+
for each condition: conditiontype, condition-fields
|
416
|
+
=end
|
417
|
+
def serialize_conditions
|
418
|
+
if conditions.empty?
|
419
|
+
0
|
420
|
+
else
|
421
|
+
[ conditions.count ] + conditions.map( &:serialize )+ [ conditions_ignore_rth, conditions_cancel_order]
|
422
|
+
end
|
423
|
+
end
|
424
|
+
|
425
|
+
def serialize_algo
|
426
|
+
if algo_strategy.nil? || algo_strategy.empty?
|
427
|
+
[algo_strategy, algo_id] # just omit the size and content-field
|
428
|
+
else
|
429
|
+
[algo_strategy,
|
430
|
+
algo_params.size,
|
431
|
+
algo_params.to_a,
|
432
|
+
algo_id ] # Vers 71
|
433
|
+
end
|
434
|
+
end
|
435
|
+
|
436
|
+
# def serialize_soft_dollar_tier
|
437
|
+
# [soft_dollar_tier_params[:name],soft_dollar_tier_params[:val]]
|
438
|
+
# end
|
439
|
+
|
440
|
+
# def initialize_soft_dollar_tier *fields
|
441
|
+
# self.soft_dollar_tier_params= HashWithIndifferentAccess.new(
|
442
|
+
# name: fields.pop, val: fields.pop, display_name: fields.pop )
|
443
|
+
# end
|
444
|
+
|
445
|
+
def serialize_misc_options
|
446
|
+
"" # Vers. 70
|
447
|
+
end
|
448
|
+
# Placement
|
449
|
+
#
|
450
|
+
# The Order is only placed, if local_id is not set
|
451
|
+
#
|
452
|
+
# Modifies the Order-Object and returns the assigned local_id
|
453
|
+
def place the_contract=nil, connection=nil
|
454
|
+
connection ||= IB::Connection.current
|
455
|
+
error "Unable to place order, next_local_id not known" unless connection.next_local_id
|
456
|
+
error "local_id present. Order is already placed. Do you want to modify?" unless local_id.nil?
|
457
|
+
self.client_id = connection.client_id
|
458
|
+
self.local_id = connection.next_local_id
|
459
|
+
connection.next_local_id += 1
|
460
|
+
self.placed_at = Time.now
|
461
|
+
modify the_contract, connection, self.placed_at
|
462
|
+
end
|
463
|
+
|
464
|
+
# Modify Order (convenience wrapper for send_message :PlaceOrder). Returns local_id.
|
465
|
+
def modify the_contract=nil, connection=nil, time=Time.now
|
466
|
+
error "Unable to modify order; local_id not specified" if local_id.nil?
|
467
|
+
self.contract = the_contract unless the_contract.nil?
|
468
|
+
connection ||= IB::Connection.current
|
469
|
+
self.modified_at = time
|
470
|
+
connection.send_message :PlaceOrder,
|
471
|
+
:order => self,
|
472
|
+
:contract => contract,
|
473
|
+
:local_id => local_id
|
474
|
+
local_id
|
475
|
+
end
|
476
|
+
|
477
|
+
# Order comparison
|
478
|
+
def == other
|
479
|
+
super(other) ||
|
480
|
+
other.is_a?(self.class) &&
|
481
|
+
(perm_id && other.perm_id && perm_id == other.perm_id ||
|
482
|
+
local_id == other.local_id && # ((p __LINE__)||true) &&
|
483
|
+
(client_id == other.client_id || client_id == 0 || other.client_id == 0) &&
|
484
|
+
parent_id == other.parent_id &&
|
485
|
+
tif == other.tif &&
|
486
|
+
action == other.action &&
|
487
|
+
order_type == other.order_type &&
|
488
|
+
total_quantity == other.total_quantity &&
|
489
|
+
limit_price == other.limit_price &&
|
490
|
+
aux_price == other.aux_price &&
|
491
|
+
origin == other.origin &&
|
492
|
+
designated_location == other.designated_location &&
|
493
|
+
exempt_code == other.exempt_code &&
|
494
|
+
what_if == other.what_if &&
|
495
|
+
algo_strategy == other.algo_strategy &&
|
496
|
+
algo_params == other.algo_params)
|
497
|
+
|
498
|
+
# TODO: compare more attributes!
|
499
|
+
end
|
500
|
+
|
501
|
+
def to_s #human
|
502
|
+
"<Order:" + instance_variables.map do |key|
|
503
|
+
value = instance_variable_get(key)
|
504
|
+
" #{key}=#{value}" unless value.nil? || value == '' || value == 0
|
505
|
+
end.compact.join(',') + " >"
|
506
|
+
end
|
507
|
+
|
508
|
+
def to_human
|
509
|
+
"<Order: " + (order_ref.present? ? order_ref.to_s : '') +
|
510
|
+
"#{self[:order_type]} #{self[:tif]} #{action} #{total_quantity} " + " @ " +
|
511
|
+
(limit_price ? "#{limit_price} " : '') + "#{status} " +
|
512
|
+
((aux_price && aux_price != 0) ? "/#{aux_price}" : '') +
|
513
|
+
"##{local_id}/#{perm_id} from #{client_id}" +
|
514
|
+
(account ? "/#{account}" : '') +
|
515
|
+
(commission ? " fee #{commission}" : '') + ">"
|
516
|
+
end
|
517
|
+
|
518
|
+
end # class Order
|
519
|
+
end # module IB
|