
    ;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        K/Users/jameslopez/projects/TradingBot25/tests/test_compare_tv_commission.py_validate_strategy_modelr      s3    AH%I!d(#Hy I-33    c                  p   d} t         | k(  }|st        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{Gzt?==)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(  }|st        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'8W- 	
 	
$Xw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  }|st        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   $Hgx8+c1E
h
(C;333CK:FMM:%: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{Gz?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    
eU
#C--111D1-D113111113111111131113111111&111&111-111111D111111111111r   c                  j   d\  } }|| z
  | z  dz  }d}t        | ||      }t        j                  } ||      }||k(  }|st        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   $Hgx8+c1E:=V;x#>V&--V-PUBVV>BVVVVV>BVVVVVVV;VVV;VVVVVVxVVVx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VPUVVVPUVVVBV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(  }|st        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(  }|st        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    llIJ&--	 G #7+Fv;!;!;!33vv;!q	A_44t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4t444!44444444Y<C6==CUCECUE)BC=)BCC<CCCCC<CCCC<CCCCCC6CCC6CCC=CCCCCCCCCCCCUCCCE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   
  	 
 	wwrww||BGGOOH$=tDE 4  W W4$

;2W-r   