• C#
  • Java
  • VB
  • C++
  • Python
Contact us
Market Scanners

Some scans in the TWS Advanced Market Scanner can be accessed via the TWS API through the IBApi.EClient.reqScannerSubscription.

  • client.reqScannerSubscription(7001, ScannerSubscriptionSamples.HighOptVolumePCRatioUSIndexes(), "", null);
    TagValue t1 = new TagValue("usdMarketCapAbove", "10000");
    TagValue t2 = new TagValue("optVolumeAbove", "1000");
    TagValue t3 = new TagValue("avgVolumeAbove", "100000000");
    List<TagValue> TagValues = new List<TagValue>{t1, t2, t3};
    client.reqScannerSubscription(7002, ScannerSubscriptionSamples.HotUSStkByVolume(), null, TagValues); // requires TWS v973+
  • client.reqScannerSubscription(7001, ScannerSubscriptionSamples.HighOptVolumePCRatioUSIndexes(), null, null);
    TagValue t1 = new TagValue("usdMarketCapAbove", "10000");
    TagValue t2 = new TagValue("optVolumeAbove", "1000");
    TagValue t3 = new TagValue("avgVolumeAbove", "100000000");
    List<TagValue> TagValues = Arrays.asList(t1, t2, t3);
    client.reqScannerSubscription(7002, ScannerSubscriptionSamples.HotUSStkByVolume(), null, TagValues); // requires TWS v973+
  • client.reqScannerSubscription(7001, ScannerSubscriptionSamples.HighOptVolumePCRatioUSIndexes(), "", Nothing)
    Dim TagValues As List(Of IBApi.TagValue) = New List(Of TagValue)
    TagValues.Add(New TagValue("usdMarketCapAbove", "10000"))
    TagValues.Add(New TagValue("optVolumeAbove", "1000"))
    TagValues.Add(New TagValue("avgVolumeAbove", "100000000"))
    client.reqScannerSubscription(7002, ScannerSubscriptionSamples.HotUSStkByVolume(), Nothing, TagValues) ' requires TWS v973+
  • m_pClient->reqScannerSubscription(7001, ScannerSubscriptionSamples::HotUSStkByVolume(), TagValueListSPtr(), TagValueListSPtr());
    TagValueSPtr t1(new TagValue("usdMarketCapAbove", "10000"));
    TagValueSPtr t2(new TagValue("optVolumeAbove", "1000"));
    TagValueSPtr t3(new TagValue("usdMarketCapAbove", "100000000"));
    TagValueListSPtr TagValues(new TagValueList());
    TagValues->push_back(t1);
    TagValues->push_back(t2);
    TagValues->push_back(t3);
    m_pClient->reqScannerSubscription(7002, ScannerSubscriptionSamples::HotUSStkByVolume(), TagValueListSPtr(), TagValues); // requires TWS v973+
  • 1  self.reqScannerSubscription(7001, ScannerSubscriptionSamples.HighOptVolumePCRatioUSIndexes(), [], [])
    2 
    3  # Generic Filters
    4  tagvalues = []
    5  tagvalues.append(TagValue("usdMarketCapAbove", "10000"))
    6  tagvalues.append(TagValue("optVolumeAbove", "1000"))
    7  tagvalues.append(TagValue("avgVolumeAbove", "10000"))
    8 
    9  self.reqScannerSubscription(7002, ScannerSubscriptionSamples.HotUSStkByVolume(), [], tagvalues) # requires TWS v973+

Available API filters and and parameters until TWS v973 and API v973.07 are defined in the IBApi.ScannerSubscription object, including [AbovePrice, BelowPrice, AboveVolume, ...] . Some Market Scanner Examples are listed at the bottom of this page.

Scans are limited to a maximum result of 50 results per scan code, and only 10 API scans can be active at a time.

Results are delivered via IBApi.EWrapper.scannerData and the IBApi.EWrapper.scannerDataEnd marker will indicate when all results have been delivered. The returned results to scannerData simply consist of a list of contracts. There are no market data fields (bid, ask, last, volume, ...) returned from the scanner, and so if these are desired they have to be requested separately with the reqMktData function. Since the scanner results do not include any market data fields, it is not necessary to have market data subscriptions to use the API scanner. However to use filters, market data subscriptions are generally required.

  • public class EWrapperImpl : EWrapper
    {
    ...
    public virtual void scannerData(int reqId, int rank, ContractDetails contractDetails, string distance, string benchmark, string projection, string legsStr)
    {
    Console.WriteLine("ScannerData. "+reqId+" - Rank: "+rank+", Symbol: "+contractDetails.Contract.Symbol+", SecType: "+contractDetails.Contract.SecType+", Currency: "+contractDetails.Contract.Currency
    +", Distance: "+distance+", Benchmark: "+benchmark+", Projection: "+projection+", Legs String: "+legsStr);
    }
    ...
    public virtual void scannerDataEnd(int reqId)
    {
    Console.WriteLine("ScannerDataEnd. "+reqId);
    }
  • public class EWrapperImpl implements EWrapper {
    ...
    @Override
    public void scannerData(int reqId, int rank, ContractDetails contractDetails, String distance, String benchmark, String projection, String legsStr) {
    System.out.println("ScannerData: " + EWrapperMsgGenerator.scannerData(reqId, rank, contractDetails, distance, benchmark, projection, legsStr));
    }
    ...
    @Override
    public void scannerDataEnd(int reqId) {
    System.out.println("ScannerDataEnd: " + EWrapperMsgGenerator.scannerDataEnd(reqId));
    }
  • Public Class EWrapperImpl
    Implements EWrapper
    ...
    Public Sub scannerData(reqId As Integer, rank As Integer, contractDetails As IBApi.ContractDetails, distance As String, benchmark As String, projection As String, legsStr As String) Implements IBApi.EWrapper.scannerData
    Console.WriteLine("ScannerData. " & reqId & " - Rank: " & rank & ", Symbol: " & contractDetails.Contract.Symbol & ", SecType: " &
    contractDetails.Contract.SecType & ", Currency: " & contractDetails.Contract.Currency & ", Distance: " & distance &
    ", Benchmark: " & benchmark & ", Projection: " & projection & ", Legs String: " & legsStr)
    End Sub
    ...
    Public Sub scannerDataEnd(reqId As Integer) Implements IBApi.EWrapper.scannerDataEnd
    Console.WriteLine("ScannerDataEnd. " & reqId & "\n")
    End Sub
  • class TestCppClient : public EWrapper
    {
    ...
    void TestCppClient::scannerData(int reqId, int rank, const ContractDetails& contractDetails,
    const std::string& distance, const std::string& benchmark, const std::string& projection,
    const std::string& legsStr) {
    printf( "ScannerData. %d - Rank: %d, Symbol: %s, SecType: %s, Currency: %s, Distance: %s, Benchmark: %s, Projection: %s, Legs String: %s\n", reqId, rank, contractDetails.contract.symbol.c_str(), contractDetails.contract.secType.c_str(), contractDetails.contract.currency.c_str(), distance.c_str(), benchmark.c_str(), projection.c_str(), legsStr.c_str());
    }
    ...
    void TestCppClient::scannerDataEnd(int reqId) {
    printf( "ScannerDataEnd. %d\n", reqId);
    }
  • 1 class TestWrapper(wrapper.EWrapper):
    ...
    1  def scannerData(self, reqId: int, rank: int, contractDetails: ContractDetails,
    2  distance: str, benchmark: str, projection: str, legsStr: str):
    3  super().scannerData(reqId, rank, contractDetails, distance, benchmark,
    4  projection, legsStr)
    5 # print("ScannerData. ReqId:", reqId, "Rank:", rank, "Symbol:", contractDetails.contract.symbol,
    6 # "SecType:", contractDetails.contract.secType,
    7 # "Currency:", contractDetails.contract.currency,
    8 # "Distance:", distance, "Benchmark:", benchmark,
    9 # "Projection:", projection, "Legs String:", legsStr)
    10  print("ScannerData. ReqId:", reqId, ScanData(contractDetails.contract, rank, distance, benchmark, projection, legsStr))
    ...
    1  def scannerDataEnd(self, reqId: int):
    2  super().scannerDataEnd(reqId)
    3  print("ScannerDataEnd. ReqId:", reqId)

Since the IBApi.EClient.reqScannerSubscription request keeps a subscription open you will keep receiving periodic updates until the request is cancelled via IBApi.EClient.cancelScannerSubscription :

  • client.cancelScannerSubscription(7001);
    client.cancelScannerSubscription(7002);
    client.cancelScannerSubscription(7003);
  • client.cancelScannerSubscription(7001);
    client.cancelScannerSubscription(7002);
    client.cancelScannerSubscription(7003);
  • client.cancelScannerSubscription(7001)
    client.cancelScannerSubscription(7002)
    client.cancelScannerSubscription(7003)
  • m_pClient->cancelScannerSubscription(7001);
    m_pClient->cancelScannerSubscription(7002);
  • 1  self.cancelScannerSubscription(7001)
    2  self.cancelScannerSubscription(7002)
    3  self.cancelScannerSubscription(7003)

Market Scanner Examples

With API v973.07 and TWS v973 and lower, the available API scans are the fields of the ScannerSubscription object, i.e. abovePrice, aboveVolume, belowPrice, etc. Beginning with the next version of the API (expected to be v973.08) and TWS v974, an extra parameter scannerSubscriptionFilterOptions has been added to the API to allow for generic filters. This field is entered as a list of TagValues which have a tag followed by its value, e.g. TagValue("usdMarketCapAbove", "10000") indicates a market cap above 10000 USD. Available filters can be found using the IBApi.EClient.reqScannerParameters function.

  • //Hot US stocks by volume
    ScannerSubscription scanSub = new ScannerSubscription();
    scanSub.Instrument = "STK";
    scanSub.LocationCode = "STK.US.MAJOR";
    scanSub.ScanCode = "HOT_BY_VOLUME";
    ...
    //Top % gainers at IBIS
    ScannerSubscription scanSub = new ScannerSubscription();
    scanSub.Instrument = "STOCK.EU";
    scanSub.LocationCode = "STK.EU.IBIS";
    scanSub.ScanCode = "TOP_PERC_GAIN";
    ...
    //Most active futures at EUREX
    ScannerSubscription scanSub = new ScannerSubscription();
    scanSub.Instrument = "FUT.EU";
    scanSub.LocationCode = "FUT.EU.EUREX";
    scanSub.ScanCode = "MOST_ACTIVE";
    ...
    //High option volume P/C ratio US indexes
    ScannerSubscription scanSub = new ScannerSubscription();
    scanSub.Instrument = "IND.US";
    scanSub.LocationCode = "IND.US";
    scanSub.ScanCode = "HIGH_OPT_VOLUME_PUT_CALL_RATIO";
  • //Hot US stocks by volume
    ScannerSubscription scanSub = new ScannerSubscription();
    scanSub.instrument("STK");
    scanSub.locationCode("STK.US.MAJOR");
    scanSub.scanCode("HOT_BY_VOLUME");
    ...
    //Top % gainers at IBIS
    ScannerSubscription scanSub = new ScannerSubscription();
    scanSub.instrument("STOCK.EU");
    scanSub.locationCode("STK.EU.IBIS");
    scanSub.scanCode("TOP_PERC_GAIN");
    ...
    //Most active futures at EUREX
    ScannerSubscription scanSub = new ScannerSubscription();
    scanSub.instrument("FUT.EU");
    scanSub.locationCode("FUT.EU.EUREX");
    scanSub.scanCode("MOST_ACTIVE");
    ...
    //High option volume P/C ratio US indexes
    ScannerSubscription scanSub = new ScannerSubscription();
    scanSub.instrument("IND.US");
    scanSub.locationCode("IND.US");
    scanSub.scanCode("HIGH_OPT_VOLUME_PUT_CALL_RATIO");
  • 'Hot US stocks by volume
    Dim scanSub As ScannerSubscription = New ScannerSubscription()
    scanSub.Instrument = "STK"
    scanSub.LocationCode = "STK.US.MAJOR"
    scanSub.ScanCode = "HOT_BY_VOLUME"
    ...
    'Top % gainers at IBIS
    Dim scanSub As ScannerSubscription = New ScannerSubscription()
    scanSub.Instrument = "STOCK.EU"
    scanSub.LocationCode = "STK.EU.IBIS"
    scanSub.ScanCode = "TOP_PERC_GAIN"
    ...
    'Most active futures at EUREX
    Dim scanSub As ScannerSubscription = New ScannerSubscription()
    scanSub.Instrument = "FUT.EU"
    scanSub.LocationCode = "FUT.EU.EUREX"
    scanSub.ScanCode = "MOST_ACTIVE"
    ...
    'High option volume P/C ratio US indexes
    Dim scanSub As ScannerSubscription = New ScannerSubscription()
    scanSub.Instrument = "IND.US"
    scanSub.LocationCode = "IND.US"
    scanSub.ScanCode = "HIGH_OPT_VOLUME_PUT_CALL_RATIO"
  • //Hot US stocks by volume
    ScannerSubscription scanSub;
    scanSub.instrument = "STK";
    scanSub.locationCode = "STK.US.MAJOR";
    scanSub.scanCode = "HOT_BY_VOLUME";
    ...
    //Top % gainers at IBIS
    ScannerSubscription scanSub;
    scanSub.instrument = "STOCK.EU";
    scanSub.locationCode = "STK.EU.IBIS";
    scanSub.scanCode = "TOP_PERC_GAIN";
    ...
    //Most active futures at EUREX
    ScannerSubscription scanSub;
    scanSub.instrument = "FUT.EU";
    scanSub.locationCode = "FUT.EU.EUREX";
    scanSub.scanCode = "MOST_ACTIVE";
    ...
    //High option volume P/C ratio US indexes
    ScannerSubscription scanSub;
    scanSub.instrument = "IND.US";
    scanSub.locationCode = "IND.US";
    scanSub.scanCode = "HIGH_OPT_VOLUME_PUT_CALL_RATIO";
  • 1  #Hot US stocks by volume
    2  scanSub = ScannerSubscription()
    3  scanSub.instrument = "STK"
    4  scanSub.locationCode = "STK.US.MAJOR"
    5  scanSub.scanCode = "HOT_BY_VOLUME"
    ...
    1  # Top % gainers at IBIS
    2  scanSub = ScannerSubscription()
    3  scanSub.instrument = "STOCK.EU"
    4  scanSub.locationCode = "STK.EU.IBIS"
    5  scanSub.scanCode = "TOP_PERC_GAIN"
    ...
    1  # Most active futures at EUREX
    2  scanSub = ScannerSubscription()
    3  scanSub.instrument = "FUT.EU"
    4  scanSub.locationCode = "FUT.EU.EUREX"
    5  scanSub.scanCode = "MOST_ACTIVE"
    ...
    1  # High option volume P/C ratio US indexes
    2  scanSub = ScannerSubscription()
    3  scanSub.instrument = "IND.US"
    4  scanSub.locationCode = "IND.US"
    5  scanSub.scanCode = "HIGH_OPT_VOLUME_PUT_CALL_RATIO"

See also Scanner Parameters

Complex Orders and Trades Scanner

The TWS Complex and Orders and Trades Scanner is a special scan type available from the API with TWS v975 and API v973.07 or higher.

  • //Complex orders and trades scan, latest trades
    ScannerSubscription scanSub = new ScannerSubscription();
    scanSub.Instrument = "NATCOMB";
    scanSub.LocationCode = "NATCOMB.OPT.US";
    scanSub.ScanCode = "COMBO_LATEST_TRADE";
  • //Complex orders and trades scan, latest trades
    ScannerSubscription scanSub = new ScannerSubscription();
    scanSub.instrument("NATCOMB");
    scanSub.locationCode("NATCOMB.OPT.US");
    scanSub.scanCode("COMBO_LATEST_TRADE");
  • 'Complex orders and trades scan, latest trades
    Dim scanSub As ScannerSubscription = New ScannerSubscription()
    scanSub.Instrument = "NATCOMB"
    scanSub.LocationCode = "NATCOMB.OPT.US"
    scanSub.ScanCode = "COMBO_LATEST_TRADE"
  • //Complex orders and trades scan, latest trades
    ScannerSubscription scanSub;
    scanSub.instrument = "NATCOMB";
    scanSub.locationCode = "NATCOMB.OPT.US";
    scanSub.scanCode = "COMBO_LATEST_TRADE";
  • 1  # High option volume P/C ratio US indexes
    2  scanSub = ScannerSubscription()
    3  scanSub.instrument = "NATCOMB"
    4  scanSub.locationCode = "NATCOMB.OPT.US"
    5  scanSub.scanCode = "COMBO_LATEST_TRADE"
  • TagValue t = new TagValue("underConID", "265598");
    List<TagValue> AAPLConIDTag = new List<TagValue>{t};
    client.reqScannerSubscription(7003, ScannerSubscriptionSamples.ComplexOrdersAndTrades(), null, AAPLConIDTag); // requires TWS v975+
  • List<TagValue> AAPLConIDTag = Collections.singletonList(new TagValue("underConID", "265598")); // 265598 is the conID for AAPL stock
    client.reqScannerSubscription(7003, ScannerSubscriptionSamples.ComplexOrdersAndTrades(), null, AAPLConIDTag); // requires TWS v975+
  • Dim AAPLConIDTag As List(Of IBApi.TagValue) = New List(Of TagValue)
    AAPLConIDTag.Add(New TagValue("underConID", "265598"))
    client.reqScannerSubscription(7003, ScannerSubscriptionSamples.ComplexOrdersAndTrades(), Nothing, AAPLConIDTag) ' requires TWS v975+
  • TagValueSPtr t(new TagValue("underConID", "265598"));
    TagValueListSPtr AAPLConIDTag(new TagValueList());
    AAPLConIDTag->push_back(t);
    m_pClient->reqScannerSubscription(7003, ScannerSubscriptionSamples::ComplexOrdersAndTrades(), TagValueListSPtr(), AAPLConIDTag); // requires TWS v975+
  • 1  AAPLConIDTag = [TagValue("underConID", "265598")]
    2  self.reqScannerSubscription(7003, ScannerSubscriptionSamples.ComplexOrdersAndTrades(), [], AAPLConIDTag) # requires TWS v975+
    3 

Complex Orders and Trades Scanner available scan codes:

  • COMBO_LATEST_TRADE
  • COMBO_QUOTES
  • COMBO_MOST_ACTIVE
  • COMBO_ALL_TRADE_TIME_ASC
  • COMBO_ALL_TRADE_TIME_DESC
  • COMBO_ALL_QUOTE_TIME_ASC
  • COMBO_ALL_QUOTE_TIME_DESC
  • COMBO_ALL_TRADE_QUOTE_TIME_ASC
  • COMBO_ALL_TRADE_QUOTE_TIME_DESC
  • COMBO_ALL_VOLUME_ASC
  • COMBO_ALL_VOLUME_DESC