Align a crypto multi-asset backtest at each decision time using only records available then. An exact-time join requires matching observation boundaries; a backward as-of join can admit older observations under a declared age limit. Preserve missing assets as explicit eligibility states, and decide whether their intended weights remain cash, move to other assets or block the rebalance before calculating allocations.
A spreadsheet with one row per minute can conceal three different portfolios. One waits for a complete cross-section, one holds cash for missing assets, and one redistributes their weights. The join operation should implement that choice, rather than make it accidentally.
Define the row you are trying to assemble
Start with a decision schedule: for example, evaluate once a minute at two seconds after the boundary. Alternatively, an event-driven model may evaluate when a specified input arrives. These schedules are different strategies and should not be mixed midway through a test.
Each candidate record needs its venue, instrument, observation interval, availability time and validity state. A completed candle ending at 12:00 is different from an update to a candle that starts at 12:00. Binance's spot stream explicitly distinguishes candle start time, close time, event time and the closed-candle flag. Those fields describe that feed; they do not establish when your application received the message. Binance spot candlestick stream fields.
The market-data freshness guide covers those individual clocks. Here, the additional question is which combinations of independently valid records belong in one portfolio decision. Normalize units and time zones before comparing them, but retain the original interval definitions. Two daily bars ending at different UTC boundaries cannot become comparable merely by formatting both dates identically.
Choose exact-time or backward as-of semantics
An exact-time join asks for records sharing a chosen key, such as the same completed one-minute interval end. It suits a rule that requires a synchronized cross-section. Filter out records unavailable at the decision first; equal interval labels do not make late data usable early.
A backward as-of join asks for a prior eligible observation for each instrument. In pandas, merge_asof supports backward, forward and nearest directions, grouping keys, tolerance and an exact-match setting. Its inputs must be sorted by the merge key. Backward means the matched right-side key is no later than the left-side key; nearest may select a future record. pandas as-of join semantics.
The chosen key matters. Joining backward on candle end can still admit a candle received later. Joining on receipt time alone can pick an old candle delivered out of order. A causal selection first restricts records to those available by the decision, resolves eligible versions, then selects the latest permitted observation boundary for each instrument. Check observation age separately from arrival delay.
| Policy | Selection rule | What it does not prove |
|---|---|---|
| Exact interval | Same required interval end, available by decision | Every asset has a qualifying record |
| Backward as-of | Latest permitted prior observation, available by decision | The old value is current enough for this signal |
| Nearest time | Smallest absolute time difference | The observation was knowable at the decision |
State whether a record available exactly at the decision is included. When timestamps have insufficient precision to establish processing order, declare an ordering convention or treat the tie as uncertain. A software default cannot resolve an unrecorded causal sequence.
Work through one missing-asset rebalance
This original hypothetical fixture evaluates three spot instruments, A, B and C, at 12:00:02 UTC. All bars use the same one-minute calendar. The test is initially flat with 9,000 USDT and intends one-third of capital per asset. Its invented backward policy permits completed observations at most 90 seconds old. That limit is an example, not a recommended default.
| Asset and record | Bar ends UTC | Available UTC | Age at decision | Eligible then? |
|---|---|---|---|---|
| A, latest bar | 12:00:00 | 12:00:01 | 2 seconds | Yes |
| B, newest bar | 12:00:00 | 12:00:04 | 2 seconds | No: arrives later |
| B, preceding bar | 11:59:00 | 11:59:01 | 62 seconds | Yes under backward policy |
| C, last record | 11:57:00 | 11:57:01 | 182 seconds | No: too old |
An exact 12:00 interval policy has only A at this decision. The declared backward policy has A and B. C has no eligible input under either policy. Loading the complete day's file and taking B's 12:00 row would erase its two-second availability gap.
Now freeze the backward-policy eligible set as A and B. The allocation stage still needs its own rule:
| Missing-asset rule | A budget | B budget | Cash | Invested capital |
|---|---|---|---|---|
| Retain intended weights | 3,000 | 3,000 | 3,000 | 6,000 |
| Renormalize eligible weights | 4,500 | 4,500 | 0 | 9,000 |
| Require all three inputs | 0 | 0 | 9,000 | 0 |
All amounts are USDT. Renormalizing divides each surviving one-third weight by the surviving weight sum of two-thirds, giving one-half each. Each eligible asset receives 1,500 more than the cash-preserving rule, a 50% budget increase. These are planned allocations, not fills or performance results; the example deliberately supplies no executable prices.
For a synchronous ranking rule, even 62-second-old B may be unacceptable despite passing the example age gate. Comparing A's latest-minute momentum with B's previous-minute momentum changes the ranking's meaning. Require a shared interval or disclose the asynchronous feature definition.
Keep eligibility separate from accounting
An unavailable input does not mean an existing holding disappeared. The example starts flat to isolate allocation. With open positions, preserve units and liabilities while applying a separate valuation policy. New-entry eligibility, permission to exit and the ability to mark equity are different states.
Likewise, do not zero a missing return or omit its entire decision row without explanation. Dropping every minute with one absent asset changes the portfolio's measurement calendar. It can also compress a multi-minute price change into a row that downstream code mistakenly treats as a one-minute return.
Fill-forward is an explicit transformation. QuantConnect documents it as using the previous data point when a sample has none, with a configurable setting. That engine behavior does not establish fresh trading activity or an executable price. QuantConnect fill-forward documentation. Preserve the source observation's age even when a transformed row receives a new grid timestamp. The missing-candle and zero-volume guide handles that data distinction in detail.
Historical universe membership is another input. A not-yet-listed asset must not enter simply because its first later price can be backfilled. The survivorship-bias audit explains dated universe evidence. After eligibility is frozen, use an observable account snapshot for sizing; the equity-timing worksheet covers that denominator.
Save a decision receipt that survives replay
Retain the decision time, intended universe, selected source-row identifiers, observation ends, availability times, ages, rejected reasons, intended weights and resulting cash. Also retain the dataset snapshot, join policy version and deterministic tie rule. The data-revisions guide explains why corrected historical values need an identifiable vintage.
Use the fixture above for focused checks. Appending B's later arrival must not change the saved 12:00:02 decision. Moving C just inside the declared age boundary should change only the eligibility consequences specified by the rule. Duplicate versions of A must not multiply its allocation. Shuffling input-file row order must leave the selection unchanged. An empty eligible set must produce the declared no-action result rather than division by zero during renormalization.
The look-ahead audit extends the append-data check to earlier signals. If historical files lack availability evidence, interval-end joins can support a stated latency assumption, but they cannot prove what arrived in a live system. Label that limitation alongside the result.
This AI-assisted educational article follows the editorial policy. Its fixture and allocation rules are invented teaching examples. The cited software documentation establishes join and feed behavior; it does not establish KLINEO support for these research controls or validate a trading strategy.
