{"item":"e02-policy-net/rep-b: small neural displacement policy on frozen mixture-B filter, replicate B","status":"complete on replica.py only. NEGATIVE: net does not close the deficit (net - mixB/table = +0.102, SE 0.056, CI [-0.007,0.212]; oracle - net = 6.185, SE 0.083). No Solidity port, no engine run, no RS2 pairing; no leaderboard or engine claim. Replica scores cannot select an entry.","headline":{"validation":"seeds 32000..32255, 10000 steps, same replica streams for 3 arms","paired":{"net_minus_mixB":{"n":256,"mean":0.102,"se":0.056,"ci95":[-0.007,0.212]},"oracle_minus_net":{"n":256,"mean":6.185,"se":0.083,"ci95":[6.023,6.347]},"oracle_minus_mixB":{"n":256,"mean":6.288,"se":0.08,"ci95":[6.13,6.445]}},"arms":{"net":{"edge":517.902,"retail_edge":547.137,"arb_edge":-29.235,"price_err_sq_sum":5.6626489062759235,"price_err_count":2661844,"pooled_rms_bps":14.585},"mixB":{"edge":517.8,"retail_edge":546.731,"arb_edge":-28.932,"price_err_sq_sum":6.073210728985771,"price_err_count":2614859,"pooled_rms_bps":15.24},"oracle":{"edge":524.087,"retail_edge":549.563,"arb_edge":-25.476}}},"frozen_estimator":{"artifact":"https://api.imd.fun/artifacts/827590bb235808bd3789c89ad42e5038d2733d133c744455327a3e4275089b26","response_sha256_equals_id":true,"embedded_source_hashes_verified":{"mf.py":"8adbd509efdac3e77ccde38d07a7272e9706b42ea4ecc926f77963e2a332445e","run.py":"7d7026c48cea6901ff3debebe5f552a7c263fa330a7f14448338a3df41837d33","agg.py":"d0e2f71bb48ab1467ca63d3af31d63f739678ce839408712f0165a3e69f77479","test_mf.py":"4192217a4bc758a6c0e5308d59224ea02a24dd217da012bd13fe5df824782ddc","sweep.py":"8e6613ef40efa930307bbea6a95acf4c438c15ce26b89afab127ee1b49b6efe5"},"constants":{"KMAX":4,"SIG0":0.000945,"N0":200.0,"TAU_ROUTER":0.0015,"ROUTER":1,"PRETAIL":0.27,"RET_MU":"ln(20)-0.72","RET_SD":1.3,"PIN_VAR":1e-12,"MINVAR":1e-12,"ARB_CONF":0.9},"use":"mf.MixFilter unchanged; NetArm calls f.update(...) then f.set_fees(net fees) so the filter's stored fee history (no-arb band, arb pin) is the net's own fees. mixB arm = mf.Arm('filter') unchanged (oracle_table on p_hat, flag parb>0.5); oracle arm = mf.Arm('oracle') (true p, true arb flag; ceiling reference only)."},"inputs_hashes":{"replica.py":"d079712fa1f4850ad8337e656e7ee8dbdde806cd4762d597fae50f547ef9c7c4","oracle_table.json":"3e9d1fc8874c6d796d4c26948d486b587f2a6b5610b20fba99923a60954cf4b5","filter-brief.md":"0ef2200226b68aa58de6aad268442ba09ada710c54b3fb0ec35c77b491f78a4b","setup.sh":"dc7fa6a1e59f5b043d3954cf68d538318b7affaf5c0db3ca69a1822680f300d4"},"policy":{"architecture":"feed-forward 3-8-2, hidden activation tanh, linear outputs; 58 parameters","features":{"d":"ln(spot/p_hat)/0.003 where p_hat=spot*exp(E[z]); own displacement from filter posterior mean in 30 bps units. Redundancy: d == -E[z]/0.003 exactly, so posterior mean and own displacement are one input","s":"sqrt(Var[z])/0.003, posterior sd in 30 bps units","a":"parb, inferred arb probability of the current callback (0 on same-timestamp follow-up callbacks)"},"normalization":"x0=clip(d,-8,8)/4; x1=clip(s,0,8)/2-1; x2=2a-1","forward":"h_i=tanh(b1_i+sum_j W1_ij x_j); ask=b2_0+sum_i W2_0i h_i; bid=b2_1+sum_i W2_1i h_i (30 bps units, offsets from p_hat)","fees":"askFee=1-exp(d*0.003-ask*0.003); bidFee=1-exp(-bid*0.003-d*0.003); each clipped to [0,0.1] (replica clamps again identically); init fees 0.003/0.003","weight_layout":"W1 row-major (8x3), b1 (8), W2 row-major (2x8), b2 (2)","weights_final":[-0.15954381,-0.03887491,-42.90458897,-0.1036117,-0.07565444,0.09331852,2.93346892,-0.02119541,0.03684401,0.82815649,-0.04245042,0.03946522,0.57856147,-0.01401935,0.02029821,-5.04825336,-0.01973325,0.05357571,-0.47317593,-0.0632413,-0.00108048,1.4867082,0.04099524,0.10490927,0.07932005,1.54068246,0.75763919,1.99850825,-0.92125281,-1.55572498,1.14566415,0.46223355,-0.02990156,3.4899082,-1.09848807,-0.18023115,3.05523558,-1.06338619,-3.63252823,0.58845065,-0.06744293,0.98705112,3.71795116,-2.80560201,3.82713061,0.56672925,5.79312761,-5.65672272,2.92328497,1.15463306],"weights_distilled":[-0.01681217,-0.03493554,-42.95313929,-0.12992635,-0.00013944,-0.00820289,2.87560797,0.00213088,-0.0002031,0.87769351,-6.66e-05,0.00057876,0.57909993,-5.99e-05,0.00070567,-4.97547514,-0.00199906,-0.00144694,-0.45502914,0.00014257,-0.00064334,1.53857873,0.00116258,-0.00029407,0.03128023,1.54820646,0.7357724,2.0001935,-0.93126051,-1.60069801,1.20268695,0.35130283,-0.07646882,3.56150111,-1.09296348,-0.18587808,2.91580058,-1.08508487,-3.64453537,0.59633927,-0.07546378,0.95114454,3.80182072,-2.73670591,3.79096241,0.58885049,5.81101231,-5.71343872,2.80108522,1.10454957],"stdlib_fallback":"inference (nnpol.py + mf.py) uses only Python math/json; numpy only in distill/agg, cma only in training","state_compute_cost":"filter state as mf (<=4 comps x3 + sigma accumulators + last pin + t + fees, ~17 slots); net adds 0 state, 24+16 mul-adds and 8 tanh per callback. No Solidity, gas unmeasured."},"distillation":{"target":"oracle_table.json ask/bid interpolated over d, +arb_flag if a>0.5; independent of s","samples":20000,"sampling":"d~U(-9,9), s~U(0,8), a in {0,1} (80%) or U(0,1) (20%)","optimizer":"full-batch Adam lr 0.01 then 0.002 at 20000, 30000 iters, numpy seed 12345","train_rms_units30bps":0.0743,"grid_rms_units30bps":0.0795,"grid_rms_bps":2.385,"grid_maxabs_units30bps":0.3631,"grid":"d in linspace(-8,8,321) x a in {0,1} x s in {0,1.5,4}"},"training":{"seeds":"31000..31255 only, CRN: generation g uses block of 16 seeds 31000+((16g+i) mod 256); all candidates + current mean + distilled warm start on the same block","episode_steps":2000,"lib":"cma 4.5.0 CMAEvolutionStrategy, popsize 12","run1":{"sigma0":0.15,"cma_seed":7,"gens":17,"result":"mean drifted below distilled in most gens (mean_w-distilled ~ -0.7..-3.0 per 2000-step episode); discarded","log_cols":"gen,first_seed,best,popmean,mean_w,distilled,sigma","log":[[0,31000,107.46,101.81,109.406,109.406,0.1415],[1,31016,114.39,106.69,117.152,117.209,0.1352],[2,31032,106.28,101.24,107.852,108.584,0.1314],[3,31048,92.77,90.17,94.925,96.214,0.1289],[4,31064,105.76,100.22,106.503,108.032,0.1268],[5,31080,99.44,95.94,101.608,103.553,0.1248],[6,31096,103.45,99.32,104.238,106.968,0.1233],[7,31112,95.74,90.56,95.366,98.379,0.1223],[8,31128,103.24,99.88,103.294,106.233,0.1208],[9,31144,106.76,103.67,108.038,110.388,0.1191],[10,31160,101.86,97.97,103.161,104.615,0.1174],[11,31176,102.66,99.76,102.614,104.552,0.1161],[12,31192,104.57,102.21,105.996,107.124,0.1157],[13,31208,102.56,99.56,102.904,104.641,0.1159],[14,31224,95.36,93.6,96.577,97.582,0.1162],[15,31240,96.29,93.63,97.169,97.955,0.1162],[16,31000,107.29,103.67,108.714,109.406,0.1151]]},"run2_frozen":{"sigma0":0.04,"cma_seed":8,"gens":15,"mean_w_minus_distilled_per_gen":[0.0,0.0,0.048,0.102,-0.07,0.226,0.226,0.042,0.101,-0.061,-0.017,-0.079,0.014,-0.028,-0.172],"log":[[0,31000,109.01,107.76,109.406,109.406,0.0381],[1,31016,117.11,115.46,117.209,117.209,0.0368],[2,31032,108.28,107.26,108.632,108.584,0.0356],[3,31048,96.01,95.24,96.316,96.214,0.0344],[4,31064,107.61,106.85,107.962,108.032,0.0333],[5,31080,103.54,102.9,103.779,103.553,0.0324],[6,31096,106.79,106.14,107.194,106.968,0.0319],[7,31112,98.35,97.48,98.421,98.379,0.0316],[8,31128,106.18,105.48,106.334,106.233,0.0313],[9,31144,110.24,109.37,110.327,110.388,0.0309],[10,31160,104.61,103.78,104.598,104.615,0.0306],[11,31176,104.17,103.7,104.473,104.552,0.0307],[12,31192,106.87,106.48,107.137,107.124,0.0306],[13,31208,104.51,103.83,104.613,104.641,0.0305],[14,31224,97.21,96.53,97.411,97.582,0.0303]]},"initial_score":"distilled net, 2000-step blocks: see 'distilled' column (e.g. 109.41 on 31000..31015)","final_score":"run2 mean: 'mean_w' column, gen 14 97.41 vs distilled 97.58 on 31224..31239; average difference over 15 gens ~0, i.e. no measurable training gain","budget":"run1 17 gens (~424 s), run2 15 gens (~422 s); 1 effective CPU (16 nominal cores gave no parallel speedup: 32 sims 6.9 s with 1 worker, 9.4 s with 16)","freeze":"run2 es.mean frozen before any validation seed was run"},"ablation_first64":{"sd":{"n":64,"mean":-1.344,"se":0.128,"ci95":[-1.596,-1.093]},"arb":{"n":64,"mean":-0.432,"se":0.113,"ci95":[-0.654,-0.211]},"both":{"n":64,"mean":-1.686,"se":0.135,"ci95":[-1.951,-1.421]},"note":"ablated minus full net, seeds 32000..32063, same weights (no refit); sd ablation fixes s=1.5 (x1=-0.25), arb ablation fixes parb=0 (x2=-1)"},"ablation_reading":"Removing sd costs -1.34 and parb -0.43 relative to the full net, yet the full net is only +0.10 over the table policy (which ignores sd). So the net's sd dependence is a distillation artifact (targets were flat in s, net is not exactly flat), not a learned uncertainty action: pinning s to 1.5 moves the net away from the table it approximates.","hidden_input_test":{"method":"subclass passes p=None, s2=None to policy; edges must be identical","rows_seed_edgefull_edgeNoP_equal":[[32000,518.9588705413438,518.9588705413438,true],[32001,549.0984096841743,549.0984096841743,true],[32002,408.8656822029651,408.8656822029651,true]]},"per_seed_cols":"seed, net_edge, mixB_edge, oracle_edge, net_retail, net_arb, mixB_retail, mixB_arb","per_seed":[[32000,518.96,517.53,526.66,548.58,-29.62,546.58,-29.05],[32001,549.1,551.5,558.67,577.84,-28.74,579.77,-28.27],[32002,408.87,408.13,413.26,434.97,-26.1,434.01,-25.88],[32003,374.23,374.43,378.92,396.03,-21.8,396.09,-21.66],[32004,391.65,393.25,398.19,414.03,-22.38,415.5,-22.25],[32005,384.11,382.78,389.2,406.53,-22.42,404.52,-21.74],[32006,433.6,432.64,440.66,459.18,-25.58,457.88,-25.24],[32007,450.0,450.33,455.98,475.77,-25.77,475.47,-25.14],[32008,603.57,602.82,609.89,632.48,-28.9,631.82,-29.0],[32009,613.17,611.84,618.5,646.09,-32.92,644.79,-32.94],[32010,440.23,439.03,446.06,464.26,-24.03,462.61,-23.58],[32011,646.05,646.9,658.42,719.72,-73.68,719.69,-72.8],[32012,673.84,675.44,680.98,708.0,-34.16,710.09,-34.65],[32013,449.07,448.06,453.0,472.55,-23.48,471.55,-23.5],[32014,433.5,432.56,440.17,459.7,-26.2,458.35,-25.79],[32015,442.11,441.88,447.05,466.76,-24.65,466.29,-24.41],[32016,481.63,481.57,486.03,507.13,-25.5,506.41,-24.84],[32017,424.52,425.15,429.19,450.2,-25.68,451.01,-25.86],[32018,593.75,593.54,599.78,623.7,-29.95,622.95,-29.41],[32019,484.82,485.36,490.58,511.72,-26.91,511.9,-26.54],[32020,623.12,623.19,631.86,653.57,-30.45,653.94,-30.76],[32021,553.56,554.38,558.85,581.48,-27.91,581.76,-27.38],[32022,664.6,664.85,670.86,695.22,-30.62,695.2,-30.35],[32023,574.05,573.41,580.58,606.69,-32.64,605.6,-32.19],[32024,555.0,556.0,562.79,584.2,-29.2,584.62,-28.63],[32025,550.85,550.49,558.45,577.43,-26.58,576.51,-26.02],[32026,436.24,436.48,440.2,459.31,-23.07,459.68,-23.2],[32027,521.6,521.22,528.03,550.65,-29.05,549.98,-28.76],[32028,632.9,633.39,639.88,665.6,-32.7,665.71,-32.31],[32029,412.45,411.57,417.24,434.62,-22.16,433.29,-21.72],[32030,381.98,382.83,388.19,406.11,-24.14,407.12,-24.29],[32031,456.8,455.95,464.76,482.93,-26.12,481.59,-25.64],[32032,625.6,624.77,631.77,657.61,-32.01,656.25,-31.47],[32033,436.17,435.51,440.14,460.38,-24.21,459.36,-23.85],[32034,594.5,594.0,602.81,626.79,-32.29,626.05,-32.05],[32035,552.53,551.92,558.16,580.77,-28.24,580.16,-28.24],[32036,414.14,414.32,418.97,437.7,-23.56,437.81,-23.49],[32037,406.19,405.71,410.94,429.96,-23.77,429.29,-23.58],[32038,529.73,529.67,534.7,558.36,-28.63,558.1,-28.44],[32039,412.25,411.32,415.16,434.12,-21.87,432.86,-21.54],[32040,445.05,444.47,449.76,469.62,-24.57,468.71,-24.24],[32041,805.25,806.63,811.97,900.18,-94.93,901.05,-94.42],[32042,534.59,534.62,541.02,562.31,-27.72,562.57,-27.95],[32043,370.12,368.89,375.92,391.83,-21.71,390.38,-21.49],[32044,521.87,521.29,525.97,548.61,-26.74,548.12,-26.83],[32045,652.67,653.92,658.07,683.03,-30.36,683.89,-29.97],[32046,636.52,636.26,643.52,667.05,-30.52,666.33,-30.07],[32047,433.1,432.88,436.84,457.02,-23.93,456.24,-23.36],[32048,501.21,500.09,506.14,529.34,-28.13,528.26,-28.16],[32049,599.69,598.79,605.72,630.9,-31.2,629.65,-30.86],[32050,478.04,477.85,487.04,506.14,-28.1,505.24,-27.39],[32051,633.45,634.3,640.52,665.16,-31.72,665.63,-31.33],[32052,633.79,634.16,638.28,663.71,-29.91,663.59,-29.43],[32053,471.42,470.93,477.06,497.42,-26.0,496.51,-25.58],[32054,381.05,381.58,386.3,402.83,-21.78,402.88,-21.29],[32055,543.68,543.72,549.85,572.95,-29.27,572.23,-28.5],[32056,569.14,568.05,574.84,597.78,-28.64,596.85,-28.8],[32057,482.05,482.46,489.64,510.91,-28.86,510.77,-28.31],[32058,470.17,470.1,476.89,495.63,-25.46,495.27,-25.17],[32059,577.73,577.16,581.98,607.32,-29.58,606.31,-29.15],[32060,412.13,411.75,418.25,435.26,-23.13,434.79,-23.05],[32061,467.8,469.35,475.64,494.21,-26.41,495.68,-26.33],[32062,521.99,522.85,528.56,548.22,-26.23,548.96,-26.11],[32063,359.04,359.63,364.26,379.25,-20.21,379.77,-20.14],[32064,599.94,601.44,607.0,630.21,-30.26,631.66,-30.21],[32065,516.15,515.31,523.41,544.4,-28.25,543.15,-27.84],[32066,687.14,686.84,694.01,720.93,-33.79,720.17,-33.33],[32067,627.95,627.45,634.18,658.72,-30.78,657.67,-30.22],[32068,519.56,520.79,525.8,547.39,-27.83,548.49,-27.69],[32069,458.49,459.42,464.13,484.26,-25.77,484.88,-25.46],[32070,626.54,624.66,631.69,659.19,-32.66,656.61,-31.95],[32071,361.35,361.02,367.25,383.77,-22.41,382.61,-21.59],[32072,650.15,650.27,656.63,682.21,-32.06,682.31,-32.03],[32073,604.29,604.29,612.49,636.67,-32.37,636.38,-32.09],[32074,608.75,608.55,614.52,640.33,-31.58,640.26,-31.71],[32075,395.93,395.32,400.27,417.65,-21.72,416.78,-21.46],[32076,459.86,459.1,465.73,486.33,-26.47,485.31,-26.21],[32077,348.81,347.88,354.4,369.9,-21.1,368.81,-20.93],[32078,589.12,588.27,596.83,620.06,-30.94,618.89,-30.62],[32079,543.68,543.75,550.69,573.15,-29.47,573.22,-29.47],[32080,586.12,587.31,594.17,617.75,-31.63,618.85,-31.54],[32081,472.83,471.45,477.86,498.5,-25.68,496.96,-25.51],[32082,550.32,550.36,554.92,584.79,-34.47,584.15,-33.79],[32083,479.28,477.06,484.69,505.98,-26.7,504.22,-27.16],[32084,451.83,451.87,458.34,478.13,-26.3,477.72,-25.85],[32085,619.74,620.02,627.22,655.27,-35.52,655.09,-35.07],[32086,558.21,556.79,563.52,586.25,-28.04,584.27,-27.49],[32087,478.32,477.89,482.66,502.62,-24.3,501.99,-24.09],[32088,419.24,418.92,425.77,445.5,-26.26,444.76,-25.84],[32089,542.63,541.58,549.98,572.9,-30.27,571.78,-30.2],[32090,476.68,476.63,483.94,500.39,-23.7,500.28,-23.65],[32091,394.53,394.37,400.96,415.69,-21.16,415.43,-21.06],[32092,658.11,657.56,665.3,689.43,-31.32,688.43,-30.86],[32093,402.05,401.35,406.65,425.96,-23.91,425.08,-23.73],[32094,458.19,458.39,464.99,482.67,-24.48,482.62,-24.23],[32095,531.83,531.7,537.54,562.52,-30.69,562.21,-30.52],[32096,542.39,541.13,549.26,569.22,-26.83,567.84,-26.7],[32097,615.12,615.19,623.33,695.58,-80.46,695.93,-80.75],[32098,498.67,500.47,506.61,524.17,-25.5,525.37,-24.9],[32099,630.32,630.07,637.55,661.65,-31.33,661.46,-31.39],[32100,419.63,420.01,425.71,446.24,-26.61,446.4,-26.39],[32101,674.96,675.36,680.77,709.72,-34.76,709.71,-34.35],[32102,484.62,484.08,491.09,511.35,-26.73,510.69,-26.61],[32103,584.18,583.37,591.56,612.79,-28.61,611.62,-28.25],[32104,497.41,497.48,500.13,527.01,-29.6,527.53,-30.05],[32105,486.12,486.31,492.37,511.78,-25.65,511.71,-25.4],[32106,567.65,568.18,572.65,605.12,-37.48,605.09,-36.91],[32107,357.99,356.61,363.26,378.77,-20.78,377.15,-20.54],[32108,399.47,399.46,406.18,421.63,-22.15,421.0,-21.54],[32109,595.82,594.82,604.16,627.98,-32.16,626.6,-31.78],[32110,533.68,533.06,540.28,565.8,-32.13,564.47,-31.42],[32111,439.7,439.25,444.73,462.54,-22.84,461.86,-22.61],[32112,354.25,353.73,360.78,376.05,-21.81,374.92,-21.19],[32113,358.38,357.99,364.83,380.98,-22.6,380.23,-22.24],[32114,555.26,554.87,562.02,584.45,-29.18,583.71,-28.84],[32115,384.26,382.9,387.55,406.24,-21.98,404.88,-21.98],[32116,478.63,479.0,485.26,504.38,-25.75,504.74,-25.74],[32117,492.02,491.74,496.66,550.75,-58.73,549.99,-58.25],[32118,413.08,411.74,418.72,435.5,-22.42,434.11,-22.37],[32119,538.76,537.66,543.69,567.26,-28.5,565.86,-28.2],[32120,421.25,420.94,427.28,444.9,-23.65,444.07,-23.13],[32121,422.54,421.05,429.01,445.08,-22.53,443.53,-22.47],[32122,503.4,502.62,510.12,530.68,-27.28,529.41,-26.79],[32123,596.6,595.6,602.54,628.55,-31.95,627.11,-31.51],[32124,647.39,648.57,655.36,680.92,-33.53,681.66,-33.09],[32125,441.61,441.26,448.12,467.26,-25.65,466.48,-25.22],[32126,633.54,634.7,641.41,664.08,-30.55,665.02,-30.32],[32127,589.18,590.28,596.72,619.37,-30.19,619.8,-29.52],[32128,624.63,625.02,630.8,758.23,-133.6,758.33,-133.31],[32129,543.65,544.41,552.16,572.97,-29.32,573.44,-29.02],[32130,517.74,517.38,523.59,546.27,-28.53,545.37,-27.99],[32131,441.32,441.31,445.33,466.38,-25.07,465.89,-24.58],[32132,433.29,432.75,439.25,457.19,-23.9,456.3,-23.55],[32133,598.36,596.68,602.44,630.39,-32.03,628.11,-31.44],[32134,503.35,503.82,509.97,531.56,-28.21,531.04,-27.22],[32135,536.06,536.06,540.34,562.06,-26.0,561.94,-25.88],[32136,527.58,526.63,533.11,556.53,-28.94,555.22,-28.58],[32137,556.07,557.79,563.5,587.12,-31.05,588.44,-30.65],[32138,543.98,544.68,551.26,572.39,-28.41,572.65,-27.97],[32139,391.63,392.64,397.97,413.33,-21.7,414.16,-21.52],[32140,462.87,461.18,466.52,486.11,-23.24,484.42,-23.24],[32141,389.34,390.09,395.57,412.56,-23.22,412.81,-22.72],[32142,613.47,613.82,620.52,648.12,-34.66,648.29,-34.47],[32143,588.44,589.74,595.03,619.82,-31.38,621.37,-31.63],[32144,491.7,492.91,499.35,526.15,-34.44,527.2,-34.29],[32145,578.82,578.3,585.45,609.05,-30.23,608.27,-29.96],[32146,627.06,627.0,632.57,658.52,-31.46,658.12,-31.12],[32147,436.72,436.75,441.76,459.92,-23.2,459.67,-22.92],[32148,616.22,615.99,622.73,646.64,-30.42,646.38,-30.39],[32149,579.89,580.53,587.54,610.59,-30.7,610.77,-30.24],[32150,594.01,596.48,601.78,627.51,-33.5,629.36,-32.88],[32151,623.22,623.49,630.02,654.47,-31.25,654.11,-30.62],[32152,590.25,590.48,596.53,620.61,-30.36,620.24,-29.76],[32153,374.45,375.23,380.14,398.48,-24.03,398.94,-23.71],[32154,412.0,411.05,419.31,434.94,-22.94,433.63,-22.58],[32155,496.95,496.34,502.94,524.11,-27.15,523.25,-26.91],[32156,387.95,388.76,396.23,410.83,-22.89,411.6,-22.84],[32157,495.96,496.75,502.46,522.57,-26.61,523.02,-26.27],[32158,504.28,504.32,510.33,530.49,-26.21,530.56,-26.25],[32159,438.91,438.5,444.99,462.5,-23.58,461.84,-23.34],[32160,534.94,534.9,540.75,563.16,-28.23,563.01,-28.11],[32161,491.84,490.24,496.09,516.28,-24.44,514.78,-24.54],[32162,468.59,468.92,473.98,495.44,-26.84,495.41,-26.49],[32163,465.77,465.43,470.27,492.0,-26.23,491.37,-25.94],[32164,451.81,451.98,456.48,476.83,-25.02,476.51,-24.53],[32165,562.6,563.02,567.71,592.6,-30.0,592.45,-29.43],[32166,589.79,591.96,599.06,619.68,-29.89,621.4,-29.44],[32167,492.89,493.28,499.54,519.77,-26.89,519.75,-26.47],[32168,682.72,681.5,689.22,723.45,-40.74,721.59,-40.08],[32169,556.58,556.96,564.81,587.42,-30.84,587.23,-30.27],[32170,490.3,490.62,496.6,520.21,-29.92,519.93,-29.31],[32171,491.79,491.88,496.62,517.81,-26.02,517.77,-25.89],[32172,584.13,584.01,589.34,615.86,-31.74,615.36,-31.35],[32173,569.93,570.43,577.8,600.29,-30.36,600.41,-29.98],[32174,363.3,363.23,367.64,384.45,-21.15,383.94,-20.71],[32175,452.09,450.84,457.85,478.87,-26.78,477.09,-26.25],[32176,406.32,405.99,412.65,429.01,-22.68,427.85,-21.87],[32177,425.39,423.53,431.92,448.26,-22.87,446.38,-22.85],[32178,456.09,456.33,462.72,480.82,-24.73,480.79,-24.46],[32179,601.26,599.94,606.83,631.76,-30.5,630.16,-30.22],[32180,438.32,439.02,444.03,461.97,-23.65,462.38,-23.35],[32181,505.32,505.54,510.88,531.52,-26.2,531.4,-25.86],[32182,597.26,597.58,601.85,626.89,-29.63,626.95,-29.36],[32183,594.96,595.84,601.86,631.33,-36.36,631.33,-35.5],[32184,535.79,535.39,540.08,564.48,-28.7,563.33,-27.94],[32185,421.78,420.88,426.72,448.0,-26.22,447.21,-26.32],[32186,471.79,471.8,479.15,500.02,-28.23,499.8,-27.99],[32187,747.49,749.53,756.48,784.48,-37.0,785.9,-36.37],[32188,564.65,564.15,569.89,592.54,-27.89,592.06,-27.91],[32189,485.59,485.84,489.28,512.33,-26.74,512.12,-26.28],[32190,460.1,461.17,468.6,486.61,-26.51,487.68,-26.51],[32191,392.08,391.73,396.4,412.25,-20.18,411.38,-19.66],[32192,490.04,489.3,496.74,516.16,-26.12,515.13,-25.84],[32193,440.01,440.18,447.8,464.42,-24.41,464.58,-24.4],[32194,496.28,495.52,502.45,524.36,-28.08,523.03,-27.52],[32195,701.01,700.75,708.62,732.48,-31.46,731.73,-30.98],[32196,440.44,441.31,445.19,464.62,-24.19,465.33,-24.02],[32197,707.99,708.3,715.86,743.63,-35.64,744.2,-35.9],[32198,589.8,589.97,596.27,619.06,-29.26,619.32,-29.35],[32199,514.09,514.79,520.44,542.17,-28.07,543.3,-28.51],[32200,487.91,487.93,493.88,520.56,-32.65,520.36,-32.44],[32201,391.06,391.11,396.17,413.32,-22.27,413.06,-21.95],[32202,616.43,616.4,623.18,647.24,-30.81,647.13,-30.73],[32203,519.54,520.28,527.32,547.75,-28.21,548.39,-28.1],[32204,592.0,592.0,596.97,622.95,-30.95,622.82,-30.82],[32205,532.11,531.44,538.04,560.63,-28.52,559.88,-28.44],[32206,432.12,432.56,437.95,457.4,-25.28,457.32,-24.77],[32207,512.33,511.87,517.29,540.76,-28.43,540.38,-28.51],[32208,460.12,458.31,465.01,485.32,-25.2,483.35,-25.04],[32209,588.99,590.4,595.53,620.06,-31.07,620.95,-30.55],[32210,497.65,497.59,504.13,524.47,-26.82,524.04,-26.45],[32211,490.84,490.08,497.3,517.08,-26.24,516.6,-26.52],[32212,428.55,428.48,433.36,453.09,-24.53,452.58,-24.1],[32213,538.83,538.54,546.11,566.55,-27.72,565.97,-27.43],[32214,569.91,570.29,575.88,601.92,-32.01,601.91,-31.62],[32215,660.3,659.77,665.8,693.86,-33.57,692.71,-32.94],[32216,480.01,479.22,485.38,510.9,-30.89,509.85,-30.63],[32217,595.46,596.45,602.03,625.81,-30.34,626.88,-30.43],[32218,463.53,463.67,469.61,486.86,-23.33,487.09,-23.42],[32219,618.34,617.42,625.78,648.95,-30.61,647.86,-30.44],[32220,521.77,521.93,529.86,550.34,-28.56,550.63,-28.7],[32221,461.96,462.9,467.22,488.27,-26.32,488.9,-26.0],[32222,446.08,444.98,451.01,470.74,-24.66,469.18,-24.2],[32223,434.59,432.73,440.42,459.88,-25.29,458.02,-25.29],[32224,493.72,494.17,500.73,520.77,-27.06,520.97,-26.8],[32225,665.15,666.52,673.56,696.48,-31.33,697.7,-31.18],[32226,506.81,507.42,512.7,536.32,-29.51,535.59,-28.17],[32227,425.04,425.2,431.64,449.76,-24.72,449.61,-24.41],[32228,571.32,568.41,577.97,602.39,-31.06,599.2,-30.79],[32229,582.98,582.13,587.46,611.37,-28.39,610.34,-28.21],[32230,523.96,524.56,530.85,551.56,-27.6,551.61,-27.06],[32231,562.16,560.55,566.62,629.98,-67.81,628.59,-68.05],[32232,551.98,550.64,558.2,581.61,-29.63,579.97,-29.33],[32233,719.5,719.25,725.56,763.05,-43.55,762.0,-42.75],[32234,678.25,677.99,682.66,712.45,-34.2,712.36,-34.38],[32235,522.28,522.32,530.32,550.34,-28.06,549.64,-27.32],[32236,679.9,677.74,686.09,717.47,-37.57,714.6,-36.86],[32237,402.57,402.94,407.46,424.89,-22.32,425.31,-22.36],[32238,502.54,502.77,509.82,532.7,-30.16,532.33,-29.56],[32239,533.15,533.31,539.37,561.8,-28.65,561.51,-28.2],[32240,544.94,543.38,551.21,573.13,-28.19,571.29,-27.91],[32241,616.86,619.96,625.72,653.87,-37.01,656.11,-36.15],[32242,495.63,494.58,502.07,521.02,-25.39,520.0,-25.41],[32243,481.06,480.83,488.16,507.28,-26.23,506.66,-25.83],[32244,530.68,530.59,537.14,560.49,-29.81,559.87,-29.28],[32245,570.79,571.82,578.17,600.18,-29.39,600.95,-29.12],[32246,658.33,659.66,666.23,692.77,-34.43,693.0,-33.33],[32247,392.13,392.0,397.71,417.4,-25.27,416.56,-24.55],[32248,608.05,606.32,615.69,639.22,-31.18,636.8,-30.47],[32249,497.5,498.22,503.96,523.9,-26.41,524.53,-26.3],[32250,460.44,460.05,469.05,486.96,-26.52,486.0,-25.95],[32251,384.68,383.34,389.42,406.27,-21.59,404.15,-20.8],[32252,575.12,575.57,578.9,603.25,-28.13,603.21,-27.64],[32253,617.66,617.12,624.11,649.37,-31.71,648.43,-31.31],[32254,588.7,588.96,595.15,622.96,-34.27,623.29,-34.33],[32255,577.48,577.04,582.64,606.97,-29.49,606.27,-29.23]],"runtime_s":{"eval_256x3":382.6,"ablation_64x3_plus_hidden":108.0,"distill":"<60"},"deps":{"python":"3.12.3","numpy":"2.5.4","cma":"4.5.0","venv":"setup.sh from research dir (amm_sim_rs wheel sha aedb6828..., not used here)","amm-challenge":"6b6921f8d463314aa7c96234e1be25a25245f704"},"dead_ends":["CMA-ES sigma0 0.15, 16 seeds x 2000 steps: noise-dominated, mean degraded vs warm start","CMA-ES sigma0 0.04: no gain over warm start within 15 gens (|mean-distilled|<0.3/episode)","Net policy on mixB filter: +0.10 (SE .056) over table; deficit to oracle stays 6.19, consistent with brief finding that price-estimate error, not the policy map, is the gap (mixB gap 6.288 here vs 6.273 reported in artifact on 10000..10255)"],"limitations":["replica only; no engine/Solidity; small CMA budget forced by 1 effective CPU","pooled price RMS logged over all own-pool callbacks (net 14.585 bps, mixB 15.24 bps); filter is identical, differences come from the fee path"],"source":{"nnpol.py":"\"\"\"Small feed-forward displacement policy on top of the FROZEN mixture-B filter (mf.py).\nInputs (all observable): d = ln(spot/p_hat)/0.003 (own displacement from filter posterior mean, 30 bps units;\n identical to -E[z]/0.003, so 'posterior mean' and 'own displacement' are ONE input, not two),\n s = posterior sd of z / 0.003, a = inferred arb probability parb in [0,1].\nNormalization: x0 = clip(d,-8,8)/4 ; x1 = clip(s,0,8)/2 - 1 ; x2 = 2*a - 1.\nNet: h = tanh(W1 x + b1) (8 hidden), o = W2 h + b2 (2 outputs: ask, bid offsets in 30 bps units).\nFees: askFee = 1-exp(d*0.003 - ask*0.003), bidFee = 1-exp(-bid*0.003 - d*0.003), each clipped to [0, 0.1].\nNo true price, label, rival state or sampled parameter is used for fees.\"\"\"\nimport math, sys, os\nsys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))\nimport mf\nH = 8; NIN = 3; NP = NIN * H + H + 2 * H + 2  # 58\n\ndef unpack(w):\n    k = 0; W1 = [[w[k + i * NIN + j] for j in range(NIN)] for i in range(H)]; k += NIN * H\n    b1 = list(w[k:k + H]); k += H\n    W2 = [[w[k + o * H + i] for i in range(H)] for o in range(2)]; k += 2 * H\n    b2 = list(w[k:k + 2]); return W1, b1, W2, b2\n\ndef feats(d, s, a):\n    return (min(max(d, -8.0), 8.0) / 4.0, min(max(s, 0.0), 8.0) / 2.0 - 1.0, 2.0 * a - 1.0)\n\ndef net(P, x):\n    W1, b1, W2, b2 = P\n    h = [math.tanh(b1[i] + W1[i][0] * x[0] + W1[i][1] * x[1] + W1[i][2] * x[2]) for i in range(H)]\n    return (b2[0] + sum(W2[0][i] * h[i] for i in range(H)), b2[1] + sum(W2[1][i] * h[i] for i in range(H)))\n\ndef fees(P, ld, s, a):\n    ask, bid = net(P, feats(ld / 0.003, s, a))\n    fa = 1 - math.exp(ld - ask * 0.003); fb = 1 - math.exp(-bid * 0.003 - ld)\n    return min(max(fb, 0.0), 0.1), min(max(fa, 0.0), 0.1)\n\nclass NetArm:\n    \"\"\"ablate: None | 'sd' (s fixed to S_FIX) | 'arb' (a fixed 0) | 'both'.\"\"\"\n    S_FIX = 1.5\n    def __init__(self, w, ablate=None): self.P = unpack(w); self.ablate = ablate\n    def init(self, sigma, lam, size):\n        self.f = mf.MixFilter(100.0, 10000.0); self.se = 0.0; self.n = 0; return 0.003, 0.003\n    def on_trade(self, is_buy, ax, ay, t, x, y, arb, p, s2):\n        ph, parb = self.f.update(is_buy, ax, ay, t, x, y)\n        sd = math.sqrt(self.f.var()) / 0.003\n        if self.ablate in ('sd', 'both'): sd = self.S_FIX\n        if self.ablate in ('arb', 'both'): parb = 0.0\n        fb, fa = fees(self.P, math.log((y / x) / ph), sd, parb)\n        if p is not None:\n            e = math.log(ph / p); self.se += e * e; self.n += 1\n        self.f.set_fees(fb, fa); return fb, fa\n","mf.py":"\"\"\"Small Gaussian-mixture posterior of z=ln(p/spot) for the AMM fee challenge (replica B).\nFilter sees only: init reserves, and per own-pool callback (is_buy, amount_x, amount_y, t, x, y)\nplus its own stored fees. Policy = frozen oracle_table driven by p_hat=spot*exp(E[z]).\"\"\"\nimport math, json, os\nSQ2 = math.sqrt(2.0)\ndef Phi(u): return 0.5 * (1.0 + math.erf(u / SQ2))\ndef phi(u): return math.exp(-0.5 * u * u) / 2.5066282746310002\nP = dict(KMAX=4, SIG0=0.000945, N0=200.0, TAU_ROUTER=0.0015, ROUTER=1, PRETAIL=0.27,\n         RET_MU=math.log(20.0) - 0.72, RET_SD=1.3, PIN_VAR=1e-12, MINVAR=1e-12, ARB_CONF=0.9)\nTAB = json.load(open(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'oracle_table.json')))\n\ndef interp(arr, u):\n    u = (u + 8.0)\n    if u <= 0: return arr[0]\n    if u >= 16: return arr[16]\n    i = int(u); f = u - i\n    return arr[i] * (1 - f) + arr[i + 1] * f\n\ndef table_fees(spot, p, arbflag):\n    d = math.log(spot / p); u = d / 0.003\n    a = interp(TAB['ask'], u) + (TAB['arb_flag'] if arbflag else 0.0)\n    b = interp(TAB['bid'], u) + (TAB['arb_flag'] if arbflag else 0.0)\n    fa = 1 - math.exp(d - a * 0.003); fb = 1 - math.exp(-b * 0.003 - d)\n    return min(max(fb, 0.0), 0.1), min(max(fa, 0.0), 0.1)\n\ndef soft_upper(m, v, b, tau2):\n    \"\"\"Gaussian(m,v) times Phi((b-z)/sqrt(tau2)) (tau2=0: hard truncation z<=b).\n    Returns (mass, mean, var).\"\"\"\n    s = math.sqrt(v + tau2); a = (b - m) / s\n    Z = Phi(a)\n    if Z < 1e-300: return 0.0, b, P['MINVAR']\n    lam = phi(a) / Z\n    mean = m - v / s * lam\n    var = v - v * v / (v + tau2) * lam * (a + lam)\n    return Z, mean, max(var, P['MINVAR'])\n\ndef soft_lower(m, v, b, tau2):\n    Z, mean, var = soft_upper(-m, v, -b, tau2)\n    return Z, -mean, var\n\ndef trunc(m, v, lo, hi):\n    \"\"\"hard truncate to [lo,hi]\"\"\"\n    s = math.sqrt(v); A = (lo - m) / s; B = (hi - m) / s\n    Z = Phi(B) - Phi(A)\n    if Z < 1e-14:  # numerically empty: put at nearest edge\n        e = lo if m < lo else hi\n        return 1e-300, min(max(e, lo), hi), P['MINVAR']\n    pa, pb = phi(A), phi(B)\n    mu = m + s * (pa - pb) / Z\n    var = v * (1 + (A * pa - B * pb) / Z - ((pa - pb) / Z) ** 2)\n    return Z, mu, max(var, P['MINVAR'])\n\nclass MixFilter:\n    def __init__(self, x0, y0, router=None):\n        self.x, self.y = x0, y0\n        self.c = [[1.0, 0.0, 1e-10]]  # weight, mean, var  (p0 == initial spot)\n        self.t = -1; self.fb = self.fa = 0.003\n        self.sig2 = P['SIG0'] ** 2; self.sq = 0.0; self.dt = 0.0\n        self.lastpin = None; self.router = P['ROUTER'] if router is None else router\n        self.merge_err = 0.0; self.nmerge = 0; self.parb = 0.0\n    def _diffuse(self, n=1):\n        d = self.sig2 * n\n        for c in self.c: c[1] += -0.5 * self.sig2 * n; c[2] += d\n    def _band(self):\n        lo = math.log(1 - self.fb) if self.fb < 1 else -50; hi = -math.log(1 - self.fa)\n        out = []; tot = 0.0\n        for w, m, v in self.c:\n            Z, mu, var = trunc(m, v, lo, hi); out.append([w * Z, mu, var]); tot += w * Z\n        return out, tot\n    def _silent(self, n):\n        # fully silent steps: diffuse+truncate each step; long gaps: after 64 steps truncation\n        # is near stationary, cap per-step loop and do remaining in chunks of diffusion+trunc\n        for _ in range(min(n, 400)):\n            self._diffuse(1)\n            out, tot = self._band()\n            if tot > 0: self.c = [[w / tot, m, v] for w, m, v in out]\n        if n > 400:\n            self._diffuse(n - 400); out, tot = self._band()\n            if tot > 0: self.c = [[w / tot, m, v] for w, m, v in out]\n    def _norm_prune(self):\n        tot = sum(c[0] for c in self.c)\n        self.c = [[w / tot, m, v] for w, m, v in self.c if w / tot > 1e-9]\n        while len(self.c) > P['KMAX']:\n            best = None\n            for i in range(len(self.c)):\n                for j in range(i + 1, len(self.c)):\n                    wi, mi, vi = self.c[i]; wj, mj, vj = self.c[j]\n                    w = wi + wj; m = (wi * mi + wj * mj) / w\n                    v = (wi * (vi + (mi - m) ** 2) + wj * (vj + (mj - m) ** 2)) / w\n                    # Runnalls KL upper bound of the merge\n                    cost = 0.5 * (w * math.log(v) - wi * math.log(vi) - wj * math.log(vj))\n                    if best is None or cost < best[0]: best = (cost, i, j, [w, m, v])\n            cost, i, j, nc = best\n            self.merge_err += cost; self.nmerge += 1\n            self.c = [c for k, c in enumerate(self.c) if k not in (i, j)] + [nc]\n    def mean(self): return sum(w * m for w, m, v in self.c)\n    def var(self):\n        mu = self.mean(); return sum(w * (v + (m - mu) ** 2) for w, m, v in self.c)\n    def update(self, is_buy, ax, ay, t, x, y):\n        \"\"\"is_buy: AMM bought X (trader sold X). Returns (p_hat, arb_prob).\"\"\"\n        ls0 = math.log(self.y / self.x); ls1 = math.log(y / x)\n        first = t != self.t\n        parb = 0.0\n        if first:\n            if t > self.t + 1: self._silent(t - self.t - 1)\n            self._diffuse(1)\n            lo = math.log(1 - self.fb); hi = -math.log(1 - self.fa)\n            # arb hypothesis: pinned z (relative to post spot), mapped back to pre-spot coords\n            if not is_buy:  # AMM sold X: arb bought X, spot_after = p(1-fa)\n                zpost = -math.log(1 - self.fa); xn = x; a = ax\n                consistent = True\n            else:            # AMM bought X: spot_after = p/(1-fb)\n                zpost = math.log(1 - self.fb); xn = x; a = ax\n                consistent = True\n            zpre = zpost + ls1 - ls0\n            dens = 0.0\n            ok = (zpre > hi) if not is_buy else (zpre < lo)\n            if ok and consistent:\n                for w, m, v in self.c:\n                    dens += w * phi((zpre - m) / math.sqrt(v)) / math.sqrt(v)\n                dens *= 2.0 * a / xn  # |dz/dln a|\n            # retail hypothesis: no-arb band, then retail density of ln(amount in Y)\n            out, tot = self._band()\n            ly = math.log(max(ay, 1e-9))\n            dret = P['PRETAIL'] * phi((ly - P['RET_MU']) / P['RET_SD']) / P['RET_SD']\n            Larb = dens; Lret = tot * dret\n            parb = Larb / (Larb + Lret) if Larb + Lret > 0 else 0.0\n            ret = [[w * (1 - parb) / max(tot, 1e-300), m - (ls1 - ls0), v] for w, m, v in out] if tot > 0 else []\n            comps = ret + ([[parb, zpost, P['PIN_VAR']]] if parb > 1e-9 else [])\n            if not comps: comps = [[1.0, zpost, P['PIN_VAR']]]\n            self.c = comps\n            if parb > P['ARB_CONF']:\n                lp = ls1 + zpost\n                if self.lastpin is not None:\n                    tp, lpp = self.lastpin; dtp = t - tp\n                    if dtp > 0:\n                        self.sq += (lp - lpp + 0.5 * self.sig2 * dtp) ** 2; self.dt += dtp\n                        self.sig2 = (P['N0'] * P['SIG0'] ** 2 + self.sq) / (P['N0'] + self.dt)\n                self.lastpin = (t, lp)\n        else:\n            for c in self.c: c[1] -= (ls1 - ls0)\n        if parb < 0.5 and self.router:\n            # weak router observation: rival marginal >= p-band => z <= -ln(1-fa) after buy-X fill\n            tau2 = P['TAU_ROUTER'] ** 2; new = []\n            for w, m, v in self.c:\n                if v <= P['PIN_VAR'] * 1.01: new.append([w, m, v]); continue\n                if not is_buy: Z, mu, var = soft_upper(m, v, -math.log(1 - self.fa), tau2)\n                else: Z, mu, var = soft_lower(m, v, math.log(1 - self.fb), tau2)\n                new.append([w * Z, mu, var])\n            if sum(c[0] for c in new) > 0: self.c = new\n        self._norm_prune()\n        self.x, self.y, self.t = x, y, t; self.parb = parb\n        return (y / x) * math.exp(self.mean()), parb\n    def set_fees(self, fb, fa): self.fb, self.fa = fb, fa\n\nclass Arm:\n    \"\"\"mode: 'oracle' (true p, true flag), 'filter' (p_hat, inferred flag),\n    'diag' (true p, inferred flag). Oracle values are passed to the filter NEVER.\"\"\"\n    def __init__(self, mode, router=None):\n        self.mode = mode; self.router = router\n    def init(self, sigma, lam, size):  # hidden params ignored\n        self.f = MixFilter(100.0, 10000.0, self.router)\n        self.se = 0.0; self.n = 0; self.cov = 0; self.parb_err = 0\n        return 0.003, 0.003\n    def on_trade(self, is_buy, ax, ay, t, x, y, arb, p, s2):\n        ph, parb = self.f.update(is_buy, ax, ay, t, x, y)\n        e = math.log(ph / p); self.se += e * e; self.n += 1\n        sd = math.sqrt(self.f.var()); self.cov += abs(e) <= 1.96 * sd + 1e-12\n        flag = parb > 0.5; self.parb_err += flag != arb\n        s = y / x\n        if self.mode == 'oracle': fb, fa = table_fees(s, p, arb)\n        elif self.mode == 'diag': fb, fa = table_fees(s, p, flag)\n        else: fb, fa = table_fees(s, ph, flag)\n        self.f.set_fees(fb, fa)\n        return fb, fa\n","distill.py":"import numpy as np, json, sys\nfrom nnpol import H, NIN, NP\nT = json.load(open('oracle_table.json'))\nask = np.array(T['ask']); bid = np.array(T['bid']); af = T['arb_flag']\nrng = np.random.default_rng(12345)\nN = 20000\nd = rng.uniform(-9, 9, N); s = rng.uniform(0, 8, N); a = rng.choice([0.0, 1.0], N)\na = np.where(rng.random(N) < 0.2, rng.random(N), a)\ndef tab(arr, d): return np.interp(np.clip(d, -8, 8), np.arange(-8, 9), arr)\nflag = (a > 0.5).astype(float)\nY = np.stack([tab(ask, d) + af * flag, tab(bid, d) + af * flag], 1)\nX = np.stack([np.clip(d, -8, 8) / 4, np.clip(s, 0, 8) / 2 - 1, 2 * a - 1], 1)\nW1 = rng.normal(0, 1.0, (H, NIN)); b1 = rng.normal(0, 0.5, H); W2 = rng.normal(0, 0.5, (2, H)); b2 = np.zeros(2)\nps = [W1, b1, W2, b2]; m = [np.zeros_like(p) for p in ps]; v = [np.zeros_like(p) for p in ps]\nlr = 0.01\nfor it in range(1, 30001):\n    Z = X @ W1.T + b1; Hh = np.tanh(Z); O = Hh @ W2.T + b2; E = O - Y\n    gO = 2 * E / N; gW2 = gO.T @ Hh; gb2 = gO.sum(0); gH = gO @ W2 * (1 - Hh ** 2)\n    gW1 = gH.T @ X; gb1 = gH.sum(0); gs = [gW1, gb1, gW2, gb2]\n    if it == 20000: lr = 0.002\n    for i in range(4):\n        m[i] = 0.9 * m[i] + 0.1 * gs[i]; v[i] = 0.999 * v[i] + 0.001 * gs[i] ** 2\n        ps[i] -= lr * (m[i] / (1 - 0.9 ** it)) / (np.sqrt(v[i] / (1 - 0.999 ** it)) + 1e-8)\n    if it % 5000 == 0: print(it, float(np.sqrt((E ** 2).mean())))\nw = np.concatenate([W1.ravel(), b1, W2.ravel(), b2])\n# error on exact grid (a in {0,1}, s in {0,4}) in 30bps units\ndg = np.linspace(-8, 8, 321); errs = []\nfor aa in (0.0, 1.0):\n    for ss in (0.0, 1.5, 4.0):\n        Xg = np.stack([dg / 4, np.full_like(dg, ss / 2 - 1), np.full_like(dg, 2 * aa - 1)], 1)\n        O = np.tanh(Xg @ W1.T + b1) @ W2.T + b2\n        Yg = np.stack([tab(ask, dg) + af * aa, tab(bid, dg) + af * aa], 1); errs.append(O - Yg)\nerrs = np.concatenate(errs)\nrep = dict(train_rms_units30bps=float(np.sqrt((E ** 2).mean())), grid_rms_units30bps=float(np.sqrt((errs ** 2).mean())),\n           grid_maxabs_units30bps=float(np.abs(errs).max()), grid_rms_bps=float(np.sqrt((errs ** 2).mean()) * 30),\n           samples=N, adam_iters=30000, seed=12345, w=w.tolist())\njson.dump(rep, open('distill.json', 'w')); print({k: v for k, v in rep.items() if k != 'w'})\n","train.py":"\"\"\"Checkpointed CMA-ES over net weights. Seeds 31000..31255 only. CRN: each generation all candidates\n(and the incumbent mean) run the SAME seed block. Usage: train.py <max_seconds>\"\"\"\nimport sys, os, json, time, pickle, math\nsys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))\nimport numpy as np, cma, replica, nnpol\nfrom multiprocessing import Pool\nNSTEPS = 2000; BLOCK = 16; POP = 12; SIG0 = 0.04\ndef one(args):\n    w, seed = args\n    return replica.run(seed, nnpol.NetArm(w), n_steps=NSTEPS)['edge']\ndef score(pool, ws, seeds):\n    jobs = [(w, s) for w in ws for s in seeds]\n    r = list(map(one, jobs))\n    return [float(np.mean(r[i * len(seeds):(i + 1) * len(seeds)])) for i in range(len(ws))]\nif __name__ == '__main__':\n    tmax = float(sys.argv[1]); t0 = time.time(); ck = 'cma.pkl'\n    if os.path.exists(ck): es, log, g = pickle.load(open(ck, 'rb'))\n    else:\n        w0 = json.load(open('distill.json'))['w']\n        es = cma.CMAEvolutionStrategy(w0, SIG0, {'popsize': POP, 'seed': 8, 'verbose': -9}); log = []; g = 0\n    if True:\n        pool = None\n        while time.time() - t0 < tmax:\n            seeds = [31000 + ((g * BLOCK + i) % 256) for i in range(BLOCK)]\n            X = es.ask(); W0 = json.load(open('distill.json'))['w']\n            sc = score(pool, [list(x) for x in X] + [list(es.mean), W0], seeds)\n            es.tell(X, [-s for s in sc[:POP]])\n            log.append(dict(gen=g, seeds=[seeds[0], seeds[-1]], best=max(sc[:POP]), popmean=float(np.mean(sc[:POP])),\n                            mean_w=sc[POP], distilled=sc[POP + 1], sigma=float(es.sigma), t=round(time.time() - t0, 1)))\n            print(log[-1], flush=True); g += 1\n            pickle.dump((es, log, g), open(ck, 'wb'))\n","ev.py":"import sys,json,time,pickle,math\nimport replica,nnpol,mf\nlo,hi,out=int(sys.argv[1]),int(sys.argv[2]),sys.argv[3]\nes,log,g=pickle.load(open('cma.pkl','rb')); w=[float(v) for v in es.mean]\njson.dump(w,open('wfinal.json','w'))\nres=[];t0=time.time()\nfor s in range(lo,hi):\n  row={'seed':s}\n  a=nnpol.NetArm(w); r=replica.run(s,a,10000); row['net']=[r['edge'],r['retail'],r['arb'],a.se,a.n]\n  b=mf.Arm('filter'); r=replica.run(s,b,10000); row['mixB']=[r['edge'],r['retail'],r['arb'],b.se,b.n]\n  c=mf.Arm('oracle'); r=replica.run(s,c,10000); row['oracle']=[r['edge'],r['retail'],r['arb']]\n  res.append(row)\njson.dump(res,open(out,'w')); print(time.time()-t0)\n","abl.py":"import json,replica,nnpol,time\nw=json.load(open('wfinal.json'));res=[];t0=time.time()\nfor s in range(32000,32064):\n  row={'seed':s}\n  for ab in ('sd','arb','both'):\n    a=nnpol.NetArm(w,ab); row[ab]=replica.run(s,a,10000)['edge']\n  res.append(row)\n# hidden-input test: p withheld (None) from policy except logging -> identical edges\nclass NoP(nnpol.NetArm):\n  def on_trade(self,*a): return super().on_trade(*a[:7],None,None)\nht=[]\nfor s in (32000,32001,32002):\n  e1=replica.run(s,nnpol.NetArm(w),10000)['edge']; e2=replica.run(s,NoP(w),10000)['edge']; ht.append([s,e1,e2,e1==e2])\njson.dump({'abl':res,'hidden':ht},open('abl.json','w'));print(time.time()-t0,ht)\n","agg.py":"import json,math,hashlib,pickle,platform\nR=json.load(open('evA.json'))+json.load(open('evB.json'))\ndef st(x):\n  n=len(x);m=sum(x)/n;sd=math.sqrt(sum((v-m)**2 for v in x)/(n-1));se=sd/math.sqrt(n)\n  return {'n':n,'mean':round(m,3),'se':round(se,3),'ci95':[round(m-1.96*se,3),round(m+1.96*se,3)]}\ndef arm(k,i): return [r[k][i] for r in R]\nagg={}\nfor k in ('net','mixB','oracle'):\n  agg[k]={'edge':st(arm(k,0))['mean'],'retail_edge':st(arm(k,1))['mean'],'arb_edge':st(arm(k,2))['mean']}\nfor k in ('net','mixB'):\n  se=sum(arm(k,3));n=sum(arm(k,4));agg[k]['price_err_sq_sum']=se;agg[k]['price_err_count']=n;agg[k]['pooled_rms_bps']=round(math.sqrt(se/n)*1e4,3)\nd1=[r['net'][0]-r['mixB'][0] for r in R];d2=[r['oracle'][0]-r['net'][0] for r in R];d3=[r['oracle'][0]-r['mixB'][0] for r in R]\npaired={'net_minus_mixB':st(d1),'oracle_minus_net':st(d2),'oracle_minus_mixB':st(d3)}\nA=json.load(open('abl.json'));base={r['seed']:r['net'][0] for r in R}\nabl={k:st([a[k]-base[a['seed']] for a in A['abl']]) for k in ('sd','arb','both')}\nabl['note']='ablated minus full net, seeds 32000..32063, same weights (no refit); sd ablation fixes s=1.5 (x1=-0.25), arb ablation fixes parb=0 (x2=-1)'\nper=[[r['seed'],round(r['net'][0],2),round(r['mixB'][0],2),round(r['oracle'][0],2),round(r['net'][1],2),round(r['net'][2],2),round(r['mixB'][1],2),round(r['mixB'][2],2)] for r in R]\nes,log2,g2=pickle.load(open('cma.pkl','rb'));_,log1,g1=pickle.load(open('cma_run1.pkl','rb'))\ndef slog(L): return [[l['gen'],l['seeds'][0],round(l['best'],2),round(l['popmean'],2),round(l['mean_w'],3),round(l['distilled'],3),round(l['sigma'],4)] for l in L]\njson.dump(dict(agg=agg,paired=paired,abl=abl,hidden=A['hidden'],per=per,log1=slog(log1),log2=slog(log2),\n  d_run2=[round(l['mean_w']-l['distilled'],3) for l in log2]),open('aggout.json','w'))\nprint(json.dumps(agg),json.dumps(paired),json.dumps(abl))\n","replica.py":"\"\"\"Pure-Python replica of benedictbrady/amm-challenge @6b6921f8 (engine.rs, cfmm.rs,\narbitrageur.rs, router.rs, retail.rs), written from the source for ceiling experiments.\nRNG streams differ from the Rust engine, so absolute scores move by the seed set;\ncompare policies paired on the same seeds.\n\nA policy gets a callback after every trade on its own pool (arb or retail), like afterSwap,\nplus an oracle view (true fair price p and the 30 bps pool's spot s2 after the pending\naction of the same event), and returns (bid_fee, ask_fee).\"\"\"\nimport math, random\n\nK = 100.0 * 10000.0\nMAXF = 0.1\nNF = 0.003  # normalizer fee\n\n\ndef clampf(f):\n    return 0.0 if f < 0.0 else (MAXF if f > MAXF else f)\n\n\ndef run(seed, policy, n_steps=10000, cfg=None):\n    cr = random.Random(10_000_000 + seed)\n    size_mean = cr.uniform(19.0, 21.0)\n    lam = cr.uniform(0.6, 1.0)\n    sigma = cr.uniform(0.000882, 0.001008)\n    if cfg:\n        size_mean, lam, sigma = cfg\n    pr = random.Random(seed)\n    rr = random.Random(seed + 1)\n    drift = -0.5 * sigma * sigma\n    mu_ln = math.log(size_mean) - 0.5 * 1.2 * 1.2\n    emlam = math.exp(-lam)\n    p = 100.0\n    x1, y1 = 100.0, 10000.0\n    x2, y2 = 100.0, 10000.0\n    fb, fa = policy.init(sigma, lam, size_mean)\n    fb, fa = clampf(fb), clampf(fa)\n    e1 = e2 = 0.0\n    ret1 = arb1 = 0.0  # our retail / arb edge\n    rv1 = av1 = 0.0\n    sum_fb = sum_fa = 0.0\n    g2 = 1.0 - NF\n    sqrt = math.sqrt\n    for t in range(n_steps):\n        p *= math.exp(drift + sigma * pr.gauss(0.0, 1.0))\n        # --- arbitrage, normalizer first (pools are independent), then ours\n        s2 = y2 / x2\n        if s2 < p:\n            nx = sqrt(K / (g2 * p)); ax = x2 - nx\n            if ax > 0:\n                ax = min(ax, x2 * 0.99)\n                nrx = x2 - ax; nry = K / nrx; net_y = nry - y2; ty = net_y / g2\n                prof = ax * p - ty\n                if prof > 0:\n                    x2, y2 = nrx, nry; e2 -= prof\n        elif s2 > p:\n            xv = sqrt(K * g2 / p); ax = (xv - x2) / g2\n            if ax > 0:\n                nrx = x2 + ax * g2; nry = K / nrx; yo = y2 - nry\n                prof = yo - ax * p\n                if yo > 0 and prof > 0:\n                    x2, y2 = nrx, nry; e2 -= prof\n        s1 = y1 / x1\n        if s1 < p:\n            g = 1.0 - fa\n            if g > 0:\n                nx = sqrt(K / (g * p)); ax = x1 - nx\n                if ax > 0:\n                    ax = min(ax, x1 * 0.99)\n                    nrx = x1 - ax; nry = K / nrx; net_y = nry - y1; ty = net_y / g\n                    prof = ax * p - ty\n                    if prof > 0:\n                        x1, y1 = nrx, nry; e1 -= prof; arb1 -= prof; av1 += ty\n                        fb, fa = policy.on_trade(False, ax, ty, t, x1, y1, True, p, y2 / x2)\n                        fb, fa = clampf(fb), clampf(fa)\n        elif s1 > p:\n            g = 1.0 - fb\n            if g > 0:\n                xv = sqrt(K * g / p); ax = (xv - x1) / g\n                if ax > 0:\n                    nrx = x1 + ax * g; nry = K / nrx; yo = y1 - nry\n                    prof = yo - ax * p\n                    if yo > 0 and prof > 0:\n                        x1, y1 = nrx, nry; e1 -= prof; arb1 -= prof; av1 += yo\n                        fb, fa = policy.on_trade(True, ax, yo, t, x1, y1, True, p, y2 / x2)\n                        fb, fa = clampf(fb), clampf(fa)\n        # --- retail\n        n = 0; q = rr.random()\n        while q > emlam:\n            n += 1; q *= rr.random()\n        for _ in range(n):\n            size = rr.lognormvariate(mu_ln, 1.2)\n            buy = rr.random() < 0.5\n            if buy:  # trader buys X with Y\n                ga = 1.0 - fa\n                a1 = sqrt(x1 * ga * y1); a2 = sqrt(x2 * g2 * y2); r = a1 / a2\n                d = ga + r * g2\n                u1 = (r * (y2 + g2 * size) - y1) / d if d != 0 else size / 2\n                u1 = 0.0 if u1 < 0 else (size if u1 > size else u1)\n                u2 = size - u1\n                if u2 > 1e-4:\n                    nry = y2 + u2 * g2; nrx = K / nry; xo = x2 - nrx\n                    if xo > 0:\n                        e2 += u2 - xo * p; x2, y2 = nrx, nry\n                if u1 > 1e-4:\n                    nry = y1 + u1 * ga; nrx = K / nry; xo = x1 - nrx\n                    if xo > 0:\n                        ed = u1 - xo * p; e1 += ed; ret1 += ed; rv1 += u1\n                        x1, y1 = nrx, nry\n                        fb, fa = policy.on_trade(False, xo, u1, t, x1, y1, False, p, y2 / x2)\n                        fb, fa = clampf(fb), clampf(fa)\n            else:  # trader sells X\n                tx = size / p\n                gb = 1.0 - fb\n                b1 = sqrt(y1 * gb * x1); b2 = sqrt(y2 * g2 * x2); r = b1 / b2\n                d = gb + r * g2\n                v1 = (r * (x2 + g2 * tx) - x1) / d if d != 0 else tx / 2\n                v1 = 0.0 if v1 < 0 else (tx if v1 > tx else v1)\n                v2 = tx - v1\n                if v2 > 1e-4:\n                    nrx = x2 + v2 * g2; nry = K / nrx; yo = y2 - nry\n                    if yo > 0:\n                        e2 += v2 * p - yo; x2, y2 = nrx, nry\n                if v1 > 1e-4:\n                    nrx = x1 + v1 * gb; nry = K / nrx; yo = y1 - nry\n                    if yo > 0:\n                        ed = v1 * p - yo; e1 += ed; ret1 += ed; rv1 += yo\n                        x1, y1 = nrx, nry\n                        fb, fa = policy.on_trade(True, v1, yo, t, x1, y1, False, p, y2 / x2)\n                        fb, fa = clampf(fb), clampf(fa)\n        sum_fb += fb; sum_fa += fa\n    return dict(edge=e1, norm=e2, retail=ret1, arb=arb1, rv=rv1, av=av1,\n                fb=sum_fb / n_steps * 1e4, fa=sum_fa / n_steps * 1e4,\n                sigma=sigma, lam=lam, size=size_mean)\n\n\nclass Fixed:\n    def __init__(self, f): self.f = f\n    def init(self, *a): return self.f, self.f\n    def on_trade(self, *a): return self.f, self.f\n\n\nclass OracleQuote:\n    \"\"\"Quote ask p(1+m) and bid p(1-m) around the TRUE fair price after every own trade.\"\"\"\n    def __init__(self, m): self.m = m\n    def init(self, *a): return 0.003, 0.003\n    def on_trade(self, is_buy, ax, ay, t, x, y, arb, p, s2):\n        s = y / x\n        fa = 1.0 - s / (p * (1 + self.m))\n        fb = 1.0 - p * (1 - self.m) / s\n        return fb, fa\n\n\nclass OracleCompete:\n    \"\"\"Know p and the 30 bps pool's spot s2. Ask quote: undercut the rival's ask by u,\n    but never below p(1+mlo); bid quote: outbid the rival's bid by u, never above p(1-mlo).\"\"\"\n    def __init__(self, mlo, u, mhi=1.0):\n        self.mlo, self.u, self.mhi = mlo, u, mhi\n    def init(self, *a): return 0.003, 0.003\n    def on_trade(self, is_buy, ax, ay, t, x, y, arb, p, s2):\n        s = y / x\n        ra = s2 / (1 - NF); rb = s2 * (1 - NF)\n        qa = max(p * (1 + self.mlo), min(ra * (1 - self.u), p * (1 + self.mhi)))\n        qb = min(p * (1 - self.mlo), max(rb * (1 + self.u), p * (1 - self.mhi)))\n        return 1.0 - qb / s, 1.0 - s / qa\n"},"source_sha256":{"nnpol.py":"1892da1bad6e8750354355bae24b9a7ca5dc1258625eb3adf202bfcd5f3d0623","mf.py":"8adbd509efdac3e77ccde38d07a7272e9706b42ea4ecc926f77963e2a332445e","distill.py":"0f2e6005d106b5929efae833905f6bd34d776460b9405d0c2416e5f612982aa6","train.py":"91fe07af27e0f8b16c8ff7e9db7bd9785a231ada98d4d22adcdf3d0d8f27019a","ev.py":"990acc749a871dd4361801529d0b000263cf41fa1d03d38c6da38bbc9c7f68a8","abl.py":"1582c34f08389f1caf67159cb489ad904ce9c3c1c79be6577be5905e40ae7cf9","agg.py":"d6589a7feeaf2a3114f693dde3653d330bb78039e39f000d3b06e668cda65921","replica.py":"d079712fa1f4850ad8337e656e7ee8dbdde806cd4762d597fae50f547ef9c7c4"}}