ib-ruby / ib-api

Lightweight Ruby interface to Interactive Brokers' TWS API
https://ib-ruby.github.io/ib-api/
GNU General Public License v3.0
18 stars 9 forks source link

problem with grains options prices #11

Closed JothamB closed 3 years ago

JothamB commented 3 years ago

`#!/usr/bin/env ruby

require "ib-api" require "pry-nav"

ib = IB::Connection.new(:port => 7497, :client_id => 1) do |gw| gw.subscribe(:Alert) {|msg| puts msg.to_human} gw.subscribe(:MarketDataType, :TickRequestParameters, :TickPrice, :TickSize, :TickString, :TickGeneric, :TickOption) do |msg| puts "#{msg.created_at}\t#{msg.data[:ticker_id]}\t#{msg.data}" if msg.data[:tick_type] == 1 || msg.data[:tick_type] == 2 end gw.subscribe(:TickSnapshotEnd) {} end

contracts = Array.new (500..580).step(5).each do |strike| contracts.push IB::Option.new(sec_type: "FOP", symbol: "ZC", exchange: "ECBOT", trading_class: "OZC", expiry: "20210219", strike: strike, right: "C") contracts.push IB::Option.new(sec_type: "FOP", symbol: "ZC", exchange: "ECBOT", trading_class: "OZC", expiry: "20210326", strike: strike, right: "C") end loop do contracts.each {|contract| ib.send_message(:RequestMarketData, contract: contract, snapshot: 1)} sleep 5 end`

this code requests some ZC options prices every 5 seconds and prints the api messages. it works well. output example:

2021-01-29 08:21:15 -0500 7658 {:version=>6, :ticker_id=>7658, :tick_type=>1, :price=>6.25, :size=>1, :can_auto_execute=>1} 2021-01-29 08:21:15 -0500 7658 {:version=>6, :ticker_id=>7658, :tick_type=>2, :price=>6.625, :size=>384, :can_auto_execute=>1} 2021-01-29 08:21:15 -0500 9260 {:version=>6, :ticker_id=>9260, :tick_type=>1, :price=>52.125, :size=>171, :can_auto_execute=>1} 2021-01-29 08:21:15 -0500 9260 {:version=>6, :ticker_id=>9260, :tick_type=>2, :price=>53.25, :size=>171, :can_auto_execute=>1} 2021-01-29 08:21:15 -0500 6721 {:version=>6, :ticker_id=>6721, :tick_type=>1, :price=>48.75, :size=>171, :can_auto_execute=>1} 2021-01-29 08:21:15 -0500 6721 {:version=>6, :ticker_id=>6721, :tick_type=>2, :price=>50.0, :size=>171, :can_auto_execute=>1} 2021-01-29 08:21:15 -0500 9771 {:version=>6, :ticker_id=>9771, :tick_type=>1, :price=>45.5, :size=>191, :can_auto_execute=>1} 2021-01-29 08:21:15 -0500 9771 {:version=>6, :ticker_id=>9771, :tick_type=>2, :price=>46.5, :size=>1, :can_auto_execute=>1} 2021-01-29 08:21:15 -0500 4158 {:version=>6, :ticker_id=>4158, :tick_type=>1, :price=>42.625, :size=>204, :can_auto_execute=>1} 2021-01-29 08:21:15 -0500 4158 {:version=>6, :ticker_id=>4158, :tick_type=>2, :price=>43.5, :size=>235, :can_auto_execute=>1} 2021-01-29 08:21:15 -0500 4268 {:version=>6, :ticker_id=>4268, :tick_type=>1, :price=>39.75, :size=>188, :can_auto_execute=>1} 2021-01-29 08:21:15 -0500 4268 {:version=>6, :ticker_id=>4268, :tick_type=>2, :price=>40.5, :size=>1, :can_auto_execute=>1} 2021-01-29 08:21:15 -0500 805 {:version=>6, :ticker_id=>805, :tick_type=>1, :price=>37.0, :size=>195, :can_auto_execute=>1} 2021-01-29 08:21:15 -0500 805 {:version=>6, :ticker_id=>805, :tick_type=>2, :price=>37.75, :size=>1, :can_auto_execute=>1}

however, when i increase the time interval between api requests there is a problem with the rounding and the output is wrong and unusable. i changed the sleep interval from 5 to 30 seconds and the output was like:

2021-01-29 08:26:31 -0500 2872 {:version=>6, :ticker_id=>2872, :tick_type=>2, :price=>25.0, :size=>223, :can_auto_execute=>1} 2021-01-29 08:26:31 -0500 1824 {:version=>6, :ticker_id=>1824, :tick_type=>1, :price=>50.0, :size=>90, :can_auto_execute=>1} 2021-01-29 08:26:31 -0500 1824 {:version=>6, :ticker_id=>1824, :tick_type=>2, :price=>50.0, :size=>1, :can_auto_execute=>1} 2021-01-29 08:26:31 -0500 7159 {:version=>6, :ticker_id=>7159, :tick_type=>1, :price=>37.5, :size=>205, :can_auto_execute=>1} 2021-01-29 08:26:31 -0500 7159 {:version=>6, :ticker_id=>7159, :tick_type=>2, :price=>50.0, :size=>156, :can_auto_execute=>1} 2021-01-29 08:26:31 -0500 3167 {:version=>6, :ticker_id=>3167, :tick_type=>1, :price=>37.5, :size=>139, :can_auto_execute=>1} 2021-01-29 08:26:31 -0500 3167 {:version=>6, :ticker_id=>3167, :tick_type=>2, :price=>37.5, :size=>264, :can_auto_execute=>1} 2021-01-29 08:26:31 -0500 3485 {:version=>6, :ticker_id=>3485, :tick_type=>1, :price=>37.5, :size=>191, :can_auto_execute=>1} 2021-01-29 08:26:31 -0500 3485 {:version=>6, :ticker_id=>3485, :tick_type=>2, :price=>37.5, :size=>100, :can_auto_execute=>1} 2021-01-29 08:26:31 -0500 9547 {:version=>6, :ticker_id=>9547, :tick_type=>1, :price=>37.5, :size=>209, :can_auto_execute=>1} 2021-01-29 08:26:31 -0500 9547 {:version=>6, :ticker_id=>9547, :tick_type=>2, :price=>37.5, :size=>288, :can_auto_execute=>1} 2021-01-29 08:26:31 -0500 3196 {:version=>6, :ticker_id=>3196, :tick_type=>1, :price=>25.0, :size=>101, :can_auto_execute=>1} 2021-01-29 08:26:31 -0500 3196 {:version=>6, :ticker_id=>3196, :tick_type=>2, :price=>25.0, :size=>101, :can_auto_execute=>1} 2021-01-29 08:26:31 -0500 8482 {:version=>6, :ticker_id=>8482, :tick_type=>1, :price=>25.0, :size=>232, :can_auto_execute=>1} 2021-01-29 08:26:31 -0500 8482 {:version=>6, :ticker_id=>8482, :tick_type=>2, :price=>25.0, :size=>191, :can_auto_execute=>1} 2021-01-29 08:26:31 -0500 5105 {:version=>6, :ticker_id=>5105, :tick_type=>1, :price=>25.0, :size=>231, :can_auto_execute=>1} 2021-01-29 08:26:31 -0500 5105 {:version=>6, :ticker_id=>5105, :tick_type=>2, :price=>25.0, :size=>151, :can_auto_execute=>1} 2021-01-29 08:26:31 -0500 9929 {:version=>6, :ticker_id=>9929, :tick_type=>1, :price=>25.0, :size=>201, :can_auto_execute=>1} 2021-01-29 08:26:31 -0500 9929 {:version=>6, :ticker_id=>9929, :tick_type=>2, :price=>25.0, :size=>269, :can_auto_execute=>1} 2021-01-29 08:26:31 -0500 1042 {:version=>6, :ticker_id=>1042, :tick_type=>1, :price=>25.0, :size=>193, :can_auto_execute=>1} 2021-01-29 08:26:31 -0500 1042 {:version=>6, :ticker_id=>1042, :tick_type=>2, :price=>25.0, :size=>51, :can_auto_execute=>1}

this problem seems to occur only with grains options. i tested stocks options and currencies futures options and it was good.

topofocus commented 3 years ago

I suggest to reduce complexity. Turn off the received-array. Second: separate the subscription part .

ib = IB::Connection.new port: 7497,  received:  true 
ib.subscribe(:Alert) {|msg| puts msg.to_human}
ib.subscribe(:MarketDataType, :TickRequestParameters, :TickPrice, :TickSize, :TickString, :TickGeneric, :TickOption) do |msg|
   puts "#{msg.created_at}\t#{msg.data[:ticker_id]}\t#{msg.data}" if [:bid_price, :ask_price].include? IB::TICK_TYPES[msg.data[:tick_type]]
end
ib.subscribe(:TickSnapshotEnd) {}

any change?

However, you might use Contract#market_price with minor adjustments. It uses a threaded approach. Then you get comparable data.

ib-extensions, there bin -> console t

o=IB::Option.new(sec_type: "FOP", symbol: "ZC", exchange: "ECBOT", trading_class: "OZC", expiry: "20210219
", right: "C")
oo = o.verify  # gets any strike
op=oo.map{ |o| o.market_price(thread: true)}.join  #  oo is modified!!
pp oo.bars 
--> [ ...
 [{:close=>124.625, :last=>135.0, :bid=>127.625, :ask=>128.25}],
 [{:last=>123.25, :close=>114.75, :bid=>117.625, :ask=>118.25}],
 [{:close=>104.75, :last=>114.0, :bid=>107.75, :ask=>108.25}],
 [{:close=>94.875, :last=>98.75, :bid=>97.875, :ask=>98.375}],
 .. ]

Its designed for EOD-Data. You may have to modify it for intraday-data requests, but works most probably. Ensure to work with a new copy of contracts each time as they are modified in the threaded-mode of market_price. contract.verify returns a fresh valid set of contracts

topofocus commented 3 years ago

Just recognized:

o=IB::Option.new(sec_type: "FOP", symbol: "ZC", exchange: "ECBOT", trading_class: "OZC", expiry: "20210219
", right: "C")

sec_type was necessary because the subclass was not properly initialized.

just pushed a fix to ib-api.

Now

o=IB::FutureOption.new( symbol: "ZC", exchange: "ECBOT", trading_class: "OZC", expiry: "20210219", right: 
"C")
o.sec_type  => :futures_option 
o.verify.count => 99
topofocus commented 3 years ago

To test your task I found this code sufficient

o=IB::FutureOption.new( symbol: "ZC", exchange: "ECBOT", trading_class: "OZC", expiry: "20210219", right: 
"C")
oo=o.verify{|c| c if (500 .. 600).include?( c.strike.to_i) }.compact
(1..50).each do 
  op=oo.map{ |o| o.market_price(thread: true)}.join
  sleep 30
end

Then the results should be present in oo.bars. Perhaps the bars property should be extended by the transmitted datetime.

Actually, `Contract.market_price' adds subsequent bars to the array if called periodically. Thus you can test, if the unexpected behavior is a serious matter.

Have you considered writing an integration-test for it?

JothamB commented 3 years ago

maybe im missing something.

when i try to define: c = IB::FutureOption.new(symbol: "ZC", exchange: "ECBOT", trading_class: "OZC", expiry: "20210423", strike: 550.0, right: "C") i get: TWS Error 200: No security definition has been found for the request

when i try to call: c.market_price i get: undefined methodmarket_price' for # (NoMethodError)`

topofocus commented 3 years ago

OK. I only pushed the FOP update to the master-branch of ib-api. just pull the last version from the respiratory You need the ib-extensions gem, modify the gemfile there

gemspec
gem "ib-api",   path: "../ib-api/"

(assumed you cloned ib-extensions to the same dir then ib-api)

Then open the console in the bin dir. (check console.yml first)

JothamB commented 3 years ago

it didnt work :(

i uninstalled ib-api. then i cloned the latest version of ib-api ib-symbols and ib-extensions from the repository and installed.

i ran this code:

`c = IB::FutureOption.new(symbol: "ZC", exchange: "ECBOT", trading_class: "OZC", expiry: "20210423", strike: 550.0, right: "C")

loop do

c = (c.verify)[0]

c.market_price(thread: true)

sleep 2

end`

and that was the output:

2021-02-02 11:33:11 -0500 3044 {:version=>6, :ticker_id=>3044, :tick_type=>1, :price=>32.375, :size=>99, :can_auto_execute=>0} 2021-02-02 11:33:11 -0500 3044 {:version=>6, :ticker_id=>3044, :tick_type=>2, :price=>32.75, :size=>1, :can_auto_execute=>0} 2021-02-02 11:33:12 -0500 5684 {:version=>6, :ticker_id=>5684, :tick_type=>1, :price=>37.5, :size=>89, :can_auto_execute=>1} 2021-02-02 11:33:12 -0500 5684 {:version=>6, :ticker_id=>5684, :tick_type=>2, :price=>37.5, :size=>124, :can_auto_execute=>1} 2021-02-02 11:33:14 -0500 3311 {:version=>6, :ticker_id=>3311, :tick_type=>1, :price=>37.5, :size=>47, :can_auto_execute=>1} 2021-02-02 11:33:14 -0500 3311 {:version=>6, :ticker_id=>3311, :tick_type=>2, :price=>37.5, :size=>175, :can_auto_execute=>1} 2021-02-02 11:33:16 -0500 9543 {:version=>6, :ticker_id=>9543, :tick_type=>1, :price=>37.5, :size=>99, :can_auto_execute=>1} 2021-02-02 11:33:16 -0500 9543 {:version=>6, :ticker_id=>9543, :tick_type=>2, :price=>37.5, :size=>4, :can_auto_execute=>1} 2021-02-02 11:33:19 -0500 7076 {:version=>6, :ticker_id=>7076, :tick_type=>1, :price=>37.5, :size=>99, :can_auto_execute=>1} 2021-02-02 11:33:19 -0500 7076 {:version=>6, :ticker_id=>7076, :tick_type=>2, :price=>37.5, :size=>1, :can_auto_execute=>1} 2021-02-02 11:33:20 -0500 3554 {:version=>6, :ticker_id=>3554, :tick_type=>1, :price=>37.5, :size=>239, :can_auto_execute=>1} 2021-02-02 11:33:20 -0500 3554 {:version=>6, :ticker_id=>3554, :tick_type=>2, :price=>37.5, :size=>1, :can_auto_execute=>1}

i get correct data for the first iteration and then it breaks.

when you run this code to print grains futures option quotes do you get correct output ?

topofocus commented 3 years ago
3.0.0 :015 > o=IB::FutureOption.new( symbol: "ZC", exchange: "ECBOT", trading_class: "OZC", expiry: "20210219", right: 
"C")
 => #<IB::FutureOption:0x00007f1a54017168 @attributes={:symbol=>"ZC", :exchange=>"ECBOT", :trading_class=>"OZC", ... 
3.0.0 :016 > oo=o.verify{|c| c if (500 .. 600).include?( c.strike.to_i) }.compact
3.0.0 :017 >op=oo.map{ |o| o.market_price(thread: true)}.join 
3.0.0 :018 > puts oo.bars
{:bid=>44.375, :ask=>44.875, :last=>45.25, :close=>51.75}
{:bid=>36.0, :ask=>36.5, :last=>38.75, :close=>43.25}
{:bid=>28.75, :ask=>29.0, :last=>28.75, :close=>35.625}
{:bid=>22.25, :ask=>22.5}
{:bid=>16.875, :ask=>17.25, :last=>19.0, :close=>23.0}
{:bid=>12.625, :ask=>12.875, :close=>18.0, :last=>12.625}
{:bid=>9.25, :ask=>9.5, :last=>9.5, :close=>13.875}
{:bid=>6.75, :ask=>6.875, :last=>7.0, :close=>10.625}
{:bid=>4.75, :ask=>5.0, :close=>7.875, :last=>4.875}
{:bid=>3.375, :ask=>3.625, :last=>3.5, :close=>5.875}
{:bid=>2.5, :ask=>2.625, :close=>4.375, :last=>2.625}
{:bid=>25.375, :ask=>25.625, :close=>32.125, :last=>27.875}
{:bid=>19.5, :ask=>19.75, :last=>0.0, :close=>25.875}
{:bid=>40.125, :ask=>40.5, :last=>0.0, :close=>47.375}
{:bid=>32.25, :ask=>32.625, :last=>33.125, :close=>39.375}
{:bid=>14.625, :ask=>15.0, :last=>16.0, :close=>20.375}
{:bid=>10.875, :ask=>11.125, :close=>15.75, :last=>0.0}
{:bid=>8.0, :ask=>8.125, :close=>12.0, :last=>8.5}
{:bid=>5.75, :ask=>5.875}
{:bid=>4.0, :ask=>4.25}
{:bid=>2.875, :ask=>3.0}
3.0.0 :019> op=oo.map{ |o| o.market_price(thread: true)}.join 
3.0.0 :020> puts oo.bars
{:bid=>44.375, :ask=>44.875, :last=>45.25, :close=>51.75}{}
{:bid=>36.0, :ask=>36.5, :last=>38.75, :close=>43.25}{}
{:bid=>28.75, :ask=>29.0, :last=>28.75, :close=>35.625}
{:last=>28.75, :close=>35.625, :bid=>28.625, :ask=>29.0}{:bid=>22.25, :ask=>22.5}{}
{:bid=>16.875, :ask=>17.25, :last=>19.0, :close=>23.0}{}
{:bid=>12.625, :ask=>12.875, :close=>18.0, :last=>12.625}{}
{:bid=>9.25, :ask=>9.5, :last=>9.5, :close=>13.875}{}
{:bid=>6.75, :ask=>6.875, :last=>7.0, :close=>10.625}{}
{:bid=>4.75, :ask=>5.0, :close=>7.875, :last=>4.875}{}
{:bid=>3.375, :ask=>3.625, :last=>3.5, :close=>5.875}{}
{:bid=>2.5, :ask=>2.625, :close=>4.375, :last=>2.625}{}
{:bid=>25.375, :ask=>25.625, :close=>32.125, :last=>27.875}{}
{:bid=>19.5, :ask=>19.75, :last=>0.0, :close=>25.875}{}
{:bid=>40.125, :ask=>40.5, :last=>0.0, :close=>47.375}{}
{:bid=>32.25, :ask=>32.625, :last=>33.125, :close=>39.35}{}
{:bid=>14.625, :ask=>15.0, :last=>16.0, :close=>20.375}{}
{:bid=>10.875, :ask=>11.125, :close=>15.75, :last=>0.0}{}
{:bid=>8.0, :ask=>8.125, :close=>12.0, :last=>8.5}{}
{:bid=>5.75, :ask=>5.875}{}
{:bid=>4.0, :ask=>4.25}{}
{:bid=>2.875, :ask=>3.0}{}

It works on principle, most probably due to missing data-subscriptions I do not get correct data in subsequent calls.

Now

3.0.0 :001 > c = IB::FutureOption.new(symbol: "ZC", exchange: "ECBOT", trading_class: "OZC", expiry: "20210423", strike
: 550.0, right: "C")
 => #<IB::FutureOption:0x0000000003a13b70 @attributes={:symbol=>"ZC", :exchange=>"ECBOT", :trading_class=>"OZC", ... 
3.0.0 :002 > (1..10).each{ c.market_price; sleep 5 }

3.0.0 :004 > c.bars
 => [{:bid=>30.75, :ask=>31.125, :close=>36.625, :last=>31.5}, {}, {}, {}, {}, {}, {}, {}, {}, {}] 

As suspected: only one price is grabbed But a subsequent call confirms my suspicion:

3.0.0 :005 > d = IB::FutureOption.new(symbol: "ZC", exchange: "ECBOT", trading_class: "OZC", expiry: "20210423", strike
: 550.0, right: "C")
 => #<IB::FutureOption:0x0000000003c72650 @attributes={:symbol=>"ZC", :exchange=>"ECBOT", :trading_class=>"OZC", ... 
3.0.0 :006 > d.market_price
No subscribers for message IB::Messages::Incoming::TickRequestParameters!
TWS Warning 10090: Part of requested market data is not subscribed. Subscription-independent ticks are still active.Delayed market data is available.ZC MAY'21/TOP/ALL
No subscribers for message IB::Messages::Incoming::MarketDataType!
TWS Warning 10167: Requested market data is not subscribed. Displaying delayed market data.
No subscribers for message IB::Messages::Incoming::TickOption!

No subscribers for message IB::Messages::Incoming::TickOption!
No subscribers for message IB::Messages::Incoming::TickOption!
No subscribers for message IB::Messages::Incoming::TickOption!
 => nil 
3.0.0 :007 > 
3.0.0 :008 > d.bars
 => [{}] 

Further data are not transmitted

3.0.0 :012 > s =  Symbols::Stocks.msft
 => #<IB::Stock:0x000000000390e5b8 @attributes={:symbol=>"MSFT", :primary_exchange=>"ISLAND", :created_at=>2021-0... 
3.0.0 :012 > (1..10).each{ s.market_price; sleep 5 }
 => 1..10 
3.0.0 :013 > s.bars
 => [{:bid=>239.6, :ask=>239.63, :last=>239.62, :close=>239.65}, {:bid=>239.64, :ask=>239.67, :last=>239.67, :close=>239.65}, {:bid=>239.67, :ask=>239.68, :last=>239.68, :close=>239.65}, {:bid=>239.67, :ask=>239.68, :last=>239.65, :close=>239.65}, {:bid=>239.64, :ask=>239.66, :last=>239.65, :close=>239.65}, {:bid=>239.69, :ask=>239.71, :last=>239.69, :close=>239.65}, {:bid=>239.69, :ask=>239.71, :last=>239.69, :close=>239.65}, {:bid=>239.66, :ask=>239.68, :last=>239.65, :close=>239.65}, {:bid=>239.66, :ask=>239.68, :last=>239.65, :close=>239.65}, {:bid=>239.67, :ask=>239.68, :last=>239.68, :close=>239.65

Thus, its not a problem of ib-ruby.

JothamB commented 3 years ago

i got the problem. the api returns wrong data (25.0, 37.5 etc) if the tws view is on other contract. when i open the option in the tws i get a stream of correct data. interestingly, after changing the tws view to other contract the stream of correct data persists and doesnt corrupt. build 978.2l

which brings up some interesting questions: why does it happen ? why does it happen only with grains options ? is this a cross-language issue ? will tws send wrong data to python java c# etc apis ?

i want to dig deep into it. where in the code the api reads the crud data out of tws ? where should i put the "binding.pry" to debug it ?

topofocus commented 3 years ago

You can print raw -data by removing comments in `lib(ib/incoming/abstract_message' , row 38 (ib-api)

If you want to dig further, there is a similar entry-point in socket.rb, where you can inspect the low-level api-data.

This is the expected output

3.0.0 :001 > d = IB::FutureOption.new(symbol: "ZC", exchange: "ECBOT", trading_class: "OZC", expiry: "20210423", strike
: 550.0, right: "C")
 => #<IB::FutureOption:0x0000000002c54520 @attributes={:symbol=>"ZC", :exchange=>"ECBOT", :trading_class=>"OZC", ... 
3.0.0 :002 > d.market_price
BUFFER :> ["1", "5168", "3"] 
No subscribers for message IB::Messages::Incoming::MarketDataType!
BUFFER :> ["2", "5168", "10167", "Requested market data is not subscribed. Displaying delayed market data."] 
TWS Warning 10167: Requested market data is not subscribed. Displaying delayed market data.
BUFFER :> ["5168", "0.00125", "bf0004", "4"] 
No subscribers for message IB::Messages::Incoming::TickRequestParameters!
BUFFER :> ["6", "5168", "68", "31.750", "10", "0"] 
BUFFER :> ["6", "5168", "88", "1612292670"] 
No subscribers for message IB::Messages::Incoming::TickString!
BUFFER :> ["6", "5168", "72", "35.875", "0", "0"] 
BUFFER :> ["6", "5168", "73", "31.375", "0", "0"] 
BUFFER :> ["6", "5168", "74", "3539"] 
No subscribers for message IB::Messages::Incoming::TickSize!
BUFFER :> ["6", "5168", "75", "36.625", "0", "0"] 
BUFFER :> ["2", "5168", "10090", "Part of requested market data is not subscribed. Subscription-independent ticks are still active.Delayed market data is available.ZC MAY'21/TOP/ALL"] 
TWS Warning 10090: Part of requested market data is not subscribed. Subscription-independent ticks are still active.Delayed market data is available.ZC MAY'21/TOP/ALL
BUFFER :> ["6", "5168", "83", "0.3464589959663948", "0.49644261633131825", "0.31499127519273046", "0.0", "0.45523811725005237", "0.01013067090107761", "-0.0021973297211928134", "5.42"] 
No subscribers for message IB::Messages::Incoming::TickOption!
BUFFER :> ["6", "5168", "82", "0.3478693451144887", "0.4965860632081808", "0.3174999952316284", "0.0", "0.4531504884636884", "0.010130393005636062", "-0.00220629685077518", "5.42"] 
No subscribers for message IB::Messages::Incoming::TickOption!
BUFFER :> ["6", "5168", "66", "-100.000", "0", "0"] 
BUFFER :> ["6", "5168", "67", "-100.000", "0", "0"] 
 => 31.75 
3.0.0 :003 > BUFFER :> ["6", "5168", "80", "-1", "-2", "-1", "0.0", "-2", "-2", "-2", "5.42"] 
No subscribers for message IB::Messages::Incoming::TickOption!
BUFFER :> ["6", "5168", "81", "-1", "-2", "-1", "0.0", "-2", "-2", "-2", "5.42"] 
No subscribers for message IB::Messages::Incoming::TickOption!
BUFFER :> ["1", "5168"] 
No subscribers for message IB::Messages::Incoming::TickSnapshotEnd!
JothamB commented 3 years ago

you are right. the problem starts from the raw data:

BUFFER:: "\x00\x00\x00\x161\x006\x005118\x004\x0034.000\x004\x000\x00" BUFFER:: "\x00\x00\x00\x0E2\x006\x005118\x008\x0064\x00\x00\x00\x00\x161\x006\x005118\x006\x0034.000\x000\x000\x00\x00\x00\x00\x161\x006\x005118\x007\x0033.250\x000\x000\x00\x00\x00\x00\x161\x006\x005118\x009\x0033.625\x000\x000\x00" BUFFER:: "\x00\x00\x00\x9021\x006\x005118\x0013\x000.33635411420623157\x000.5356850703928409\x000.34651328215819094\x000.0\x000.46566777895949146\x000.01012010128282348\x00-0.0021892866432574377\x005.51\x00\x00\x00\x00\x8E21\x006\x005118\x0010\x000.3326121171393609\x000.5352473430796741\x000.3449999988079071\x000.0\x000.4706766089317893\x000.010120792563770742\x00-0.0021650456809645387\x005.51\x00\x00\x00\x00\x8E21\x006\x005118\x0011\x000.33876846256476156\x000.535727905319348\x000.35249999165534973\x000.0\x000.4620799808545129\x000.010119651252230188\x00-0.002204924406219419\x005.51\x00\x00\x00\x00\x8F21\x006\x005118\x0012\x000.32991909172285533\x000.5350381054973323\x000.3400000035762787\x000.0\x000.47453754449177626\x000.010121285381394951\x00-0.002147597057582271\x005.51\x00\x00\x00\x00\n57\x001\x005118\x00" BUFFER:: "\x00\x00\x00\x1981\x006707\x000.00125\x00bf0004\x003\x00" BUFFER:: "\x00\x00\x00\f58\x001\x006707\x001\x00" BUFFER:: "\x00\x00\x00\x181\x006\x006707 \x001\x0037.500 \x00143\x001\x00" 2021-02-04 03:23:56 -0500 6707 {:version=>6, :ticker_id=>6707, :tick_type=>1, :price=>37.5, :size=>143, :can_auto_execute=>1} BUFFER:: "\x00\x00\x00\x161\x006\x006707 \x002\x0037.500 \x002\x001\x00\x00\x00\x00\x1846\x006\x006707\x0045\x001612406812\x00\x00\x00\x00\x161\x006\x006707\x004\x0034.000\x004\x000\x00" 2021-02-04 03:23:56 -0500 6707 {:version=>6, :ticker_id=>6707, :tick_type=>2, :price=>37.5, :size=>2, :can_auto_execute=>1}

so now what ?

how many layers are there between the tws and ib-api ? is it possible that this is a problem with all apis that relay on ib tws ? should i report an issue with interactive brokers ? is there anyone to talk with there ?

topofocus commented 3 years ago

Hi,

thanks for your forensic investigation.

First: we can fix this easily in the message-handler.

I want integrate this in the tests.

Its important to know, when and why such tickdata are transmitted.

Perhaps ask in the ib-api-forum?

you can reach me via signal: (germany) one seven six four seven nine three two six.

I guess its time to continue face 2 face

call me in the evening, if you like.

hartmut

topofocus commented 3 years ago

At last: the unexpected behavior occured when using a demo-account. On a »real« account, everything works as expected.