Ë
    Bp±j  ã                   óL  — d Z ddlZddlmc mZ ddlZddlZddl	Z	ej                  j                  ej                  j                  ej                  j                  e«      d«      «      Zej                  j!                  de«       ddlmZmZmZ d„ Zd„ Zd„ Zd„ Zd	„ Zd
„ Zd„ Zy)aâ  
Commission-awareness of tools/compare_tv_trades.py
===================================================

Guards the parity comparator's P&L against the "no commission" footgun: TV's
per-trade Net PnL % is commission-inclusive, so the Python side must pay the
same 0.5%/side commission or the constant ~1%/trade offset compounds into a
misleading multi-x cumulative gap (BTC 6H once read 7,649% gross vs 2,553% TV).

The model must stay identical to strategies/validate_strategy.py.
é    Nz..)ÚCOMMISSION_RATEÚnet_pnl_pctÚextract_python_tradesc                 ó8   — | d|z   z  }|d|z
  z  }||z
  |z  dz  S )zGRe-implementation of the exact formula in validate_strategy.py:210-213.é   éd   © )Úentry_pxÚexit_pxÚrateÚ	eff_entryÚeff_exits        úq/Users/jameslopez/projects/TradingBot25/.worktrees/mlp-comparable-measurement/tests/test_compare_tv_commission.pyÚ_validate_strategy_modelr      s3   € à˜A ™HÑ%€IØ˜!˜d™(Ñ#€HØ�yÑ  IÑ-°Ñ3Ð3ó    c                  óp  — d} t         | k(  }|s¥t        j                  d|fdt         | f«      dt        j                  «       v st        j
                  t         «      rt        j                  t         «      ndt        j                  | «      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}} y )Ng{®Gázt?©ú==)z%(py0)s == %(py3)sr   )Úpy0Úpy3zassert %(py5)sÚpy5)	r   Ú
@pytest_arÚ_call_reprcompareÚ@py_builtinsÚlocalsÚ_should_repr_global_nameÚ	_safereprÚAssertionErrorÚ_format_explanation)Ú@py_assert2Ú@py_assert1Ú@py_format4Ú@py_format6s       r   Ú4test_default_rate_matches_pine_and_validate_strategyr$      s[   € à#Ð#Œ?˜eÑ#×#×#Õ#Œ?˜e×#×#×#×#×#Ñ#Œ?×#×#Ó#Œ?×#×#Ô#˜e×#×#×#×#×#×#Ò#r   c                  ó"  — dD �]	  \  } }t        | |«      }t        j                  }t        | |t        «      } ||«      }||k(  }|�s¼t        j                  d|fd||f«      dt        j                  «       v st        j                  t         «      rt        j                  t         «      nddt        j                  «       v st        j                  | «      rt        j                  | «      nddt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      dt        j                  «       v st        j                  t        «      rt        j                  t        «      ndt        j                  |«      dt        j                  «       v st        j                  t        «      rt        j                  t        «      nddt        j                  «       v st        j                  | «      rt        j                  | «      nddt        j                  «       v st        j                  |«      rt        j                  |«      ndd	t        j                  «       v st        j                  t        «      rt        j                  t        «      nd	t        j                  |«      t        j                  |«      d
œz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}x}x}}�Œ y )N)©ç      Y@ç     €[@)g      i@g     Àb@)gq=
×C¡Í@gš™™™ù®Î@r   )zª%(py4)s
{%(py4)s = %(py0)s(%(py1)s, %(py2)s)
} == %(py16)s
{%(py16)s = %(py8)s
{%(py8)s = %(py6)s.approx
}(%(py14)s
{%(py14)s = %(py9)s(%(py10)s, %(py11)s, %(py12)s)
})
}r   r
   r   Úpytestr   r   )r   Úpy1Úpy2Úpy4Úpy6Úpy8Úpy9Úpy10Úpy11Úpy12Úpy14Úpy16zassert %(py18)sÚpy18)r   r)   Úapproxr   r   r   r   r   r   r   r   r   r   )	r
   r   Ú@py_assert3Ú@py_assert7Ú@py_assert13Ú@py_assert15Ú@py_assert5Ú@py_format17Ú@py_format19s	            r   Ú.test_net_pnl_matches_validate_strategy_formular>   $   s¡  € ô TÑˆ�'Ü˜8 WÓ-ð 	
´·±ð 	
Ü$ X¨w¼ÓHð	
±ØHó2
ð 	
Ð-ð 2
ñ 
÷ 	
ð 	
ïé ó	
Ð-ð 2
÷ 	
ò 	
ç	�6÷	
ò 	
ïé ô ÷ 	
ñ 	
ç 	�	ô ÷ 	
ó 	
ç	�6÷	
ò 	
ïé ð $÷ 	
ñ 	
ç 	�	ð $÷ 	
ó 	
ç	�6÷	
ò 	
ïé ð &-÷ 	
ñ 	
ç 	�	ð &-÷ 	
ò 	
ç 	�	ð .÷ 	
ñ 	
ç	�6÷	
ò 	
ïé ô 28÷ 	
ñ 	
ç 	�	ô 28÷ 	
ò 	
ç 	�	ð 2?÷ 	
ñ 	
ç	�6÷	
ò 	
ïé ô %÷	
ñ 	
ç 	�	ô %÷	
ó 	
ç	�6÷	
ò 	
ïé ð &.÷	
ñ 	
ç 	�	ð &.÷	
ó 	
ç	�6÷	
ò 	
ïé ð 07÷	
ñ 	
ç 	�	ð 07÷	
ó 	
ç	�6÷	
ò 	
ïé ô 9H÷	
ñ 	
ç 	�	ô 9H÷	
ò 	
ç 	�	ð I÷	
ð 	
ç 	�	ð2
÷ 	
÷ 	
÷ 	
ñ 	
ïé ÷	
÷ 	
õ 	
ñ Tr   c            
      ó  — d\  } }|| z
  | z  dz  }t        | |«      }||k  }|sÆt        j                  d|fd||f«      dt        j                  «       v st        j
                  |«      rt        j                  |«      nddt        j                  «       v st        j
                  |«      rt        j                  |«      nddœz  }dd	|iz  }t        t        j                  |«      «      ‚d }||z
  }t        j                  }d
}	d}
 ||	|
¬«      }||k(  }|�s_t        j                  d|fd||f«      dt        j                  «       v st        j
                  |«      rt        j                  |«      nddt        j                  «       v st        j
                  |«      rt        j                  |«      nddt        j                  «       v st        j
                  t        «      rt        j                  t        «      ndt        j                  |«      t        j                  |	«      t        j                  |
«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}x}x}	x}
}y )Nr&   r   ©Ú<)z%(py0)s < %(py2)sÚnetÚgross)r   r+   zassert %(py4)sr,   g¸…ëQ¸ð?gš™™™™™©?©Úabsr   )zh(%(py0)s - %(py1)s) == %(py12)s
{%(py12)s = %(py6)s
{%(py6)s = %(py4)s.approx
}(%(py8)s, abs=%(py10)s)
}r)   )r   r*   r,   r-   r.   r0   r2   zassert %(py14)sr3   )r   r   r   r   r   r   r   r   r   r)   r6   )r
   r   rC   rB   r!   Ú@py_format3Ú@py_format5r    r;   r8   Ú@py_assert9Ú@py_assert11r7   Ú@py_format13Ú@py_format15s                  r   Ú8test_net_is_below_gross_by_roughly_round_trip_commissionrL   .   st  € Ø$Ñ€HˆgØ�xÑ 8Ñ+¨cÑ1€EÜ
�h Ó
(€CØ�‰;××Õˆ3�×××××Ñˆ3××Óˆ3×××××Ò�××Ó�××××××Ñà�C‰KÐ:œFŸM™MÐ:¨%Ð:°TÐ:™M¨%°TÔ:Ð:ˆKÐ:Ñ:×:×:Ö:ˆKÐ:×:×:×:×:×:Ñ:ˆE×:×:Ó:ˆE×:×:×:×:×:Ò:�C×:×:Ó:�C×:×:×:×:×:Ò:œF×:×:Ó:œF×:×:Ô:˜M×:×:Ò:¨%×:×:Ò:°T×:×:Ò:Ð:×:×:×:×:×:×:×:Ò:r   c            	      óÂ  — t        dd«      } t        j                  }d}| }d} |||¬«      }| |k(  }|�st        j                  d|fd| |f«      dt        j                  «       v st        j                  | «      rt        j                  | «      nddt        j                  «       v st        j                  t        «      rt        j                  t        «      ndt        j                  |«      t        j                  |«      t        j                  |«      t        j                  |«      d	œz  }d
d|iz  }t        t        j                  |«      «      ‚d x}x}x}x}x}}y )Nr'   g×£p=
×ï?g{®Gáz„?rD   r   )z\%(py0)s == %(py11)s
{%(py11)s = %(py4)s
{%(py4)s = %(py2)s.approx
}(-%(py6)s, abs=%(py9)s)
}rB   r)   )r   r+   r,   r-   r/   r1   zassert %(py13)sÚpy13©r   r)   r6   r   r   r   r   r   r   r   r   )	rB   r7   r;   r8   Ú@py_assert8Ú@py_assert10r!   Ú@py_format12Ú@py_format14s	            r   Ú+test_flat_trade_loses_round_trip_commissionrT   7   sÎ   € ä
�e˜UÓ
#€CÜ—-‘-Ð1 Ð1  Ð1¨DÐ1‘- ¨DÔ1Ð1ˆ3Ð1Ñ1×1×1Ö1ˆ3Ð1×1×1×1×1×1Ñ1ˆ3×1×1Ó1ˆ3×1×1×1×1×1Ò1”&×1×1Ó1”&×1×1Ô1�-×1×1Ò1 ×1×1Ò1¨D×1×1Ò1Ð1×1×1×1×1×1×1×1Ò1r   c                  ój  — d\  } }|| z
  | z  dz  }d}t        | ||¬«      }t        j                  } ||«      }||k(  }|�sét        j                  d|fd||f«      dt        j                  «       v st        j                  t         «      rt        j                  t         «      nddt        j                  «       v st        j                  | «      rt        j                  | «      ndd	t        j                  «       v st        j                  |«      rt        j                  |«      nd	t        j                  |«      t        j                  |«      d
t        j                  «       v st        j                  t        «      rt        j                  t        «      nd
t        j                  |«      dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      dœ	z  }dd|iz  }	t        t        j                  |	«      «      ‚d x}x}x}x}}y )N)r'   g     0a@r   g        )Úcommission_rater   )z‘%(py6)s
{%(py6)s = %(py0)s(%(py1)s, %(py2)s, commission_rate=%(py4)s)
} == %(py13)s
{%(py13)s = %(py10)s
{%(py10)s = %(py8)s.approx
}(%(py11)s)
}r   r
   r   r)   rC   )	r   r*   r+   r,   r-   r.   r0   r1   rN   zassert %(py15)sÚpy15rO   )
r
   r   rC   r7   r;   rH   Ú@py_assert12r8   rS   Ú@py_format16s
             r   Ú!test_zero_commission_equals_grossrZ   =   sC  € Ø$Ñ€HˆgØ�xÑ 8Ñ+¨cÑ1€EØ:=ÐVŒ;�x ¸#Ô>ÐVÄ&Ç-Á-ÐVÁ-ÐPUÓBVÐVÐ>ÐBVÑV×V×VÖVÐ>ÐBV×V×V×V×V×VÑVŒ;×V×VÓVŒ;×V×V×V×V×VÒV�x×V×VÓV�x×V×V×V×V×VÒV ×V×VÓV ×V×VÔV¸#×V×VÒVÐ>×V×V×V×V×VÐVÄ&×V×VÓVÄ&×V×VÔVÀ-×V×V×V×V×VÐVÐPU×V×VÓVÐPU×V×VÔVÐBV×V×V×V×V×V×V×VÐVr   c                  óè  — dd l } | j                  | j                  g d¢«      g d¢g d¢g d¢dœ«      }t        |«      }t	        |«      }d}||k(  }|söt        j                  d|fd	||f«      d
t        j                  «       v st        j                  t        «      rt        j                  t        «      nd
dt        j                  «       v st        j                  |«      rt        j                  |«      ndt        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}x}}|d   }|d   }	t        j                  }d}
 ||
«      }|	|k(  }|sÝt        j                  d|fd|	|f«      t        j                  |	«      dt        j                  «       v st        j                  t        «      rt        j                  t        «      ndt        j                  |«      t        j                  |
«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}	x}x}x}
}|d   }	t        j                  }d}d}t        ||«      } ||«      }|	|k(  }|�sNt        j                  d|fd|	|f«      t        j                  |	«      dt        j                  «       v st        j                  t        «      rt        j                  t        «      ndt        j                  |«      dt        j                  «       v st        j                  t        «      rt        j                  t        «      ndt        j                  |«      t        j                  |«      t        j                  |«      t        j                  |«      dœz  }dd|iz  }t        t        j                  |«      «      ‚d x}	x}x}x}x}x}}|d   }	|d   }|	|k  }|slt        j                  d|fd|	|f«      t        j                  |	«      t        j                  |«      d œz  }d!d"|iz  }t        t        j                  |«      «      ‚d x}	x}}y )#Nr   )z
2020-01-01z
2020-01-02z
2020-01-03)r'   g     @Z@r(   )TFF)FFT)ÚtimeÚcloseÚexecute_entryÚexecute_exitr   r   )z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)sÚlenÚtrades)r   r*   r   r-   zassert %(py8)sr.   Úgross_pnl_pctg      $@)zL%(py1)s == %(py9)s
{%(py9)s = %(py5)s
{%(py5)s = %(py3)s.approx
}(%(py7)s)
}r)   )r*   r   r   Úpy7r/   zassert %(py11)sr1   Úpnl_pctr'   r(   )zx%(py1)s == %(py14)s
{%(py14)s = %(py5)s
{%(py5)s = %(py3)s.approx
}(%(py12)s
{%(py12)s = %(py6)s(%(py8)s, %(py10)s)
})
}r   )r*   r   r   r-   r.   r0   r2   r3   zassert %(py16)sr4   r@   )z%(py1)s < %(py4)s)r*   r,   zassert %(py6)sr-   )ÚpandasÚ	DataFrameÚto_datetimer   r`   r   r   r   r   r   r   r   r   r)   r6   r   )ÚpdÚsignalsra   r    r;   Ú@py_assert4Ú@py_format7Ú@py_format9ÚtÚ@py_assert0Ú@py_assert6rP   Ú@py_format10rR   r8   rH   rI   r9   rK   r<   r7   rG   s                         r   Ú/test_extract_python_trades_stores_net_and_grossrq   C   s¨  € Ûð �l‰lØ—‘ÒIÓJÚ&Ú-Ú-ñ	ó €Gô # 7Ó+€FÜˆv‹;Ð˜!Ðˆ;˜!Ñ××Õˆ;˜!×××××ÑŒ3××ÓŒ3×××××Òˆv××Óˆv××Ôˆ;××Ò˜!××××××ÓØˆq‰	€Aàˆ_ÑÐ4¤§¡Ð4¨tÐ4¡¨tÓ!4Ð4ÐÐ!4Ñ4×4×4Õ4ÐÐ!4×4×4Ó4Ð×4×4×4×4×4Ð4¤×4×4Ó4¤×4×4Ô4 ×4×4Ò4¨t×4×4Ò4Ð!4×4×4×4×4×4×4×4ØˆY‰<ÐCœ6Ÿ=™=ÐC°UÐC¸EÐC¬°U¸EÓ)BÐC™=Ð)BÓCÐCˆ<ÐCÑC×C×CÖCˆ<ÐC×C×CÓCˆ<×C×C×C×C×CÐCœ6×C×CÓCœ6×C×CÔC˜=×C×C×C×C×CÐC¬×C×CÓC¬×C×CÔC°U×C×CÒC¸E×C×CÒCÐ)B×C×CÒCÐC×C×C×C×C×C×C×CÓCØˆY‰<Ð,˜!˜OÑ,Ð,ˆ<Ð,Ñ,×,×,Õ,ˆ<Ð,×,×,Ó,ˆ<×,×,Ò,Ð,×,×,×,×,×,×,Ô,r   )Ú__doc__Úbuiltinsr   Ú_pytest.assertion.rewriteÚ	assertionÚrewriter   ÚosÚsysr)   ÚpathÚabspathÚjoinÚdirnameÚ__file__ÚREPOÚinsertÚtools.compare_tv_tradesr   r   r   r   r$   r>   rL   rT   rZ   rq   r	   r   r   Ú<module>r�      sƒ   ðñ
÷ „ ƒ	Û 
ã à	‡w�w‡��r—w‘w—|‘| B§G¡G§O¡O°HÓ$=¸tÓDÓE€Ø ‡�‡���4Ô ç WÑ Wò4ò$ò

ò;ò2òWó-r   