
    ʥj*                    t   d Z ddlmZ ddlZddlZddlmZ ddlmZ ddl	Z
ddlZ ee      j                         j                  j                  Zedz  dz  dz  Zd	Zd
Z ej(                  d      Z ej(                  d      ZddZddZddZdddZddZddZdddd dZd!dZedk(  r e  e             y)"a  Point-in-time Treasury-curve event study against BTC daily forward returns.

This is research only: it neither changes strategy inputs nor optimizes a
trading rule.  Treasury observations are shifted one BTC day before signals
are evaluated, so a same-day Treasury close can never affect that day's BTC
return.

Examples:
    python tools/run_treasury_curve_event_study.py --download-fred
    python tools/run_treasury_curve_event_study.py --yields /path/to/yields.csv
    )annotationsN)Path)IterabledatamlpzCOINBASE_BTCUSD, 1D.csvzChttps://fred.stlouisfed.org/graph/fredgraph.csv?id=DGS2,DGS10,DGS30)      
      <   z
2026-02-28z
2026-03-01c                f    | j                   D ]  }|j                         dv s|c S  t        d      )N>   datetimedatetimeobservation_datezGExpected a date column named DATE, observation_date, time, or datetime.)columnslower
ValueError)framecolumns     O/Users/jameslopez/projects/TradingBot25/tools/run_treasury_curve_event_study.py_date_columnr      s2    --<<>MMM   ^
__    c                   t        j                  |       }t        |      }d}|D cg c]  }||j                  vs| }}|rt	        ddj                  |             ||g|   j                         }t        j                  ||   d      ||<   |D ]  }t        j                  ||   d      ||<   ! |j                         j                  |di      j                  d      j                  d      S c c}w )zCLoad FRED-format yields, dropping non-numeric missing observations.DGS2DGS10DGS30z(Yield data is missing required columns: z, coerceerrorsr   )r   )pdread_csvr   r   r   joincopyto_datetime
to_numericdropnarenamesort_valuesdrop_duplicates)path_or_urlr   date_columnrequiredr   missings         r   load_yieldsr0   &   s    KK$Eu%K)H$,LH&emm0KvHGLCDIIgDVCWXYY;**+002Ek(:8LE+eFmHEf <<>  +v)> ?KKFSccdjkk Ms
   C7C7c                   t        j                  |       }t        |      }d|j                  D ch c]  }|j	                          c}vrt        d      t        d |j                  D              }|||g   j                         }ddg|_        t        j                  |d   d      |d<   t        j                  |d   d      |d<   |j                         j                  d      j                  d      S c c}w )NclosezBTC data needs a close column.c              3  H   K   | ]  }|j                         d k(  s|  yw)r2   N)r   ).0r   s     r   	<genexpr>zload_btc.<locals>.<genexpr>:   s     X]6fllnPW>W]s   ""r   r   r    )r"   r#   r   r   r   r   nextr%   r&   r'   r(   r*   r+   )pathr   r-   r   close_columns        r   load_btcr9   5   s    KKEu%KEMMBM&v||~MBB9::XU]]XXL;-.335EW%EMNN5=BE&M]]5>(CE'N<<>%%f-==fEE Cs   C8c                N   |dk  rt        d      |j                  d      g d   j                  t        j                  | d               j                         }|j                  |      }| j                  d      j                  |      j                         j                         S )zHJoin yields to BTC while making daily Treasury data usable next BTC day.r   z/availability_lag_days must be at least one day.r   r   )
r   	set_indexreindexr"   DatetimeIndexffillshiftr$   r(   reset_index)btcyieldsavailability_lag_daysratess       r   align_point_in_timerE   B   s    q JKKV$%?@HHIYIYZ]^dZeIfgmmoEKK-.E== %%e,335AACCr   c                    | j                         }|d   |d   kD  |d<   |g d   j                  |      dz  }|d   | k  |d<   || k  j                  d	      |d
<   |S )zACreate the two hypotheses fixed before examining forward returns.r   r   ten_above_thirtyr   d   r   two_year_sharply_fallingr   )axisall_yields_sharply_falling)r%   diffall)r   change_dayssharp_drop_bpsoutputchanges_bpss        r   build_signalsrR   K   s}    ZZ\F!'6'?!BF3499+FLK)4V)<)OF%&,7N?,J+O+OUV+O+WF'(Mr   c           
        t        |j                               i d}|D ]  }| j                  |d| df   j                         }t        t	        |            t	        |      r#t        t        |j                               d      nd t	        |      r#t        t        |j                               d      nd t	        |      r)t        t        |dkD  j                         dz        d      nd d|d	   t        |      <    |S )
N)signal_dayshorizonsforward_d_return_pct   r   rH   r   )nmean_return_pctmedian_return_pctpositive_return_pctrU   )
intsumlocr(   lenroundfloatmeanmedianstr)r   maskrU   resulthorizonreturnss         r   _summaryrj   V   s    03DHHJR PF))DHWI\"BBCJJLS\"BEg,uU7<<>%:A>TXFI'luW^^-='>!BX\RUV]R^5!/A/A/Cc/I)JA#Ndh	,
z3w<(  Mr   r
         9@rN   rO   c                  t        t        | |      ||      }t        D ]*  }|d   j                  |       |d   z  dz
  dz  |d| d<   , ||d   t        k     ||d   t
        k\     |d}d}dd	d
|dd| dd|dd| dt        t              dt        |d   j                         j                               t        |d   j                         j                               t        |      d|j                         D 	
ci c][  \  }}	|dt        |	t        j                  d|	j                         t              i|D 
ci c]  }
|
t        |	|	|
   t               c}
] c}
}	}dS c c}
w c c}
}	}w )Nr2   r   rH   rV   rW   r   )ISOOSfull)rG   rI   rK   zDGS10 > DGS30zDGS2 declines at least gz	 bp over z	 BTC daysz-DGS2, DGS10, and DGS30 each decline at least )yield_availability_lag_btc_daysrG   rI   rK    forward_return_horizons_btc_days)startendbarsbaselineT)index)methodcoveragewindows)rR   rE   HORIZONSr?   IS_END	OOS_STARTlistre   minr   maxr`   itemsrj   r"   Seriesrx   )rA   rB   rN   rO   r   rh   r{   signalsnamewindowsignals              r   studyr   c   s   -c6:KXE38>3G3G3QTYZaTb3bef3fjm2m	./  E&MV+,U6]i/0G
 ]G 01 /*A.QRASS\]h\iir(s,YZhijYkkt  vA  uB  BK  +L04X
 "%-"3"3"5":":"<=c%PV-J[J[J]JbJbJdFeorsxoyz !(
 !0f :x		$fll0SU]^ aW^_W^Vfhvvf~xHHW^_a a /
  `
s   >E/E*E/*E/c                    t        j                  t              } | j                  dt        t
               | j                  dd       | j                  ddd	
       | j                  dt        d       | j                  dt        d       | j                  dt        d       | j                         }t        |j                        t        |j                        k(  r| j                  d       |j                  dk  s|j                  dk  r| j                  d       t        t!        |j"                        t%        |j                  rt&        n|j                        |j                  |j                        }t)        j*                  |d      dz   }t-        |d       |j.                  rB|j.                  j0                  j3                  dd       |j.                  j5                  |       y)N)descriptionz--btc)typedefaultz--yieldsz2Local FRED CSV with DATE,DGS2,DGS10,DGS30 columns.)helpz--download-fred
store_truez4Read the public FRED CSV directly; does not save it.)actionr   z--change-daysr
   z--sharp-drop-bpsrk   z--outputzOptional JSON output path.)r   r   z2provide exactly one of --yields or --download-fredr   r   z3--change-days and --sharp-drop-bps must be positiverl      )indent
 )ru   T)parentsexist_ok)argparseArgumentParser__doc__add_argumentr   DEFAULT_BTCr]   rb   
parse_argsboolrB   download_frederrorrN   rO   r   r9   rA   r0   FRED_URLjsondumpsprintrP   parentmkdir
write_text)parserargsreporttexts       r   mainr      s   $$9F
dK@

)]^
),E{|
c2>
*E

4PQDDKKD!3!344IJ!t22a7JK8DHH%{t?Q?Q8W[WbWb'c#//@S@SUF::fQ'$.D	$B{{   =t$r   __main__)r   pd.DataFramereturnre   )r,   z
str | Pathr   r   )r7   r   r   r   )r   )rA   r   rB   r   rC   r]   r   r   )r   r   rN   r]   rO   rb   r   r   )r   r   rf   z	pd.SeriesrU   zIterable[int]r   dict[str, object])
rA   r   rB   r   rN   r]   rO   rb   r   r   )r   r]   )!r   
__future__r   r   r   pathlibr   typingr   numpynppandasr"   __file__resolver   REPOr   r   r|   	Timestampr}   r~   r   r0   r9   rE   rR   rj   r   r   __name__
SystemExit r   r   <module>r      s   
 #       H~&&--Vme#&??P	l	#BLL&	`l
FD
 JLei 8. z
TV
 r   