Skip to content

Learn

Stock Screening

Check whether stock screening rules transfer across markets

A stock screening request can be portable in meaning without being executable against every market’s current data connection. Check each condition’s definition, currency, fiscal period and coverage before running A-share, Hong Kong and US pools separately. Deliver a capability table and distinct market results, including partial or blocked execution. Do not combine incomplete markets into a supposedly global passing list.

This guide uses synthetic contracts for three market pools and deliberately disables one field in one connection. It demonstrates capability gating and separate execution, not the actual current coverage of any vendor. CoTrading’s cross-market screening remains planned or unverified. A reference tool or preset stock pool does not establish a ready-made global screening service.

Translate the request into required fields

The example request combines positive trailing PE below 20, annual revenue growth at least 10% and a local liquidity floor. Store PE definition, the exact two revenue periods and the turnover window. A shared label such as growth does not establish whether the observation describes revenue, profit, a quarter or a full fiscal year.

The SEC EDGAR API documentation describes financial facts with unit and reporting-period context. It provides one official example of why context must accompany numbers; it does not supply equivalent A-share or Hong Kong coverage. For each real market, obtain the appropriate disclosure or licensed source and verify the field contract independently.

Resolve securities before comparing their fields. The OpenFIGI documentation illustrates identifier mapping with exchange context. A local symbol, an ordinary share and a different listing of the same issuer need not be interchangeable screening objects. This fixture uses explicit synthetic stock labels and does not call a mapping service or solve cross-listing equivalence.

Build a condition-by-market capability table

For each connection, mark a condition executable only when its field is supported and its definition matches the request. Separate unavailable capability from a missing observation on one stock. A supported field with an empty row can go to a data queue; a connection without the field cannot execute that condition for the pool merely by retrying the same request.

ConditionA fixtureHong Kong fixtureUS fixture
Comparable trailing PEsupportedsupportedsupported
Specified annual growthsupportedunsupportedsupported
Turnover currencyCNYHKDUSD
Full requestexecutablepartial onlyexecutable

These are the example’s supplied capabilities, not claims about all data for those markets. In particular, the Hong Kong field is intentionally unavailable in this fixture; it does not mean Hong Kong companies never disclose revenue. A different authorized connection could change that capability after its definition and coverage are verified.

The common numerical subset is the PE condition. Label its output “common PE pass,” not “full-request pass.” Retaining a partial calculation is useful only if readers can see which requested conditions it omits.

Treat currency-sensitive conditions as local policies

The fixture uses a liquidity threshold of 20 million local currency units in each pool. That is three explicitly supplied local policies, not an economically equivalent common liquidity floor. Twenty million CNY, HKD and USD represent different amounts. Repeating the number 20 across a configuration does not normalize purchasing power or tradability.

If the researcher truly needs one common-currency floor, define a dated FX source, conversion convention and relevant market timing before execution. This example has no FX layer and does not produce a combined absolute-turnover ranking. It instead retains each local currency beside the rule and runs each pool independently.

Dimensionless ratios can also be incompatible. PE definitions can differ by earnings basis, and growth can differ by fiscal calendar or consolidation scope. Declaring a metric dimensionless is not permission to ignore these definitions. Only conditions already accepted as comparable should enter the shared subset.

Execute full and partial branches explicitly

if not contract["growth"]:
    output[market] = {"status": "partial",
                      "common_pe_pass": common,
                      "full_pass": None,
                      "blocked_field": "growth"}
else:
    passed = [symbol for symbol, pe, growth, turnover in rows[market]
              if 0 < pe < 20 and growth is not None
              and growth >= .10 and turnover >= 20]

Download the complete example. Use Python 3.12+, the standard library and synthetic contracts; run python R527.py. The authoring source is docs/growth/research/round-5/examples/R527.py.

Actual output selects A1 for the A pool and U1 for the US pool under their full local requests. A2 passes PE and growth but fails local turnover. U2 passes PE and turnover but fails growth. The Hong Kong pool retains H1 in the common PE subset, reports status partial and leaves full_pass null because growth is unsupported.

Null is intentional. An empty full list would suggest the complete rule ran and found no match, whereas this branch did not execute the whole request. Keep that difference visible in both tables and narrative. The script asserts the full results, the partial H1 result and the blocked-field designation.

Test an incompatible-ranking counterexample

The fixture also attempts to rank A1’s turnover 30 CNY million against U1’s 30 USD million. A guard rejects mixed_currency_ranking. The numbers are equal, but the quantities are not on a shared scale. Averaging, sorting or assigning a global rank before conversion would manufacture comparability.

Unsupported growth is a different failure mechanism. Replacing it with price momentum or setting it to zero would execute a different rule or assert a nonexistent observation. The correct partial branch preserves PE results while blocking the full selection claim. A field-capability repair requires a source and definition, not a substitute metric with a convenient name.

Similarly, no stock row should disappear simply because its market failed capability checking. Reconcile all requested pools to complete, partial or blocked status and retain their input counts. A combined table can list these statuses, but a common status table is not a common economic ranking.

Review comparability before merging research queues

Deliver the request, field dictionary, capability matrix, per-market rule variants, input snapshots and execution results. Include the common subset and local conditions as separately labeled outputs. Have a reviewer trace A2’s turnover rejection, U2’s growth rejection and H1’s incomplete full evaluation. Those paths demonstrate that markets were not silently skipped or given invented replacements.

If the team later merges research queues, decide how attention is allocated across markets without implying that local turnover values share a currency scale. The queue can preserve market groups, use a separately justified priority method or wait for normalization. Do not let a generic sort silently create a global order.

Reopen the capability check after a provider change, field-definition revision, new market connection or currency-policy change. Reexecute affected pools and retain the old capability version. This workflow makes transferability a concrete decision about executable conditions and supported outputs, while leaving cross-currency backtesting and global investment ranking outside its verified scope.

Keep capability evidence versioned

For every executable cell in the capability table, retain the source field name, definition, unit, period coverage and the evidence supporting that mapping. A check mark without those details can conceal a substitute metric. For a blocked cell, record whether the limitation belongs to the connection, the requested period or an individual security.

When a new source is introduced, test it against a small accepted record and a deliberately incompatible one before enabling the whole market. Confirm that a fiscal-year mismatch stays blocked and that a missing field does not become a numerical zero. These checks concern the adapter’s interpretation, not a guarantee of universal provider coverage.

Maintain separate completion counts for markets and stocks. A market can be partially executable while several of its individual PE observations are valid. Reporting only the number of successful rows can hide the unsupported condition; reporting only the partial-market label can hide useful supported work. The paired outputs preserve both facts without upgrading the partial result into a full-screen claim.

FAQ

Does unsupported growth in this fixture describe the whole market?

No. It describes one supplied example connection. Coverage must be checked against the actual source.

Can equal local-currency thresholds be called one global floor?

No. A shared currency basis would require an explicit conversion method and dated inputs.