Separate stale stock valuation marks from executable backtest bars
A stock can remain in a backtest’s equity while having no executable bar. Ownership has not disappeared, so a valuation policy may carry its last observed close. That carried mark is an accounting input, not a new market observation. A pending sale must still require an eligible raw bar rather than treating a forward-filled price as a trading opportunity.
This guide separates raw observations, valuation marks and execution decisions in one synthetic account. The local reference engine has distinct trading and valuation views in its statically inspected code, but this independent standard-library fixture does not run it. CoTrading’s exact missing-bar behavior and halt-data integration remain planned or unverified. The example validates a declared mechanism, not real historical halt performance.
Separate missing data from a confirmed halt
An absent stock row may reflect a holiday, suspension, prelisting interval, vendor outage or incomplete download. A broad market calendar helps identify some cases, but cannot establish the reason for every stock-specific gap. Without external status evidence, keep the cause unknown. Calling every missing row a suspension invents information that the price file does not contain.
The Investor.gov explanation of trading halts and delays describes regulatory and non-regulatory cases and exchange decisions. It supplies market context, not a classifier for a sparse CSV. A real diagnostic should connect a dated security identifier to official status evidence separately from documenting the presence or absence of a downloaded bar.
Our four indices represent already supplied common sessions. Stock A has a raw bar at zero, none at one and two, and a new bar at three. The gap’s cause remains unspecified. This avoids pretending to have downloaded an official suspension and resumption record. The later bar demonstrates renewed data availability under the fixture, not independent proof of an exchange’s formal resumption announcement.
Maintain three separate series
The raw sequence preserves absent rows as absent. A valid observed bar contains finite positive opening and closing prices and finite nonnegative volume. The valuation sequence carries the last valid observed close across subsequent missing observations and records its age in supplied sessions. No backward fill is allowed, so a stock never observed has an unknown mark rather than a price borrowed from its future.
The execution sequence checks the actual raw bar at the requested session and the fixture’s positive-volume condition. A known close with zero volume is an observed valuation input but is not executable under this deliberately conservative policy. Zero volume differs from missing or invalid volume. Neither case can be turned into a fresh positive-volume row merely because the account wants to exit.
The script uses the finite-number checks described in the Python Decimal reference. A malformed, None, NaN or infinite opening fails the bar validation and does not create an order. Decimal arithmetic keeps the hand account transparent; it does not recover missing observations, prove market status or establish that every positive-volume daily bar guarantees a fill.
Reproduce the unchanged marked position
Start with 1,000 cash, no stock and no prior mark. At index zero the observed bar has opening ten, close ten and volume one hundred. Buy forty shares at ten, charge one fee and leave cash 599. Quantity is forty, mark ten, quote age zero and equity 999. The one-unit decrease from capital is the completed purchase fee.
At indices one and two the exit condition requests a sale, but no raw bar exists. Both requests are rejected without an order, commission or inventory change. Cash remains 599, quantity forty and cumulative fees one. The mark remains ten with ages one and two, giving accounting equity 999 on each row. A flat equity line here describes the chosen stale marking policy, not an observed zero market return.
Keep the rejection and valuation fields together. A report showing only equity can conceal why a requested exit did not occur. A report showing only rejected orders can conceal that the account still owns the asset. Quantity, raw presence, mark age, cash and equity explain different parts of the same retained exposure and should not be collapsed into a single availability flag.
Execute on the new bar and explain the jump
At index three a raw bar supplies opening eight, close 8.5 and volume one hundred. The still-required sale executes forty shares at eight, receiving 319 after one fee. Cash and equity finish at 918, inventory zero and total fees two. The new close 8.5 becomes a fresh valuation observation with age zero, but no shares remain for that closing mark to value.
The account changes from stale-marked equity 999 to liquidated cash 918, a decline of eighty-one. Forty shares times the move from the old mark ten to the actual execution eight explains eighty; the exit fee explains one. Do not instead use the later close 8.5 as the earlier opening sale price. Updating a mark and executing a pending order are different timed events.
The complete cash bridge is 1,000 minus 401 plus 319 equals 918. The price loss is eighty and commissions two. No hidden cash transfer occurs during the gap. Recording a zero stock value merely because the bar is missing, then restoring the position at the later row, would create another artificial jump unrelated to ownership or trading.
Demonstrate the false-fill mechanism
The intentionally wrong control copies the last valuation mark into a fabricated opening and closing bar with positive volume at index one. It then sells forty at ten, finishing with cash 998 after two fees. That result is eighty better than the valid raw-bar path, entirely because the control invents execution before the lower observed opening arrives.
This is not a second trading strategy or a superior missing-data method. The forged bar changes the available execution evidence. A forward-fill operation can be useful for valuation while becoming invalid when the same output is passed into an execution layer. A data-processing label such as filled prices does not tell a downstream consumer which use is authorized.
The formal path never enters the forging branch. Its assertions require empty orders on both missing rows and the exact sale at index three. A production pipeline should enforce the same separation structurally, for example by retaining a raw-observation mask and immutable source identifiers instead of allowing an accounting series to overwrite the original market table.
Test unknown marks and observed zero activity
A separate control begins with a declared existing forty-share holding but no observed price anywhere in the supplied two-row window. Its stock mark and total equity remain unknown, while quantity remains forty. The account does not assign zero value, borrow a future price or erase ownership. This control tests reporting incompleteness rather than estimating the missing asset’s true worth.
Another control supplies a fresh bar with volume zero. Quote age resets to zero because the price observation exists, but the sale remains blocked and the forty shares stay held. This distinguishes freshness from execution eligibility: a recently supplied value need not authorize a transaction under the chosen policy. Actual zero-volume semantics must be checked against the data provider before using them as a market rule.
The example also tests invalid openings individually. Running the first three rows produces exactly the same ledger prefix as the full run, without a forced final-row sale. Replacing the later opening with one hundred cannot change the two earlier rejections or stale marks. These controls prevent future availability and dataset truncation from retroactively creating trades.
Run and diagnose the real handoff boundary
Download the complete example and run python R602.py with Python 3.12 or newer. Only the standard library is required. The raw data, requested actions and prices are synthetic. Output includes the valid ledger, forged-fill control, unknown initial mark and zero-volume control. It does not access an exchange, status vendor, brokerage account or product service.
For a real discrepancy, export the original stock rows, aligned session index, valuation-forward-fill output, quote ages, pending requests and actual orders. Find the first point where an absent raw row becomes executable. Preserve the original cause as unknown unless separately evidenced. Correct valuation carry can keep ownership visible, but cannot certify liquidation value, remove halt risk or prove that every suspension and reopening has been modeled.
FAQ
Does an unchanged equity line mean the stock traded flat?
No. In this fixture it can reflect an old valuation mark carried through missing raw observations. Quote age makes that limitation visible.
Can a forward-filled close execute the pending exit?
Not under this contract. A valid current raw bar and the declared execution conditions are required; otherwise quantity and cash remain unchanged.