Skip to content

Learn

Stock Strategy Development

Trace stock strategy parameters from specification to effective code

When a stock strategy parameter appears to have no effect, trace its value from the specification to the expression that uses it. A JSON field named window does not automatically enter a zero-argument strategy constructor. Record the effective value and its source, then use a short input whose expected signals change when exactly one approved parameter changes.

This guide uses an authored minimal loader and an explicit alternative adapter. CoTrading parameter injection remains planned or unverified. The loader deliberately reproduces an ignored-field mechanism; it is not evidence that every external runner ignores the same key. The deliverable is an effective-parameter table and executable counterexamples, not a parameter search.

Give each parameter one effective source

List strategy window, comparison threshold, engine execution settings and account-cost settings separately. A window controls the indicator’s input slice; an execution lag controls scheduling; a commission controls cash. Similar names in one configuration file do not establish that the same component reads them.

For each field save the requested value, allowed type, default, effective value, origin and consuming expression. Origins might be a source constant or an explicitly implemented adapter. Do not claim that a prompt instruction or a UI field is effective until code or an observed resolved configuration demonstrates the connection.

The fixture’s class defines WINDOW = 3 and THRESHOLD = 0.0. It has no required constructor arguments. Python’s inspect documentation describes signature inspection; the script asserts that the class signature is empty. An empty signature proves constructibility here, not automatic injection of arbitrary configuration fields.

Define the threshold’s unit

The rule is current close strictly greater than the trailing average multiplied by one plus threshold. Threshold zero means simply above average. Threshold 0.2 means twenty percent above that average, not twenty price units and not 0.2 percentage points. Put the unit into the specification before comparing outputs.

The window includes the current completed observation. Fewer observations than the window produce zero in this particular signal contract. Changing the window can change both warmup and the average; a test should inspect those separate effects rather than assume only the last row can differ.

The approved default is window three and threshold zero. Do not silently change either to satisfy a loader’s convenience. A default is a strategy choice once it affects signals, so a mismatch between the specification and the class is an actionable contract problem even if the code imports and runs successfully.

Reproduce an ignored JSON field

The authored reference_style_load(config) returns a new default class instance and does not read strategy parameters from config. Load it once with an empty dictionary and once with a requested window two. Both instances still use window three. This controlled example isolates the missing binding step without contacting a product service.

Input closes ten, twenty and eighteen. The three-observation average at the final row is sixteen, so eighteen qualifies. Both default and ignored-config outputs are [0,0,1]. The requested two is visible in the report, but the effective window remains three; the unchanged signal is explained by code, not guessed from a larger backtest.

In a real incident, inspect the actual loader, its accepted fields and the resolved instance before declaring a key ignored. An engine may legitimately consume the field elsewhere or use a differently named strategy adapter. Preserve that evidence and avoid installing a new injection path merely because the field name seems intuitive.

Bind values through an explicit adapter

The alternative explicit_adapter(spec) is written in this example. It accepts exactly window and threshold, creates a subclass with those declared class constants and returns a zero-argument instance. This is a demonstrated local mechanism, not a claim that CoTrading already provides the adapter.

With window two and threshold zero, outputs become [0,1,0]. At index one, twenty exceeds the average of ten and twenty, fifteen. At the final row, eighteen is below the average of twenty and eighteen, nineteen. The last decision reverses for the expected arithmetic reason.

Reset the window to three and change only threshold to 0.2. The final required level becomes sixteen times 1.2, or 19.2; eighteen does not qualify. Outputs are [0,0,0]. These two one-change tests show that both declared parameters actually reach their consuming expressions.

Validate values before evaluating prices

The supported window is an integer of at least two, with Boolean values rejected even though Python treats them as integer-like in some operations. The threshold must be finite and nonnegative. Python’s math reference supports the finite-value guard; NaN must not quietly make every comparison false.

The test supplies window zero, a Boolean window and a NaN threshold. Each raises ValueError during generation. An extra or missing adapter field is also outside the declared schema. Do not silently fall back to defaults after rejecting a requested value, because that recreates the original problem under a misleading successful status.

These checks are not an optimizer. No grid, selection by return or cross-run ranking occurs. The short fixture was chosen because the expected arithmetic distinguishes the settings, not because one setting produces more profitable trades. There is no account or return result in this parameter-binding task.

Run the effective-parameter pack

Download the complete example, save it as R578.py and run python R578.py with Python 3.12 or later. The standard-library source is docs/growth/research/round-5/examples/R578.py; all prices are synthetic.

Assertions check zero-argument construction, the default and ignored-field equality, effective window three, explicit window-two sequence, explicit threshold sequence and invalid-value rejection. The output reports requested and effective values together. Reading only the requested JSON would miss the central result.

Produce a useful incident handoff

For a real report, attach the specification, configuration, strategy source version, loader version, effective snapshot and a row-level calculation. Identify the first place where requested and effective values diverge. If the source constant is the intended authority, correct the misleading configuration; if an adapter is intended, implement and test the binding explicitly.

Keep execution-engine parameters out of an indicator-equivalence assertion unless they genuinely feed the indicator. A fee change can alter equity while leaving signals identical; a window change should alter the chosen fixture’s signal. These are different expected effects. Name them separately so a legitimate unchanged output is not mistaken for a failure.

Revalidate after changing the loading path

Defaults, source constants and resolved adapters can change when code is regenerated. Save the effective source alongside the value, rather than rely on a screenshot of an earlier request. Rerun one discriminating input whenever the loader, class or configuration schema changes.

Do not accept “the new value is in the file” as the stopping condition. Acceptance requires that another reader can trace the value to the actual calculation and reproduce the expected one-parameter signal change. Keep the ignored-field control so future refactors cannot accidentally reintroduce an unconnected setting while still passing an import-only test.

The explicit adapter also rejects an extra commission field. That field belongs to an account or engine contract, not this two-parameter signal schema. Silent acceptance would make the caller believe it controls something the adapter never uses. Keep a rejection or a clearly documented separate consumer instead.

For handoff, show both the requested object and the resolved class constants immediately before generation. If they agree only because duplicated defaults happen to match, retain the source-of-truth decision anyway. A later single-field change can expose the unresolved precedence. The discriminating fixture should be rerun after that change, so effective binding remains an observed behavior rather than an assumption based on names.

FAQ

Does a JSON key automatically become a constructor argument?

No. A loader or adapter must explicitly implement that binding.

Does an unchanged equity curve prove the parameter was ignored?

No. Inspect the effective value and use a fixture where the specified calculation should change.