# 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