# Cross-venue lead-lag and price dislocation, BTC, one day -- raw side ## Question Lead-lag and dislocation. For the BTC perpetual on Hyperliquid, edgeX, ApeX, Pacifica and dYdX on 2026-09-27 (UTC day), using 1-minute closing prices: (1) for each of the other four venues, the cross-correlation of its 1-minute log returns with Hyperliquid's at lags -3..+3 minutes, and which venue leads; (2) for each of the four, the largest absolute 1-minute close dislocation versus Hyperliquid in basis points and the minute it happened. Say how you handled minutes where a venue did not trade. ## System prompt You are an agent assisting a quantitative researcher. Work the question end to end: find the data, compute, check your own numbers, and make the judgement calls a careful quant would make. You have a Bash tool; Python 3 with duckdb, pandas, pyarrow and numpy is at /tmp/peerfeed-a21/venv/bin/python. Work inside your current directory. When you are done, end with a section headed FINAL ANSWER that gives every number asked for and states each judgement call you made. The researcher has downloaded PeerFeed's parquet archive for the relevant venues and data types to /tmp/peerfeed-a21/archive, in the layout PeerFeed delivers it. That directory is your only source of market data; there is no API access. ## [tool call 1] Bash { "command": "cd /tmp/peerfeed-a21/archive; find . | head -100; find . -type f | wc -l; find . -name \"*.md\" -o -name \"*.txt\" -o -name \"*.json\" | head" } ## [tool result] . ./apex ./dydx ./paradex ./pacifica ./edgex ./extended ./hyperliquid ./nado ./apex/trades ./dydx/trades ./paradex/trades ./pacifica/trades ./pacifica/prices ./edgex/trades ./edgex/ticker ./extended/funding ./hyperliquid/trades ./hyperliquid/activeAssetCtx ./nado/funding_rate ./nado/trades ./extended/funding/parquet ./hyperliquid/trades/parquet ./hyperliquid/activeAssetCtx/parquet ./nado/funding_rate/parquet ./nado/trades/parquet ./apex/trades/parquet ./dydx/trades/parquet ./paradex/trades/parquet ./pacifica/trades/parquet ./pacifica/prices/parquet ./edgex/trades/parquet ./edgex/ticker/parquet ./extended/funding/parquet/2026 ./hyperliquid/trades/parquet/2026 ./hyperliquid/activeAssetCtx/parquet/2026 ./nado/funding_rate/parquet/2026 ./nado/trades/parquet/2026 ./apex/trades/parquet/2026 ./dydx/trades/parquet/2026 ./paradex/trades/parquet/2026 ./pacifica/trades/parquet/2026 ./pacifica/prices/parquet/2026 ./edgex/trades/parquet/2026 ./edgex/ticker/parquet/2026 ./extended/funding/parquet/2026/09 ./hyperliquid/trades/parquet/2026/09 ./hyperliquid/activeAssetCtx/parquet/2026/09 ./nado/funding_rate/parquet/2026/09 ./nado/trades/parquet/2026/09 ./extended/funding/parquet/2026/09/27 ./extended/funding/parquet/2026/09/22 ./extended/funding/parquet/2026/09/26 ./extended/funding/parquet/2026/09/20 ./extended/funding/parquet/2026/09/23 ./extended/funding/parquet/2026/09/24 ./extended/funding/parquet/2026/09/21 ./extended/funding/parquet/2026/09/28 ./extended/funding/parquet/2026/09/25 ./hyperliquid/trades/parquet/2026/09/27 ./hyperliquid/trades/parquet/2026/09/22 ./hyperliquid/trades/parquet/2026/09/26 ./hyperliquid/trades/parquet/2026/09/20 ./hyperliquid/trades/parquet/2026/09/23 ./hyperliquid/trades/parquet/2026/09/24 ./hyperliquid/trades/parquet/2026/09/21 ./hyperliquid/trades/parquet/2026/09/28 ./hyperliquid/trades/parquet/2026/09/25 ./hyperliquid/activeAssetCtx/parquet/2026/09/27 ./hyperliquid/activeAssetCtx/parquet/2026/09/22 ./hyperliquid/activeAssetCtx/parquet/2026/09/26 ./hyperliquid/activeAssetCtx/parquet/2026/09/20 ./hyperliquid/activeAssetCtx/parquet/2026/09/23 ./hyperliquid/activeAssetCtx/parquet/2026/09/24 ./hyperliquid/activeAssetCtx/parquet/2026/09/21 ./hyperliquid/activeAssetCtx/parquet/2026/09/28 ./hyperliquid/activeAssetCtx/parquet/2026/09/25 ./nado/funding_rate/parquet/2026/09/27 ./nado/funding_rate/parquet/2026/09/22 ./nado/funding_rate/parquet/2026/09/26 ./nado/funding_rate/parquet/2026/09/20 ./nado/funding_rate/parquet/2026/09/23 ./nado/funding_rate/parquet/2026/09/24 ./nado/funding_rate/parquet/2026/09/21 ./nado/funding_rate/parquet/2026/09/28 ./nado/funding_rate/parquet/2026/09/25 ./nado/trades/parquet/2026/09/27 ./nado/trades/parquet/2026/09/22 ./nado/trades/parquet/2026/09/26 ./nado/trades/parquet/2026/09/20 ./nado/trades/parquet/2026/09/23 ./nado/trades/parquet/2026/09/24 ./nado/trades/parquet/2026/09/21 ./nado/trades/parquet/2026/09/28 ./nado/trades/parquet/2026/09/25 ./apex/trades/parquet/2026/09 ./dydx/trades/parquet/2026/09 ./paradex/trades/parquet/2026/09 ./pacifica/trades/parquet/2026/09 ./pacifica/prices/parquet/2026/09 1220 Shell cwd was reset to /tmp/peerfeed-a21/work-t2-raw ## [tool call 2] Bash { "command": "cd /tmp/peerfeed-a21/archive; for v in hyperliquid edgex apex pacifica dydx; do echo == $v; ls $v/trades/parquet/2026/09/27 | head; ls $v/trades/parquet/2026/09/27 | wc -l; ls $v/trades/parquet/2026/09/26 | head -3; done; find . -type f ! -name \"*.parquet\" | head" } ## [tool result] == hyperliquid 00-02.parquet 02-04.parquet 04-06.parquet 06-08.parquet 08-10.parquet 10-12.parquet 12-14.parquet 14-16.parquet 16-18.parquet 18-20.parquet 12 00-02.parquet 02-04.parquet 04-06.parquet == edgex 00-02.parquet 02-04.parquet 04-06.parquet 06-08.parquet 08-10.parquet 10-12.parquet 12-14.parquet 14-16.parquet 16-18.parquet 18-20.parquet 12 00-02.parquet 02-04.parquet 04-06.parquet == apex 00-02.parquet 02-04.parquet 04-06.parquet 06-08.parquet 08-10.parquet 10-12.parquet 12-14.parquet 14-16.parquet 16-18.parquet 18-20.parquet 12 00-02.parquet 02-04.parquet 04-06.parquet == pacifica 00-02.parquet 02-04.parquet 04-06.parquet 06-08.parquet 08-10.parquet 10-12.parquet 12-14.parquet 14-16.parquet 16-18.parquet 18-20.parquet 12 00-02.parquet 02-04.parquet 04-06.parquet == dydx 00-02.parquet 02-04.parquet 04-06.parquet 06-08.parquet 08-10.parquet 10-12.parquet 12-14.parquet 14-16.parquet 16-18.parquet 18-20.parquet 12 00-02.parquet 02-04.parquet 04-06.parquet Shell cwd was reset to /tmp/peerfeed-a21/work-t2-raw ## [tool call 3] Bash { "command": "cd /tmp/peerfeed-a21/archive; P=/tmp/peerfeed-a21/venv/bin/python; $P -c \"\nimport duckdb\nfor v in ['hyperliquid','edgex','apex','pacifica','dydx']:\n g=f'{v}/trades/parquet/2026/09/27/*.parquet'\n print('==',v)\n print(duckdb.sql(f\\\"describe select * from read_parquet('{g}')\\\").df()[['column_name','column_type']].to_string())\n print(duckdb.sql(f\\\"select * from read_parquet('{g}') limit 3\\\").df().to_string())\n\"" } ## [tool result] == hyperliquid column_name column_type 0 coin VARCHAR 1 side VARCHAR 2 px DOUBLE 3 sz DOUBLE 4 time TIMESTAMP WITH TIME ZONE 5 hash VARCHAR 6 tid BIGINT 7 users VARCHAR[] 8 recorded_at TIMESTAMP WITH TIME ZONE coin side px sz time hash tid users recorded_at 0 TAO A 321.75000 0.032 2026-09-27 01:58:59.772000+02:00 0x7d48c022c93347397ec20445481cd901e600d8086436660b21116b7588372124 328399079171261 [0x4ef66df2067c588eb98896ede3a8e80f85aff085, 0x38f96bba487a628d2a84afc3fe5c7d77eb07cb04] 2026-09-27 01:59:00.054000+02:00 1 NIL A 0.10401 8882.000 2026-09-27 01:58:59.772000+02:00 0x17a1d2ec9610c242191b0445481cd901e400ead23113e114bb6a7e3f55149c2c 772434366847256 [0x8184405076b61ab78013f16393322eaf0d0a01a1, 0xbb828515677729c4db2f790a52cf14b1c659e19f] 2026-09-27 01:59:00.054000+02:00 2 xyz:SHEIN A 4.53360 2.400 2026-09-27 01:58:59.772000+02:00 0x6110fe607c2c189b628a0445481cd901ed001646172f376d04d9a9b33b2ff286 743643697789906 [0x33ad48ed92e3e91a98278f0f7456eae6eafa516e, 0x11ec18ffa0559dc4701168fc0348477417df23d9] 2026-09-27 01:59:00.060000+02:00 == edgex column_name column_type 0 ticketId VARCHAR 1 time TIMESTAMP WITH TIME ZONE 2 price DOUBLE 3 size DOUBLE 4 value DOUBLE 5 takerOrderId BIGINT 6 makerOrderId BIGINT 7 takerAccountId BIGINT 8 makerAccountId BIGINT 9 contractId BIGINT 10 contractName VARCHAR 11 isBestMatch BOOLEAN 12 isBuyerMaker BOOLEAN 13 recorded_at TIMESTAMP WITH TIME ZONE ticketId time price size value takerOrderId makerOrderId takerAccountId makerAccountId contractId contractName isBestMatch isBuyerMaker recorded_at 0 27cae54b-5344-463e-9494-872c07b986e5 2026-09-27 01:59:00.071000+02:00 84394.50 0.005 421.9725 798877087459968406 798877087459967382 682137798040678998 689460913991158962 30000001 BTCUSDC True True 2026-09-27 01:59:00.196000+02:00 1 71cdb22b-129f-4cae-be43-679b1bb7a415 2026-09-27 01:59:00.553000+02:00 263.53 0.510 134.4003 798877089485817649 798877089485816625 670462573470574782 689326752872066727 30000077 MRVLUSDC True True 2026-09-27 01:59:00.670000+02:00 2 ed7763b4-0114-47c9-b5a7-4801491d9afd 2026-09-27 01:59:00.554000+02:00 1770.60 0.050 88.5300 798877089485817456 798877089485816432 684713256153791006 686789603503575167 30000034 SNDKUSDC True False 2026-09-27 01:59:00.670000+02:00 == apex column_name column_type 0 T TIMESTAMP WITH TIME ZONE 1 s VARCHAR 2 S_1 VARCHAR 3 v DOUBLE 4 p DOUBLE 5 L VARCHAR 6 i VARCHAR 7 recorded_at TIMESTAMP WITH TIME ZONE T s S_1 v p L i recorded_at 0 2026-09-26 10:13:36.801000+02:00 CASHCATUSDT Buy 229.0 0.18590 MinusTick 4191875c-dbdd-5682-948a-b76360c960d1 2026-09-27 01:59:05.748000+02:00 1 2026-09-26 10:51:23.802000+02:00 CASHCATUSDT Buy 234.0 0.18200 MinusTick af752a07-927c-5048-abf4-e72d73ee1179 2026-09-27 01:59:05.748000+02:00 2 2026-09-26 11:11:41.801000+02:00 CASHCATUSDT Buy 234.0 0.18136 MinusTick 0ab51958-8060-5d86-80ec-91616b625882 2026-09-27 01:59:05.748000+02:00 == pacifica column_name column_type 0 h BIGINT 1 s VARCHAR 2 a DOUBLE 3 p DOUBLE 4 d VARCHAR 5 tc VARCHAR 6 t TIMESTAMP WITH TIME ZONE 7 li BIGINT 8 it BIGINT 9 recorded_at TIMESTAMP WITH TIME ZONE h s a p d tc t li it recorded_at 0 286347936 LIT 0.10 4.85220 close_short normal 2026-09-27 01:59:00.370000+02:00 13314198732 0 2026-09-27 01:59:00.492000+02:00 1 286347938 CL 0.01 94.32000 close_short normal 2026-09-27 01:59:00.501000+02:00 13314198769 0 2026-09-27 01:59:00.630000+02:00 2 286347944 ADA 0.10 0.25424 close_short normal 2026-09-27 01:59:01.497000+02:00 13314198984 0 2026-09-27 01:59:01.622000+02:00 == dydx column_name column_type 0 id VARCHAR 1 size DOUBLE 2 price DOUBLE 3 side VARCHAR 4 createdAt TIMESTAMP WITH TIME ZONE 5 type VARCHAR 6 market VARCHAR id size price side createdAt type market 0 06616fda0000000200000002 0.001 2697.5 SELL 2026-09-27 01:59:01.222000+02:00 LIMIT ETH-USD 1 06616fdd0000000200000002 1.500 2697.5 SELL 2026-09-27 01:59:03.295000+02:00 LIMIT ETH-USD 2 06616fdf0000000200000002 0.001 2697.5 SELL 2026-09-27 01:59:04.563000+02:00 LIMIT ETH-USD Shell cwd was reset to /tmp/peerfeed-a21/work-t2-raw ## [agent thinking] ## [tool call 4] Bash { "command": "cd /tmp/peerfeed-a21/archive; P=/tmp/peerfeed-a21/venv/bin/python; $P -c \"\nimport duckdb\ncon=duckdb.connect(); con.sql(\\\"set timezone='UTC'\\\")\nq={'hyperliquid':(\\\"coin\\\",'time','px'),'edgex':('contractName','time','price'),'apex':('s','T','p'),'pacifica':('s','t','p'),'dydx':('market','createdAt','price')}\nfor v,(s,t,p) in q.items():\n g=f'{v}/trades/parquet/2026/09/2[678]/*.parquet'\n print('==',v)\n print(con.sql(f\\\"select {s} sym,count(*) n,min({p}),max({p}) from read_parquet('{g}') where upper({s}) like '%BTC%' group by 1 order by n desc limit 8\\\").df().to_string())\n print(con.sql(f\\\"select filename, min({t}),max({t}),min(recorded_at) ,count(*) from read_parquet('{v}/trades/parquet/2026/09/27/*.parquet',filename=true) group by 1 order by 1 limit 3\\\").df().to_string() if v!='dydx' else con.sql(f\\\"select filename, min({t}),max({t}),count(*) from read_parquet('{v}/trades/parquet/2026/09/27/*.parquet',filename=true) group by 1 order by 1 limit 3\\\").df().to_string())\n\"" } ## [tool result] == hyperliquid sym n min(px) max(px) 0 BTC 635095 82550.0 85138.0 filename min("time") max("time") min(recorded_at) count_star() 0 hyperliquid/trades/parquet/2026/09/27/00-02.parquet 2026-09-26 00:09:45.196000+00:00 2026-09-27 01:58:59.669000+00:00 2026-09-26 23:59:00.054000+00:00 285787 1 hyperliquid/trades/parquet/2026/09/27/02-04.parquet 2026-09-26 02:04:35.236000+00:00 2026-09-27 03:58:59.630000+00:00 2026-09-27 01:59:00.068000+00:00 228270 2 hyperliquid/trades/parquet/2026/09/27/04-06.parquet 2026-09-26 04:08:09.512000+00:00 2026-09-27 05:58:59.599000+00:00 2026-09-27 03:59:00.014000+00:00 253576 == edgex sym n min(price) max(price) 0 BTCUSDC 229980 82478.5 85110.3 filename min("time") max("time") min(recorded_at) count_star() 0 edgex/trades/parquet/2026/09/27/00-02.parquet 2026-09-26 23:59:00.071000+00:00 2026-09-27 01:58:59.662000+00:00 2026-09-26 23:59:00.196000+00:00 69721 1 edgex/trades/parquet/2026/09/27/02-04.parquet 2026-09-27 01:59:00.080000+00:00 2026-09-27 03:58:59.633000+00:00 2026-09-27 01:59:00.195000+00:00 67709 2 edgex/trades/parquet/2026/09/27/04-06.parquet 2026-09-27 03:59:00.552000+00:00 2026-09-27 05:58:59.632000+00:00 2026-09-27 03:59:00.670000+00:00 74469 == apex sym n min(p) max(p) 0 BTCUSDT 65446 82526.8 85132.0 filename min(T) max(T) min(recorded_at) count_star() 0 apex/trades/parquet/2026/09/27/00-02.parquet 2026-09-26 08:13:36.801000+00:00 2026-09-27 01:58:59.792000+00:00 2026-09-26 23:59:05.655000+00:00 31958 1 apex/trades/parquet/2026/09/27/02-04.parquet 2026-09-26 10:23:58.802000+00:00 2026-09-27 03:58:58.403000+00:00 2026-09-27 01:59:05.735000+00:00 30675 2 apex/trades/parquet/2026/09/27/04-06.parquet 2026-09-26 16:24:22.803000+00:00 2026-09-27 05:58:59.499000+00:00 2026-09-27 03:59:00.356000+00:00 31265 == pacifica sym n min(p) max(p) 0 BTC 26535 82551.0 85106.0 filename min(t) max(t) min(recorded_at) count_star() 0 pacifica/trades/parquet/2026/09/27/00-02.parquet 2026-09-26 23:59:00.370000+00:00 2026-09-27 01:58:59.701000+00:00 2026-09-26 23:59:00.492000+00:00 25801 1 pacifica/trades/parquet/2026/09/27/02-04.parquet 2026-09-27 01:58:59.940000+00:00 2026-09-27 03:58:59.611000+00:00 2026-09-27 01:59:00.074000+00:00 24831 2 pacifica/trades/parquet/2026/09/27/04-06.parquet 2026-09-27 03:59:00.087000+00:00 2026-09-27 05:58:59.673000+00:00 2026-09-27 03:59:00.211000+00:00 24982 == dydx sym n min(price) max(price) 0 BTC-USD 14575 82576.0 85248.0 filename min(createdAt) max(createdAt) count_star() 0 dydx/trades/parquet/2026/09/27/00-02.parquet 2026-09-26 23:59:01.222000+00:00 2026-09-27 01:58:54.539000+00:00 2588 1 dydx/trades/parquet/2026/09/27/02-04.parquet 2026-09-27 01:59:02.605000+00:00 2026-09-27 03:54:10.835000+00:00 534 2 dydx/trades/parquet/2026/09/27/04-06.parquet 2026-09-27 04:00:24.894000+00:00 2026-09-27 05:56:10.128000+00:00 1120 Shell cwd was reset to /tmp/peerfeed-a21/work-t2-raw ## [agent thinking] ## [tool call 5] Bash { "command": "cd /tmp/peerfeed-a21/work-t2-raw; cat > load.py <<'EOF'\nimport duckdb, pandas as pd\nA='/tmp/peerfeed-a21/archive'\ncon=duckdb.connect(); con.sql(\"set timezone='UTC'\")\nq={'hyperliquid':(\"coin='BTC'\",'time','px','sz','tid'),'edgex':(\"contractName='BTCUSDC'\",'time','price','size','ticketId'),\n 'apex':(\"s='BTCUSDT'\",'T','p','v','i'),'pacifica':(\"s='BTC'\",'t','p','a','h'),'dydx':(\"market='BTC-USD'\",'createdAt','price','size','id')}\nout={}\nfor v,(w,t,p,s,k) in q.items():\n g=f\"{A}/{v}/trades/parquet/2026/09/2[678]/*.parquet\"\n df=con.sql(f\"select {t} as ts, {p} as px, {s} as sz, cast({k} as varchar) as k from read_parquet('{g}') where {w}\").df()\n n=len(df); nd=df.duplicated().sum(); nk=df.k.duplicated().sum()\n # key dup with differing content?\n d2=df.drop_duplicates(); nk2=d2.k.duplicated().sum()\n df=d2.drop_duplicates('k')\n df=df[(df.ts>='2026-09-27')&(df.ts<'2026-09-28')].sort_values(['ts','k'])\n print(v,n,'fullrowdups',nd,'keydups',nk,'keydups-after-fullrow',nk2,'day rows',len(df), 'px',df.px.min(),df.px.max(), 'sz<=0',(df.sz<=0).sum())\n out[v]=df\npd.to_pickle(out,'trades.pkl')\nEOF\n/tmp/peerfeed-a21/venv/bin/python load.py" } ## [tool result] hyperliquid 635095 fullrowdups 6 keydups 6 keydups-after-fullrow 0 day rows 175800 px 84082.0 85138.0 sz<=0 0 edgex 229980 fullrowdups 11 keydups 11 keydups-after-fullrow 0 day rows 63737 px 84075.6 85110.3 sz<=0 0 apex 65446 fullrowdups 1687 keydups 1687 keydups-after-fullrow 0 day rows 18490 px 84086.5 85132.0 sz<=0 0 pacifica 26535 fullrowdups 0 keydups 0 keydups-after-fullrow 0 day rows 8317 px 84127.0 85106.0 sz<=0 0 dydx 14575 fullrowdups 7427 keydups 7427 keydups-after-fullrow 0 day rows 1784 px 84078.0 85248.0 sz<=0 0 ## [agent thinking] ## [agent] Loaded and de-duplicated trades for all five venues (files overlap at the edges and some repeat older trades). Next I'm building 1-minute closes and checking for bad prints. ## [tool call 6] Bash { "command": "cd /tmp/peerfeed-a21/work-t2-raw; cat > bars.py <<'EOF'\nimport pandas as pd, numpy as np\nT=pd.read_pickle('trades.pkl')\nidx=pd.date_range('2026-09-27',periods=1440,freq='min',tz='UTC')\nC={}\nfor v,df in T.items():\n df=df.copy(); df['m']=df.ts.dt.floor('min')\n c=df.groupby('m').px.last().reindex(idx); C[v]=c\n print(v,'minutes traded',c.notna().sum(),'first',c.first_valid_index())\nC=pd.DataFrame(C); C.to_pickle('close.pkl')\nd=(C.drop(columns='hyperliquid').div(C.hyperliquid,axis=0)-1)*1e4\nprint(d.describe().T)\nfor v in d: \n s=d[v].abs().sort_values(ascending=False).head(4); print(v, [(str(i.time()),round(d[v][i],2)) for i in s.index])\nEOF\n/tmp/peerfeed-a21/venv/bin/python bars.py" } ## [tool result] hyperliquid minutes traded 1440 first 2026-09-27 00:00:00+00:00 edgex minutes traded 1440 first 2026-09-27 00:00:00+00:00 apex minutes traded 1440 first 2026-09-27 00:00:00+00:00 pacifica minutes traded 1411 first 2026-09-27 00:00:00+00:00 dydx minutes traded 409 first 2026-09-27 00:01:00+00:00 count mean std ... 50% 75% max edgex 1440.0 -3.047882 0.993272 ... -3.112298 -2.372209 1.528581 apex 1440.0 -1.883750 1.382644 ... -2.073856 -0.994507 4.961339 pacifica 1411.0 -1.295958 2.212082 ... -1.063227 0.000000 8.556251 dydx 409.0 1.427367 5.498833 ... 1.411532 3.906944 66.362799 [4 rows x 8 columns] edgex [('06:27:00', np.float64(-5.51)), ('06:28:00', np.float64(-5.4)), ('19:17:00', np.float64(-5.39)), ('05:30:00', np.float64(-5.38))] apex [('07:12:00', np.float64(-5.6)), ('16:23:00', np.float64(-5.44)), ('08:33:00', np.float64(-5.18)), ('13:09:00', np.float64(-5.06))] pacifica [('13:33:00', np.float64(-10.58)), ('13:31:00', np.float64(-9.88)), ('10:11:00', np.float64(-9.41)), ('10:14:00', np.float64(-8.7))] dydx [('14:29:00', np.float64(66.36)), ('10:54:00', np.float64(-30.2)), ('07:41:00', np.float64(28.49)), ('11:05:00', np.float64(-13.08))] ## [agent thinking] ## [tool call 7] Bash { "command": "cd /tmp/peerfeed-a21/work-t2-raw; /tmp/peerfeed-a21/venv/bin/python -c \"\nimport pandas as pd\nT=pd.read_pickle('trades.pkl')\nfor m in ['14:29','10:54','07:41']:\n a=pd.Timestamp('2026-09-27 '+m,tz='UTC')\n for v in ['dydx','hyperliquid']:\n d=T[v]; x=d[(d.ts>=a-pd.Timedelta('2min'))&(d.ts ana.py <<'EOF'\nimport pandas as pd, numpy as np\nT=pd.read_pickle('trades.pkl')\nidx=pd.date_range('2026-09-27',periods=1440,freq='min',tz='UTC')\ndef closes(tiebreak):\n C={}\n for v,df in T.items():\n df=df.copy()\n if tiebreak=='file': df=df.sort_index(kind='stable').sort_values('ts',kind='stable')\n df['m']=df.ts.dt.floor('min')\n if tiebreak=='vwap_last_ts':\n last=df.groupby('m').ts.transform('max'); x=df[df.ts==last]\n c=(x.px*x.sz).groupby(x.m).sum()/x.sz.groupby(x.m).sum()\n else: c=df.groupby('m').px.last()\n C[v]=c.reindex(idx)\n return pd.DataFrame(C)\ndef xc(C,ffill):\n X=C.ffill() if ffill else C\n R=np.log(X).diff() # NaN if either endpoint missing (no ffill)\n out={}\n for v in ['edgex','apex','pacifica','dydx']:\n row={}\n for k in range(-3,4):\n a=R[v]; b=R.hyperliquid.shift(-k) # corr(r_v(t), r_HL(t+k)); k>0 => venue leads\n m=a.notna()&b.notna(); row[k]=(round(a[m].corr(b[m]),3))\n row['n0']=int((R[v].notna()&R.hyperliquid.notna()).sum())\n out[v]=row\n return pd.DataFrame(out).T\nfor tb in ['file','vwap_last_ts']:\n C=closes(tb)\n print('### close def',tb)\n print('-- no fill (returns only across consecutive traded minutes)'); print(xc(C,False))\n print('-- ffill'); print(xc(C,True))\n d=(C.drop(columns='hyperliquid').div(C.hyperliquid,axis=0)-1)*1e4\n for v in d:\n i=d[v].abs().idxmax(); print(v,'max|disloc| bp',round(d[v][i],2),i,'venue',C[v][i],'HL',C.hyperliquid[i],'mean',round(d[v].mean(),2),'n',d[v].notna().sum())\n C.to_pickle(f'close_{tb}.pkl')\nEOF\n/tmp/peerfeed-a21/venv/bin/python ana.py" } ## [tool result] ### close def file -- no fill (returns only across consecutive traded minutes) -3 -2 -1 0 1 2 3 n0 edgex 0.022 0.046 0.027 0.958 0.051 0.044 0.009 1439.0 apex 0.000 0.047 0.053 0.920 0.063 0.045 0.006 1439.0 pacifica 0.050 0.019 0.310 0.728 0.056 0.040 -0.011 1381.0 dydx 0.001 0.051 0.195 0.336 0.068 -0.014 0.044 197.0 -- ffill -3 -2 -1 0 1 2 3 n0 edgex 0.022 0.046 0.027 0.958 0.051 0.044 0.009 1439.0 apex 0.000 0.047 0.053 0.920 0.063 0.045 0.006 1439.0 pacifica 0.052 0.022 0.307 0.725 0.056 0.042 -0.009 1439.0 dydx 0.033 0.083 0.195 0.273 0.014 0.023 -0.012 1438.0 edgex max|disloc| bp -5.51 2026-09-27 06:27:00+00:00 venue 84551.4 HL 84598.0 mean -3.05 n 1440 apex max|disloc| bp -5.68 2026-09-27 08:44:00+00:00 venue 84667.9 HL 84716.0 mean -1.88 n 1440 pacifica max|disloc| bp -11.05 2026-09-27 13:31:00+00:00 venue 84946.0 HL 85040.0 mean -1.3 n 1411 dydx max|disloc| bp 66.36 2026-09-27 14:29:00+00:00 venue 85248.0 HL 84686.0 mean 1.43 n 409 ### close def vwap_last_ts -- no fill (returns only across consecutive traded minutes) -3 -2 -1 0 1 2 3 n0 edgex 0.021 0.047 0.026 0.960 0.051 0.043 0.012 1439.0 apex -0.001 0.048 0.050 0.922 0.063 0.045 0.009 1439.0 pacifica 0.051 0.019 0.311 0.730 0.055 0.042 -0.009 1381.0 dydx 0.033 0.052 0.301 0.436 0.096 -0.024 0.029 197.0 -- ffill -3 -2 -1 0 1 2 3 n0 edgex 0.021 0.047 0.026 0.960 0.051 0.043 0.012 1439.0 apex -0.001 0.048 0.050 0.922 0.063 0.045 0.009 1439.0 pacifica 0.052 0.022 0.308 0.728 0.055 0.043 -0.007 1439.0 dydx 0.052 0.098 0.252 0.321 0.020 0.025 -0.024 1438.0 edgex max|disloc| bp -5.51 2026-09-27 06:27:00+00:00 venue 84551.3705882353 HL 84598.0 mean -3.05 n 1440 apex max|disloc| bp -5.6 2026-09-27 07:12:00+00:00 venue 84466.7 HL 84514.0 mean -1.88 n 1440 pacifica max|disloc| bp -10.68 2026-09-27 13:31:00+00:00 venue 84946.0 HL 85036.80260000001 mean -1.29 n 1411 dydx max|disloc| bp 36.7 2026-09-27 14:29:00+00:00 venue 84996.7918 HL 84686.0 mean 1.41 n 409 ## [agent thinking] ## [agent] Intra-millisecond tie-breaking changes the Apex and Pacifica maxima, so I'm checking those minutes directly. ## [tool call 9] Bash { "command": "cd /tmp/peerfeed-a21/work-t2-raw; /tmp/peerfeed-a21/venv/bin/python -c \"\nimport pandas as pd\nT=pd.read_pickle('trades.pkl')\ndef show(v,m):\n a=pd.Timestamp('2026-09-27 '+m,tz='UTC'); d=T[v].sort_index(kind='stable')\n x=d[(d.ts>=a+pd.Timedelta('55s'))&(d.ts 0 means the venue leads) - **edgeX:** 0.022, 0.046, 0.027, **0.958**, 0.051, 0.044, 0.009. Moves in the same minute as Hyperliquid. - **ApeX:** 0.000, 0.047, 0.053, **0.920**, 0.063, 0.045, 0.006. Moves in the same minute as Hyperliquid. - **Pacifica:** 0.050, 0.019, 0.310, **0.728**, 0.056, 0.040, −0.011. Hyperliquid leads by about 1 minute. - **dYdX:** 0.001, 0.051, 0.195, **0.336**, 0.068, −0.014, 0.044. Hyperliquid leads by about 1 minute (weaker evidence: 197 returns). - No venue leads Hyperliquid; where anyone leads, it is Hyperliquid. **(2) Largest absolute dislocation versus Hyperliquid** - **edgeX:** −5.51 bp at 06:27 UTC - **ApeX:** −5.68 bp at 08:44 UTC - **Pacifica:** −11.05 bp at 13:31 UTC - **dYdX:** +66.36 bp at 14:29 UTC. This is a real sweep of a thin book; it is +36.7 bp if the close is the volume-weighted price of that last millisecond. **Judgement calls** 1. Used the UTC day, filtering on each trade's own timestamp, and removed duplicate trades by ID. 2. The close is the last trade of the minute; trades in the same millisecond keep file order (fill order), not ID order. 3. Minutes without trades are left empty, not filled with the last price. Returns and dislocations use only minutes with real trades; each lag uses the minutes where both series have data. Carrying prices forward was run only as a check. 4. The dYdX sweep was kept because the fills are genuine, and the lower volume-weighted figure is given alongside it. Files are in /tmp/peerfeed-a21/work-t2-raw: - load.py - ana.py - trades.pkl - close_file.pkl - close_vwap_last_ts.pkl ## [run ended] subtype=success turns=10 duration_ms=87062