erdewit / ib_insync

Python sync/async framework for Interactive Brokers API
BSD 2-Clause "Simplified" License
2.81k stars 755 forks source link

"no security definition has been found" error for stocks obtained using positions() #140

Closed poori closed 5 years ago

poori commented 5 years ago

Hi

Firstly, thank you for creating and sharing this wonderful library. I'm relatively new to both python, async programming and IB and it has been incredibly easy and friendly to use.

I wanted to file a bug report as an FYI: I get a "no security definition has been found" error when qualifying contracts attached to positions obtained via ib.positions()

Minimal code to recreate issue:

Buy 10 NFLX Stock in trading account.

import ib_insync as IB
ib = IB.IB()
ib.connect('127.0.0.1', 7496, clientId=6)
positions = ib.positions() 
for position in positions:
    ib.qualifyContracts(position.contract)
Error 200, reqId 21: No security definition has been found for the request, contract: Stock(conId=15124833, symbol='NFLX', exchange='NASDAQ', currency='USD', localSymbol='NFLX', tradingClass='NMS')
Unknown contract: Stock(conId=15124833, symbol='NFLX', exchange='NASDAQ', currency='USD', localSymbol='NFLX', tradingClass='NMS')
Error 200, reqId 22: No security definition has been found for the request, contract: Stock(conId=15124833, symbol='NFLX', exchange='NASDAQ', currency='USD', localSymbol='NFLX', tradingClass='NMS')
Error 200, reqId 23: No security definition has been found for the request, contract: Stock(conId=15124833, symbol='NFLX', exchange='NASDAQ', currency='USD', localSymbol='NFLX', tradingClass='NMS')

Extracting the contract ID and creating a new contract and using that works fine, however. This is what i'm using as a workaround.

import ib_insync as IB
ib = IB.IB()
ib.connect('127.0.0.1', 7496, clientId=6)
positions = ib.positions() 
for position in positions:
    contract_with_only_id = IB.Contract(conId=position.contract.conId)
    ib.qualifyContracts(contract_with_only_id)

What also seems to work is removing the exchange information

c.exchange = ''
ib.qualifyContracts(c)

thanks!!

erdewit commented 5 years ago

This is an internal inconsistency on the IB side of things, were a contract as sent by IB is not valid for use with reqContractDetails.

In this case, simply do not qualify the position contracts since there is no need anyway.