Turin LT: the curve matches, the live signal does not¶
This is the cleanest possible answer to a messy replication request: historical fidelity passes; strategy admission fails. The notebook reruns everything from committed offline fixtures. It never fetches TradingView.
from pathlib import Path
import json
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from IPython.display import HTML, display
from backtest.turin_lt_claudified import run_fidelity_backtest, fidelity_comparison
ROOT = Path.cwd()
result, events = run_fidelity_backtest()
curves, metrics = fidelity_comparison(result, events)
pd.Series(metrics, name='frozen 80% replay').to_frame()
1. What is known — and what is not¶
| Part | Publicly documented | Still protected |
|---|---|---|
| Entry | breadth washout + A/D thrust + realized-vol gate | exact breadth horizon/EMA/threshold, A/D formula, vol window/floor |
| Exit | breadth repair | exact repair threshold |
| Position | long only, 80% of equity, pyramiding one | SPY chart vs SPXL metadata conflict |
| Costs | 0% commission, 0 ticks slippage | no hidden exceptions observed |
| Timing | process_orders_on_close=false |
Pine text is unavailable, so no source hash exists |
Unavailable values stay unavailable. Nothing below estimates them.
rule_table = pd.DataFrame([
{'rule':'Entry','implementation':'Replay exact published entry event at 80% SPY','divergence':'Cannot generate a new entry'},
{'rule':'Exit','implementation':'Replay exact published exit event to 0% SPY','divergence':'Hidden repair threshold'},
{'rule':'Lag','implementation':'run_backtest(... execution=next_open)','divergence':'Event replay, not live causality'},
{'rule':'Cash','implementation':'Residual zero-yield cash','divergence':'Source cash yield undisclosed'},
])
rule_table
2. The visual result¶
Both lines start at $1. The solid line is the published report reconstructed from cumulative profit; the dashed line is QuantModel's canonical engine. The match is about the whole path, not just the endpoint.
fig, ax = plt.subplots(figsize=(11, 5.5))
ax.plot(curves.index, curves['tradingview_equity'], lw=2.4, label='Published report')
ax.plot(curves.index, curves['replay_equity'], '--', lw=1.8, label='QuantModel replay')
ax.set(title=f"Normalized event equity · corr {metrics['correlation']:.6f}", xlabel='Event date', ylabel='Growth of $1')
ax.grid(alpha=.25); ax.legend(frameon=False); plt.show()
3. Stress the result without tuning it¶
The frozen robustness matrix includes costs, a 100% sizing ablation, the final open mark, a daily adjusted-SPY path, and one extra event lag. The extra-lag failure is important: it proves timing is doing real work and was not massaged away.
robust = json.loads((ROOT/'research/findings/turin-lt-robustness-qm-wpx5.json').read_text())
rows=[]
for name, item in robust['matrix'].items():
metric=item.get('metrics', {})
rows.append({'variant':name, 'status':item.get('status'), 'correlation':metric.get('correlation', item.get('event_equity_correlation')), 'terminal ratio':metric.get('final_normalized_ratio')})
pd.DataFrame(rows)
4. Try the predeclared cost range¶
Move the slider from 0 to 20 basis points. Every position was precomputed by the real backtest engine; the browser redraws annual derived summaries and recomputes correlation and the terminal ratio. This is a sensitivity viewer, not an optimizer.
source_annual = curves['tradingview_equity'].resample('YE').last()
cost_payload = {'labels':[d.date().isoformat() for d in source_annual.index], 'source':source_annual.tolist(), 'curves':{}}
for bps in range(21):
r, e = run_fidelity_backtest(fee_bps=float(bps))
c, _ = fidelity_comparison(r, e)
annual = c['replay_equity'].resample('YE').last().reindex(source_annual.index)
cost_payload['curves'][str(bps)] = annual.tolist()
DATA = json.dumps(cost_payload, separators=(',', ':'))
display(HTML('''<div id="turin-cost-playground" style="border:1px solid #ddd;padding:16px;border-radius:10px">
<label for="turin-cost-slider"><b>One-way cost:</b> <span id="turin-cost-value">0</span> bps</label>
<input id="turin-cost-slider" type="range" min="0" max="20" value="0" step="1" style="width:100%">
<p id="turin-cost-metrics"></p><canvas id="turin-cost-canvas" width="900" height="360" style="max-width:100%;height:auto"></canvas></div>
<script>(function(){const D=''' + DATA + ''';const s=document.getElementById('turin-cost-slider'),v=document.getElementById('turin-cost-value'),m=document.getElementById('turin-cost-metrics'),cv=document.getElementById('turin-cost-canvas'),x=cv.getContext('2d');
function corr(a,b){let n=a.length,ma=a.reduce((q,z)=>q+z,0)/n,mb=b.reduce((q,z)=>q+z,0)/n,xy=0,xx=0,yy=0;for(let i=0;i<n;i++){let da=a[i]-ma,db=b[i]-mb;xy+=da*db;xx+=da*da;yy+=db*db}return xy/Math.sqrt(xx*yy)}
function line(a,color,dash){x.strokeStyle=color;x.lineWidth=3;x.setLineDash(dash);x.beginPath();let all=D.source.concat(a),lo=Math.min(...all),hi=Math.max(...all);a.forEach((z,i)=>{let px=45+i*(cv.width-70)/(a.length-1),py=cv.height-35-(z-lo)*(cv.height-65)/(hi-lo);i?x.lineTo(px,py):x.moveTo(px,py)});x.stroke()}
function draw(){let b=s.value,a=D.curves[b];v.textContent=b;m.textContent='Correlation '+corr(a,D.source).toFixed(6)+' · terminal ratio '+(a[a.length-1]/D.source[D.source.length-1]).toFixed(4);x.clearRect(0,0,cv.width,cv.height);x.fillStyle='#666';x.fillText('Annual normalized equity (blue: report, orange: replay)',45,18);line(D.source,'#4c72b0',[]);line(a,'#dd8452',[8,5])}s.addEventListener('input',draw);draw()})();</script>'''))
5. Decision¶
Fidelity only. Correlation and visual shape pass, but a strategy catalog entry must produce future allocations from point-in-time inputs. This replay consumes the historical orders themselves. The Pine source, exact signal defaults, and an untouched economic window are unavailable.
Raw TradingView HTML, the publisher screenshot, fill prices, and individual trade observations are intentionally absent from this public notebook output.
pd.DataFrame([
{'artifact':'public page archive', 'sha256':'eba7a280…f364', 'public output':'hash and rule summary only'},
{'artifact':'equity fixture', 'sha256':'564e1af6…e4dd', 'public output':'annual normalized summaries + generated chart'},
{'artifact':'frozen protocol', 'sha256':'3229e940…f898', 'public output':'full protocol summary'},
{'artifact':'strategy code', 'sha256':'0a4515c6…e1d', 'public output':'repository source'},
])