Ë
    îL±jë"  ã                  ób   — d Z ddlmZ ddlZddlZddlmZ ddœ	 	 	 d	d„Z	d
d„Z
	 d	 	 	 	 	 dd„Zy)zJOpt-in stop research utilities; never imported by the production strategy.é    )ÚannotationsN)ÚCOMMISSION_RATE)Úwidthsc               óˆ
  ‡‡— t        | «      }| j                  j                  t        «      | j                  j                  t        «      }}t        j                  |«      j                  «       r6t        j                  |«      j                  «       r|dk  j                  «       rt        d«      ‚t        |d   «      Št        j                  ‰«      rd‰cxk  rdk  st        d«      ‚ t        d«      ‚‰�Ft        j                  ‰t        ¬«      Š‰j                  |fk7  rt        d«      ‚‰dk  rt        d	«      ‚| j                  t        j                  |«      k\  | j                  t        j                  |«      t        j                  d¬
«      z   k  z  j                  «       |d   z  }t        j                   |t"        «      t        j                   |t$        «      t        j                   |t$        «      }}
}	t        j&                  |t
        j(                  «      t        j&                  |t
        j(                  «      t        j&                  |t
        j(                  «      }}}t        j&                  |dt"        «      }g }d\  }}ddt
        j(                  }}}d$ˆˆfd„}t+        |«      D �]¶  }|�r<||dz   k7  rt-        |||   «      }‰dkD  r8 ||dz
  «      }|d|z
  z  }‰€|nt-        ||||   d‰z
  z  «      }||c||<   ||<   ‰dkD  xr ||   |k  }t%        |r|d   |   n|d   |   «      }||c||<   ||<   ||   �r|s|�r|j/                  |t1        | j                  j2                  |   «      |||z
  d|rdnd|t%        |«      ||   ||   |‰dkD  r|nd|rdt-        d|||   z
  ||   z  «      z  nd‰dkD  rdt-        dd‰z
  ||   ||   z  z
  «      z  nddœ«       d\  }}d||<   no||   rj|d   |   rbd|||   }}}d|
|<   |d   xr |d   |   |d   k  }‰dkD  r/ ||«      }|d|z
  z  }‰�t-        ||d‰z
  z  «      }||c||<   ||<   ||c||<   ||<   ||	|<   �Œ¹ | j5                  «       }|	|
|c|d<   |d<   |d<   |||c|d<   |d<   |d<   ||d <   |j6                  j9                  dd¬!«      |j                  j;                  «       j=                  d«      z  t>        |j@                  j9                  dd"¬!«      jC                  t        «      |jD                  jC                  t        «      z   z  z
  |d#<   ||fS )%a5  Canonical execution with an optional causal, ratcheted width series.

    None disables the experiment (retains the canonical stop, including zero).
    Widths are observable at each close; entry uses t, holding decisions t-1.
    Candidate threshold risk is capped at the baseline entry loss percentage.
    r   z)Prices must be finite and closes positiveÚtrailé   zInvalid baseline stopN)Údtypezwidth length must match framez9Candidate requires a positive baseline maximum loss bound©ÚdaysÚtime_okéÿÿÿÿ)FFç        c                óŒ   •— ‰€‰nt        ‰|    «      }t        j                  |«      rd|cxk  rdk  sn t        d| › �«      ‚|S )Nr   r   zInvalid active width at bar )ÚfloatÚnpÚisfiniteÚ
ValueError)ÚtÚvaluer   r   s     €€úI/Users/jameslopez/projects/TradingBot25/strategies/mlp_volatility_stop.pyÚwidth_atzreplay_stop.<locals>.width_at(   sE   ø€ Ø˜‘¬U°6¸!±9Ó-=ˆÜ�{‰{˜5Ô!¨¨U¬°Q¬ÜÐ;¸A¸3Ð?Ó@Ð@Øˆó    ÚfallbackÚexitÚtrailing_stopÚ
score_exitéd   )ÚbarÚtimeÚ	entry_barÚage_barsÚactionÚreasonr   Ústop_hitÚentry_priceÚ
exit_priceÚ
trade_highÚ
stop_priceÚthreshold_overshoot_pctÚentry_bound_breach_pctTÚentryÚ	dead_zoneÚexit_thresholdÚpositionÚexecute_entryÚexecute_exitr(   Úrequested_widthr'   r    )Ú
fill_valueFÚstrategy_return)r   ÚintÚreturnr   )#ÚlenÚcloseÚto_numpyr   Úhighr   r   ÚallÚanyr   ÚasarrayÚshaper   ÚpdÚ	TimestampÚ	TimedeltaÚzerosr4   ÚboolÚfullÚnanÚrangeÚmaxÚappendÚstrÚilocÚcopyr.   ÚshiftÚ
pct_changeÚfillnar   r/   Úastyper0   )ÚframeÚopportunitiesÚstartÚendr   Únr7   r9   ÚallowedÚ	positionsÚenteredÚexitedÚstopsÚ
used_widthÚpeaksÚ	entry_idsÚeventsÚactiveÚuse_rawr    ÚpeakÚstopr   r   ÚwidthÚproposedr$   r   Úresultr   s       `                        @r   Úreplay_stoprd   
   s^  ù€ ô 	ˆE‹
€AØ—+‘+×&Ñ&¤uÓ-¨u¯z©z×/BÑ/BÄ5Ó/Iˆ4€EÜ�;‰;�uÓ×!Ñ!Ô#¬2¯;©;°tÓ+<×+@Ñ+@Ô+BÀuÐPQÁz×FVÑFVÔFXÜÐDÓEÐEÜ�- Ñ(Ó)€EÜ�;‰;�uÔ Q¨%¤^°!¢^ÜÐ0Ó1Ð1ð &4ÜÐ0Ó1Ð1ØÐÜ—‘˜F¬%Ô0ˆØ�<‰<˜A˜4ÒÜÐ<Ó=Ð=Ø�AŠ:ÜÐXÓYÐYØ—
‘
œbŸl™l¨5Ó1Ñ1Ø—
‘
œRŸ\™\¨#Ó.¬r¯|©|ÀÔ/CÑCÑCñEßFNÁhÃjÐS`ÐajÑSkñl€Gä!#§¡¨!¬SÓ!1´2·8±8¸A¼tÓ3DÄbÇhÁhÈqÔRVÓFW˜ˆw€IÜ!Ÿw™w q¬"¯&©&Ó1´2·7±7¸1¼b¿f¹fÓ3EÄrÇwÁwÈqÔRT×RXÑRXÓGY�uˆ:€EÜ—‘˜˜2œsÓ#€IØ€FØ"�O€FˆGØ ¤B§F¡F�Tˆt€Iöô �1�XˆÚØ�I˜a‘KÒÜ˜4  a¡Ó)�Ø�qŠyÙ   1¡›�Ø  5¡™>�Ø#) >‘x´s¸4ÀÈ5ÐQZÑK[Ð]^Ð_dÑ]dÑKeÓ7f�Ø*.°Ð'��a‘˜* Q™-Ø˜q‘yÒ5 U¨1¡X°Ñ%5ˆHÜ¹g˜m¨JÑ7¸Ò:È=ÐY_ÑK`ÐabÑKcÓdˆJØ%)¨9Ð"ˆE�!‰H�i ‘lØ�q‹z™xª:Ø—‘ a´°U·Z±Z·_±_ÀQÑ5GÓ1HÐW`Ø+,¨Y©;À&Ù<D©È,Ø-7ÄTÈ(Ã^Ø.3°IÑ.>ÈeÐTUÉhØ-1ÈÐQRÊÁÐX\Ùks¸#¼cÀ"ÀtÈEÐRSÉHÁ}ÐV[Ð\eÑVfÑFfÓ>gÒ:gÐy{ØkpÐstÒkt¸¼SÀÀQÀuÁWÈUÐSTÉXÐV[Ð\eÑVfÑMfÑEfÓ=gÒ9gÐz|ñ~ô ð #/‘�˜Ø ��q’	Ø�QŠZ˜M¨'Ñ2°1Ò5Ø&*¨A¨u°Q©x˜t�IˆFØˆG�A‰JØ# KÑ0Òu°]À<Ñ5PÐQRÑ5SÐVcÐdtÑVuÑ5uˆGØ�qŠyÙ  ›�Ø˜Q˜u™W‘~�ØÐ%Ü˜t T¨1¨U©7¡^Ó4�DØ*.°Ð'��a‘˜* Q™-Ø%)¨1Ð"ˆE�!‰H�i ‘lØˆ	�!‹ðE ðF �Z‰Z‹\€FØJSÐU\Ð^dÐG€Fˆ:Ñ˜˜Ñ/°¸Ñ1GØLQÐS]Ð_dÐI€Fˆ<Ñ˜&Ð!2Ñ3°V¸LÑ5IØ#€Fˆ;ÑØ!'§¡×!6Ñ!6°qÀQÐ!6Ó!GÈÏÉ×H_ÑH_ÓHa×HhÑHhÐijÓHkÑ!kÜ"1°6×3GÑ3G×3MÑ3MÈaÐ\aÐ3MÓ3b×3iÑ3iÔjoÓ3pØ5;×5HÑ5H×5OÑ5OÔPUÓ5Vñ4Wñ #Xñ"X€FÐÑð �6ˆ>Ðr   c                óz  — | g d¢   j                  t        «      }t        j                  |«      j	                  «       r|dk  j                  «       rt        d«      ‚| j                  | g d¢   j                  d¬«      k  j                  «       s2| j                  | ddg   j                  d¬«      kD  j                  «       rt        d	«      ‚| j                  j                  r(| j                  j                  «       j                  «       rt        d
«      ‚| j                  j                  d«      }t!        j"                  | j                  | j                  z
  | j                  |z
  j%                  «       | j                  |z
  j%                  «       gd¬«      j                  d¬«      j                  «       }t        j&                  t)        | «      t        j*                  «      }t)        | «      dk\  rG|dd j-                  «       |d<   t/        dt)        | «      «      D ]  }d||dz
     z  ||   z   dz  ||<   Œ t!        j0                  || j                  j                  «       z  t        j2                  | j                  «      j5                  «       j7                  d«      j9                  «       dœ| j:                  ¬«      S )zŠWilder ATR(14), SMA seed; realized log-return std(20), ddof=1.

    Values on t use only OHLC through t. Replay uses t-1 after entry.
    )Úopenr9   Úlowr7   r   z OHLC must be finite and positive)rf   r7   rg   r   )Úaxisrf   r7   zInvalid OHLC orderingz!Times must be strictly increasingé   Né   é   )Ú	atr_priceÚrv20)Úindex)r8   r   r   r   r:   r;   r   r9   rF   rg   Úminr   Úis_monotonic_increasingÚ
duplicatedr7   rK   r>   ÚconcatÚabsrC   r6   rD   ÚmeanrE   Ú	DataFrameÚlogÚdiffÚrollingÚstdrn   )rO   ÚpricesÚpreviousÚtrÚatrr   s         r   Ú
volatilityr~   [   s+  € ð
 Ò3Ñ4×=Ñ=¼eÓD€FÜ�;‰;�vÓ×"Ñ"Ô$¨°1©×(9Ñ(9Ô(;ÜÐ;Ó<Ð<Ø�
‰
�UÒ3Ñ4×8Ñ8¸aÐ8Ó@Ñ@×EÑEÔGØ�I‰I˜˜v wÐ/Ñ0×4Ñ4¸!Ð4Ó<Ñ<¿c¹c»eðLDäÐ0Ó1Ð1Ø�:‰:×-Ò-°·±×1FÑ1FÓ1H×1LÑ1LÔ1NÜÐ<Ó=Ð=Ø�{‰{× Ñ  Ó#€HÜ	�‰�E—J‘J˜uŸy™yÑ(¨5¯:©:°hÑ+>×*CÑ*CÓ*EØ—Y‘Y˜xÑ'×,Ñ,Ó.ð0Ø67ô
9ß9<¹À!¸»ÇXÁXÃZð ä
�'‰'”#�e“*œbŸf™fÓ
%€CÜ
ˆ5ƒz�RÒØ�S�b�'—,‘,“.ˆˆB‰Ü�rœ3˜u›:Ö&ˆAØ˜˜Q˜q™S™‘k " Q¡%Ñ'¨Ñ+ˆC�ŠFð 'ä�<‰< c¨%¯+©+×*>Ñ*>Ó*@Ñ&@Ü!#§¡¨¯©Ó!4×!9Ñ!9Ó!;×!CÑ!CÀBÓ!G×!KÑ!KÓ!MñOØV[×VaÑVaôcð cr   c                óÎ  — g }t        j                  |«      t        j                  d¬«      z   }|D �ci c]  }|d“Œ }}| j                  j	                  d¬«      }	| j
                  j                  «       }
|D �]Ò  }|j                  d«      dk7  rŒ|d   |d	   }}|D �]ª  }||z   }|t        | «      k  xr |	j                  |   |k  }|xr\ t        |	j                  ||dz    j                  «       j                  «       t        j                  d
¬«      k7  j                  «       «      }|xr | }|xr |||   kD  }|r|||<   i d|“d	|“dt        |	j                  |   «      “d|d   “d|d   “d|“d|“d|“d|“d|rt        |	j                  |   «      nd“d|	j                  |   |	j                  |   z
  j                  «       dz  “dd|
|   |
|   z  dz
  z  “dd|j                   j                  |   z  “dd|j                   j                  |   z  “dd|j"                  j                  |   z  “dd|j"                  j                  |   z  “}|ræ|
|dz   |dz    |
|   z  dz
  }|
|dz   |dz    |
|| z  dz
  }|dxx   t$        z  cc<   t'        j(                  d|z   «      dt$        z
  z
  }|j+                  d|d   z  d|z  dt-        d|j-                  «       «      z  dt-        d|j/                  «        «      z  dt-        d| «      z  t        |
|dz   |dz    |
|   k\  j                  «       «      ¬«       |j1                  |«       �Œ­ �ŒÕ t        j2                  |«      S c c}w ) zàDescriptive exit continuations, not additive strategy returns.

    Greedily retain disjoint horizons across BOTH exit types, separately per
    horizon. Incomplete/window-crossing/gapped horizons stay as censored rows.
    r   r
   r   T)Údropr"   r   r   r    é   )Úhoursr   r#   Úscore_exit_alsor   Úhorizon_barsÚvalidÚgapÚ
nonoverlapÚ	label_endNÚholding_hoursi  Útrade_price_return_pctr   Úentry_atr_pctÚexit_atr_pctÚentry_rv_pctÚexit_rv_pctr   )Úterminal_return_pctÚhold_advantage_pctÚmissed_recovery_pctÚsubsequent_decline_pctÚterminal_loss_avoided_pctÚrecovered_entry)r>   r?   r@   r   Úreset_indexr7   r8   Úgetr6   rI   rB   rw   Údropnar;   rH   Útotal_secondsrl   rm   r   r   ÚprodÚupdaterF   ro   rG   ru   )rO   Ú	decisionsÚvolrR   ÚhorizonsÚrowsÚboundaryÚhÚlast_retainedÚtimesr7   Údecisionr   r+   ÚhorizonÚendpointÚcompleter†   r…   ÚretainedÚrowÚpathÚfuture_returnsÚ	advantages                           r   Úevent_studyr¬   t   sÑ  € ð €DÜ�|‰|˜CÓ ¤§¡°1Ô!5Ñ5€HÙ$,Ó-¡H˜q�Q˜‘U H€MÐ-Ø�J‰J×"Ñ"¨Ð"Ó-€EØ�K‰K× Ñ Ó"€EÜˆØ�<‰<˜Ó! VÒ+ØØ˜E‘? H¨[Ñ$9ˆ5ˆÜˆGØ˜‘yˆHØ¤# e£*Ñ,ÒP°·±¸HÑ1EÈÑ1PˆHØÒoœt U§Z¡Z°°8¸A±:Ð%>×%CÑ%CÓ%E×%LÑ%LÓ%NÔRT×R^ÑR^ÐefÔRgÑ%g×$lÑ$lÓ$nÓoˆCØÒ( S ˆEØÒ;  ]°7Ñ%;Ñ!;ˆHÙØ)1�˜gÑ&ð	8�5˜!ð 	8˜[¨%ð 	8°¼¸U¿Z¹ZÈ¹]Ó9Kð 	8Ø˜X hÑ/ð	8Ø1BÀHÈ\ÑDZð	8à! 7ð	8à,3°Uð	8à<AÀ3ð	8àHTÐV^ð	8ð ¹X¤ E§J¡J¨xÑ$8Ô 9È4ð	8ð # U§Z¡Z°¡]°5·:±:¸eÑ3DÑ%D×$SÑ$SÓ$UÐVZÑ$Zð		8ð
 ,¨S°%¸±(¸5À¹<Ñ2GÈÑ2IÑ-Jð	8ð # C¨¯©×(:Ñ(:¸5Ñ(AÑ$Að	8ð " 3 s§}¡}×'9Ñ'9¸!Ñ'<Ñ#<ð	8ð " 3 s§x¡x§}¡}°UÑ';Ñ#;ð	8ð ! # c§h¡h§m¡m°AÑ&6Ñ"6ð	8ˆCñ Ø˜Q˜q™S ¨!¡Ð,¨U°1©XÑ5°aÑ7�ð "' q¨¡s¨8°A©:Ð!6°u¸Q¸xÐ7HÑ!HÈÑ!J�Ø˜rÓ"¤oÑ5Ó"ÜŸG™G A nÑ$4Ó5°q¼Ñ7HÑI�	Ø—
‘
¨s°4¸±8©|Ø.1°)©mØ/2´3°r¸4¿8¹8»:Ó3FÑ/FØ25´c¸"¸t¿x¹x»z¸kÓ6JÑ2JØ58¼¸RÀ)ÀÓ9LÑ5LÜ+/°°q¸±s¸8ÀA¹:Ð1FÈ%ÐPUÉ,Ñ1V×0[Ñ0[Ó0]Ó+^ð ô `ð �K‰K˜Öò?  ð	 ôH �<‰<˜ÓÐùòO .s   ³
M")rO   úpd.DataFramerP   ÚdictrQ   rH   rR   rH   r   znp.ndarray | Noner5   ztuple[pd.DataFrame, list[dict]])rO   r­   r5   r­   ))é   é   é*   )rO   r­   r›   z
list[dict]rœ   r­   rR   rH   r�   ztuple[int, ...]r5   r­   )Ú__doc__Ú
__future__r   Únumpyr   Úpandasr>   Ú%strategies.strategy_activation_scoresr   rd   r~   r¬   © r   r   Ú<module>r¸      s[   ðÙ PÝ "ã Û å Að -1ñNØ)ðNØ5TóNóbcð4 7Bð0Øð0Ø$3ð0ØFRô0r   