ó
    '´}jµ5  ã            	       óv   • S r SSKrSSKrSSKJrJr  SSKJrJ	r	J
r
   " S S5      r SS\	\   S\S	\S
\4S jjrg)zº
Diversification limit manager for MoERegression.

Prevents over-diversification by limiting number of simultaneous trades.
This reduces correlation risk and improves portfolio quality.
é    N)ÚdatetimeÚ	timedelta)ÚDictÚListÚOptionalc            	       ó6  • \ rS rSrSrS S\4S jjrS\4S jr S!S\S	\\   S
\	S\4S jjr
S\S\S\	4S jrS\S\	S\	4S jrS\S\	S\	S\	4S jrS\\   4S jrS\S\\   4S jrS\S\\   4S jrS!S
\	S\	4S jjrS\\\	4   S\	4S jrS\	4S jrS\4S jrSrg)"ÚDiversificationManageré   z4Manage diversification limits for trading positions.NÚconfigc                 ó\   • U=(       d    U R                  5       U l        0 U l        0 U l        g)z&Initialize diversification parameters.N)Úget_default_configr   Úopen_positionsÚ
entry_time)Úselfr   s     Ú>/home/ai/projects/AI_Strategy/trade/diversification_manager.pyÚ__init__ÚDiversificationManager.__init__   s&   € à×9 × 7Ñ 7Ó 9ˆŒØ/1ˆÔØˆ�ó    Úreturnc                 ó   • SSSSSSSS.$ )zGet default configuration.é   é   é   é   g      $@)Úmax_open_positionsÚmax_trades_per_tickerÚmax_trades_per_directionÚmax_trades_per_marketÚmin_position_age_hoursÚcooldown_hours_after_lossÚmax_position_risk_pct© ©r   s    r   r   Ú)DiversificationManager.get_default_config   s/   € ð #$ð &'ð )*ð &'ð ')ð *+ð &*ñ)
ð 	
r   ÚsignalÚcurrent_positionsÚportfolio_valuec                 óâ  • SSSS.n[        U5      U R                  S   :¼  a-  SUS'   S[        U5       S	U R                  S    3US
'   SUS'   U$ U Vs/ s H  oUS   PM	     nnUS   U;   aP  UR                  US   5      nXpR                  S   :¼  a*  SUS'   SUS    SU S	U R                  S    3US
'   SUS'   U$ U Vs/ s H  oUS   PM	     nnUS   U;   aP  UR                  US   5      nXpR                  S   :¼  a*  SUS'   SUS    SU S	U R                  S    3US
'   SUS'   U$ / n	U HO  nUR                  S5      (       d  M  [	        US   [
        [        45      (       d  M;  U	R                  US   5        MQ     [        U	SS9n
U
S:”  a~  [        R                  " 5       [        R                  " U
5      -
  n[        U R                  S   S9nX¼:  a7  SUS'   SUR                  5       S-  S SU R                  S    S3US
'   S US'   U$ / nU H¥  nUR                  S5      (       a  [	        US   [
        [        45      (       d  M9  [        R                  " 5       [        R                  " US   5      -
  R                  5       S:  d  M|  UR                  S!S5      S:  d  M”  UR                  U5        M§     U(       a-  U R                  S"   nSUS'   S#[        U5       S$3US
'   S%US'   U$ US:”  a`  UR                  S&S5      UR                  S'S(5      -  S)-  nXðR                  S*   :”  a&  SUS'   S+US S,U R                  S*    S-3US
'   S.US'   U$ SUS'   S/US
'   SUS'   U$ s  snf s  snf )0z¢
Check if a new position can be opened.

Returns dict with:
    - can_open: bool
    - reason: str (if cannot open)
    - score: float (0-1, how open is allowed)
TNç      ð?)Úcan_openÚreasonÚscorer   Fr*   zMax positions reached: Ú/r+   ç        r,   Útickerr   zToo many positions in z: g      à?Ú	directionr   z	Too many z positions: r   r   )Údefaultr   )ÚhourszPosition too recent: i  z.1fzh < Úhg333333Ó?Úpnlr    zCooldown active: z losing positions in last hourgš™™™™™É?Ú	atr_entryÚentry_priceé   éd   r!   zPosition too risky: z% > Ú%çš™™™™™Ù?zPosition approved)Úlenr   ÚcountÚgetÚ
isinstanceÚintÚfloatÚappendÚmaxr   ÚnowÚfromtimestampr   Útotal_seconds)r   r%   r&   r'   ÚresultsÚpÚtickers_with_positionsr<   Ú
directionsÚ
timestampsÚlatest_position_timeÚ	time_diffÚmin_ageÚrecent_losersÚcooldown_hoursÚposition_risk_pcts                   r   Úcan_open_positionÚ(DiversificationManager.can_open_position0   s=  € ð ØØñ
ˆô Ð Ó! T§[¡[Ð1EÑ%FÓFØ"'ˆG�JÑØ"9¼#Ð>OÓ:PÐ9QÐQRÐSW×S^ÑS^Ð_sÑStÐRuÐ vˆG�HÑØ"ˆG�GÑØˆNñ 8IÓ!IÒ7H°! H¤+Ñ7HÐÐ!IØ�(ÑÐ5Ó5Ø*×0Ñ0°¸Ñ1AÓBˆEØŸ™Ð$;Ñ<Ó<Ø&+�˜
Ñ#Ø&<¸VÀHÑ=MÐ<NÈbÐQVÐPWÐWXÐY]×YdÑYdÐe|ÑY}ÐX~Ð$�˜Ñ!Ø#&�˜Ñ Ø�ñ /@Ó@Ò.?¨˜”nÑ.?ˆ
Ð@Ø�+Ñ *Ó,Ø×$Ñ$ V¨KÑ%8Ó9ˆEØŸ™Ð$>Ñ?Ó?Ø&+�˜
Ñ#Ø&/°°{Ñ0CÐ/DÀLÐQVÐPWÐWXÐY]×YdÑYdÐeñ  ZAð  YBð  %C�˜Ñ!Ø#&�˜Ñ Ø�ð ˆ
Û"ˆAØ�u‰u�\×"Ó"¤z°!°L±/ÄCÌÀ<×'PÓ'PØ×!Ñ! ! L¡/Ö2ñ #ô  # :°qÑ9Ðà !Ó#Ü Ÿš›¬×)?Ò)?Ð@TÓ)UÑUˆIô   d§k¡kÐ2JÑ&KÑLˆGØÓ"Ø&+�˜
Ñ#Ø&;¸I×<SÑ<SÓ<UÐVZÑ<ZÐ[^Ð;_Ð_cÐdh×doÑdoð  qIñ  eJð  dKð  KLð  %M�˜Ñ!Ø#&�˜Ñ Ø�ð ˆÛ"ˆAØ—5‘5˜×&Ñ&¬j¸¸<¹Ì3ÔPUÈ,×.WÑ.WÙÜ—’“¤×!7Ò!7¸¸,¹Ó!HÑH×WÑWÓYÐ\`Õ`Ðef×ejÑejÐkpÐrsÓetÐwxÕexØ×$Ñ$ QÖ'ñ	 #ö Ø!Ÿ[™[Ð)DÑEˆNØ"'ˆG�JÑØ"3´C¸Ó4FÐ3GÐGeÐ fˆG�HÑØ"ˆG�GÑØˆNð ˜QÓØ &§
¡
¨;¸Ó :¸V¿Z¹ZÈÐWXÓ=YÑ YÐ\_Ñ _Ðà §;¡;Ð/FÑ#GÓGØ&+�˜
Ñ#Ø&:Ð;LÈSÐ:QÐQUÐVZ×VaÑVaÐbyÑVzÐU{Ð{|Ð$}�˜Ñ!Ø#&�˜Ñ Ø�ð #ˆ�
ÑØ/ˆ�ÑØˆ�ÑØˆùòG "Jùò As   ÁM'ÃM,Úposition_idr   c                 ód   • US   US   US   US   USS.U R                   U'   X0R                  U'   g)zRegister a new open position.r/   r0   r6   r5   r   )r/   r0   r6   r5   r   r4   N©r   r   )r   rS   r%   r   s       r   Úopen_positionÚ$DiversificationManager.open_position�   sJ   € ð ˜XÑ&Ø Ñ,Ø! -Ñ0Ø Ñ,Ø$Øñ,
ˆ×Ñ˜KÑ(ð (2�‰˜Ò$r   Úcurrent_priceÚatrc                 óR   • XR                   ;   a  U R                   U   nX$S'   X4S'   gg)z+Update position with current price and ATR.rX   Úcurrent_atrN)r   )r   rS   rX   rY   Úposs        r   Úupdate_positionÚ&DiversificationManager.update_position™   s3   € à×-Ñ-Ó-Ø×%Ñ% kÑ2ˆCØ#0�Ñ Ø!$�Òð .r   Ú
exit_pricer4   Ú	exit_timec                 ó¾   • XR                   ;   aN  X R                   U   S'   X@R                   U   S'   X0R                   U   S'   U R                   U	 U R                  U	 gg)z-Close a position and remove it from tracking.r_   r`   r4   NrU   )r   rS   r_   r4   r`   s        r   Úclose_positionÚ%DiversificationManager.close_position    sh   € à×-Ñ-Ó-Ø=G×Ñ Ñ,¨\Ñ:Ø<E×Ñ Ñ,¨[Ñ9Ø69×Ñ Ñ,¨UÑ3ð ×#Ñ# KÐ0Ø—‘ Ñ,ð .r   c                 óH   • [        U R                  R                  5       5      $ )z%Get list of currently open positions.)Úlistr   Úvaluesr#   s    r   Úget_open_positionsÚ)DiversificationManager.get_open_positions«   s   € ä�D×'Ñ'×.Ñ.Ó0Ó1Ð1r   c                 ó8   • U R                   R                  U5      $ )zGet position by ID.)r   r=   )r   rS   s     r   Úget_position_by_idÚ)DiversificationManager.get_position_by_id¯   s   € à×"Ñ"×&Ñ& {Ó3Ð3r   r/   c                 óv   • U R                   R                  5        Vs/ s H  o"S   U:X  d  M  UPM     sn$ s  snf )zGet all positions for a ticker.r/   ©r   rf   )r   r/   rG   s      r   Úget_position_by_tickerÚ-DiversificationManager.get_position_by_ticker³   s4   € à×.Ñ.×5Ñ5Ô7ÓQÒ7�a¸X¹;È&Ñ;P—Ñ7ÑQÐQùÒQs   �6­6c                 ój   • SnU R                   R                  5        H  nUS   US   -  nX$-  nM     U$ )z8Calculate total portfolio risk (sum of ATR % of prices).r.   r[   r6   rm   )r   r'   Ú
total_riskr\   Úatr_pcts        r   Úget_portfolio_riskÚ)DiversificationManager.get_portfolio_risk·   sD   € àˆ
Ø×&Ñ&×-Ñ-Ö/ˆCØ˜-Ñ(¨3¨}Ñ+=Ñ=ˆGØÑ!ŠJñ 0ð Ðr   Úcurrent_pricesc                 óº   • SnU R                   R                  5        H:  u  p4UR                  X4S   5      nXTS   -
  UR                  SS5      -  S-  nX&-  nM<     U$ )z0Calculate unrealized PnL for all open positions.r.   r6   Úvolumeiè  )r   Úitemsr=   )r   ru   Ú	total_pnlÚpos_idr\   rX   r4   s          r   Úget_unrealized_pnlÚ)DiversificationManager.get_unrealized_pnlÀ   sj   € àˆ	à×.Ñ.×4Ñ4Ö6‰KˆFØ*×.Ñ.¨v¸=Ñ7IÓJˆMØ  }Ñ#5Ñ5¸¿¹ÀÈ4Ó9PÑPÐSWÑWˆCØÑŠIñ 7ð
 Ðr   c                 óÄ  • U R                   (       d  g[        [        S U R                   R                  5        5       5      5      nU R                  S   n[        X-  S5      nU R                   R                  5        Vs/ s H  oDS   PM	     nnUR                  S5      nUR                  S5      nXg-   S:”  a  [        Xg5      [        Xg5      -  OSnSU-  S	U-  -   $ s  snf )
z0Calculate portfolio diversification score (0-1).r)   c              3   ó*   #   • U  H	  oS    v •  M     g7f)r/   Nr"   )Ú.0rG   s     r   Ú	<genexpr>ÚIDiversificationManager.calculate_diversification_score.<locals>.<genexpr>Ò   s   é € ÐRÒ5Q° (¦Ò5Qùs   ‚r   r0   ÚLONGÚSHORTr   g333333ã?r:   )r   r;   Úsetrf   r   Úminr<   rB   )	r   Útickers_countÚmax_tickersÚticker_scorerG   rI   Ú
long_countÚshort_countÚdirection_scores	            r   Úcalculate_diversification_scoreÚ6DiversificationManager.calculate_diversification_scoreË   sÞ   € à×"×"Øô œCÑR°T×5HÑ5H×5OÑ5OÔ5QÓRÓRÓSˆØ—k‘kÐ"6Ñ7ˆÜ˜=Ñ6¸Ó<ˆð /3×.AÑ.A×.HÑ.HÔ.JÓKÒ.J¨˜”nÑ.Jˆ
ÐKØ×%Ñ% fÓ-ˆ
Ø ×&Ñ& wÓ/ˆØZdÑZrÐvwÓYwœ#˜jÓ6¼¸ZÓ9UÒUð  ~Aˆð �\Ñ! C¨/Ñ$9Ñ9Ð9ùò Ls   Á?Cc                 ó|   • [        U R                  5       [        U R                  5       5      U R                  S   S9$ )z3Calculate and return diversification report string.r   )r&   Ú
open_countÚmax_positions)Úcreate_diversification_reportrg   r;   r   r#   s    r   Ú calculate_diversification_reportÚ7DiversificationManager.calculate_diversification_reportß   s9   € ä,Ø"×5Ñ5Ó7Ü˜4×2Ñ2Ó4Ó5ØŸ+™+Ð&:Ñ;ñ
ð 	
r   )r   r   r   )N)i † )Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__r   r   r   r   r@   rQ   r?   rV   r]   rb   rg   r   rj   Ústrrn   rs   r{   rŒ   r’   Ú__static_attributes__r"   r   r   r	   r	      s-  † Ù>ñ˜tõ ð
 Dô 
ð4 39ñ[¨ð [ÀÀdÁð [Ø*/ð[Ø=Aõ[ðz
2¨ð 
2°dð 
2Èô 
2ð%¨3ð %¸uð %È5ô %ð	-¨#ð 	-¸5ð 	-Àuð 	-ÐY^ô 	-ð2 D¨¡Jô 2ð4¨cð 4°h¸t±nô 4ðR¨Sð R°X¸d±^ô Rñ°%ð ÀUõ ð	°°c¸5°jÑ1Að 	Àeô 	ð:°ô :ð(
°#÷ 
r   r	   r&   r�   r�   r   c           	      óH  • US:X  a  g0 nU  HD  nUS   nXS;  a  S[        5       S.X5'   X5   S==   S-  ss'   X5   S   R                  US   5        MF     S	U S
U S3nUS-  nUR                  5        H,  u  pWSR                  US   5      nUSUS SUS    SU S3-  nM.     U$ )z-Create human-readable diversification report.r   zNo open positionsr/   )r<   rI   r<   r7   rI   r0   u   
ðŸ“Š Diversification Report (r-   z positions):
z=------------------------------------------------------------
z, z  z<10Ú z pos | Ú
)r„   Úaddrx   Újoinr™   ÚtupleÚboolr@   )
r&   r�   r�   Úticker_statsr\   r/   ÚreportÚstatsÚdirections_strÚcheck_diversifications
             r   r‘   r‘   è   sá   € ð �QƒØ"ð €LÛ ˆØ�X‘ˆØÓ%Ø-.¼c»eÑ#DˆLÑ ØÑ˜WÓ%¨Ñ*Ó%ØÑ˜\Ñ*×.Ñ.¨s°;Ñ/?Ö@ñ !ð /¨z¨l¸!¸M¸?È.ÐY€FØ
ˆoÑ€Fà%×+Ñ+Ö-‰ˆØŸ™ 5¨Ñ#6Ó7ˆØ�B�v˜c�l ! E¨'¡NÐ#3°7¸>Ð:JÈ"ÐMÑMŠñ .ð €Mr   )r   )r˜   ÚpandasÚpdÚnumpyÚnpr   r   Útypingr   r   r   r	   r?   r™   r‘   r"   r   r   Ú<module>r¬      sY   ðñó Û ß (ß 'Ñ '÷W
ñ W
ðv 9:ñU!°T¸$±Zð U!ÈSð U!Ø25ðU!Ø>AöU!r   