Skip to content

Learn

Stock Portfolio Research

Check which stock trades a simulation universe can observe

A fixed simulation basket may never examine a stock appearing in your trading journal. Its absence from the output therefore cannot establish that the rule rejected the trade or that no opportunity existed. Build a coverage ledger before comparing signals, using security identity, effective membership and usable observations rather than matching display names alone.

This guide checks five synthetic requests against a versioned two-stock USD basket. It does not access a user’s journal or scan the market. Basket coverage auditing is an external method; the example does not establish that CoTrading offers arbitrary universe selection, all-market observation or a persistent monitoring service. The fixed basket and the limited observation interval remain part of every result.

Inventory the actual observation scope

Obtain the exact basket used by the experiment, its version, the time membership became effective and its market/currency contract. A suggested list in a planning note is not proof that a run consumed that list. Keep a run reference or the supplied fixture beside the membership snapshot so the claimed coverage can be reconstructed independently.

Our basket contains A from January one up to but excluding January five, and B from January three up to but excluding January six, all in 2026 UTC. These are fictional security identities and dates. They are not a list of supported real stocks, recommendations or an assertion that those dates are trading sessions in any particular exchange calendar.

The journal-side input is a list of requested securities and observation times, not a filtered list of matching simulated trades. All five requests are explicit fixtures. Preserve requests outside the basket too. Starting with only successful matches would hide the very blind spots this audit is intended to reveal, and starting with future winners would also introduce an outcome-dependent coverage denominator.

Resolve security and time identities before classifying

Use a canonical security identity that distinguishes market, share class and currency where necessary. The fixture deliberately uses only exact A and B keys and rejects blank identities. A real alias map needs independently verified mappings; a similar company name or ticker text does not justify merging different listings. Unknown identity is unresolved input, not a negative rule decision.

The Python datetime documentation distinguishes timezone-aware from naive timestamps. The example requires an explicit offset. January one at 08:00 with offset +08:00 equals January one at 00:00 UTC and receives the same membership result. A timestamp without an offset raises an error rather than being guessed as the researcher’s local time.

Do not infer exchange session alignment from this timestamp comparison. Real calendars, holidays, intraday cutoffs and data-availability delays require a separate preparation layer. The sample answers whether an instant falls inside declared membership intervals. It does not prove that a quote was tradable at that instant or that a market was open.

Define membership boundary behavior

Intervals include their start and exclude their end. This convention assigns a security at an exact handoff instant to the new interval without double counting. The supplied intervals have positive duration and no overlapping ranges for the same stock. Keep such validation with any real universe importer rather than relying on a chart’s visual ordering of dates.

Changing interval conventions changes coverage. A request for A exactly at January five 00:00 UTC is outside its interval even if an old member list still includes A’s name. Record the effective snapshot that governed the opportunity, not whichever list is current when someone later reviews the journal. Otherwise historical coverage can silently expand after results are known.

The Python hashlib documentation supports a digest of the serialized basket. The example checks that its membership representation remains unchanged during classification. This is a content identity check, not authenticated proof of when the basket was frozen. Preserve the effective-date evidence and approval records separately from its checksum.

Require usable observations after membership passes

Membership and data availability are separate gates. A covered security with a missing quote receives covered_quote_unknown. The method does not copy another stock’s price, carry a later quote backward or assume a zero return. A finite positive quote makes the request observable under this limited fixture, but observability alone still does not mean the trading condition passed.

A NaN or nonpositive quote for an active member is invalid input and is rejected. The ordering matters: a quote for an outside stock is not used to fabricate a simulated opportunity within the basket. Keep those out-of-scope records in the coverage report, and explain that validating all source quotes would be a different data-quality task rather than a rule-evaluation result.

In a fuller pipeline, distinguish missing feature history from a missing current quote. Both can prevent rule evaluation, but their remediation differs. This sample has only a quote field and does not claim a complete feature-availability engine. Any additional field should carry its own availability boundary rather than inheriting the security’s membership status.

Read the five-request main case

A requested on January two has valid membership and a quote of 100, producing observable. B requested on January two is outside_effective_interval because it joins only on January three. C requested on January three is outside_basket because no membership record exists. These outcomes precede any trading-rule comparison.

B requested on January three is a member, but its quote is None, producing covered_quote_unknown. A requested exactly at January five’s boundary is outside_effective_interval. Across five requests only one is observable. Two are outside their effective interval, one is outside the basket, and one has unknown quote data. The total status count still reconciles to five.

That one-of-five observation count describes this supplied request set. It is not a universe-wide opportunity coverage estimate, because the requests are not a complete exchange security/session population. The program prints rule_rejection_count=not_inferred. None of the four unavailable requests should be relabeled as the rule declining a trade, and the observable request has not yet been tested by a strategy.

Challenge classifications through independent boundaries

The offset-equivalent timestamp tests the time interpretation without changing a security or price. The exact end-boundary request tests interval policy. The missing B quote tests data availability while membership is true. These are different mechanisms; a check that only verifies A’s name is present would miss all three distinctions.

The program also rejects a naive timestamp and a NaN quote for an active stock. Keep those failures visible rather than replacing them with a convenient uncovered status. An invalid source value is not the same evidence as a valid security outside the declared basket. Repairing the input requires a recorded revision and rerun, not only editing the summary count.

Run and hand off the coverage ledger

Download the complete example, save R642.py and run python R642.py with Python 3.12 or later. It uses only the standard library and synthetic membership, requests and quotes. Assertions verify all five statuses, their counts, timezone equivalence, naive-time rejection, nonfinite-quote rejection and unchanged basket content. No credentials or market service are accessed.

Deliver the observable list, excluded requests with reasons, basket identity, interval convention and unresolved data. Update coverage only through a new effective version when the basket changes. Extending the basket after seeing a missed winner is a new experiment, not a correction proving the old strategy would have captured it. A subsequent opportunity matcher should consume this ledger so coverage gaps cannot be mistaken for human execution deviations.

When updating the audit, compare old and new members, validate their effective intervals, then rerun request classification. Label membership changes separately from quote corrections. A repaired observable row is an input revision, not evidence that a model improved or that a previously unobserved strategy made a successful decision.

FAQ

Does outside_basket mean the strategy rejected the stock?

No. The strategy did not observe that stock under the declared scope. Rejection requires an actual evaluated condition.

Is a member with a quote guaranteed to generate a signal?

No. Observable only clears this coverage check. Rule inputs and decisions still require separate evaluation.