Trace insufficient cash through stock basket order scaling
Insufficient cash in a stock basket should be diagnosed before orders are committed. Release cash from eligible reductions, price all proposed purchases including their fees, and apply one declared scaling policy to the capital-consuming sleeve. A sequence that simply buys the first stock until cash runs out can make portfolio membership depend on the input order.
This guide reproduces a common-factor planning mechanism in a small synthetic US-dollar stock account. A static reading of the local reference engine shows separate reduction, planning and cash-fitting paths. The downloadable program is an independent standard-library reproduction; it does not run that engine. CoTrading’s corresponding basket execution and diagnostic output remain planned or unverified.
Freeze the account and full-size requests
The account begins with cash 50 and ten OLD shares marked at 10, so initial equity is 150. The current request fully sells OLD at 10. A one-unit sale fee means the account receives 99, producing available cash 149 and no OLD inventory. The new basket requests eight A at 10, eight B at 10 and one C at 20, each with a one-share sizing grid.
These are already priced full-size purchase plans. They do not include leverage, foreign exchange, short proceeds or unsettled-cash restrictions. All prices are finite and positive, quantities and lots positive integers, every full-size quantity already a whole lot multiple, and symbols unique. The reduction is explicitly executable in the fixture; a blocked real sale would not release its hypothetical proceeds for the new basket.
At full size, A costs 81, B costs 81 and C costs 21 after one fee per completed purchase. Total required cash is 183, greater than the available 149. Comparing principal alone would report 180 and still miss three units of costs. More generally, a basket that just fits before fees can overdraft after commissions, so cash preflight must use the actual cost function.
The Investor.gov fee bulletin distinguishes transaction charges from continuing expenses. This fixture chooses a synthetic one-unit transaction fee; it does not copy a real broker schedule or claim that other market charges are included. Recalculate fees after quantities change rather than scaling a full-size fee without checking its definition.
Fit the whole opening sleeve
For a candidate common factor between zero and one, multiply every requested quantity by that same factor and round down to its declared lot. A positive rounded purchase pays one fee; a zero quantity creates no order and pays nothing. Sum all candidate costs before changing cash or holdings. The trial function has no portfolio side effects and emits no rejection diagnostics.
If the full basket fits, use factor one directly. Otherwise the fixture performs fifty binary-search trials and retains the last affordable candidate. It uses Python Fraction for exact rational factors and integer floor operations, avoiding a floating approximation at a lot boundary. This is a reproduction policy, not proof of a universal optimal allocator for arbitrary nonmonotonic fees.
With nonnegative fixed per-order fees and floor-rounded quantities, cost is nondecreasing as the common factor increases. Discrete jumps mean the factor is not simply 149 divided by 183. The search can approach one from below while still producing seven A, seven B and zero C. At exactly one, both eight-share positions and C reappear and the basket becomes unaffordable.
The chosen orders each cost 71, totaling 142. Available cash falls from 149 to seven. Holdings become seven A and seven B; cumulative fees, including the OLD reduction, are three. Opening equity is seven cash plus 140 of stock, or 147, matching the initial 150 less paid fees. Rounding changes exact weight proportions even though every requested sleeve shared the same factor.
Explain unfilled quantities without inventing exchange fills
Report the requested, selected and unfilled quantity for every plan. A and B each requested eight, selected seven and left one unfilled. C requested one, selected zero and left one unfilled. The diagnostic list records C once as insufficient_capital, because its positive full-size plan disappeared during the funding fit.
The fifty trial evaluations are not fifty failed market orders. They must not each append a zero_size rejection or charge a fee. The script checks that C appears once in the rejection list and that only two new purchases enter the completed order list. A report that mixes trial counts with actual order counts would exaggerate execution activity and obscure the source of the cash constraint.
These unfilled planning amounts are also not evidence of broker partial fills. The synthetic planner elects smaller orders before submission; it does not submit eight shares and observe seven executions from an exchange. Real order lifecycle, partial execution, cancellation and settlement require different evidence. Keep the planning shortfall and market fill status as separate fields.
Test order independence with a different mechanism
Run all six permutations of the three purchase plans. The full result, including chosen orders, shortfalls, rejection and remaining cash, must be identical. Sorting identifiers stabilizes reporting, while common-factor planning prevents the first input symbol from consuming a privileged cash allocation. Sorting alone would not repair a sequential first-come allocation policy.
The deliberately different greedy control buys as much as possible for each input name before considering the next. In A, B, C order it obtains eight A, six B and zero C. Reversing the sequence changes the quantities. This is not a second price scenario; it is a different funding mechanism that violates the declared input-order invariance even though its cash may remain nonnegative.
A separate invalid-plan control requests one share with a hundred-share lot, or 150 shares with that lot. Both raise plan_not_board_lot_multiple before cash fitting. They are malformed full-size plans, not capital rejections; unlike C, they were never valid positive full-size orders on the supplied grid.
The zero-budget control produces no purchases, unchanged cash zero and one capital rejection per full-size plan. The exact-budget control at 183 accepts the full basket with factor one. Together they test an empty affordable sleeve and the direct-fit boundary. Invalid or negative available cash is rejected rather than silently interpreted as borrowing capacity.
Close the account through actual selected quantities
For a separate terminal fixture, sell seven A at 11 and seven B at nine, charging one unit each. A returns 76 net and B returns 62 net. Add those proceeds to the seven remaining cash and final cash is 145, with no stock and five total fees. The OLD sale was flat in price, A gained seven and B lost seven, so the entire five-unit decline from starting equity is commission.
The full completed sequence is OLD sell ten, A buy seven, B buy seven, A sell seven and B sell seven. Exact order assertions prevent a plausible final number from hiding an incorrect basket. The ending identity is 145 equals initial equity 150 minus fees five; using initial cash 50 as the performance denominator would ignore the OLD asset supplied at the beginning.
Do not call this a historical strategy return. Every price and lot is synthetic, and the final sale is an explicitly supplied accounting fixture. Extending the procedure to another market requires effective lot rules, execution eligibility, its own fee model and a separate cash account. It does not establish financing, cross-currency cash pooling or actual settlement support.
Run and retain the planning evidence
Download the complete example and run python R601.py using Python 3.12 or newer. The script needs only the standard library and synthetic inputs. It prints the initial holdings and cash, reduction proceeds, full basket cost, common factor, chosen orders, rejected quantities and final ledger. No broker, data source or product runner is called.
For an actual discrepancy, compare available cash after genuine reductions, execution prices, fee function, lot rounding and the complete set of new requests before examining the final equity curve. Freeze those inputs and replay permutations. If the first difference occurs during planning, changing a signal threshold cannot repair it; if a reduction was blocked, the funding premise must be corrected before any scaling result is trusted.
FAQ
Does a shared factor preserve exact final weights?
No. It applies a common scaling decision before discrete lot rounding and fees. The resulting quantities and cash reserve must still be reported explicitly.
Is the missing C share a broker partial fill?
No. C is dropped during synthetic planning before an executable order is created. Actual market fills require a separate order-lifecycle model.