Correct the holding rule, execution lag and asymmetry index; regenerate all downstream results - #2
Open
Tofik (plut777) wants to merge 17 commits into
Open
Conversation
Unmodified import of the correction branch produced by another AI agent (Codex) and delivered as alpha-asymmetry-corrected-branch.zip. It is committed here as a single, clearly labelled starting point so that every subsequent change on this branch is separately reviewable. This commit is a submission under audit. Its contents are not endorsed and have not been verified. In particular the manuscript changes in paper/alpha-asymmetry.tex are known to include at least one edit that rewrites the specification to match the code rather than correcting the code to match the specification. Base: upstream/master 4d21c69
Records, for every change on this branch, what changed, who originated it, and whether it is a bug fix or a specification decision. Findings from this first pass, all verified against the upstream history: - All four originally reported implementation bugs are confirmed in 4d21c69:analysis/full_pipeline.py. Three of them were genuine code-vs-paper defects fixed in the correct direction. - The rebalancing rule in the manuscript was rewritten from "Weekly (end of Friday close)" to "none within an episode" with no disclosure anywhere. The original code also resized weekly in effect, so paper and code had agreed. - Freezing position size at entry and redefining "trades" as holding episodes are specification decisions, not implementation bugs, and are currently listed as bugs. - The claim that Monday opening prices are absent from the dataset looks false; daily bars carry an Open column. Verification pending. - Table provenance footnotes recording the paper's own earlier corrections were deleted. - The pre-correction "before" figures Codex hard-codes are accurate. No analysis code or manuscript text changed in this commit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Seven of the eight recorded SHA-256 hashes reproduce byte-for-byte on an independent download. SPY differs because it is fetched with auto_adjust=True and its history is back-adjusted by dividend factors between fetches. Rerunning the full pipeline on the fresh data changes exactly five values, all in the SPY cross-market row, all in the fifth or sixth significant figure. No number printed in the manuscript changes. The EUR/JPY analysis is identical throughout. Constraint checks on the rerun: n = 504 spanning 2016-01-08 to 2025-08-29; factor intercept -0.00013783 against a mean weekly return of -0.00013928; low- and high-VIX returns compound to -7.573378% against a full-sample -7.573378%. Both identities hold. Also resolves EX-3: the downloaded frames carry an Open column, so the manuscript's claim that Monday opening prices are absent from the dataset is false. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The raw CSVs stay out of the repository: Yahoo Finance data may be subject to redistribution terms, which is why analysis/cache/ was gitignored to begin with. Publishing them is the repository owner's decision to make knowingly, so it is raised in the PR text rather than taken here. What a fresh clone needs instead is a way to fetch the inputs and confirm they are the right ones. - add analysis/fetch_data.py, which downloads the eight series and checks each file's SHA-256 against the committed manifest, separating expected differences from unexpected ones and failing only on the latter; - record per-series hash stability in analysis/data_access.py and annotate the committed manifest with it. Six series are FX spot rates or index levels with no corporate-action adjustment and cannot drift; GLD made no distribution over the window; SPY is a distributing ETF fetched with auto_adjust=True and is the only file in the set that can change. The annotation adds fields only: no recorded hash or timestamp was altered, so data_manifest.json remains the record of the run that produced the committed results; - stop full_pipeline.py overwriting data_manifest.json with its own observed hashes. That destroyed the reference fetch_data.py compares against, so after a single pipeline run a reader would have been checking their data against itself. The observed manifest now goes to a separate, gitignored data_manifest.observed.json; - rewrite the README Data section with the correct expectation. No analysis result changes. Verified by running the pipeline before and after and diffing every value in full_pipeline_results.json: zero differences. pytest: 11 passed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Records three instructions to apply in later steps so they survive: the sizing write-up must not present weekly resizing as a pure restoration or -7.57% as a baseline being departed from; the provenance footnotes deleted from 4d21c69 must be restored; and the changelog and PR text must be split into implementation defects, proposed methodological changes, and manuscript corrections, with the 25-of-504 exposure figure stated plainly. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The file mixes CRLF and LF line endings. Editing it through Python's text mode rewrote every CRLF line as LF, which turned a one-line addition into a 71-line diff and would have looked, in review, like an unexplained rewrite of the ignore rules. Restores the file byte-for-byte from its previous state and re-inserts only the single new entry, matching its neighbours' terminator. No rule other than analysis/data_manifest.observed.json is added, removed, or reordered. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…rule Resolves the sizing conflict the Codex branch introduced and left self-contradictory: Equation 10 reads "contemporaneous AI_t" while the same paragraph asserts the size is fixed at entry. Verified against 4d21c69, the July 2026 version: the manuscript said "Rebalancing: Weekly (end of Friday close)", Equation 10 subscripted AI by t, and the original code recomputed the size from the current ai_20w on every bar where the entry signal fired -- which, given the dead exit branch, was every bar on which a position was held. Paper and code agreed on weekly resizing. Codex departed from both and rewrote the rebalancing line to match its code, disclosing the change nowhere. This is a SPECIFICATION DECISION, not a bug fix, and neither option is a pure restoration. Repairing the dead exit branch creates held-but-unsignalled weeks that the published rule never had to size, because the original implementation could not reach that state. Weekly resizing is adopted as the smaller extension: it keeps the manuscript's stated rebalancing frequency and Equation 10's contemporaneous index, and changes no published sentence. Freezing at entry is reported as the alternative, and the argument against weekly resizing -- that it promotes AI toward a second timing signal -- is recorded in docs/REVIEW_NOTES.md rather than omitted. - run_asymmetry_strategy takes sizing="weekly" (default) or sizing="entry"; resizing changes the notional only, never opening or closing an episode, flipping direction, or resetting the four-return holding clock; - both variants run in the pipeline and are reported under sizing_variants; - trade_ledger column position_size renamed entry_position_size, since the notional now varies within an episode; - corrects the strategy.py claim that Monday-open prices are unavailable: the daily bars carry an Open column, so the Friday-close proxy is a choice. Results, weekly vs entry: return -6.64% vs -7.57%, Sharpe -0.153 vs -0.173, drawdown -12.56% vs -14.29%, turnover 52.00 vs 49.15 units, execution legs 61 vs 30. Entries, exits, direction, hit rate, 55 in-position weeks and 15 holding episodes are identical under both. No conclusion in the paper turns on the choice. Constraints: n = 504, 2016-01-08 to 2025-08-29. Factor intercept -0.00011964 against a mean weekly return of -0.00012029. Low- and high-VIX returns compound to -6.640684% against a full-sample -6.640684%. Both identities hold. pytest: 14 passed, from 11. One test encoded the frozen-size specification and was rewritten to the weekly one; three were added. Changing a test to match changed behaviour is disclosed deliberately -- the rewritten assertions are part of the specification decision, not incidental maintenance. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ssification Answers two questions on the record rather than by inference. Cost scaling: analysis/strategy.py:329 defines unit_cost as a cost per unit of notional, and every event multiplies it by the notional actually traded. There is no fixed per-leg term in the model. Verified empirically -- total units charged equal total turnover exactly under both sizing modes. So doubling the legs is irrelevant and the 5.8% turnover rise is what matters; cost rose 5.6%. Resizes are 51% of legs but 11% of turnover, because ai_20w is a 20-week rolling statistic and moves slowly. Carries the caveat that this is partly a property of the cost model: it has no per-ticket component, so it cannot penalise 31 extra small orders. Added to the backlog. Records the full cost sensitivity table and the White RC and Hansen SPA figures under weekly sizing alongside the frozen ones, and notes that break-even is undefined under both because the gross return is already negative. Reclassifies the rewritten test assertions out of the constraint-check block and into the specification decision, so they are reviewed as category (b) methodological changes rather than as maintenance. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The walk-forward reported a 2.74% pooled return, a 0.3186 Sharpe ratio, a 50% hit rate and a 0.35% annualized return from new_episodes = 1. A Sharpe ratio, a hit rate and an annualized return are sample statistics; from one holding episode they describe the path that happened and carry no information about the path that would be expected. The 50% hit rate is one profitable week and one unprofitable week. - full_pipeline.py gains MIN_EPISODES_FOR_INFERENCE = 2 and emits inference_supported per year and pooled, with a reporting_rule string. Two is not a threshold at which inference becomes sound; it is the point below which these quantities stop being statistics at all; - the pipeline logs the suppression when it fires, so the decision is visible in the run output rather than being an absence; - every suppressed quantity is still computed and still written to full_pipeline_results.json. That file is the audit record, and deleting numbers from it would make the reporting decision unverifiable; - tab:oos is rebuilt around what the procedure did -- test year, training window, selected threshold, new holding episodes. The performance columns are removed rather than filled with dashes, and the note states that their absence is deliberate; - the prose now argues the point positively: the finding is the activity count itself, which is a stronger result than any return from one episode because it does not depend on how that episode turned out. Raises but does not resolve a consistency question: the threshold-sensitivity table reports a Sharpe ratio and hit rate for the 1.25 threshold from the same single episode. The identical objection applies. Left untouched because item 3 named the walk-forward, and recorded in REVIEW_NOTES for a decision. No analysis result changes. n = 504, 2016-01-08 to 2025-08-29; both identities hold. pytest: 14 passed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Step 4, with the approved extension of step 3 folded in.
Sensitivity table (approved scope extension): the 1.25 threshold reported a
Sharpe ratio and hit rate from one holding episode -- the same 2020 episode
the walk-forward selects. MIN_EPISODES_FOR_INFERENCE, supports_inference()
and INFERENCE_REPORTING_RULE are now module-level and applied wherever such
statistics are produced, so a quantity withheld in one table cannot reappear
in another. Both suppressions are logged when they fire.
The defect there is row-level rather than column-level -- thresholds 0.50,
0.75 and 1.00 rest on 25, 15 and 4 episodes -- so removing the columns would
have deleted valid information for three rows to suppress one. The table now
leads with Episodes and Exposed Weeks, which vary monotonically where the
return does not, and the 1.25 row's performance cells are replaced by a single
spanned "single episode: not reported" with the reason given. Nothing is
dashed and nothing is unexplained.
Momentum finding: previously visible only in the factor table and in two
passing adjectives. Now argued in the text from the current weekly-sizing
column -- b = -0.046, t = -2.08, p = 0.038 full sample; b = -0.823,
t = -3.73, p = 0.00019 in position, against -0.007 (p = 0.71) and -0.247
(p = 0.61) in the published version.
Written into the factor-table note with the pre-correction values, into two
new paragraphs of the Factor Attribution discussion, into the Discussion as a
fifth failure mode ("It Is Not Trading Asymmetry"), and into the abstract.
The substantive claim: read on the exposure sample the strategy behaves close
to a one-for-one short position in twelve-week momentum on the pair it trades,
a mechanical consequence of a short leg that fires after the price has run
above its sixty-day average. An asymmetry strategy that is a disguised
short-momentum bet is not harvesting asymmetry, which sharpens the null rather
than softening it.
Caveats written in: the full-sample p = 0.038 is marginal and would not
survive this paper's own Bonferroni discipline at family size six; the
full-sample coefficient is mechanically attenuated by 449 structurally zero
weeks; Mom is a single-pair rule, not the cross-sectional factor; 55 weeks
from 15 episodes is small and serially dependent.
No analysis result changes. n = 504, 2016-01-08 to 2025-08-29; both identities
hold. pytest: 14 passed.
Cannot compile the PDF -- no LaTeX toolchain here -- so paper/alpha-asymmetry.pdf
is stale. Structural checks were run on the source instead. docs/PROPOSED_PR.md
still claims the PDF was compiled and inspected; that is Codex's claim and must
be removed or re-earned.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Step 5, plus the PDF disclosure. Cost accounting, comments only, no executable line changed: - pip_size = 0.01 is yen-pair specific and is now documented at the point of use. A pip is 0.01 only for pairs quoted to two decimals; for GBP/USD it is 0.0001 and for SPY or GLD the notion does not apply. Passing JPY pips to a non-JPY market overstates cost by a factor of 100 and raises nothing. Nothing is currently mispriced -- the cost table runs only on EUR/JPY and the cross-market section runs at zero cost -- but that is a property of the callers, not of the default, and the comment says so; - the absence of any fixed per-leg or per-ticket term is stated where the cost is computed, so total charged units equalling total turnover is documented rather than left to be derived; - the resize branch's reachability is documented, including that it is unreachable under sizing="entry", which is why sizing is a parameter and not a fork. The other half of item 5 -- removing the dead resize branch -- is withdrawn by consequence rather than skipped. It was dead only under Codex's frozen sizing. Under weekly sizing it prices all 31 within-episode notional changes, 11% of turnover. docs/PROPOSED_PR.md: deletes the claim that "LaTeX was compiled and the resulting PDF was rendered and visually inspected." That claim originated with Codex, is false for this branch, and must not reach the repository owner inside a pull request about unverified assertions. Replaced with an explicit statement that the committed PDF is Codex's stale September build, that no LaTeX toolchain was available, and exactly which structural checks were run on the source instead -- brace balance, matched table/tabular/equation environments, and per-table column counts including multicolumn spans -- together with what those checks do not establish. The owner has the toolchain and should rebuild and inspect. Also records in REVIEW_NOTES.md that the sensitivity-table deviation from the instruction to remove columns was proposed and approved explicitly, with the reason, and that leading the table with Episodes and Exposed Weeks is a substantive improvement rather than formatting: activity falls monotonically where the return ordering is noise. pytest: 14 passed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…output Sweeps the manuscript to the weekly-sizing results and lands the three statements agreed after step 2. Every table figure was machine-checked against analysis/full_pipeline_results.json; all match. Specification text, carried over from step 2 and not previously in the paper: - Position Sizing now states that the sizing equation is evaluated at each Friday close while a direction is held, and the execution list restores "Rebalancing: weekly at the Friday close" in place of Codex's "none within an episode"; - a paragraph discloses the sizing choice as a choice: repairing the exit rule creates held-but-unsignalled weeks the published specification never had to size, both readings are extensions to that state, weekly is adopted as the smaller one, and no conclusion depends on it; - the false claim that Monday opening prices are absent from the dataset is replaced with a statement that the Friday-close proxy is a choice, since the daily bars carry an opening price. Break-even, stated rather than dropped: the published 19.2-pip figure was meaningful only while gross return was positive. There is now no break-even cost at all -- the strategy does not break even at any cost because it does not break even at zero cost. Written into the cost section, the cost-table note, the abstract and the conclusion, as a stronger statement of the null than the cost table it replaces. Cost-model limitation: spread is charged strictly in proportion to notional with no fixed or minimum per-order component, while the corrected specification generates 31 resizings averaging 0.19 units -- exactly the population a per-ticket charge falls hardest on. The reported drag is a lower bound, and "costs are immaterial" is a claim this model cannot make. Data-snooping footnote explaining why the RC and SPA statistics are identical across sizing specifications: both take a maximum over the candidate universe, that maximum belongs to the seeded random candidate, and only the bootstrap covariance sees a change confined to the asymmetry rule. Prose contradicted by the corrected numbers without containing a figure: - the robustness intro described an in-sample backtest "statistically indistinguishable from zero" and asked whether costs "erode strategy returns"; both presuppose an edge that no longer exists; - the drawdown paragraph called -12.56% "only modestly smaller" than buy-and-hold's -15.78%; it now notes that losing four-fifths of a permanently invested position's drawdown while exposed in 55 of 504 weeks is not evidence of risk control; - the trading-frequency paragraph said "no resizing", which is false under weekly sizing. The momentum finding is added to the conclusions, which previously carried it nowhere despite it being a fifth failure mode in the discussion. No analysis result changes. pytest: 14 passed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…gory Three record items plus the footnote restoration. Footnotes: 4d21c69 carried nine "an earlier version of this table..." notes recording the paper's own prior corrections. Codex deleted seven and kept two, which is not a systematic editorial decision. All seven are restored. Four were named in review; the other three -- the cross-market MR/TF/HAT categories, the cost table's net return rising with costs, and RC = 2.14 -- were found by enumerating the notes at the base commit rather than by working from the list. Each is restored verbatim, with any current value appended as a following sentence rather than woven into the original. These notes are a dated record of what was wrong and when; editing them to agree with today's numbers would destroy what makes them worth having. Verified mechanically that all nine original sentences appear as exact substrings. That check caught a violation: the first attempt inserted "then reported" inside the factor-attribution sentence, a two-word rewrite of the historical record. Fixed, and the check is kept. The 2020 subsample return of 2.74% is identical under both sizing specifications and identical to the lone walk-forward episode, because 2020 contains a single holding episode whose notional was never revised. It looks exactly like a figure someone forgot to update, so the subsample table note now says why it is not. Cross-market traceability, recorded before anyone asks: the spread widened toward a more striking result, so the provenance is established. The cross_market code block is byte-identical between the Codex import and HEAD, and rerunning it with sizing="entry" and no other change reproduces Codex's committed figures exactly. The movement is the sizing default alone; the input skewness statistics are unchanged. REVIEW_NOTES records the prose fixes as their own category, separate from the count of figures changed: "statistically indistinguishable from zero", "do trading costs erode strategy returns", "no resizing", and the drawdown framing were all wrong without containing a wrong digit. The general form is that the published paper argued a modest edge survived measurement and was not eliminated by costs; every sentence resting on that architecture is wrong under the corrected numbers regardless of its digits, and such sentences must be hunted by reading for the argument rather than by checking figures. pytest: 14 passed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Rebuilds the correction narrative on 4d21c69, the published July 2026 version, rather than on the unreviewed intermediate draft this branch started from. That draft was never adopted upstream and its figures have no standing with the repository owner, so every before/after comparison now runs published versus corrected. before_after_results.csv is rebuilt on the published baseline with a per-row "stage" column attributing each change to the correction that produced it -- implementation defect, accounting redefinition, sizing choice, or reporting decision -- and a note explaining it. Rows added for volatility, Sortino, turnover, execution legs, the four subsample returns, all four momentum coefficients, break-even, and the withheld walk-forward statistics. The GBP/USD sign flip is called out explicitly: +17.18% published to -13.32% corrected, attributable to the implementation fixes rather than to the sizing proposal, since the frozen-notional alternative gives -14.11%. The published paper's claim that FX offers more favourable conditions rested on that 17%, and rejecting the sizing proposal does not restore it. Changelog and PR restructured into the agreed categories: (a) implementation defects, where the paper and code genuinely disagreed and the code was wrong; (b) methodological changes proposed, where they agreed and we are departing -- the sizing rule for held-but-unsignalled weeks, the trade-accounting redefinition, and the refusal to report single-episode statistics; (c) manuscript corrections, split into the paper mis-stating its own code and the two disagreements resolved in the code's favour against the working rule; (d) prose wrong without a wrong figure; (e) restored footnotes; (f) reproducibility. The sizing freeze is out of "confirmed implementation bugs" entirely -- it was never a defect. The 25-of-504 exposure figure leads both documents as the single most important number, with the explanation that it is why the published null result had little content. The footnote entry names the data-snooping note specifically: RC = 2.14 (p = 0.042) was the paper's most quotable statistic and the only significant one in it, and the deleted note recorded that it was already known to be irreproducible. Records that keeping two of nine is what happens when notes are dropped during a prose rewrite rather than an editorial choice, and records the verbatim-restoration violation the substring check caught -- as method, since the claim of verbatim restoration is only worth something because it was machine-enforced. The Codex-labelled-it-a-bug framing is dropped throughout both documents. Codex remains as a short provenance note in each, saying what 5135bac is and that it was audited rather than adopted, and in the sizing evidence trail where it is load-bearing. REVIEW_NOTES.md gains a header stating that it is the working audit record and not part of the PR's argument. pytest: 14 passed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Author block: Tofik Israfilov added as second author, affiliated to Dissensus, tofiq@dissensus.ai. No ORCID supplied, so none is printed. The "Sole author" contribution line is replaced with an itemised statement -- original research, design, analysis code and manuscript to M. Farzulla; audit of the published version against its code, identification of the specification mismatches, the decisions resolving them, and the correction record to T. Israfilov, with an explicit statement that he did not author the analysis code. Confidence pass on the two new claims. The break-even subsection survived unchanged. The momentum section did not, and one problem was not a matter of emphasis: The text argued that the strategy's loss was partly explained by a momentum exposure "one that lost money over this sample", citing -18.92%. That figure belongs to the twenty-week benchmark, not to the twelve-week regressor, and the argument inverts: the strategy is SHORT momentum, so a momentum factor that lost money would have made it money. The twelve-week factor in fact gained 2.63% over the full sample and 1.93% over the 55 exposed weeks. The conclusion survives -- momentum rose and the strategy was short it, costing roughly -1.6 percentage points, about a quarter of the -6.64% loss -- but the reason given was backwards. Also corrected: R^2 of 0.203 was attributed to momentum alone when it is the three-factor figure (momentum alone is 0.122); "close to a one-for-one short position" now carries the 95% CI [-1.26, -0.39] and is bounded accordingly; "largely explained" replaced, since twelve percent leaves seven-eighths unexplained; the mechanism is offered rather than asserted; the section heading changes from "It Is Not Trading Asymmetry" to "It Is Partly Trading Momentum"; and the R^2 comparison no longer reads as a like-for-like rise between two different samples. Applied in all four places the claim appears -- abstract, discussion, factor section, conclusion -- and every figure re-verified against full_pipeline_results.json and by independent recomputation of the confidence interval, the partial R-squared and the exposure contribution. REVIEW_NOTES records the inverted argument as its own finding: it sat in the section presented as the paper's new contribution, it passed the numbers sweep because its figure was correctly computed and attached to the wrong claim, and it was caught by asking what the regressor itself returned rather than by proofreading. Also records the contrast with the break-even section, and the PR text's own now-false claim about the LaTeX toolchain. pytest: 14 passed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
AI disclosure rewritten with symmetric attribution: both authors are named as directing AI assistance in their own phase, M. Farzulla for the original version and T. Israfilov for the corrections. The earlier draft named only the latter, which would have implied the former was not answerable for the assistance used in his own work. Retains the statement that the verification apparatus caught errors that review by reading did not, and adds that the apparatus is part of the contribution rather than housekeeping -- it is what lets these corrections be checked instead of trusted, and it is reusable. Version bumped 3.0.0 -> 3.1.0. The reasoning offered for this was checked and was partly wrong: 3.0.0 was not set by the intermediate draft but by Studio Farzulla in f04ae08 on 2026-07-21. It was however never deposited, which CITATION.cff confirms. The repository carried three disagreeing version identifiers before this branch -- 3.0.0 in the .tex, 2.1.0-dev in CITATION.cff, and v2.0.1 as the last Zenodo deposit -- and reconciling them is on the backlog as the author's call. Note that \paperver and \paperdoi are defined but never rendered, so neither appears in the compiled PDF. CITATION.cff: second author added to both the authors list and the preferred citation, version aligned to 3.1.0-dev with the prior disagreement documented in the file, repository-code corrected from studiofarzulla to dissensus-ai. PR text: the summary bullet still carried the pre-confidence-pass phrasing ("substantially a short momentum bet"); brought in line with the manuscript. The PDF sections of both documents are rewritten -- they had asserted that no LaTeX toolchain was available and the PDF could not be rebuilt, which was true when written and is no longer. The sequence is recorded rather than tidied away, since a document asserting something about itself that stopped being true is the failure this PR exists to correct. Adds the recommendation to post a correction notice against the superseded record, given a signed headline moving from +3.60% to -6.64%. PDF rebuilt with Tectonic: 27 pages, zero overfull and underfull boxes, no undefined references, no LaTeX warnings, bibliography resolved. Both figures confirmed byte-identical to a fresh pipeline run before compiling. pytest: 14 passed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The title page reads "Tofik Israfilov"; the GitHub account, the git commit authorship on this branch and the personal email all read "tofigisrafilov". Left as-is for the pull request on instruction, and recorded as a decision owed before deposit. Once a version carries a DOI the author string propagates into Scholar, ORCID and Crossref, and disambiguation services key on exact strings, so the two forms would be indexed as two people. Free to fix now, expensive after the first citation. Notes that registering an ORCID is what makes the question survivable if both forms are going to exist. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Proposed pull request
Title
Correct the holding rule, execution lag and asymmetry index; regenerate all downstream results
Summary
The published code did not implement the strategy the published paper describes.
Three defects are corrected here. The largest of them meant that
It closed any open position the moment its entry signal stopped firing, which is
not the exit rule §2.4 states. Corrected, it holds a position in 55 weeks.
Every headline figure in the paper — the +3.60% return, the 0.149 Sharpe ratio,
the factor regression with its 25-observation effective sample, the "immaterial"
transaction costs, the 19.2-pip break-even — described that five percent of the
sample. That is why the published null result had so little content: a strategy
that is almost never invested cannot demonstrate much in either direction.
The corrected strategy loses 6.64% gross over the decade, Sharpe −0.153,
across 15 holding episodes. The paper's conclusion is unchanged in direction and
considerably stronger in substance. Two findings are new, and both sharpen the
null rather than softening it:
break-even presumes a gross profit to be consumed, and there is none.
negatively and significantly on time-series momentum (β = −0.82, 95% CI
[−1.26, −0.39], p = 0.00019 on in-position weeks), a loading that was
insignificant before correction. Momentum rose over the exposed weeks and the
strategy was short it, which accounts for roughly a quarter of the realized
loss — so part of that loss reflects a known factor exposure rather than a
failure specific to asymmetry. Momentum alone explains 12% of the variation in
in-position returns, so this is a material exposure rather than the whole
story.
The sample is unchanged: n = 504, 8 January 2016 to 29 August 2025.
How to read this PR
Changes are grouped so that each group can be accepted or rejected on its own:
does X. Three items. Nothing is in this group unless the published paper and
the published code genuinely disagreed.
this PR proposes something different. Three items, each reversible without
disturbing (a).
it wrongly.
docs/CORRECTION_CHANGELOG.mdhas the full detail.analysis/before_after_results.csvgives every changed figure with its publishedvalue, its corrected value, and which category produced the change.
(a) Implementation defects corrected
4d21c69)pos.var()/neg.var()— re-centres each subgroup, uses n−1, and returns a neutral-looking1.0where the statistic is undefineda1 is the one that matters: 25 → 55 exposed weeks, and the dominant driver of
nearly every changed figure.
(b) Methodological changes proposed
These are judgement calls. The published paper and the published code agreed in
each case; this PR proposes departing from them.
b1. How to size a week in which a direction is held but no signal fires
Fixing a1 creates a state the published specification never had to describe,
because the published implementation could never reach it. The published rule was
"Rebalancing: Weekly (end of Friday close)" with Equation 10 evaluated at the
contemporaneous
AI_t, and the published code did resize on every bar it held aposition — so paper and code agreed. Neither ever faced a held but unsignalled
week.
Proposed: evaluate the sizing equation weekly while a direction is held, as
the smaller of the two available extensions — it keeps the published rebalancing
frequency and the contemporaneous subscript, and changes no published sentence.
Freezing the notional at entry is the alternative; it is computed in the same run
and reported.
Entries, exits, direction and exposure are identical. No conclusion depends on
the choice. The argument against the proposal is in the changelog rather than
omitted.
b2. "Trades" reported as holding episodes and execution legs
The published paper defined trades as "position-change events divided by two" and
the code implemented exactly that — but the label said "completed round trips",
which that formula does not compute. For the momentum benchmark it reported 27
round trips for 54 directional holdings and 107 executions.
Proposed: report holding episodes and execution legs separately, with
resizing and turnover, from dated ledgers. Headline: 17 published "trades" → 15
episodes and 61 legs. The underlying returns are untouched by this item.
b3. Statistics from a single episode are not reported as performance
The corrected walk-forward opens one out-of-sample episode in eight test
years. A Sharpe ratio, a hit rate and an annualized return computed from one
episode are not estimates of anything — the published 60% hit rate meant three
weeks, and one episode would mean one up week and one down week.
Proposed: decline to print them. The rule is enforced in code, applied
wherever such statistics arise rather than table by table, and logged when it
fires. Suppressed values stay in
full_pipeline_results.jsonso the decision ischeckable. Withheld figures are removed with the reason given, never replaced by
an unexplained placeholder.
The walk-forward table now reports what the procedure did — training window,
selected threshold, episodes opened. The activity count is the finding, and
it is a stronger one than any return from a single episode because it does not
depend on how that episode happened to turn out.
(c) Manuscript corrections
The paper mis-stated its own code in four places: the fast-alpha equation showed
a price difference where the code uses a percentage return (the printed version
divides yen by a percentage volatility and is dimensionally incoherent); the
position-size formula carried an unreachable 0.5 floor and a "no leverage" claim
when the real range is [1, 2] gross-notional units; hedge alpha was printed with
a time-varying rate differential that exists nowhere in the repository, the code
using a fixed −2% constant; and the tail-alpha window was described in weeks
where the code uses trading days.
Two disagreements were resolved in favour of the code, against the working
rule that the code gets fixed to match the paper. Both are flagged so they can be
overruled:
close. The Friday close is kept — but a false justification is removed. An
earlier draft of this correction claimed Monday opening prices are absent from
the dataset. They are present; the daily bars carry an
Opencolumn. TheFriday-close proxy is a choice, and the paper now says so. Implementing
Monday-open execution is on the backlog.
exceedances; the code fits absolute weekly returns. The section is relabelled
as a weekly-return diagnostic. The rule says the code should have been changed
instead; refitting is on the backlog, and the relabelling should not be
mistaken for the fix.
(d) Prose corrected without a wrong figure
The manuscript sweep changed 38 figures across 21 locations. But a
figure-by-figure sweep does not catch a sentence whose argument depends on a
result that no longer holds, and those matter more.
The published paper argued that a modest gross edge survived measurement and was
not eliminated by costs. Every sentence resting on that architecture is wrong
under the corrected numbers regardless of its digits. Examples, none containing
an incorrect figure: the robustness section described a backtest "statistically
indistinguishable from zero" (defensible on the interval, but it presents a
losing strategy as a null one) and asked whether costs "erode strategy returns"
(presupposing returns to erode); the drawdown paragraph called the figure "only
modestly smaller" than buy-and-hold's, presenting as mitigating what is damning —
four-fifths of a permanently invested position's drawdown, incurred while exposed
in 55 of 504 weeks.
The break-even statement is the clearest case. The published paper reported a
break-even round-trip cost of 19.2 pips and read it as reassurance. That figure
was meaningful only while the gross return was positive. It is not that the
corrected break-even is larger, or harder to estimate: it does not exist, and
the paper now says so in the cost section, the abstract and the conclusion. It is
a cleaner statement of the null than the cost table it replaces.
One qualification is added rather than removed: costs remain small in magnitude
(0.38pp at two pips), but the model charges spread strictly in proportion to
notional with no per-order component, while the corrected specification
generates 31 resizings averaging 0.19 units — exactly the population a per-ticket
charge would fall hardest on. The reported drag is a lower bound.
(e) Provenance footnotes restored
4d21c69carried nine table notes recording the paper's own earlier corrections.Seven had been deleted during the drafting of this branch; all seven are
restored. Two survived — and keeping two of nine is not an editorial decision,
it is what happens when notes get dropped while the prose around them is
rewritten.
One deserves singling out. The data-snooping note recorded that the published
RC = 2.14 (p = 0.042)was not reproducible from any specification of the statedcandidate universe. That is the paper's most quotable statistic — the one number
in it that reported a significant result. Deleting the note deleted the record
that it was already known to be unreliable.
Each note is restored verbatim, with current values appended as a following
sentence rather than woven into the original. These notes are a dated record of
what was wrong and when; editing them to match today's numbers would destroy what
makes them worth keeping.
That preservation was enforced mechanically, not by eye: every one of the nine
original sentences is checked to appear in the current source as an exact
substring. The check earned its place — a first attempt inserted the words "then
reported" inside the factor-attribution sentence, a two-word rewrite of the
historical record that reading would not have caught. The claim of verbatim
restoration is worth something only because a machine enforced it.
Result changes
Full table with per-item attribution in
analysis/before_after_results.csv.4d21c69)The GBP/USD sign flip is a finding, not a rounding. The published paper reads
+17.18% on GBP/USD as evidence that FX offers more favourable conditions for the
strategy than equities or gold. Corrected, it is −13.32%, and the flip is
attributable to the implementation fixes, not to the sizing proposal: with the
implementation fixes and the frozen-notional alternative the figure is −14.11%.
Rejecting (b1) does not restore the published reading. The cross-market section's
claim about FX conditions no longer has a basis.
For the same reason, the widened cross-market spread is traceable: the
cross_marketcode block is byte-identical to the version this branch startedfrom, and rerunning it under the frozen alternative reproduces the intermediate
figures exactly. The movement is the sizing default alone; the input skewness
statistics are unchanged in all four markets.
Verification
timing convention, entry, hold, expiry, reversal, simultaneous signals,
no-signal periods, both sizing modes, resize cost accounting and reversal
accounting.
--offline.download (see Data below).
analysis/full_pipeline_results.json.presence.
intercept matches the strategy's own mean weekly return
(−0.00011964 against −0.00012029); the low- and high-VIX returns compound to
the full-sample return (−6.640684% against −6.640684%).
The PDF was rebuilt and inspected
paper/alpha-asymmetry.pdfis rebuilt from the corrected source. It compilesclean: 27 pages, zero overfull boxes, zero underfull boxes, no undefined
references or citations, bibliography resolved against
references.bib.Both figures were regenerated from the current pipeline and compared
byte-for-byte against the committed versions.
backtest_results.pngis drawnfrom the corrected return series.
alpha_asymmetry_analysis.pngis unchangedsince before the sizing change, which is correct: it shows the alpha
distributions, which do not depend on the strategy.
The PDF's own text was extracted and checked. The corrected figures are present;
none of the superseded ones appear anywhere.
A note on this section, because it is the third time this document has made a
claim about its own provenance. The draft this branch started from asserted
that the PDF had been compiled and visually inspected when it had not. That was
removed and replaced with a statement that no LaTeX toolchain was available and
the PDF was stale. That statement was true when written and later stopped being
true, when a self-contained engine was installed and the paper compiled. A
document asserting something about itself that has since become false is the
failure this pull request exists to correct, so the sequence is recorded rather
than tidied away, and the build was deliberately left until last so that the
claim and the artefact became true at the same moment.
Version, DOI and supersession — decisions for you
The manuscript now carries
\paperver 3.1.0, incremented from the 3.0.0 you setin
f04ae08for the July manuscript. Three things need your decision:The version identifiers in this repository disagree with each other, and did
before this branch.
paper/alpha-asymmetry.texcarried3.0.0for the Julymanuscript;
CITATION.cffcalled the same work2.1.0-dev; the last depositedversion is
v2.0.1(10.5281/zenodo.20635291). Neither3.0.0nor2.1.0-devwas ever deposited.
CITATION.cffis set to3.1.0-devto follow the numberprinted on the paper, with the disagreement documented in the file. Reconciling
them properly is yours.
Depositing mints a new Zenodo version DOI, which cannot be known in advance.
\paperdoiis therefore left as the concept DOI10.5281/zenodo.18638784, whichresolves to the newest version. After deposit, record the new version DOI in
CITATION.cffandCLAUDE.md. The SSRN record (SSRN:6147567) is separate andneeds its own revision; Zenodo does not propagate to it.
We recommend posting a correction notice against the superseded record, not
merely depositing a new version. The headline result changes sign: +3.60% to
−6.64%. A reader who lands on v2.0.1 through a citation or a search result has no
way to know it has been superseded, and the specific claim they would take away —
that the strategy earns a small positive gross return — is wrong rather than
imprecise. Depositing a new version alone leaves that reader uninformed. This is
your call as author and it carries reputational weight either way, but asked
directly: we would post the notice.
Data, and a decision for you
The raw CSVs are not committed, and
analysis/cache/remains gitignored.analysis/data_access.pygives the reason: Yahoo Finance data may be subject toredistribution terms. Publishing eight files of vendor data in a public
repository is a licensing decision for the repository owner, not one an outside
contributor should make inside a correctness PR — so it is raised here for you
to decide rather than taken.
What is provided instead:
analysis/fetch_data.pydownloads the inputs andverifies each file's SHA-256 against the committed manifest, so a fresh clone can
obtain the data and confirm it is the same data.
Seven of eight hashes reproduce byte-for-byte. Six of the eight series are FX
spot rates or index levels, which carry no corporate-action adjustment and
structurally cannot drift; GLD paid no distribution over the window. SPY, a
distributing ETF fetched with
auto_adjust=True, has its entire history rescaledby every new distribution — the only file in the set that could differ, and it
did. That is the expected outcome rather than a near miss. The difference moves
five values in the SPY cross-market row in their fifth or sixth significant
figure, each rounding to the same printed number, and nothing else in the
pipeline.
Reproduction
Questions for you
fetch-and-verify approach?
computed; no conclusion depends on it.
report single-episode statistics. Both are reversible.
specifying Monday open, and relabelling the EVT section rather than refitting
it. Either could be done properly instead.
would let hedge alpha stop being a constant multiplied by a correlation.
Provenance
This branch began from an unreviewed draft produced by an AI agent, committed
unmodified as
5135bacand labelled as such. That commit was audited ratherthan adopted: its claims were checked against
4d21c69, its manuscript editswere reviewed line by line, several were reversed, and every change that survives
is justified in this PR and in the changelog against the published paper. It
carries no authority and is kept in the history only so that the work done after
it is separately reviewable.
docs/REVIEW_NOTES.mdis the working audit record from that process. It is notpart of the argument here.
No branch has been pushed, no pull request opened, and nothing merged.
🤖 Generated with Claude Code