@tangle-network/agent-bench 0.11.3 → 0.13.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/HARNESS.md +6 -2
  3. package/README.md +1 -4
  4. package/package.json +5 -5
  5. package/scripts/run-package-tests.mjs +2 -2
  6. package/src/quant-arena/README.md +0 -144
  7. package/src/quant-arena/backtest.test.mts +0 -135
  8. package/src/quant-arena/backtest.ts +0 -218
  9. package/src/quant-arena/data.test.mts +0 -44
  10. package/src/quant-arena/data.ts +0 -141
  11. package/src/quant-arena/driver.test.mts +0 -253
  12. package/src/quant-arena/driver.ts +0 -219
  13. package/src/quant-arena/fixtures/data/PROVENANCE.md +0 -26
  14. package/src/quant-arena/fixtures/data/holdout/IDX.csv +0 -523
  15. package/src/quant-arena/fixtures/data/holdout/S01.csv +0 -523
  16. package/src/quant-arena/fixtures/data/holdout/S02.csv +0 -523
  17. package/src/quant-arena/fixtures/data/holdout/S03.csv +0 -523
  18. package/src/quant-arena/fixtures/data/holdout/S04.csv +0 -523
  19. package/src/quant-arena/fixtures/data/holdout/S05.csv +0 -523
  20. package/src/quant-arena/fixtures/data/holdout/S06.csv +0 -523
  21. package/src/quant-arena/fixtures/data/holdout/S07.csv +0 -523
  22. package/src/quant-arena/fixtures/data/holdout/S08.csv +0 -523
  23. package/src/quant-arena/fixtures/data/holdout/S09.csv +0 -523
  24. package/src/quant-arena/fixtures/data/holdout/S10.csv +0 -523
  25. package/src/quant-arena/fixtures/data/insample/IDX.csv +0 -2087
  26. package/src/quant-arena/fixtures/data/insample/S01.csv +0 -2087
  27. package/src/quant-arena/fixtures/data/insample/S02.csv +0 -2087
  28. package/src/quant-arena/fixtures/data/insample/S03.csv +0 -2087
  29. package/src/quant-arena/fixtures/data/insample/S04.csv +0 -2087
  30. package/src/quant-arena/fixtures/data/insample/S05.csv +0 -2087
  31. package/src/quant-arena/fixtures/data/insample/S06.csv +0 -2087
  32. package/src/quant-arena/fixtures/data/insample/S07.csv +0 -2087
  33. package/src/quant-arena/fixtures/data/insample/S08.csv +0 -2087
  34. package/src/quant-arena/fixtures/data/insample/S09.csv +0 -2087
  35. package/src/quant-arena/fixtures/data/insample/S10.csv +0 -2087
  36. package/src/quant-arena/fixtures/demo-campaign/cost-ledger.jsonl +0 -16
  37. package/src/quant-arena/fixtures/demo-campaign/notebook.jsonl +0 -5
  38. package/src/quant-arena/fixtures/demo-campaign/rollout-manifest.json +0 -171
  39. package/src/quant-arena/fixtures/demo-campaign/strategies/cand-001-default-author/strategy.ts +0 -119
  40. package/src/quant-arena/fixtures/demo-campaign/strategies/cand-002-default-author/strategy.ts +0 -119
  41. package/src/quant-arena/fixtures/demo-campaign/strategies/cand-003-quant-researcher/strategy.ts +0 -105
  42. package/src/quant-arena/fixtures/demo-campaign/strategies/cand-004-quant-researcher/strategy.ts +0 -102
  43. package/src/quant-arena/fixtures/demo-campaign-v2/cost-ledger.jsonl +0 -4
  44. package/src/quant-arena/fixtures/demo-campaign-v2/notebook.jsonl +0 -2
  45. package/src/quant-arena/fixtures/demo-campaign-v2/rollout-manifest.json +0 -84
  46. package/src/quant-arena/fixtures/demo-campaign-v2/strategies/cand-001-quant-researcher/strategy.ts +0 -117
  47. package/src/quant-arena/holdout-certify.mts +0 -206
  48. package/src/quant-arena/holdout-certify.test.mts +0 -82
  49. package/src/quant-arena/leak-audit.test.mts +0 -79
  50. package/src/quant-arena/leak-audit.ts +0 -95
  51. package/src/quant-arena/make-fixtures.mts +0 -161
  52. package/src/quant-arena/multiplicity.test.mts +0 -68
  53. package/src/quant-arena/multiplicity.ts +0 -87
  54. package/src/quant-arena/nautilus-certify.ts +0 -31
  55. package/src/quant-arena/oms.ts +0 -90
  56. package/src/quant-arena/profiles/quant-researcher.profile.json +0 -12
  57. package/src/quant-arena/python/pyproject.toml +0 -8
  58. package/src/quant-arena/python/uv.lock +0 -1297
  59. package/src/quant-arena/python/vbt-worker.py +0 -192
  60. package/src/quant-arena/quant-loop.mts +0 -840
  61. package/src/quant-arena/quant-loop.test.mts +0 -75
  62. package/src/quant-arena/strategies/buy-hold-index/strategy.ts +0 -11
  63. package/src/quant-arena/strategies/equal-weight/strategy.ts +0 -20
  64. package/src/quant-arena/strategies/sma-crossover/strategy.ts +0 -42
  65. package/src/quant-arena/types.ts +0 -133
  66. package/src/quant-arena/vbt-client.ts +0 -321
  67. package/src/quant-arena/vbt-parity.test.mts +0 -183
  68. package/src/quant-arena/windows.test.mts +0 -45
  69. package/src/quant-arena/windows.ts +0 -54
  70. package/src/rollout-ledger/backfill-swe-arena.mts +0 -610
  71. package/src/rollout-ledger/backfill-swe-arena.test.mts +0 -347
  72. package/src/rollout-ledger/settle-capture.mts +0 -448
  73. package/src/rollout-ledger/settle-capture.test.mts +0 -270
  74. package/src/swe-arena/activation.mts +0 -225
  75. package/src/swe-arena/activation.test.mts +0 -300
  76. package/src/swe-arena/analyze.ts +0 -211
  77. package/src/swe-arena/arms.ts +0 -862
  78. package/src/swe-arena/bootstrap-meta.mts +0 -188
  79. package/src/swe-arena/bootstrap-meta.test.mts +0 -51
  80. package/src/swe-arena/briefing.mts +0 -217
  81. package/src/swe-arena/briefing.test.mts +0 -179
  82. package/src/swe-arena/calibrate.ts +0 -217
  83. package/src/swe-arena/capabilities.mts +0 -76
  84. package/src/swe-arena/capabilities.test.mts +0 -57
  85. package/src/swe-arena/capacity.ts +0 -198
  86. package/src/swe-arena/cell-evidence.mts +0 -437
  87. package/src/swe-arena/cell-evidence.test.mts +0 -248
  88. package/src/swe-arena/diagnosis-ensemble.test.mts +0 -210
  89. package/src/swe-arena/diagnosis-ensemble.ts +0 -523
  90. package/src/swe-arena/execution.test.mts +0 -1171
  91. package/src/swe-arena/factory-command-container.ts +0 -284
  92. package/src/swe-arena/factory-judge-child.mts +0 -228
  93. package/src/swe-arena/factory.test.mts +0 -645
  94. package/src/swe-arena/fixtures/analyze.py +0 -80
  95. package/src/swe-arena/fixtures/excludes.txt +0 -8
  96. package/src/swe-arena/fixtures/factory/agent-eval-309/calibration.md +0 -51
  97. package/src/swe-arena/fixtures/factory/agent-eval-309/manifest.json +0 -29
  98. package/src/swe-arena/fixtures/factory/agent-eval-309/spec.md +0 -64
  99. package/src/swe-arena/fixtures/factory/agent-runtime-232/calibration.md +0 -48
  100. package/src/swe-arena/fixtures/factory/agent-runtime-232/manifest.json +0 -29
  101. package/src/swe-arena/fixtures/factory/agent-runtime-232/spec.md +0 -48
  102. package/src/swe-arena/fixtures/factory/loops-28/calibration.md +0 -47
  103. package/src/swe-arena/fixtures/factory/loops-28/manifest.json +0 -30
  104. package/src/swe-arena/fixtures/factory/loops-28/spec.md +0 -50
  105. package/src/swe-arena/fixtures/gen1-salvage/README.md +0 -45
  106. package/src/swe-arena/fixtures/gen1-salvage/cand0-e6d7361.diff +0 -116
  107. package/src/swe-arena/fixtures/gen1-salvage/cand1-76a8590.diff +0 -293
  108. package/src/swe-arena/fixtures/holdout-preregister.log +0 -12
  109. package/src/swe-arena/fixtures/holdout.json +0 -44
  110. package/src/swe-arena/fixtures/instances.json +0 -146
  111. package/src/swe-arena/fixtures/ledger.jsonl +0 -12
  112. package/src/swe-arena/fixtures/patches/pallets__flask-5014.solo.patch +0 -36
  113. package/src/swe-arena/fixtures/patches/pydata__xarray-4687.sup.patch +0 -33
  114. package/src/swe-arena/fixtures/rejudge.jsonl +0 -15
  115. package/src/swe-arena/fixtures/rematch.jsonl +0 -3
  116. package/src/swe-arena/fixtures/rematch2.jsonl +0 -3
  117. package/src/swe-arena/fixtures/rematch3.jsonl +0 -3
  118. package/src/swe-arena/fixtures/run-report/README.md +0 -43
  119. package/src/swe-arena/fixtures/run-report/factory-agent-eval-309-FSUP0.json +0 -173
  120. package/src/swe-arena/fixtures/run-report/factory-agent-eval-309-FSUP0.md +0 -100
  121. package/src/swe-arena/fixtures/run-report/gen3-rollup.json +0 -551
  122. package/src/swe-arena/fixtures/run-report/gen3-rollup.md +0 -64
  123. package/src/swe-arena/fixtures/sup-journal-true.json +0 -19
  124. package/src/swe-arena/fixtures/verify/astropy__astropy-13033.sh +0 -48
  125. package/src/swe-arena/fixtures/verify/django__django-11532.sh +0 -50
  126. package/src/swe-arena/fixtures/verify/matplotlib__matplotlib-20826.sh +0 -76
  127. package/src/swe-arena/fixtures/verify/pydata__xarray-4687.sh +0 -44
  128. package/src/swe-arena/fixtures/verify/pytest-dev__pytest-6197.sh +0 -32
  129. package/src/swe-arena/fixtures/verify/sphinx-doc__sphinx-9658.sh +0 -51
  130. package/src/swe-arena/fixtures/worker-tokens.json +0 -42
  131. package/src/swe-arena/fixtures.ts +0 -237
  132. package/src/swe-arena/gepa-seat.mts +0 -886
  133. package/src/swe-arena/gepa-seat.test.mts +0 -1136
  134. package/src/swe-arena/holdout-certify.mts +0 -408
  135. package/src/swe-arena/holdout-certify.test.mts +0 -160
  136. package/src/swe-arena/implementation-ref.test.mts +0 -64
  137. package/src/swe-arena/implementation-ref.ts +0 -62
  138. package/src/swe-arena/judge-child.mts +0 -37
  139. package/src/swe-arena/ledger-orphans.mts +0 -77
  140. package/src/swe-arena/ledger-orphans.test.mts +0 -149
  141. package/src/swe-arena/manifest.mts +0 -293
  142. package/src/swe-arena/manifest.test.mts +0 -169
  143. package/src/swe-arena/materialize.ts +0 -142
  144. package/src/swe-arena/outer-loop.mts +0 -2854
  145. package/src/swe-arena/outer-loop.test.mts +0 -714
  146. package/src/swe-arena/parity.test.mts +0 -87
  147. package/src/swe-arena/premeasured-from-cells.mts +0 -296
  148. package/src/swe-arena/premeasured-from-cells.test.mts +0 -201
  149. package/src/swe-arena/proc.test.mts +0 -172
  150. package/src/swe-arena/proc.ts +0 -260
  151. package/src/swe-arena/profiles/deepseek-author.profile.json +0 -12
  152. package/src/swe-arena/profiles/default-author.profile.json +0 -12
  153. package/src/swe-arena/proposer-fanout.mts +0 -736
  154. package/src/swe-arena/proposer-fanout.test.mts +0 -660
  155. package/src/swe-arena/proposer-provenance.mts +0 -176
  156. package/src/swe-arena/proposer-provenance.test.mts +0 -106
  157. package/src/swe-arena/reconcile.ts +0 -0
  158. package/src/swe-arena/replay.mts +0 -183
  159. package/src/swe-arena/replay.test.mts +0 -300
  160. package/src/swe-arena/run-experiment.mts +0 -729
  161. package/src/swe-arena/run-report.mts +0 -75
  162. package/src/swe-arena/run-supervisor.mjs +0 -297
  163. package/src/swe-arena/run-supervisor.test.mts +0 -539
  164. package/src/swe-arena/score-split.mts +0 -140
  165. package/src/swe-arena/score-split.test.mts +0 -123
  166. package/src/swe-arena/scratch-worktree-serialization.test.mts +0 -72
  167. package/src/swe-arena/scratch-worktree.test.mts +0 -56
  168. package/src/swe-arena/scratch-worktree.ts +0 -64
  169. package/src/swe-arena/serialized-judge.ts +0 -414
  170. package/src/swe-arena/types.ts +0 -218
@@ -1,16 +0,0 @@
1
- {"version":1,"record":{"status":"pending","callId":"f0af6aca-8e22-4264-91d0-81f1a391e345","channel":"driver","phase":"search.proposal","actor":"proposer-shot:default-author","model":"sonnet","timestamp":1784753519601,"tags":{"candidateId":"cand-001-default-author"}}}
2
- {"version":1,"record":{"status":"settled","callId":"f0af6aca-8e22-4264-91d0-81f1a391e345","channel":"driver","phase":"search.proposal","actor":"proposer-shot:default-author","model":"sonnet","timestamp":1784753519601,"inputTokens":2,"outputTokens":12384,"cachedTokens":14844,"costUsd":0.36238919999999997,"costUnknown":false,"usageUnknown":false,"actualCostUsd":0.36238919999999997,"tags":{"candidateId":"cand-001-default-author"}}}
3
- {"version":1,"record":{"status":"pending","callId":"cc0c7780-83e5-4f6b-8cff-42ce8fcee086","channel":"driver","phase":"audit.leak","actor":"leak-auditor:claude","model":"haiku","timestamp":1784753648815,"tags":{"candidateId":"cand-001-default-author","attempt":"0"}}}
4
- {"version":1,"record":{"status":"settled","callId":"cc0c7780-83e5-4f6b-8cff-42ce8fcee086","channel":"driver","phase":"audit.leak","actor":"leak-auditor:claude","model":"haiku","timestamp":1784753648815,"inputTokens":10,"outputTokens":5672,"cachedTokens":10942,"costUsd":0.0626702,"costUnknown":false,"usageUnknown":false,"actualCostUsd":0.0626702,"tags":{"candidateId":"cand-001-default-author","attempt":"0"}}}
5
- {"version":1,"record":{"status":"pending","callId":"15f76357-12e9-4164-a575-609ea19d6caf","channel":"driver","phase":"search.proposal","actor":"proposer-shot:default-author","model":"sonnet","timestamp":1784753707786,"tags":{"candidateId":"cand-002-default-author"}}}
6
- {"version":1,"record":{"status":"settled","callId":"15f76357-12e9-4164-a575-609ea19d6caf","channel":"driver","phase":"search.proposal","actor":"proposer-shot:default-author","model":"sonnet","timestamp":1784753707786,"inputTokens":2,"outputTokens":14095,"cachedTokens":20285,"costUsd":0.3580005,"costUnknown":false,"usageUnknown":false,"actualCostUsd":0.3580005,"tags":{"candidateId":"cand-002-default-author"}}}
7
- {"version":1,"record":{"status":"pending","callId":"544ff960-2698-4b41-a86e-4a43da853e15","channel":"driver","phase":"audit.leak","actor":"leak-auditor:claude","model":"haiku","timestamp":1784753850937,"tags":{"candidateId":"cand-002-default-author","attempt":"0"}}}
8
- {"version":1,"record":{"status":"settled","callId":"544ff960-2698-4b41-a86e-4a43da853e15","channel":"driver","phase":"audit.leak","actor":"leak-auditor:claude","model":"haiku","timestamp":1784753850937,"inputTokens":10,"outputTokens":3333,"cachedTokens":14989,"costUsd":0.0432539,"costUnknown":false,"usageUnknown":false,"actualCostUsd":0.0432539,"tags":{"candidateId":"cand-002-default-author","attempt":"0"}}}
9
- {"version":1,"record":{"status":"pending","callId":"7c240191-60d7-4322-868f-86dee8a8356b","channel":"driver","phase":"search.proposal","actor":"proposer-shot:quant-researcher","model":"sonnet","timestamp":1784753888358,"tags":{"candidateId":"cand-003-quant-researcher"}}}
10
- {"version":1,"record":{"status":"settled","callId":"7c240191-60d7-4322-868f-86dee8a8356b","channel":"driver","phase":"search.proposal","actor":"proposer-shot:quant-researcher","model":"sonnet","timestamp":1784753888358,"inputTokens":2,"outputTokens":16166,"cachedTokens":14853,"costUsd":0.4205679,"costUnknown":false,"usageUnknown":false,"actualCostUsd":0.4205679,"tags":{"candidateId":"cand-003-quant-researcher"}}}
11
- {"version":1,"record":{"status":"pending","callId":"5492fe01-633d-4513-800b-194834546a77","channel":"driver","phase":"audit.leak","actor":"leak-auditor:claude","model":"haiku","timestamp":1784754065621,"tags":{"candidateId":"cand-003-quant-researcher","attempt":"0"}}}
12
- {"version":1,"record":{"status":"settled","callId":"5492fe01-633d-4513-800b-194834546a77","channel":"driver","phase":"audit.leak","actor":"leak-auditor:claude","model":"haiku","timestamp":1784754065621,"inputTokens":10,"outputTokens":10662,"cachedTokens":14989,"costUsd":0.0799569,"costUnknown":false,"usageUnknown":false,"actualCostUsd":0.0799569,"tags":{"candidateId":"cand-003-quant-researcher","attempt":"0"}}}
13
- {"version":1,"record":{"status":"pending","callId":"d5f20214-c3f3-472a-ada6-130aeec8e76b","channel":"driver","phase":"search.proposal","actor":"proposer-shot:quant-researcher","model":"sonnet","timestamp":1784754170071,"tags":{"candidateId":"cand-004-quant-researcher"}}}
14
- {"version":1,"record":{"status":"settled","callId":"d5f20214-c3f3-472a-ada6-130aeec8e76b","channel":"driver","phase":"search.proposal","actor":"proposer-shot:quant-researcher","model":"sonnet","timestamp":1784754170071,"inputTokens":2,"outputTokens":7930,"cachedTokens":20449,"costUsd":0.2651307,"costUnknown":false,"usageUnknown":false,"actualCostUsd":0.2651307,"tags":{"candidateId":"cand-004-quant-researcher"}}}
15
- {"version":1,"record":{"status":"pending","callId":"a9f6a64b-2c17-4100-b1a1-cca2ce406ab7","channel":"driver","phase":"audit.leak","actor":"leak-auditor:claude","model":"haiku","timestamp":1784754251978,"tags":{"candidateId":"cand-004-quant-researcher","attempt":"0"}}}
16
- {"version":1,"record":{"status":"settled","callId":"a9f6a64b-2c17-4100-b1a1-cca2ce406ab7","channel":"driver","phase":"audit.leak","actor":"leak-auditor:claude","model":"haiku","timestamp":1784754251978,"inputTokens":10,"outputTokens":6020,"cachedTokens":14989,"costUsd":0.0571829,"costUnknown":false,"usageUnknown":false,"actualCostUsd":0.0571829,"tags":{"candidateId":"cand-004-quant-researcher","attempt":"0"}}}
@@ -1,5 +0,0 @@
1
- {"schema":"quant-arena.baselines.v1","at":"2026-07-22T20:51:59.593Z","seed":20260722,"costBps":10,"slippageBps":5,"windows":[{"start":199,"end":703,"startDate":"2017-04-06","endDate":"2019-03-12"},{"start":468,"end":972,"startDate":"2018-04-18","endDate":"2020-03-23"},{"start":546,"end":1050,"startDate":"2018-08-06","endDate":"2020-07-09"},{"start":594,"end":1098,"startDate":"2018-10-11","endDate":"2020-09-15"},{"start":680,"end":1184,"startDate":"2019-02-08","endDate":"2021-01-13"},{"start":1014,"end":1518,"startDate":"2020-05-21","endDate":"2022-04-26"},{"start":1057,"end":1561,"startDate":"2020-07-21","endDate":"2022-06-24"},{"start":1449,"end":1953,"startDate":"2022-01-20","endDate":"2023-12-26"}],"perWindowSharpe":{"buy-hold-index":[1.2094835481971722,0.2675576296109006,0.022309846317549994,-0.0258536811697932,0.3077114359626541,0.17304649923812107,0.0849232983176449,0.7851782377956339],"equal-weight":[1.1460678820228547,0.6061551930118717,0.2850058348026951,0.17908115506948746,0.660766081694157,0.5185595955384733,0.5223261328904791,1.214848475647775],"sma-crossover":[1.1152950659005165,0.0909886478242654,-0.05356223388832718,-0.014348351421960373,0.35996356736295215,0.2507467148916318,0.20379525595898224,1.2082647202257235]},"bestPerWindow":[1.2094835481971722,0.6061551930118717,0.2850058348026951,0.17908115506948746,0.660766081694157,0.5185595955384733,0.5223261328904791,1.214848475647775],"fullSample":{"buy-hold-index":{"start":0,"end":2086,"days":2086,"totalReturn":1.1730593785405552,"maxDrawdown":0.28396402140244215,"sharpe":0.5895302710354368,"tradeCount":1,"turnover":1},"equal-weight":{"start":0,"end":2086,"days":2086,"totalReturn":2.756912129075394,"maxDrawdown":0.26001662984291696,"sharpe":0.8405076018418971,"tradeCount":1100,"turnover":6.9338160520867085},"sma-crossover":{"start":0,"end":2086,"days":2086,"totalReturn":1.777456044807273,"maxDrawdown":0.3575492066705734,"sharpe":0.6592535650279422,"tradeCount":1789,"turnover":111.15341469281668}}}
2
- {"schema":"quant-arena.candidate.v1","at":"2026-07-22T20:51:59.600Z","candidateId":"cand-001-default-author","proposer":"default-author","authorModel":"sonnet","strategyPath":"/tmp/claude-1000/-home-drew-code-supervisor-lab/f06fd156-042a-4ef9-bd88-f2ec7f52b90c/scratchpad/qa-demo/strategies/cand-001-default-author/strategy.ts","sha256":"sha256:942976dc88981ab88b05602e023769c3e9a730133dec85aefdf49c7be7d41d44","authoringCostUsd":0.36238919999999997,"nTried":1,"leakAudit":{"truncation":{"clean":true,"cutoffs":[121,514,906,1299,1691,2084],"divergence":null},"llm":{"verdict":"clean","evidence":""}},"eval":{"perWindow":[{"start":199,"end":703,"startDate":"2017-04-06","endDate":"2019-03-12","sharpe":0.4152508658831424,"bestBaselineSharpe":1.2094835481971722,"excess":-0.7942326823140298},{"start":468,"end":972,"startDate":"2018-04-18","endDate":"2020-03-23","sharpe":-0.1221685157179545,"bestBaselineSharpe":0.6061551930118717,"excess":-0.7283237087298262},{"start":546,"end":1050,"startDate":"2018-08-06","endDate":"2020-07-09","sharpe":-0.3255205884630931,"bestBaselineSharpe":0.2850058348026951,"excess":-0.6105264232657882},{"start":594,"end":1098,"startDate":"2018-10-11","endDate":"2020-09-15","sharpe":-0.24745501555808566,"bestBaselineSharpe":0.17908115506948746,"excess":-0.4265361706275731},{"start":680,"end":1184,"startDate":"2019-02-08","endDate":"2021-01-13","sharpe":0.22164394268361348,"bestBaselineSharpe":0.660766081694157,"excess":-0.4391221390105435},{"start":1014,"end":1518,"startDate":"2020-05-21","endDate":"2022-04-26","sharpe":0.22882389795977512,"bestBaselineSharpe":0.5185595955384733,"excess":-0.2897356975786982},{"start":1057,"end":1561,"startDate":"2020-07-21","endDate":"2022-06-24","sharpe":0.23448567716788063,"bestBaselineSharpe":0.5223261328904791,"excess":-0.28784045572259853},{"start":1449,"end":1953,"startDate":"2022-01-20","endDate":"2023-12-26","sharpe":1.397778520983859,"bestBaselineSharpe":1.214848475647775,"excess":0.1829300453360838}],"meanExcessSharpe":-0.4241734039891216,"wins":1,"requiredWins":6,"threshold":0.1},"inSampleFull":{"start":0,"end":2086,"days":2086,"totalReturn":0.409063349034412,"maxDrawdown":0.14736423468316553,"sharpe":0.5043406767893703,"tradeCount":1703,"turnover":59.702106319096856},"verdict":"rejected-no-edge","reasons":["consistency: beat the best baseline in only 1/8 windows (need 6)","multiplicity: mean excess Sharpe -0.424 < required 0.100 (bar after 1 tried candidate)"]}
3
- {"schema":"quant-arena.candidate.v1","at":"2026-07-22T20:55:07.785Z","candidateId":"cand-002-default-author","proposer":"default-author","authorModel":"sonnet","strategyPath":"/tmp/claude-1000/-home-drew-code-supervisor-lab/f06fd156-042a-4ef9-bd88-f2ec7f52b90c/scratchpad/qa-demo/strategies/cand-002-default-author/strategy.ts","sha256":"sha256:8e81dd7939b38e9af3323fab63f7a9be18961bee660c6a43736ff0a4086683d9","authoringCostUsd":0.3580005,"nTried":2,"leakAudit":{"truncation":{"clean":true,"cutoffs":[121,514,906,1299,1691,2084],"divergence":null},"llm":{"verdict":"clean","evidence":""}},"eval":{"perWindow":[{"start":199,"end":703,"startDate":"2017-04-06","endDate":"2019-03-12","sharpe":0.4361239890211772,"bestBaselineSharpe":1.2094835481971722,"excess":-0.773359559175995},{"start":468,"end":972,"startDate":"2018-04-18","endDate":"2020-03-23","sharpe":0.04317392068219127,"bestBaselineSharpe":0.6061551930118717,"excess":-0.5629812723296804},{"start":546,"end":1050,"startDate":"2018-08-06","endDate":"2020-07-09","sharpe":-0.37020834846200457,"bestBaselineSharpe":0.2850058348026951,"excess":-0.6552141832646996},{"start":594,"end":1098,"startDate":"2018-10-11","endDate":"2020-09-15","sharpe":-0.5064161668353256,"bestBaselineSharpe":0.17908115506948746,"excess":-0.685497321904813},{"start":680,"end":1184,"startDate":"2019-02-08","endDate":"2021-01-13","sharpe":0.2622191188983631,"bestBaselineSharpe":0.660766081694157,"excess":-0.3985469627957939},{"start":1014,"end":1518,"startDate":"2020-05-21","endDate":"2022-04-26","sharpe":0.20867457049898017,"bestBaselineSharpe":0.5185595955384733,"excess":-0.3098850250394931},{"start":1057,"end":1561,"startDate":"2020-07-21","endDate":"2022-06-24","sharpe":0.403492143125228,"bestBaselineSharpe":0.5223261328904791,"excess":-0.11883398976525111},{"start":1449,"end":1953,"startDate":"2022-01-20","endDate":"2023-12-26","sharpe":0.8154427981443754,"bestBaselineSharpe":1.214848475647775,"excess":-0.3994056775033997}],"meanExcessSharpe":-0.4879654989723907,"wins":0,"requiredWins":6,"threshold":0.2766115033773212},"inSampleFull":{"start":0,"end":2086,"days":2086,"totalReturn":0.193975994870764,"maxDrawdown":0.2551410492136035,"sharpe":0.25557327907858696,"tradeCount":3862,"turnover":170.38253887993517},"verdict":"rejected-no-edge","reasons":["consistency: beat the best baseline in only 0/8 windows (need 6)","multiplicity: mean excess Sharpe -0.488 < required 0.277 (bar after 2 tried candidates)"]}
4
- {"schema":"quant-arena.candidate.v1","at":"2026-07-22T20:58:08.358Z","candidateId":"cand-003-quant-researcher","proposer":"quant-researcher","authorModel":"sonnet","strategyPath":"/tmp/claude-1000/-home-drew-code-supervisor-lab/f06fd156-042a-4ef9-bd88-f2ec7f52b90c/scratchpad/qa-demo/strategies/cand-003-quant-researcher/strategy.ts","sha256":"sha256:560aa30401092c749a42bb51329afa56929390994c957f77486d1b4bc4203804","authoringCostUsd":0.4205679,"nTried":3,"leakAudit":{"truncation":{"clean":true,"cutoffs":[121,514,906,1299,1691,2084],"divergence":null},"llm":{"verdict":"clean","evidence":""}},"eval":{"perWindow":[{"start":199,"end":703,"startDate":"2017-04-06","endDate":"2019-03-12","sharpe":0.4473951213548188,"bestBaselineSharpe":1.2094835481971722,"excess":-0.7620884268423533},{"start":468,"end":972,"startDate":"2018-04-18","endDate":"2020-03-23","sharpe":0.2641934383071636,"bestBaselineSharpe":0.6061551930118717,"excess":-0.34196175470470813},{"start":546,"end":1050,"startDate":"2018-08-06","endDate":"2020-07-09","sharpe":0.017374599330440648,"bestBaselineSharpe":0.2850058348026951,"excess":-0.2676312354722544},{"start":594,"end":1098,"startDate":"2018-10-11","endDate":"2020-09-15","sharpe":-0.2012077443814074,"bestBaselineSharpe":0.17908115506948746,"excess":-0.38028889945089484},{"start":680,"end":1184,"startDate":"2019-02-08","endDate":"2021-01-13","sharpe":0.47142122049408347,"bestBaselineSharpe":0.660766081694157,"excess":-0.1893448612000735},{"start":1014,"end":1518,"startDate":"2020-05-21","endDate":"2022-04-26","sharpe":0.21206398259244125,"bestBaselineSharpe":0.5185595955384733,"excess":-0.30649561294603206},{"start":1057,"end":1561,"startDate":"2020-07-21","endDate":"2022-06-24","sharpe":0.10190929084441298,"bestBaselineSharpe":0.5223261328904791,"excess":-0.42041684204606616},{"start":1449,"end":1953,"startDate":"2022-01-20","endDate":"2023-12-26","sharpe":0.5759685014944753,"bestBaselineSharpe":1.214848475647775,"excess":-0.6388799741532998}],"meanExcessSharpe":-0.4133884508519602,"wins":0,"requiredWins":6,"threshold":0.3223455711051266},"inSampleFull":{"start":0,"end":2086,"days":2086,"totalReturn":0.26253273244807596,"maxDrawdown":0.1824773874551917,"sharpe":0.33772524926578196,"tradeCount":2720,"turnover":38.18313115650708},"verdict":"rejected-no-edge","reasons":["consistency: beat the best baseline in only 0/8 windows (need 6)","multiplicity: mean excess Sharpe -0.413 < required 0.322 (bar after 3 tried candidates)"]}
5
- {"schema":"quant-arena.candidate.v1","at":"2026-07-22T21:02:50.071Z","candidateId":"cand-004-quant-researcher","proposer":"quant-researcher","authorModel":"sonnet","strategyPath":"/tmp/claude-1000/-home-drew-code-supervisor-lab/f06fd156-042a-4ef9-bd88-f2ec7f52b90c/scratchpad/qa-demo/strategies/cand-004-quant-researcher/strategy.ts","sha256":"sha256:8b7ecc3f848dbd5e6e101edca551cbdce2d7411fc5493ff30ce8c3ebc23be70b","authoringCostUsd":0.2651307,"nTried":4,"leakAudit":{"truncation":{"clean":true,"cutoffs":[121,514,906,1299,1691,2084],"divergence":null},"llm":{"verdict":"clean","evidence":""}},"eval":{"perWindow":[{"start":199,"end":703,"startDate":"2017-04-06","endDate":"2019-03-12","sharpe":0.9360771493648261,"bestBaselineSharpe":1.2094835481971722,"excess":-0.2734063988323461},{"start":468,"end":972,"startDate":"2018-04-18","endDate":"2020-03-23","sharpe":0.5593419153525067,"bestBaselineSharpe":0.6061551930118717,"excess":-0.04681327765936505},{"start":546,"end":1050,"startDate":"2018-08-06","endDate":"2020-07-09","sharpe":0.2027012985944738,"bestBaselineSharpe":0.2850058348026951,"excess":-0.08230453620822129},{"start":594,"end":1098,"startDate":"2018-10-11","endDate":"2020-09-15","sharpe":0.06825952465388957,"bestBaselineSharpe":0.17908115506948746,"excess":-0.1108216304155979},{"start":680,"end":1184,"startDate":"2019-02-08","endDate":"2021-01-13","sharpe":0.5277496931124905,"bestBaselineSharpe":0.660766081694157,"excess":-0.13301638858166642},{"start":1014,"end":1518,"startDate":"2020-05-21","endDate":"2022-04-26","sharpe":0.45263397984168435,"bestBaselineSharpe":0.5185595955384733,"excess":-0.06592561569678895},{"start":1057,"end":1561,"startDate":"2020-07-21","endDate":"2022-06-24","sharpe":0.4374222361779944,"bestBaselineSharpe":0.5223261328904791,"excess":-0.08490389671248472},{"start":1449,"end":1953,"startDate":"2022-01-20","endDate":"2023-12-26","sharpe":1.331981880357958,"bestBaselineSharpe":1.214848475647775,"excess":0.11713340471018285}],"meanExcessSharpe":-0.08500729242453595,"wins":1,"requiredWins":6,"threshold":0.3497663833473093},"inSampleFull":{"start":0,"end":2086,"days":2086,"totalReturn":1.8312941452636022,"maxDrawdown":0.19344761427023227,"sharpe":0.8783321625049441,"tradeCount":970,"turnover":10.48094104002003},"verdict":"rejected-no-edge","reasons":["consistency: beat the best baseline in only 1/8 windows (need 6)","multiplicity: mean excess Sharpe -0.085 < required 0.350 (bar after 4 tried candidates)"]}
@@ -1,171 +0,0 @@
1
- {
2
- "schema": "quant-arena.rollout.v1",
3
- "outDir": "/tmp/claude-1000/-home-drew-code-supervisor-lab/f06fd156-042a-4ef9-bd88-f2ec7f52b90c/scratchpad/qa-demo",
4
- "at": "2026-07-22T21:05:12.016Z",
5
- "notebookRows": 5,
6
- "strategies": [
7
- {
8
- "label": "baseline-buy-hold-index",
9
- "campaignDir": "/tmp/claude-1000/-home-drew-code-supervisor-lab/f06fd156-042a-4ef9-bd88-f2ec7f52b90c/scratchpad/qa-demo/campaign/baseline-buy-hold-index",
10
- "cells": 8,
11
- "scenarios": [
12
- "window-1014-1518",
13
- "window-1057-1561",
14
- "window-1449-1953",
15
- "window-199-703",
16
- "window-468-972",
17
- "window-546-1050",
18
- "window-594-1098",
19
- "window-680-1184"
20
- ]
21
- },
22
- {
23
- "label": "baseline-equal-weight",
24
- "campaignDir": "/tmp/claude-1000/-home-drew-code-supervisor-lab/f06fd156-042a-4ef9-bd88-f2ec7f52b90c/scratchpad/qa-demo/campaign/baseline-equal-weight",
25
- "cells": 8,
26
- "scenarios": [
27
- "window-1014-1518",
28
- "window-1057-1561",
29
- "window-1449-1953",
30
- "window-199-703",
31
- "window-468-972",
32
- "window-546-1050",
33
- "window-594-1098",
34
- "window-680-1184"
35
- ]
36
- },
37
- {
38
- "label": "baseline-sma-crossover",
39
- "campaignDir": "/tmp/claude-1000/-home-drew-code-supervisor-lab/f06fd156-042a-4ef9-bd88-f2ec7f52b90c/scratchpad/qa-demo/campaign/baseline-sma-crossover",
40
- "cells": 8,
41
- "scenarios": [
42
- "window-1014-1518",
43
- "window-1057-1561",
44
- "window-1449-1953",
45
- "window-199-703",
46
- "window-468-972",
47
- "window-546-1050",
48
- "window-594-1098",
49
- "window-680-1184"
50
- ]
51
- },
52
- {
53
- "label": "cand-001-default-author",
54
- "campaignDir": "/tmp/claude-1000/-home-drew-code-supervisor-lab/f06fd156-042a-4ef9-bd88-f2ec7f52b90c/scratchpad/qa-demo/campaign/cand-001-default-author",
55
- "cells": 8,
56
- "scenarios": [
57
- "window-1014-1518",
58
- "window-1057-1561",
59
- "window-1449-1953",
60
- "window-199-703",
61
- "window-468-972",
62
- "window-546-1050",
63
- "window-594-1098",
64
- "window-680-1184"
65
- ]
66
- },
67
- {
68
- "label": "cand-002-default-author",
69
- "campaignDir": "/tmp/claude-1000/-home-drew-code-supervisor-lab/f06fd156-042a-4ef9-bd88-f2ec7f52b90c/scratchpad/qa-demo/campaign/cand-002-default-author",
70
- "cells": 8,
71
- "scenarios": [
72
- "window-1014-1518",
73
- "window-1057-1561",
74
- "window-1449-1953",
75
- "window-199-703",
76
- "window-468-972",
77
- "window-546-1050",
78
- "window-594-1098",
79
- "window-680-1184"
80
- ]
81
- },
82
- {
83
- "label": "cand-003-quant-researcher",
84
- "campaignDir": "/tmp/claude-1000/-home-drew-code-supervisor-lab/f06fd156-042a-4ef9-bd88-f2ec7f52b90c/scratchpad/qa-demo/campaign/cand-003-quant-researcher",
85
- "cells": 8,
86
- "scenarios": [
87
- "window-1014-1518",
88
- "window-1057-1561",
89
- "window-1449-1953",
90
- "window-199-703",
91
- "window-468-972",
92
- "window-546-1050",
93
- "window-594-1098",
94
- "window-680-1184"
95
- ]
96
- },
97
- {
98
- "label": "cand-004-quant-researcher",
99
- "campaignDir": "/tmp/claude-1000/-home-drew-code-supervisor-lab/f06fd156-042a-4ef9-bd88-f2ec7f52b90c/scratchpad/qa-demo/campaign/cand-004-quant-researcher",
100
- "cells": 8,
101
- "scenarios": [
102
- "window-1014-1518",
103
- "window-1057-1561",
104
- "window-1449-1953",
105
- "window-199-703",
106
- "window-468-972",
107
- "window-546-1050",
108
- "window-594-1098",
109
- "window-680-1184"
110
- ]
111
- }
112
- ],
113
- "receipts": [
114
- {
115
- "callId": "f0af6aca-8e22-4264-91d0-81f1a391e345",
116
- "phase": "search.proposal",
117
- "actor": "proposer-shot:default-author",
118
- "model": "sonnet",
119
- "costUsd": 0.36238919999999997
120
- },
121
- {
122
- "callId": "cc0c7780-83e5-4f6b-8cff-42ce8fcee086",
123
- "phase": "audit.leak",
124
- "actor": "leak-auditor:claude",
125
- "model": "haiku",
126
- "costUsd": 0.0626702
127
- },
128
- {
129
- "callId": "15f76357-12e9-4164-a575-609ea19d6caf",
130
- "phase": "search.proposal",
131
- "actor": "proposer-shot:default-author",
132
- "model": "sonnet",
133
- "costUsd": 0.3580005
134
- },
135
- {
136
- "callId": "544ff960-2698-4b41-a86e-4a43da853e15",
137
- "phase": "audit.leak",
138
- "actor": "leak-auditor:claude",
139
- "model": "haiku",
140
- "costUsd": 0.0432539
141
- },
142
- {
143
- "callId": "7c240191-60d7-4322-868f-86dee8a8356b",
144
- "phase": "search.proposal",
145
- "actor": "proposer-shot:quant-researcher",
146
- "model": "sonnet",
147
- "costUsd": 0.4205679
148
- },
149
- {
150
- "callId": "5492fe01-633d-4513-800b-194834546a77",
151
- "phase": "audit.leak",
152
- "actor": "leak-auditor:claude",
153
- "model": "haiku",
154
- "costUsd": 0.0799569
155
- },
156
- {
157
- "callId": "d5f20214-c3f3-472a-ada6-130aeec8e76b",
158
- "phase": "search.proposal",
159
- "actor": "proposer-shot:quant-researcher",
160
- "model": "sonnet",
161
- "costUsd": 0.2651307
162
- },
163
- {
164
- "callId": "a9f6a64b-2c17-4100-b1a1-cca2ce406ab7",
165
- "phase": "audit.leak",
166
- "actor": "leak-auditor:claude",
167
- "model": "haiku",
168
- "costUsd": 0.0571829
169
- }
170
- ]
171
- }
@@ -1,119 +0,0 @@
1
- type Bar = { date: string; open: number; high: number; low: number; close: number; volume: number };
2
- type Signal = { t: number; weights: number[] };
3
-
4
- export function generateSignals(bars: Bar[][]): Signal[] {
5
- const N = bars.length;
6
- const T = bars[0].length;
7
-
8
- const SHORT_LB = 20;
9
- const LONG_LB = 80;
10
- const VOL_LB = 40;
11
- const MIN_AVAIL = 25;
12
- const REBAL_EVERY = 5;
13
- const CHANGE_THRESHOLD = 0.05;
14
- const MAX_WEIGHT = 0.30;
15
- const TARGET_VOL = 0.15;
16
- const MAX_GROSS = 0.95;
17
- const MIN_SCALE = 0.15;
18
- const TRADING_DAYS = 252;
19
-
20
- const closesByTicker: number[][] = bars.map((series) => series.map((b) => b.close));
21
-
22
- function smaAt(closes: number[], t: number, lb: number): number {
23
- const start = Math.max(0, t - lb + 1);
24
- let s = 0;
25
- let n = 0;
26
- for (let i = start; i <= t; i++) {
27
- s += closes[i];
28
- n++;
29
- }
30
- return n > 0 ? s / n : NaN;
31
- }
32
-
33
- function annualizedVol(closes: number[], t: number, lb: number): number {
34
- const start = Math.max(1, t - lb + 1);
35
- const rets: number[] = [];
36
- for (let i = start; i <= t; i++) {
37
- const prev = closes[i - 1];
38
- const cur = closes[i];
39
- if (prev > 0 && cur > 0) rets.push(Math.log(cur / prev));
40
- }
41
- if (rets.length < 2) return NaN;
42
- let m = 0;
43
- for (const r of rets) m += r;
44
- m /= rets.length;
45
- let v = 0;
46
- for (const r of rets) v += (r - m) * (r - m);
47
- v /= (rets.length - 1);
48
- return Math.sqrt(v) * Math.sqrt(TRADING_DAYS);
49
- }
50
-
51
- const signals: Signal[] = [];
52
- let lastWeights: number[] = new Array(N).fill(0);
53
-
54
- for (let t = 0; t < T; t++) {
55
- const avail = t + 1;
56
- if (avail < MIN_AVAIL || t % REBAL_EVERY !== 0) continue;
57
-
58
- const shortLb = Math.min(SHORT_LB, avail);
59
- const longLb = Math.min(LONG_LB, avail);
60
- const volLb = Math.min(VOL_LB, avail - 1);
61
-
62
- const weights: number[] = new Array(N).fill(0);
63
- const eligible: number[] = [];
64
- const invVol: number[] = new Array(N).fill(0);
65
-
66
- for (let k = 0; k < N; k++) {
67
- const closes = closesByTicker[k];
68
- const price = closes[t];
69
- const smaShort = smaAt(closes, t, shortLb);
70
- const smaLong = smaAt(closes, t, longLb);
71
- const vol = annualizedVol(closes, t, volLb);
72
- const trendUp = Number.isFinite(smaShort) && Number.isFinite(smaLong) && price > smaLong && smaShort > smaLong;
73
- if (trendUp && Number.isFinite(vol) && vol > 1e-6) {
74
- eligible.push(k);
75
- invVol[k] = 1 / vol;
76
- }
77
- }
78
-
79
- if (eligible.length > 0) {
80
- const sumInv = eligible.reduce((s, k) => s + invVol[k], 0);
81
- for (const k of eligible) weights[k] = invVol[k] / sumInv;
82
-
83
- for (let iter = 0; iter < 5; iter++) {
84
- let excess = 0;
85
- const uncapped: number[] = [];
86
- for (const k of eligible) {
87
- if (weights[k] > MAX_WEIGHT) {
88
- excess += weights[k] - MAX_WEIGHT;
89
- weights[k] = MAX_WEIGHT;
90
- } else {
91
- uncapped.push(k);
92
- }
93
- }
94
- if (excess <= 1e-9 || uncapped.length === 0) break;
95
- const add = excess / uncapped.length;
96
- for (const k of uncapped) weights[k] += add;
97
- }
98
-
99
- let basketVolSum = 0;
100
- for (const k of eligible) basketVolSum += 1 / invVol[k];
101
- const basketVol = basketVolSum / eligible.length;
102
- let scale = basketVol > 0 ? TARGET_VOL / basketVol : MIN_SCALE;
103
- if (!Number.isFinite(scale)) scale = MIN_SCALE;
104
- scale = Math.max(MIN_SCALE, Math.min(1, scale));
105
-
106
- for (const k of eligible) weights[k] *= scale * MAX_GROSS;
107
- }
108
-
109
- let diff = 0;
110
- for (let k = 0; k < N; k++) diff += Math.abs(weights[k] - lastWeights[k]);
111
-
112
- if (diff > CHANGE_THRESHOLD) {
113
- signals.push({ t, weights: weights.slice() });
114
- lastWeights = weights;
115
- }
116
- }
117
-
118
- return signals;
119
- }
@@ -1,119 +0,0 @@
1
- type Bar = { date: string; open: number; high: number; low: number; close: number; volume: number };
2
- type Signal = { t: number; weights: number[] };
3
-
4
- export function generateSignals(bars: Bar[][]): Signal[] {
5
- const nTickers = bars.length;
6
- const nDays = bars[0].length;
7
- const nStocks = nTickers - 1; // exclude index at k=0 (IDX) from direct allocation
8
-
9
- const VOL_LOOKBACK = 20;
10
- const MOM_LOOKBACK = 40;
11
- const SMA_FAST = 20;
12
- const SMA_SLOW = 60;
13
- const MIN_HISTORY = SMA_SLOW;
14
- const REBALANCE_INTERVAL = 21;
15
- const VOL_TARGET = 0.12;
16
- const TRADE_BAND = 0.04;
17
- const URGENT_BAND = 0.15;
18
-
19
- const signals: Signal[] = [];
20
- if (nDays === 0 || nStocks <= 0) return signals;
21
-
22
- const stdev = (rets: number[]): number => {
23
- const n = rets.length;
24
- if (n === 0) return 0;
25
- let mean = 0;
26
- for (let i = 0; i < n; i++) mean += rets[i];
27
- mean /= n;
28
- let v = 0;
29
- for (let i = 0; i < n; i++) {
30
- const d = rets[i] - mean;
31
- v += d * d;
32
- }
33
- return Math.sqrt(v / n);
34
- };
35
-
36
- const sma = (k: number, t: number, period: number): number => {
37
- let s = 0;
38
- for (let i = t - period + 1; i <= t; i++) s += bars[k][i].close;
39
- return s / period;
40
- };
41
-
42
- let lastWeights: number[] | null = null;
43
- let lastTradeT = -Infinity;
44
-
45
- for (let t = 0; t < nDays; t++) {
46
- let target: number[] | null = null;
47
-
48
- if (t === 0) {
49
- target = new Array(nTickers).fill(0);
50
- for (let k = 1; k <= nStocks; k++) target[k] = 1 / nStocks;
51
- } else if (t >= MIN_HISTORY) {
52
- const fast = sma(0, t, SMA_FAST);
53
- const slow = sma(0, t, SMA_SLOW);
54
- const uptrend = fast >= slow;
55
- const regimeScale = uptrend ? 1.0 : 0.5;
56
-
57
- const stats: { k: number; mom: number; vol: number }[] = [];
58
- for (let k = 1; k <= nStocks; k++) {
59
- const closes = bars[k];
60
- const c0 = closes[t - MOM_LOOKBACK].close;
61
- const c1 = closes[t].close;
62
- const mom = c0 > 0 ? c1 / c0 - 1 : 0;
63
-
64
- const rets: number[] = [];
65
- for (let i = t - VOL_LOOKBACK + 1; i <= t; i++) {
66
- const prev = closes[i - 1].close;
67
- rets.push(prev > 0 ? closes[i].close / prev - 1 : 0);
68
- }
69
- const vol = stdev(rets);
70
- stats.push({ k, mom, vol });
71
- }
72
-
73
- let pool = stats.filter((s) => s.mom > 0);
74
- if (pool.length === 0) pool = stats;
75
-
76
- const invVols = pool.map((s) => 1 / Math.max(s.vol, 1e-4));
77
- const sumInv = invVols.reduce((a, b) => a + b, 0);
78
- const rawWeights = pool.map((_, i) => invVols[i] / sumInv);
79
-
80
- let weightedVol = 0;
81
- for (let i = 0; i < pool.length; i++) weightedVol += rawWeights[i] * pool[i].vol;
82
- const annVol = weightedVol * Math.sqrt(252);
83
- let volScale = annVol > 0 ? VOL_TARGET / annVol : 1;
84
- volScale = Math.min(volScale, 1);
85
- volScale = Math.max(volScale, 0);
86
-
87
- const combinedScale = Math.min(regimeScale, volScale);
88
-
89
- target = new Array(nTickers).fill(0);
90
- for (let i = 0; i < pool.length; i++) {
91
- target[pool[i].k] = rawWeights[i] * combinedScale;
92
- }
93
- }
94
-
95
- if (target === null) continue;
96
-
97
- if (lastWeights === null) {
98
- signals.push({ t, weights: target });
99
- lastWeights = target;
100
- lastTradeT = t;
101
- continue;
102
- }
103
-
104
- let l1 = 0;
105
- for (let k = 0; k < nTickers; k++) l1 += Math.abs(target[k] - lastWeights[k]);
106
-
107
- const scheduled = t - lastTradeT >= REBALANCE_INTERVAL;
108
- const urgent = l1 >= URGENT_BAND;
109
- const worthTrading = l1 >= TRADE_BAND;
110
-
111
- if ((scheduled && worthTrading) || urgent) {
112
- signals.push({ t, weights: target });
113
- lastWeights = target;
114
- lastTradeT = t;
115
- }
116
- }
117
-
118
- return signals;
119
- }
@@ -1,105 +0,0 @@
1
- type Bar = { date: string; open: number; high: number; low: number; close: number; volume: number };
2
- type Signal = { t: number; weights: number[] };
3
-
4
- // ECONOMIC RATIONALE (one compound "regime quality" effect on a long-only equal-weight basket):
5
- //
6
- // 1) TREND BREADTH: capital is deployed in proportion to the fraction of the 10 names
7
- // trading above their own trailing moving average. Broad participation in an uptrend
8
- // is a well-documented leading indicator of continuation; breadth deteriorates BEFORE
9
- // and DURING systemic drawdowns (fewer names hold their trend as a selloff spreads),
10
- // so scaling exposure by breadth cuts risk ahead of/through the worst stretches without
11
- // ever forecasting direction or shorting.
12
- //
13
- // 2) VOLATILITY TARGETING: equity returns cluster in volatility, and the conditional
14
- // Sharpe ratio is empirically lower in high-vol regimes than in calm ones. Scaling
15
- // exposure by (target vol / realized vol) keeps risk roughly constant through time,
16
- // which mechanically improves the risk-adjusted return by underweighting exactly the
17
- // stretches where the same dollar of exposure buys worse risk-adjusted payoff.
18
- //
19
- // Both signals are pure regime-quality throttles on ONE equal-weight book (no stock
20
- // picking, no shorting, no leverage - final scalar in [0,1]). They are combined
21
- // multiplicatively so the book only runs near-full size when trend AND vol conditions are
22
- // both benign, and de-risks fast (toward cash) when either deteriorates. A rebalance band
23
- // plus a minimum holding gap keep trading infrequent so 15bps one-way cost cannot eat the
24
- // edge - this strategy trades on regime shifts, not on daily noise.
25
- export function generateSignals(bars: Bar[][]): Signal[] {
26
- const numTickers = bars.length;
27
- const numStocks = numTickers - 1;
28
- const numDays = bars[0].length;
29
-
30
- const TREND_SMA = 100; // trailing window defining "in an uptrend" per stock
31
- const VOL_LOOKBACK = 20; // trailing window for realized-vol estimate of the basket
32
- const TARGET_VOL = 0.15; // annualized vol target for the invested basket
33
- const REBAL_BAND = 0.08; // min change in target exposure to justify paying the spread
34
- const MIN_GAP_DAYS = 5; // minimum days between rebalances, avoids whipsaw churn
35
-
36
- const signals: Signal[] = [];
37
-
38
- const closeWindows: number[][] = [];
39
- const closeSums: number[] = [];
40
- for (let k = 0; k < numTickers; k++) {
41
- closeWindows.push([]);
42
- closeSums.push(0);
43
- }
44
-
45
- const basketReturns: number[] = [];
46
-
47
- let lastScalar = -1;
48
- let lastSignalDay = -Infinity;
49
-
50
- for (let t = 0; t < numDays; t++) {
51
- for (let k = 1; k < numTickers; k++) {
52
- const c = bars[k][t].close;
53
- closeWindows[k].push(c);
54
- closeSums[k] += c;
55
- if (closeWindows[k].length > TREND_SMA) {
56
- closeSums[k] -= closeWindows[k].shift() as number;
57
- }
58
- }
59
-
60
- if (t >= 1) {
61
- let sumRet = 0;
62
- for (let k = 1; k < numTickers; k++) {
63
- const prev = bars[k][t - 1].close;
64
- const cur = bars[k][t].close;
65
- sumRet += prev > 0 ? (cur - prev) / prev : 0;
66
- }
67
- basketReturns.push(sumRet / numStocks);
68
- if (basketReturns.length > VOL_LOOKBACK) basketReturns.shift();
69
- }
70
-
71
- const trendReady = closeWindows[1].length >= TREND_SMA;
72
- const volReady = basketReturns.length >= VOL_LOOKBACK;
73
- if (!trendReady || !volReady) continue;
74
-
75
- let above = 0;
76
- for (let k = 1; k < numTickers; k++) {
77
- const sma = closeSums[k] / closeWindows[k].length;
78
- if (bars[k][t].close > sma) above++;
79
- }
80
- const breadth = above / numStocks;
81
-
82
- const mean = basketReturns.reduce((a, b) => a + b, 0) / basketReturns.length;
83
- const variance =
84
- basketReturns.reduce((a, b) => a + (b - mean) * (b - mean), 0) / basketReturns.length;
85
- const annualizedVol = Math.sqrt(variance) * Math.sqrt(252);
86
- const volScalar =
87
- annualizedVol > 1e-8 ? Math.max(0, Math.min(1, TARGET_VOL / annualizedVol)) : 1;
88
-
89
- const scalar = Math.max(0, Math.min(1, breadth * volScalar));
90
-
91
- const daysSinceLast = t - lastSignalDay;
92
- const moved = Math.abs(scalar - lastScalar) >= REBAL_BAND;
93
-
94
- if (lastScalar < 0 || (moved && daysSinceLast >= MIN_GAP_DAYS)) {
95
- const weights = new Array(numTickers).fill(0);
96
- const perStock = scalar / numStocks;
97
- for (let k = 1; k < numTickers; k++) weights[k] = perStock;
98
- signals.push({ t, weights });
99
- lastScalar = scalar;
100
- lastSignalDay = t;
101
- }
102
- }
103
-
104
- return signals;
105
- }