public synchronized void reqScannerSubscription( int tickerId, ScannerSubscription subscription, Vector<TagValue> scannerSubscriptionOptions) {
        // not connected?
        if( !m_connected) {
            notConnected();
            return;
        }

        if (m_serverVersion < 24) {
          error(EClientErrors.NO_VALID_ID, EClientErrors.UPDATE_TWS,
                "  It does not support API scanner subscription.");
          return;
        }

        final int VERSION = 4;

        try {
            send(REQ_SCANNER_SUBSCRIPTION);
            send(VERSION);
            send(tickerId);
            sendMax(subscription.numberOfRows());
            send(subscription.instrument());
            send(subscription.locationCode());
            send(subscription.scanCode());
            sendMax(subscription.abovePrice());
            sendMax(subscription.belowPrice());
            sendMax(subscription.aboveVolume());
            sendMax(subscription.marketCapAbove());
            sendMax(subscription.marketCapBelow());
            send(subscription.moodyRatingAbove());
            send(subscription.moodyRatingBelow());
            send(subscription.spRatingAbove());
            send(subscription.spRatingBelow());
            send(subscription.maturityDateAbove());
            send(subscription.maturityDateBelow());
            sendMax(subscription.couponRateAbove());
            sendMax(subscription.couponRateBelow());
            send(subscription.excludeConvertible());
            if (m_serverVersion >= 25) {
                sendMax(subscription.averageOptionVolumeAbove());
                send(subscription.scannerSettingPairs());
            }
            if (m_serverVersion >= 27) {
                send(subscription.stockTypeFilter());
            }
            
            // send scannerSubscriptionOptions parameter
            if(m_serverVersion >= MIN_SERVER_VER_LINKING) {
                StringBuilder scannerSubscriptionOptionsStr = new StringBuilder();
                int scannerSubscriptionOptionsCount = scannerSubscriptionOptions == null ? 0 : scannerSubscriptionOptions.size();
                if( scannerSubscriptionOptionsCount > 0) {
                    for( int i = 0; i < scannerSubscriptionOptionsCount; ++i) {
                        TagValue tagValue = (TagValue)scannerSubscriptionOptions.get(i);
                        scannerSubscriptionOptionsStr.append( tagValue.m_tag);
                        scannerSubscriptionOptionsStr.append( "=");
                        scannerSubscriptionOptionsStr.append( tagValue.m_value);
                        scannerSubscriptionOptionsStr.append( ";");
                    }
                }
                send( scannerSubscriptionOptionsStr.toString());
            }
            
        }
        catch( Exception e) {
            error( tickerId, EClientErrors.FAIL_SEND_REQSCANNER, "" + e);
            close();
        }
    }