import%20marimo%0A%0A__generated_with%20%3D%20%220.23.9%22%0Aapp%20%3D%20marimo.App(width%3D%22medium%22)%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20%23%20Parcel-level%20flood%20penalty%20%E2%80%94%20within-neighborhood%20fixed-effects%20regression%0A%0A%20%20%20%20**Question%3A**%20on%20the%20*same%20streets*%2C%20did%20flood-zone%20houses%20lose%20more%20value%20than%0A%20%20%20%20dry%20houses%20after%20Helene%20%2F%20Milton%20(2024)%3F%0A%0A%20%20%20%20**Design%3A**%20repeat-sales%20price%20change%20per%20parcel%20(same%20house%2C%20pre-%20vs%20post-storm)%2C%0A%20%20%20%20regressed%20on%20the%20parcel's%20own%20flood-zone%20designation%2C%20with%20**zip%20fixed%20effects**%0A%20%20%20%20(compares%20flood%20vs%20dry%20houses%20*within%20the%20same%20zip*%20%E2%80%94%20absorbs%20boom%20%2F%20city%20%2F%20schools)%0A%20%20%20%20and%20**standard%20errors%20clustered%20by%20zip**.%20Run%20three%20ways%20(no-trim%20%2F%20trimmed%20%2F%0A%20%20%20%20robust)%20so%20the%20result%20can't%20be%20an%20artifact%20of%20outlier%20handling.%0A%0A%20%20%20%20**Headline%20(F21)%3A**%20a%20stable%20**%E2%88%929%25%20to%20%E2%88%9210%25**%20within-neighborhood%20flood%20penalty%2C%0A%20%20%20%20robust%20across%20all%20three%3B%20significance%20*marginal*%20once%20correctly%20clustered%0A%20%20%20%20(p%20%E2%89%88%200.06%E2%80%930.11).%20Rebuild-masking%20(flooded%20homes%20resold%20as%20renovated)%20biases%20this%0A%20%20%20%20*toward%20zero*%20%E2%86%92%20a%20conservative%20floor.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20from%20pathlib%20import%20Path%0A%0A%20%20%20%20import%20duckdb%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20import%20pandas%20as%20pd%0A%20%20%20%20import%20statsmodels.api%20as%20sm%0A%20%20%20%20import%20statsmodels.formula.api%20as%20smf%0A%0A%20%20%20%20return%20Path%2C%20duckdb%2C%20mo%2C%20np%2C%20pd%2C%20plt%2C%20sm%2C%20smf%0A%0A%0A%40app.cell%0Adef%20_(Path%2C%20duckdb)%3A%0A%20%20%20%20def%20_find_db()%20-%3E%20str%3A%0A%20%20%20%20%20%20%20%20for%20d%20in%20%5BPath.cwd()%2C%20*Path.cwd().parents%5D%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(d%20%2F%20%22analytics.db%22).exists()%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20str(d%20%2F%20%22analytics.db%22)%0A%20%20%20%20%20%20%20%20raise%20FileNotFoundError(%22analytics.db%20not%20found%20walking%20up%20from%20cwd%22)%0A%0A%20%20%20%20conn%20%3D%20duckdb.connect(_find_db()%2C%20read_only%3DTrue)%20%20%23%20read-only%3A%20project%20convention%0A%20%20%20%20return%20(conn%2C)%0A%0A%0A%40app.cell%0Adef%20_(conn%2C%20np)%3A%0A%20%20%20%20%23%20Repeat-sales%20pairs%3A%20same%20parcel%20sold%20pre-storm%20(2022..Aug-2024)%20AND%20post-storm%2C%0A%20%20%20%20%23%20arms-length%2C%20flip-screened%20(held%20%3E%3D%201yr).%20Predictor%20%3D%20the%20parcel's%20own%20flood%20zone.%0A%20%20%20%20pairs%20%3D%20conn.execute(%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20%20%20%20%20WITH%20arms%20AS%20(%0A%20%20%20%20%20%20%20%20%20%20SELECT%20p.parcel_id%2C%20p.zip%2C%20p.flood_zone%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20CASE%20WHEN%20upper(p.flood_zone)%20LIKE%20'A%25'%20OR%20upper(p.flood_zone)%20LIKE%20'V%25'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20THEN%201%20ELSE%200%20END%20AS%20in_sfha%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20s.sale_date%2C%20s.sale_price%0A%20%20%20%20%20%20%20%20%20%20FROM%20sales_history%20s%20JOIN%20parcels%20p%20USING%20(parcel_id)%0A%20%20%20%20%20%20%20%20%20%20WHERE%20s.sale_price%20%3E%3D%2010000%0A%20%20%20%20%20%20%20%20%20%20%20%20AND%20(s.buyer%20IS%20NULL%20OR%20s.seller%20IS%20NULL%20OR%20s.buyer%20%3C%3E%20s.seller)%0A%20%20%20%20%20%20%20%20%20%20%20%20AND%20p.sqft_living%20%3E%200%20AND%20s.sale_price%20%2F%20p.sqft_living%20BETWEEN%2020%20AND%202000%0A%20%20%20%20%20%20%20%20%20%20%20%20AND%20p.flood_zone%20IS%20NOT%20NULL%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20pre%20AS%20(SELECT%20parcel_id%2C%20zip%2C%20in_sfha%2C%20flood_zone%2C%20sale_date%20pre_date%2C%20sale_price%20pre_price%20FROM%20arms%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20WHERE%20sale_date%20BETWEEN%20DATE%20'2022-01-01'%20AND%20DATE%20'2024-08-31'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20QUALIFY%20row_number()%20OVER%20(PARTITION%20BY%20parcel_id%20ORDER%20BY%20sale_date%20DESC)%20%3D%201)%2C%0A%20%20%20%20%20%20%20%20post%20AS%20(SELECT%20parcel_id%2C%20sale_date%20post_date%2C%20sale_price%20post_price%20FROM%20arms%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20WHERE%20sale_date%20%3E%3D%20DATE%20'2024-09-01'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20QUALIFY%20row_number()%20OVER%20(PARTITION%20BY%20parcel_id%20ORDER%20BY%20sale_date%20ASC)%20%3D%201)%0A%20%20%20%20%20%20%20%20SELECT%20pre.zip%2C%20pre.in_sfha%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20CASE%20WHEN%20upper(pre.flood_zone)%20LIKE%20'V%25'%20THEN%20'VE'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20WHEN%20upper(pre.flood_zone)%20LIKE%20'A%25'%20THEN%20'AE'%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20ELSE%20'X'%20END%20AS%20zone%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(post.post_date%20-%20pre.pre_date)%20AS%20days_held%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pre.pre_price%2C%20post.post_price%0A%20%20%20%20%20%20%20%20FROM%20pre%20JOIN%20post%20USING%20(parcel_id)%0A%20%20%20%20%20%20%20%20WHERE%20(post.post_date%20-%20pre.pre_date)%20%3E%3D%20365%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20).df()%0A%20%20%20%20pairs%5B%22logratio%22%5D%20%3D%20np.log(pairs%5B%22post_price%22%5D%20%2F%20pairs%5B%22pre_price%22%5D)%0A%20%20%20%20pairs%5B%22days_held%22%5D%20%3D%20pairs%5B%22days_held%22%5D.astype(float)%0A%20%20%20%20pairs%0A%20%20%20%20return%20(pairs%2C)%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20pairs%2C%20pd%2C%20sm%2C%20smf)%3A%0A%20%20%20%20%23%20Three%20ways%2C%20all%20with%20zip%20fixed%20effects.%20Outcome%20%3D%20log(post%2Fpre).%0A%20%20%20%20def%20_row(res)%3A%0A%20%20%20%20%20%20%20%20b%20%3D%20res.params%5B%22in_sfha%22%5D%0A%20%20%20%20%20%20%20%20return%20%7B%22coef%22%3A%20b%2C%20%22pct%22%3A%20100%20*%20(np.exp(b)%20-%201)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22se%22%3A%20res.bse%5B%22in_sfha%22%5D%2C%20%22p%22%3A%20res.pvalues%5B%22in_sfha%22%5D%2C%20%22n%22%3A%20int(res.nobs)%7D%0A%0A%20%20%20%20_f%20%3D%20%22logratio%20~%20in_sfha%20%2B%20days_held%20%2B%20C(zip)%22%0A%20%20%20%20_m1%20%3D%20smf.ols(_f%2C%20data%3Dpairs).fit(cov_type%3D%22cluster%22%2C%20cov_kwds%3D%7B%22groups%22%3A%20pairs%5B%22zip%22%5D%7D)%0A%20%20%20%20_lo%2C%20_hi%20%3D%20pairs%5B%22logratio%22%5D.quantile(%5B0.01%2C%200.99%5D)%0A%20%20%20%20_trim%20%3D%20pairs%5Bpairs%5B%22logratio%22%5D.between(_lo%2C%20_hi)%5D%0A%20%20%20%20_m2%20%3D%20smf.ols(_f%2C%20data%3D_trim).fit(cov_type%3D%22cluster%22%2C%20cov_kwds%3D%7B%22groups%22%3A%20_trim%5B%22zip%22%5D%7D)%0A%20%20%20%20_m3%20%3D%20smf.rlm(_f%2C%20data%3Dpairs%2C%20M%3Dsm.robust.norms.HuberT()).fit()%0A%0A%20%20%20%20results%20%3D%20pd.DataFrame(%7B%0A%20%20%20%20%20%20%20%20%22OLS%2C%20no%20trim%20(cluster%20SE)%22%3A%20_row(_m1)%2C%0A%20%20%20%20%20%20%20%20%22OLS%2C%20trim%201%2F99%20(cluster%20SE)%22%3A%20_row(_m2)%2C%0A%20%20%20%20%20%20%20%20%22Robust%20RLM%20Huber%20(NOT%20clustered)%22%3A%20_row(_m3)%2C%0A%20%20%20%20%7D).T.round(4)%0A%20%20%20%20results%0A%20%20%20%20return%20(results%2C)%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20**Reading%20the%20table.**%20The%20coefficient%20is%20**stable**%20(%E2%89%88%20%E2%88%929%20to%20%E2%88%9210%25)%20across%20all%0A%20%20%20%20three%20%E2%86%92%20not%20an%20outlier%20artifact.%20The%20RLM's%20tiny%20p%20is%20**misleading**%3A%20it%20treats%0A%20%20%20%20every%20house%20as%20independent%2C%20ignoring%20that%20houses%20in%20a%20zip%20share%20the%20boom%20shock%0A%20%20%20%20(*pseudoreplication*%20%E2%86%92%20fake%20precision).%20The%20**clustered-OLS**%20p-values%20(0.06%E2%80%930.11)%0A%20%20%20%20are%20the%20honest%20ones%20%E2%86%92%20*marginal*.%20The%20cluster%20bootstrap%20below%20is%20the%20standard%0A%20%20%20%20few-clusters%20fix.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20pairs)%3A%0A%20%20%20%20%23%20Cluster%20(block)%20bootstrap%20over%20zips%20%E2%80%94%20the%20standard%20fix%20for%20few%20clusters%20(~47).%0A%20%20%20%20%23%20FE%20via%20within-demeaning%20(Frisch%E2%80%93Waugh)%3A%20demean%20each%20var%20by%20its%20zip%2C%20then%20the%0A%20%20%20%20%23%20fixed-effects%20slope%20is%20plain%20OLS%20on%20the%20demeaned%20data.%20Resample%20whole%20zips%2C%20refit.%0A%20%20%20%20_w%20%3D%20pairs.copy()%0A%20%20%20%20for%20_c%20in%20%5B%22logratio%22%2C%20%22in_sfha%22%2C%20%22days_held%22%5D%3A%0A%20%20%20%20%20%20%20%20_w%5B_c%5D%20%3D%20_w%5B_c%5D%20-%20_w.groupby(%22zip%22)%5B_c%5D.transform(%22mean%22)%0A%20%20%20%20_zips%20%3D%20pairs%5B%22zip%22%5D.unique()%0A%20%20%20%20_arr%20%3D%20%7Bz%3A%20(_w.loc%5Bpairs%5B%22zip%22%5D%20%3D%3D%20z%2C%20%5B%22in_sfha%22%2C%20%22days_held%22%5D%5D.values%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20_w.loc%5Bpairs%5B%22zip%22%5D%20%3D%3D%20z%2C%20%22logratio%22%5D.values)%20for%20z%20in%20_zips%7D%0A%0A%20%20%20%20def%20_slope(zlist)%3A%0A%20%20%20%20%20%20%20%20_X%20%3D%20np.vstack(%5B_arr%5Bz%5D%5B0%5D%20for%20z%20in%20zlist%5D)%0A%20%20%20%20%20%20%20%20_y%20%3D%20np.concatenate(%5B_arr%5Bz%5D%5B1%5D%20for%20z%20in%20zlist%5D)%0A%20%20%20%20%20%20%20%20return%20np.linalg.lstsq(_X%2C%20_y%2C%20rcond%3DNone)%5B0%5D%5B0%5D%0A%0A%20%20%20%20point_fe%20%3D%20_slope(_zips)%0A%20%20%20%20_rng%20%3D%20np.random.default_rng(42)%0A%20%20%20%20boot%20%3D%20np.array(%5B_slope(_rng.choice(_zips%2C%20len(_zips)%2C%20replace%3DTrue))%20for%20_%20in%20range(1000)%5D)%0A%20%20%20%20boot_ci%20%3D%20np.percentile(boot%2C%20%5B2.5%2C%2097.5%5D)%0A%20%20%20%20boot_p%20%3D%202%20*%20min((boot%20%3E%3D%200).mean()%2C%20(boot%20%3C%3D%200).mean())%0A%20%20%20%20return%20boot%2C%20boot_ci%2C%20boot_p%2C%20point_fe%0A%0A%0A%40app.cell%0Adef%20_(boot_ci%2C%20boot_p%2C%20mo%2C%20np%2C%20point_fe)%3A%0A%20%20%20%20mo.md(f%22%22%22%0A%20%20%20%20**Cluster%20bootstrap%20(1%2C000%20resamples%20of%20zips)%3A**%20FE%20coefficient%0A%20%20%20%20**%7Bpoint_fe%3A%2B.3f%7D**%20(%E2%89%88%20%7B100%20*%20(np.exp(point_fe)%20-%201)%3A%2B.1f%7D%25)%2C%0A%20%20%20%2095%25%20CI%20**%5B%7Bboot_ci%5B0%5D%3A%2B.3f%7D%2C%20%7Bboot_ci%5B1%5D%3A%2B.3f%7D%5D**%2C%20two-sided%20p%20%E2%89%88%20**%7Bboot_p%3A.3f%7D**.%0A%20%20%20%20The%20CI%20**%7B'excludes'%20if%20boot_ci%5B1%5D%20%3C%200%20else%20'includes'%7D%20zero**%20%E2%80%94%20consistent%20with%20the%0A%20%20%20%20clustered-OLS%20read%3A%20a%20real%2C%20sizeable%20effect%2C%20estimated%20with%20marginal%20precision.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(boot_ci%2C%20plt%2C%20point_fe%2C%20results)%3A%0A%20%20%20%20%23%20Stable%20point%20estimate%2C%20varying%20precision%20%E2%80%94%20and%20the%20RLM's%20deceptively%20tight%20bar.%0A%20%20%20%20_labels%20%3D%20list(results.index)%0A%20%20%20%20_fig%2C%20_ax%20%3D%20plt.subplots(figsize%3D(8%2C%204))%0A%20%20%20%20_ax.errorbar(results%5B%22coef%22%5D%2C%20range(len(results))%2C%20xerr%3D1.96%20*%20results%5B%22se%22%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fmt%3D%22o%22%2C%20color%3D%22steelblue%22%2C%20capsize%3D4%2C%20label%3D%22estimate%20%C2%B1%201.96%C2%B7SE%22)%0A%20%20%20%20_ax.errorbar(%5Bpoint_fe%5D%2C%20%5Blen(results)%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20xerr%3D%5B%5Bpoint_fe%20-%20boot_ci%5B0%5D%5D%2C%20%5Bboot_ci%5B1%5D%20-%20point_fe%5D%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fmt%3D%22s%22%2C%20color%3D%22crimson%22%2C%20capsize%3D4%2C%20label%3D%22FE%20%2B%20cluster-bootstrap%2095%25%20CI%22)%0A%20%20%20%20_ax.axvline(0%2C%20color%3D%22gray%22%2C%20lw%3D1)%0A%20%20%20%20_ax.set_yticks(list(range(len(results)))%20%2B%20%5Blen(results)%5D)%0A%20%20%20%20_ax.set_yticklabels(_labels%20%2B%20%5B%22FE%20bootstrap%20(honest)%22%5D)%0A%20%20%20%20_ax.set_xlabel(%22flood%20coefficient%20(log%20points%3B%20%20%3C%200%20%3D%20flood%20houses%20lost%20more)%22)%0A%20%20%20%20_ax.set_title(%22Within-neighborhood%20flood%20penalty%3A%20stable%20estimate%2C%20varying%20precision%22)%0A%20%20%20%20_ax.legend(fontsize%3D8%2C%20loc%3D%22lower%20left%22)%0A%20%20%20%20_ax.grid(alpha%3D0.3%2C%20axis%3D%22x%22)%0A%20%20%20%20_fig%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20%23%23%23%201%20%C2%B7%20Within-zip%20flood%20vs%20dry%20%E2%80%94%20the%20identifying%20variation%0A%0A%20%20%20%20Each%20point%20is%20a%20zip%20with%20both%20flood%20and%20dry%20repeat-sales.%20x%20%3D%20median%20price%20change%20of%0A%20%20%20%20its%20**dry**%20houses%2C%20y%20%3D%20its%20**flood**%20houses.%20Below%20the%20dashed%20line%20%3D%20flood%20houses%20did%0A%20%20%20%20worse%20*in%20that%20neighborhood*.%20The%20fixed-effects%20coefficient%20is%20the%20pooled%20version%20of%0A%20%20%20%20these%20within-zip%20gaps.%20Ridge%20in%20red.%20(Small-cell%20zips%20are%20noisy%20%E2%80%94%20the%20eyeball%20view.)%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20pairs%2C%20plt)%3A%0A%20%20%20%20_g%20%3D%20(pairs.assign(pct%3D100%20*%20(np.exp(pairs%5B%22logratio%22%5D)%20-%201))%0A%20%20%20%20%20%20%20%20%20%20.groupby(%5B%22zip%22%2C%20%22in_sfha%22%5D)%5B%22pct%22%5D.median().unstack())%0A%20%20%20%20_g.columns%20%3D%20%5B%22dry%22%2C%20%22flood%22%5D%0A%20%20%20%20_g%20%3D%20_g.dropna()%0A%20%20%20%20_ridge%20%3D%20_g.index.isin(%5B%2233710%22%2C%20%2233713%22%5D)%0A%20%20%20%20_lim%20%3D%20%5B_g.values.min()%20-%205%2C%20_g.values.max()%20%2B%205%5D%0A%20%20%20%20_fig%2C%20_ax%20%3D%20plt.subplots(figsize%3D(6.5%2C%206.5))%0A%20%20%20%20_ax.plot(_lim%2C%20_lim%2C%20ls%3D%22--%22%2C%20color%3D%22gray%22%2C%20lw%3D1%2C%20label%3D%22flood%20%3D%20dry%22)%0A%20%20%20%20_ax.scatter(_g.loc%5B~_ridge%2C%20%22dry%22%5D%2C%20_g.loc%5B~_ridge%2C%20%22flood%22%5D%2C%20alpha%3D0.55%2C%20label%3D%22zip%22)%0A%20%20%20%20_ax.scatter(_g.loc%5B_ridge%2C%20%22dry%22%5D%2C%20_g.loc%5B_ridge%2C%20%22flood%22%5D%2C%20color%3D%22crimson%22%2C%20s%3D90%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20zorder%3D5%2C%20label%3D%22ridge%22)%0A%20%20%20%20_ax.set_xlim(_lim)%0A%20%20%20%20_ax.set_ylim(_lim)%0A%20%20%20%20_ax.set_aspect(%22equal%22)%0A%20%20%20%20_ax.set_xlabel(%22dry-house%20median%20%CE%94%20(%25)%22)%0A%20%20%20%20_ax.set_ylabel(%22flood-house%20median%20%CE%94%20(%25)%22)%0A%20%20%20%20_ax.set_title(%22Within%20each%20zip%3A%20flood%20vs%20dry%20price%20change%5Cn(below%20dashed%20%3D%20flood%20underperformed)%22)%0A%20%20%20%20_ax.legend(fontsize%3D8)%0A%20%20%20%20_ax.grid(alpha%3D0.3)%0A%20%20%20%20_fig%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20%23%23%23%202%20%C2%B7%20Bootstrap%20distribution%20%E2%80%94%20the%20precision%2C%20made%20visible%0A%0A%20%20%20%20The%201%2C000%20cluster-bootstrap%20estimates%20of%20the%20flood%20coefficient.%20The%20bulk%20sits%20in%0A%20%20%20%20negative%20territory%20(a%20flood%20penalty)%2C%20but%20the%20right%20tail%20crosses%20**zero**%20%E2%80%94%20that's%0A%20%20%20%20exactly%20what%20%22real%20effect%2C%20marginal%20precision%22%20looks%20like.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(boot%2C%20boot_ci%2C%20plt%2C%20point_fe)%3A%0A%20%20%20%20_fig%2C%20_ax%20%3D%20plt.subplots(figsize%3D(8%2C%204))%0A%20%20%20%20_ax.hist(boot%2C%20bins%3D40%2C%20color%3D%22steelblue%22%2C%20alpha%3D0.75)%0A%20%20%20%20_ax.axvline(0%2C%20color%3D%22crimson%22%2C%20lw%3D1.5%2C%20label%3D%22zero%22)%0A%20%20%20%20_ax.axvline(point_fe%2C%20color%3D%22black%22%2C%20lw%3D1.5%2C%20label%3Df%22point%20estimate%20%7Bpoint_fe%3A%2B.3f%7D%22)%0A%20%20%20%20_ax.axvline(boot_ci%5B0%5D%2C%20color%3D%22gray%22%2C%20ls%3D%22--%22%2C%20lw%3D1)%0A%20%20%20%20_ax.axvline(boot_ci%5B1%5D%2C%20color%3D%22gray%22%2C%20ls%3D%22--%22%2C%20lw%3D1%2C%20label%3D%2295%25%20CI%22)%0A%20%20%20%20_ax.set_xlabel(%22flood%20coefficient%20(log%20points)%22)%0A%20%20%20%20_ax.set_ylabel(%22bootstrap%20draws%22)%0A%20%20%20%20_ax.set_title(%22Cluster-bootstrap%20distribution%20of%20the%20flood%20coefficient%22)%0A%20%20%20%20_ax.legend(fontsize%3D8)%0A%20%20%20%20_ax.grid(alpha%3D0.3%2C%20axis%3D%22y%22)%0A%20%20%20%20_fig%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20%23%23%23%203%20%C2%B7%20Trim%20sensitivity%20%E2%80%94%20not%20a%20trimming%20artifact%0A%0A%20%20%20%20The%20flood%20coefficient%20(clustered%2095%25%20CI)%20across%20symmetric%20trim%20thresholds.%20A%20flat%20line%0A%20%20%20%20means%20the%20result%20doesn't%20hinge%20on%20how%20aggressively%20we%20cut%20outliers%20%E2%80%94%20inoculation%0A%20%20%20%20against%20%22trimmed%20until%20it%20worked.%22%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(pairs%2C%20plt%2C%20smf)%3A%0A%20%20%20%20_f%20%3D%20%22logratio%20~%20in_sfha%20%2B%20days_held%20%2B%20C(zip)%22%0A%20%20%20%20_ts%20%3D%20%5B0.0%2C%200.005%2C%200.01%2C%200.025%2C%200.05%5D%0A%20%20%20%20_co%2C%20_err%20%3D%20%5B%5D%2C%20%5B%5D%0A%20%20%20%20for%20_t%20in%20_ts%3A%0A%20%20%20%20%20%20%20%20_d%20%3D%20pairs%20if%20_t%20%3D%3D%200%20else%20pairs%5Bpairs%5B%22logratio%22%5D.between(*pairs%5B%22logratio%22%5D.quantile(%5B_t%2C%201%20-%20_t%5D))%5D%0A%20%20%20%20%20%20%20%20_m%20%3D%20smf.ols(_f%2C%20data%3D_d).fit(cov_type%3D%22cluster%22%2C%20cov_kwds%3D%7B%22groups%22%3A%20_d%5B%22zip%22%5D%7D)%0A%20%20%20%20%20%20%20%20_co.append(_m.params%5B%22in_sfha%22%5D)%0A%20%20%20%20%20%20%20%20_err.append(1.96%20*%20_m.bse%5B%22in_sfha%22%5D)%0A%20%20%20%20_fig%2C%20_ax%20%3D%20plt.subplots(figsize%3D(8%2C%204))%0A%20%20%20%20_ax.errorbar(%5Bt%20*%20100%20for%20t%20in%20_ts%5D%2C%20_co%2C%20yerr%3D_err%2C%20fmt%3D%22o-%22%2C%20color%3D%22steelblue%22%2C%20capsize%3D4)%0A%20%20%20%20_ax.axhline(0%2C%20color%3D%22gray%22%2C%20lw%3D1)%0A%20%20%20%20_ax.set_xlabel(%22symmetric%20trim%20threshold%20(%25%20each%20tail)%22)%0A%20%20%20%20_ax.set_ylabel(%22flood%20coefficient%20(log%20points)%22)%0A%20%20%20%20_ax.set_title(%22Trim%20sensitivity%20%E2%80%94%20coefficient%20stable%20across%20cutoffs%22)%0A%20%20%20%20_ax.grid(alpha%3D0.3)%0A%20%20%20%20_fig%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20%23%23%23%204%20%C2%B7%20Dose-response%20by%20zone%20severity%20%E2%80%94%20*attempted%2C%20not%20shown*%0A%0A%20%20%20%20We%20wanted%20to%20split%20the%20flood%20flag%20into%20**AE**%20(1%25-chance%20floodplain)%20vs%20**VE**%20(coastal%0A%20%20%20%20high-velocity)%20to%20test%20for%20a%20within-parcel%20severity%20gradient.%20It%20doesn't%20work%3A%20only%0A%20%20%20%20**3**%20repeat-sale%20pairs%20are%20in%20VE%20zones%20(vs%20805%20AE%2C%202%2C549%20dry).%20A%20coefficient%20on%203%0A%20%20%20%20houses%20is%20noise%2C%20so%20we%20don't%20report%20it.%20The%20parcel-level%20flood%20effect%20is%20essentially%0A%20%20%20%20all%20AE%20(%E2%89%88%20the%20%E2%88%929.7%25%20binary%20result)%3B%20there's%20no%20VE%20sample%20to%20estimate%20a%20gradient%20from.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20%23%23%20Verdict%0A%0A%20%20%20%20On%20the%20same%20streets%2C%20flood-zone%20houses%20lost%20**~9%E2%80%9310%25%20more**%20value%20than%20dry%20houses%0A%20%20%20%20post-storm%20%E2%80%94%20stable%20across%20no-trim%20%2F%20trimmed%20%2F%20robust%2C%20so%20**not**%20an%20outlier%0A%20%20%20%20artifact.%20Significance%20is%20**marginal**%20under%20correct%20(clustered%20%2F%20bootstrap)%0A%20%20%20%20inference%3B%20the%20RLM's%20p%20%3C%200.001%20is%20pseudoreplication%20and%20should%20be%20ignored.%20Because%0A%20%20%20%20rebuild-masking%20biases%20the%20estimate%20*toward%20zero*%2C%20**%E2%88%929%25%20is%20a%20conservative%20floor.**%0A%0A%20%20%20%20**Decision%20read%3A**%20the%20flood%20penalty%20is%20real%20at%20the%20parcel%20level%20%E2%80%94%20dry%20ground%0A%20%20%20%20(the%20ridge)%20protects%20value%20even%20against%20dry-vs-wet%20neighbors%20on%20the%20same%20block.%0A%20%20%20%20Direction%20and%20magnitude%20are%20trustworthy%3B%20the%20precise%20p-value%20is%20the%20one%20number%20to%0A%20%20%20%20hold%20loosely.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
3243528fbb171044fdf8f01a9d8d7bd8