Test generated stock signals on sparse and incomplete input bars
Sparse stock inputs need explicit signal behavior. Decide what happens with insufficient history, a missing bar, a nonfinite price and an observed zero-volume session before evaluating the generated strategy. Preserve unknown status rather than forward-fill an executable bar or convert every gap into a valid zero signal.
This guide supplies a standard-library fixture for a three-observation trailing comparison. CoTrading input-boundary tooling remains planned or unverified. All observations are synthetic, and passing the tests does not mean a data provider repairs missing history or that every generated strategy handles all bad inputs safely.
Declare the aligned input schema
Each list position represents one already identified market session. A complete bar contains numeric-or-missing close and volume fields; an absent bar occupies an explicit None slot. The example does not obtain an exchange calendar. If a source simply omits a date, the adapter must first restore the known calendar slot rather than compress time silently.
Use positive finite closes for this raw-stock-price contract. Volume must be finite and nonnegative. Python’s math reference documents the finite-number checks used before comparisons. None, NaN and positive or negative infinity do not become eligible measurements merely because Python can store them in a list.
Keep the original observation and the decision status separate. A missing bar is not proof that the exchange officially halted the security. An observed zero volume is not the same as an unknown volume. The status describes what this input contract can establish, not an invented market-event classification.
Define the conservative window policy
The indicator needs three consecutive valid, positive-activity bars. It compares the current close with the mean of those three closes, including the current one. A strict greater-than gives target one; equality or lower gives a ready target zero. Fewer than three valid consecutive observations produce an unknown signal represented by null.
Any missing bar or invalid numeric field resets the window. This avoids calculating a nominal three-session indicator from three observations separated by an unknown gap. A different strategy can allow nonconsecutive observations, but then it must name that clock and its missing-data policy explicitly rather than call it the same window.
Zero volume is preserved as the distinct zero_volume reason. For this fixture it makes the bar ineligible for a trading signal and also resets the indicator window. That is an intentionally conservative policy, not a universal statement that a supplied close with zero volume cannot ever be useful for valuation.
Distinguish null from a ready zero
Normal closes ten, ten and twelve with volume one hundred give null, null and one. The first two rows have insufficient history; the third is a completed comparison. Three equal tens with positive volume instead produce a ready zero on the third row. The script asserts that distinction directly.
Do not turn null into zero just to fit an integer output schema. Zero says the approved rule evaluated and did not request a long state. Null says the rule could not be evaluated under the input contract. An existing account needs a separate policy for that unknown state; it should not accidentally liquidate or hold depending on a downstream default.
Similarly, do not label every warmup row a blocked trade. There was no completed signal opportunity yet. Keep counts of warmup, unavailable observations, ready zero and ready one so a no-trade run can be explained without adjusting the strategy threshold to force activity.
Rebuild a missing-bar path
Supply one valid ten, an absent bar and then valid closes ten, ten and twelve. The output signals are null, null, null, null and one. The second row’s reason is missing_bar; the next two are fresh warmup after the reset. The earlier ten is not carried across the absent session to complete the window prematurely.
The missing row is not filled with the prior close or volume. Such filling would create a fabricated observation, possibly a ready signal and eventually an imagined fill. Valuation systems may separately carry a mark for an existing holding, but that does not create an executable bar or a fresh indicator observation.
This fixture is different from carrying an old factor score until expiry. Here the input is the price-bar sequence needed by a specific rolling calculation. Reusing a score and repairing a bar are different operations with different evidence requirements. Keep their policies in separate modules or configuration fields.
Exercise invalid prices without accidental ranking
Replace the second close with each of None, NaN, positive infinity, negative infinity, zero and minus one. Every case emits invalid_price, keeps the signal unknown and resets the window. Three new valid bars are then required to obtain the final ready one.
A nonfinite comparison must not quietly evaluate false and be presented as a genuine zero strategy decision. Nor should positive infinity become an especially strong buy. The validity check occurs before the indicator, making the source problem observable instead of letting numeric comparison semantics decide a trading state.
The schema here is numeric-or-missing. An adapter receiving arbitrary text or malformed objects needs a separate parsing contract. The fixture is not described as a universal validator for all possible provider payloads; it proves the listed numeric boundaries through actual calls and assertions.
Exercise volume failures and real zero activity
The volume cases include missing, NaN, both infinities and minus one, all labeled invalid_volume. Zero receives zero_volume instead. All produce unknown signals and restart warmup in this policy, but the distinct reason preserves the difference between bad information and a known no-activity observation.
Do not divide by a zero volume or replace it with one merely to keep a volume-based indicator running. This particular rule does not divide by volume; it uses volume as an explicit eligibility gate. Other formulas require their own denominator assertions and cannot inherit correctness from this short example.
After each bad or zero-volume bar, the same three good bars recover to a ready one. Recovery is part of the acceptance path: a strategy that never resumes after a single missing observation is also incorrect under this contract. Resetting state should be deliberate and finite, not a permanent hidden disable flag.
Run the complete boundary pack
Download the complete example, save it as R577.py and run python R577.py with Python 3.12 or later. It uses only the standard library and synthetic data. The source is docs/growth/research/round-5/examples/R577.py.
Assertions cover normal warmup, a ready zero, the absent-bar sequence, six price boundaries, six volume boundaries, empty input and a short input. Every prefix of the gap fixture must reproduce the same earlier rows. The output contains signal and reason together, and it represents problematic input values as diagnostic strings rather than leaking NaN into the exported eligible signal.
Carry the policy into a real adapter
Archive the calendar alignment, input types, finite checks, activity requirement, window-reset rule and unknown-signal handling with the strategy version. Review a missing session and a zero-volume session separately using actual source evidence before applying the method to historical data.
Record which rows were excluded, whether they interrupted warmup and when calculation resumed. Do not claim that a test passing on synthetic inputs fixed a provider outage or recreated a halt history. Completion means the code exhibits the declared waiting, skipping and recovery behavior on each input class, while data acquisition, execution and account policy remain separately evidenced tasks.
Check the output adapter as well as the calculation. A later conversion that replaces every null with integer zero changes this contract even if the boundary function itself passes. If an external interface requires a complete numeric series, define its separate waiting policy and test the conversion explicitly. Do not borrow another tutorial’s zero/one vocabulary without deciding how unknown input affects an existing holding. The portable fixture deliberately keeps those decisions visible.
FAQ
Does zero volume mean the same as missing volume?
No. This policy blocks both from signaling but retains distinct reasons and does not infer a formal halt.
Can I forward-fill a missing close to complete warmup?
Not under this consecutive-valid-bar contract. A different imputation rule would need its own explicit experiment.