Skip to content

Learn

Stock Backtest Research

Diagnose ignored stock target changes in hold mode

A changed stock target can be read correctly and still produce no trade when the execution mode deliberately holds an existing same-direction position. Diagnose the target, mode, rounded desired quantity and actual inventory separately. Otherwise a valid mode decision can be mistaken for a failed signal, while a true cash or rounding problem is hidden behind the same no-fill symptom.

This guide compares hold and rebalance semantics using executable long-only targets and a complete synthetic account. Static inspection of the local reference engine shows a hold-mode dropped-adjustment log and a separate target-rebalance path. The downloadable standard-library fixture is independently authored and does not execute that engine. CoTrading’s corresponding settings and diagnostics remain planned or unverified.

Fix target timing and meaning before comparing modes

The four targets are 0.4, 0.8, 0.2 and zero at four already eligible execution observations. Each number is a desired fraction of pretrade equity, not a requested count of shares and not a raw entry event. This example begins at the execution boundary; it does not generate a signal or decide whether a close-based value needs a next-opening delay.

All supplied prices are ten. The initial account has cash 1,000 and no shares, the sizing grid is one share and each completed order costs one unit. There is no short selling, leverage, tax or currency conversion. Targets must be finite and between zero and one. Unknown modes are rejected rather than silently interpreted as hold or rebalance.

The fixture also accepts an explicit None as no decision, preserving an existing position. This is its declared input contract, not a claim that every missing signal in the reference product is passed through the same way. A zero target is different: it requests a flat position and can trigger an exit. Do not replace unknown inputs with zero without deciding whether that changes the desired economic action.

Define hold as a mode policy

In hold mode, a flat account may enter a positive target and an existing long position may exit when the target becomes zero. While the position stays long and the new target is also positive, its share count is retained. A change from 0.4 to 0.8 or from 0.8 to 0.2 is recorded as a dropped same-direction adjustment rather than executed.

The diagnostic compares successive target values, not the target with the actual portfolio weight. Price movements can change actual weight even when the strategy repeatedly requests the same value. Counting every such drift as a dropped new request would manufacture strategy decisions that never occurred. The fixture uses a declared target-change tolerance of one millionth for that comparison.

An ignored adjustment is not an order rejected by the exchange. It is discarded before an execution delta is submitted under this mode policy. Preserve the previous and requested target, timestamp and reason so a reader can distinguish intentional hold behavior from an unavailable raw bar, insufficient cash, zero rounded quantity or unprocessed input.

Reproduce the hold account

At observation zero, pretrade equity is 1,000. Target 0.4 at price ten implies forty shares. Buy forty, pay one fee and leave cash 599, inventory forty and equity 999. At the next observation the 0.8 target is visible but the position remains forty; cash and fees do not change. The log records previous target 0.4, requested 0.8 and reason hold_same_direction.

The third target, 0.2, is another same-direction adjustment and is also dropped. Its comparison is against the previous requested 0.8, not the original entry target 0.4. Inventory stays forty and cash 599. The final zero target exits all forty at ten, receives 399 net and leaves cash 998, zero stock and cumulative fees two.

The complete hold quantity path is forty, forty, forty, zero. Its completed orders are only the initial forty-share purchase and final forty-share sale. The account’s two-unit loss is entirely commission on flat prices. Logging the intermediate requested weights does not authorize reporting eighty or twenty actual shares when no corresponding order occurred.

Rebalance from current pretrade equity

Under rebalance mode, recompute the rounded desired share count from current equity at every supplied execution observation. The initial forty-share purchase is the same. At observation one, equity is 999, so target 0.8 implies 799.2 of stock, or 79.92 shares before rounding. Desired quantity is seventy-nine; buy thirty-nine more for 390 principal plus one fee.

Cash becomes 208, holdings seventy-nine and cumulative fees two, leaving equity 998. At the next target 0.2, pretrade equity 998 implies 199.6 of stock, or 19.96 shares. Round to nineteen, sell sixty at ten and receive 599 after the fee. Cash becomes 807, quantity nineteen and cumulative fees three.

The final zero target sells nineteen for 189 net. Final cash is 996, inventory zero and total fees four. The rebalance quantity path is forty, seventy-nine, nineteen, zero; exact deltas are buy forty, buy thirty-nine, sell sixty and sell nineteen. The two-unit difference from hold comes from two extra completed orders on the same flat price path, not from a changed signal or market return.

The Python Decimal reference supplies the decimal arithmetic and finite-input behavior used in this hand account. The fee changes equity before the next sizing decision, so an intuitive eighty-share target can legitimately become seventy-nine. Recompute from the actual account rather than forcing a desired round number and then adjusting cash to make it fit.

Separate rounding and fee controls from mode effects

In rebalance mode, change the second target only from 0.4 to 0.401. With equity 999 and price ten, the desired quantity still rounds to forty. No order occurs, but the reason is rounded_same_size, not hold-mode dropping. The target was processed; the discrete sizing grid eliminated its small economic change.

A separate ten-share-grid control uses the original four targets and the same mode, prices and fees. Its quantity path becomes forty, seventy, ten, zero, including a thirty-share increase rather than thirty-nine. It ends at the same 996 because there are still four flat-price completed orders with identical fixed fees. Equal final cash therefore cannot prove the quantity paths were identical.

The zero-fee control produces forty, eighty, twenty, zero and ends at cash 1,000. Comparing it with the one-fee rebalance path isolates the effect of accumulated cost on future equity and quantities. These are independent controls for lot rounding and fees, not evidence that a real broker or market offers the chosen grid or zero commission schedule.

Do not count price drift as a new request

Another hold control keeps the positive target constant at 0.4 while prices move through ten, twelve and eleven before a zero exit. Actual share weight drifts, but there are no dropped target-change records because the requested target did not change. The position remains forty until the exit and ends at cash 1,038 after two fees.

This is different from the main target sequence’s explicit changes. A chart of requested weight and actual weight can diverge under both circumstances, but the diagnostic cause is not the same. Preserve actual shares and cash alongside the target history instead of inferring executions from the requested-weight plot alone.

The fixture’s cash rejection is tested separately with an initially flat target of one: one hundred shares at ten plus a fee require 1,001 against cash 1,000. It rejects that increase rather than borrowing or invoking a basket scaler. A fuller engine may implement the separately declared common-factor policy, but that behavior is not silently included in this single-position mode demonstration.

Run and identify the first differing layer

Download the complete example and run python R604.py using Python 3.12 or newer. The program uses only the standard library and synthetic executable targets and prices. Output shows both mode ledgers, dropped requests, rounded desired quantities, exact orders, cash, fees and the independent controls. It does not call a signal model, market feed or live runner.

For an actual no-trade complaint, verify the effective mode, target availability, previous request, actual inventory and rounded desired quantity before inspecting market rejections. The Investor.gov order reference also reminds readers that an instruction is not a guaranteed execution price; a mode comparison cannot validate real fills. Switching modes requires another check of cash, market rules and costs, rather than a promise that every requested weight will be reached exactly.

FAQ

Did hold fail to read the 0.8 target?

Not in this example. It records the change and deliberately retains the existing same-direction inventory under the declared mode policy.

Does no order in rebalance mean the target was ignored?

No. It may round to the existing quantity or fail cash or execution checks. Inspect the recorded reason and desired quantity before attributing it to signal failure.