
    mjD                    @   d dl mZ d dlZd dlmc mZ d dlm	Z	 d dl
Z
d dlmZ d dlmZmZmZmZmZmZ d dlmZ d dlmZ d dlmZmZ d d	lmZ d d
lmZmZ d Z d Z!d Z"d Z#d Z$d Z%d Z&d Z'd Z(d Z)d Z*d Z+d Z,d Z-d Z.d Z/d Z0d Z1d Z2d Z3d Z4d  Z5d! Z6d" Z7dS )#    )annotationsN)Decimal)ContainerConfirmRequest)annualize_returnattribution_bridge_v1price_fx_attribution_v1stable_input_fingerprintttwror_daily_v1xirr_v1)ensure_canonical_cash_accounts)confirm_account)!set_performance_cashflow_coverage$set_performance_scope_classification)connect_memory)apply_migrationsget_schema_versionc                    t          dt          d          fdt          d          fgg           } | j        }d}t          |          }||k    }|st          j        d|fd||f          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        |          t          j        |          d
z  }dd|iz  }t          t          j
        |                    d x}x}x}}d S N
2025-01-01d   
2025-12-31n   0.1==zK%(py2)s
{%(py2)s = %(py0)s.value
} == %(py8)s
{%(py8)s = %(py4)s(%(py6)s)
}resultr   py0py2py4py6py8assert %(py10)spy10r
   r   value
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanationr   @py_assert1@py_assert5@py_assert7@py_assert3@py_format9@py_format11s          Y/home/agent/.hermes/repos/FinanceManager/tests/unit/test_sprint14_performance_contract.py&test_ttwror_without_external_cashflowsr8      j   |WS\\:\7SV<<<XY[]^^F<)5)75>>)<>))))))))))<>))))))))))))6)))))6))))))<)))))))))))7)))))7))))))5))))>)))))))))))))))))))))))))))))))    c                    t          dt          d          fdt          d          fgdt          d          dfg          } | j        }d}t          |          }||k    }|st          j        d|fd	||f          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        |          t          j        |          dz  }dd|iz  }t          t          j
        |                    d x}x}x}}d S )Nr   r   
2025-01-02   2   external_depositr   r   r   r   r   r   r$   r%   r&   r0   s          r7   #test_ttwror_deposit_at_period_startr@      s   
	%gcll'CD
%7	89 F <)5)75>>)<>))))))))))<>))))))))))))6)))))6))))))<)))))))))))7)))))7))))))5))))>)))))))))))))))))))))))))))))))r:   c                    t          dt          d          fdt          d          fgdt          d          dfg          } | j        }d}t          |          }||k    }|st          j        d	|fd
||f          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        |          t          j        |          dz  }dd|iz  }t          t          j
        |                    d x}x}x}}| j        }|j        }d}||k    }|st          j        d	|fd||f          dt          j                    v st          j        |           rt          j        |           ndt          j        |          t          j        |          t          j        |          dz  }dd|iz  }	t          t          j
        |	                    d x}x}x}}d S )Nr   r   r<   r=   z2025-01-01T12:00:00Zr>   r?   r   r   r   r   r   r   r$   r%   completezK%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.quality
}.status
} == %(py7)sr   r    r!   py7assert %(py9)spy9)r
   r   r'   r(   r)   r*   r+   r,   r-   r.   r/   qualitystatus)
r   r1   r2   r3   r4   r5   r6   @py_assert6@py_format8@py_format10s
             r7   Ftest_ttwror_matches_timestamped_cashflow_to_its_calendar_day_valuationrM   '   s}   
	%gcll'CD
 '"++/A	BC F <)5)75>>)<>))))))))))<>))))))))))))6)))))6))))))<)))))))))))7)))))7))))))5))))>)))))))))))))))))))))))))))))>.> .J. J.......... J............6.....6......>.... ....J...............................r:   c                    t          dt          d          fdt          d          fdt          d          fgg           } | j        }d }||u }|st          j        d|fd||f          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}}| j        }|j        }d}||k    }|st          j        d|fd||f          d	t          j                    v st          j        |           rt          j        |           nd	t          j        |          t          j        |          t          j        |          dz  }dd|iz  }t          t          j
        |                    d x}x}x}}d S )Nz2025-01-01T00:00:00Zr   z2025-01-01T23:00:00Ze   r<   r   isz-%(py2)s
{%(py2)s = %(py0)s.value
} is %(py5)sr   r   r    py5assert %(py7)srE   )ambiguous_daily_valuationr   zL%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.quality
}.reasons
} == %(py7)srD   rF   rG   r
   r   r'   r(   r)   r*   r+   r,   r-   r.   r/   rH   reasons	r   r1   @py_assert4r4   @py_format6rK   rJ   r2   rL   s	            r7   8test_ttwror_rejects_ambiguous_duplicate_daily_valuationsr]   0   s*   #WS\\2#WS\\273<<(	

 	 F <4<4<466<4>C>!C%CC!%CCCCCCCCCCC!%CCCCCCCCCCCCC6CCCCC6CCCCCC>CCCC!CCCC%CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCr:   c                    t          dt          d          fdt          d          fgdt          d          dfg          } | j        }d}t          |          }||k    }|st          j        d|fd	||f          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        |          t          j        |          dz  }dd|iz  }t          t          j
        |                    d x}x}x}}d S )Nr   r   r<   Z   iexternal_withdrawalr   r   r   r   r   r   r$   r%   r&   r0   s          r7   $test_ttwror_withdrawal_at_period_endra   =   s   
	%gbkk'BC
&;	<= F <)5)75>>)<>))))))))))<>))))))))))))6)))))6))))))<)))))))))))7)))))7))))))5))))>)))))))))))))))))))))))))))))))r:   c                    t          dt          d          fdt          d          fdt          d          fgdt          d          dfg          } | j        }d	}t          |          }||k    }|st          j        d
|fd||f          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        |          t          j        |          dz  }dd|iz  }t          t          j
        |                    d x}x}x}}d S )Nr   r   
2025-02-01r   
2025-03-01   r>   r?   0.21r   r   r   r   r   r$   r%   r&   r0   s          r7   3test_ttwror_geometrically_links_multiple_subperiodsrg   E   s   73<<(73<<(73<<(	

 %7	89 F <*6*76??*<?**********<?************6*****6******<***********7*****7******6****?*******************************r:   c                    t          dt          d          fdt          d          fgdt          d          dfg          } | j        }d }||u }|st          j        d|fd	||f          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}}| j        }|j        }d}||k    }|st          j        d|fd||f          d
t          j                    v st          j        |           rt          j        |           nd
t          j        |          t          j        |          t          j        |          dz  }dd|iz  }t          t          j
        |                    d x}x}x}}d S )Nr   r   rd   re   rc   r>   r?   rP   rR   r   rS   rU   rE   )missing_cashflow_valuationr   rW   rD   rF   rG   rX   rZ   s	            r7   7test_ttwror_requires_stored_cashflow_boundary_valuationrj   Q   s(   
	%gcll'CD
%7	89 F <4<4<466<4>D>!D%DD!%DDDDDDDDDDD!%DDDDDDDDDDDDD6DDDDD6DDDDDD>DDDD!DDDD%DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDr:   c                    t          dt          d          fdt          d          fgdt          d          dfg          } | j        }d }||u }|st          j        d|fd||f          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}}| j        }|j        }d}||k    }|st          j        d|fd||f          d	t          j                    v st          j        |           rt          j        |           nd	t          j        |          t          j        |          t          j        |          dz  }dd|iz  }t          t          j
        |                    d x}x}x}}d S )Nr   r   rc   r   r?   rP   rR   r   rS   rU   rE   )invalid_cashflow_signr   rW   rD   rF   rG   rX   rZ   s	            r7   8test_ttwror_rejects_inconsistent_external_cashflow_signsrn   Z   s(   
	%gcll'CD
&8	9: F <4<4<466<4>?>!?%??!%???????????!%?????????????6?????6??????>????!????%????????????????????????????????r:   c                    t          dt          d          fdt          d          fgdt          d          dfg          } | j        }d }||u }|st          j        d|fd||f          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}}| j        }|j        }d}||k    }|st          j        d|fd||f          d	t          j                    v st          j        |           rt          j        |           nd	t          j        |          t          j        |          t          j        |          dz  }dd|iz  }t          t          j
        |                    d x}x}x}}d S )Nr   r   rc   r   
   r?   rP   rR   r   rS   rU   rE   )!cashflow_outside_return_subperiodr   rW   rD   rF   rG   rX   rZ   s	            r7   9test_ttwror_rejects_cashflow_that_has_no_return_subperiodrr   c   s(   
	%gcll'CD
%7	89 F <4<4<466<4>K>!K%KK!%KKKKKKKKKKK!%KKKKKKKKKKKKK6KKKKK6KKKKKK>KKKK!KKKK%KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKr:   c                    t          dt          d          fdt          d          fgg           } | j        }d}t          |          }||k    }|st          j        d|fd||f          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        |          t          j        |          d
z  }dd|iz  }t          t          j
        |                    d x}x}x}}d S r   r&   r0   s          r7   =test_ttwror_never_treats_buy_sell_dividend_or_fee_as_externalrt   l   r9   r:   c                    d} t          |           }d}t          ||          }d}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        t                     rt          j        t                     ndt          j        |           t          j        |          t          j        |          t          j        |          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}x}x}}d} t          |           }d}t          ||          }d }	||	u }|s5t          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        t                     rt          j        t                     ndt          j        |           t          j        |          t          j        |          t          j        |          t          j        |	          dz  }
dd|
iz  }t          t          j	        |                    d x} x}x}x}x}}	d S )Nrf   i  z0.100000000000r   )zy%(py9)s
{%(py9)s = %(py0)s(%(py5)s
{%(py5)s = %(py1)s(%(py3)s)
}, %(py7)s)
} == %(py15)s
{%(py15)s = %(py11)s(%(py13)s)
}r   r   	r   py1py3rT   rE   rG   py11py13py15zassert %(py17)spy17r   im  rP   )zX%(py9)s
{%(py9)s = %(py0)s(%(py5)s
{%(py5)s = %(py1)s(%(py3)s)
}, %(py7)s)
} is %(py12)sr   rw   rx   rT   rE   rG   py12assert %(py14)spy14)
r   r   r(   r)   r*   r+   r,   r-   r.   r/   )@py_assert2r[   rJ   @py_assert8@py_assert12@py_assert14@py_assert10@py_format16@py_format18@py_assert11@py_format13@py_format15s               r7   2test_ttwror_annualized_is_separate_from_cumulativer   q   sU   $*NGFOONSNOS11N=MNW=M5N5NN15NNNNNNNNNNN15NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNGNNNNNGNNNNNNFNNNNONNNNSNNNN1NNNNNNNNNNNWNNNNNWNNNNNN=MNNNN5NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN$)8GENN8C8NC008D80D88888888880D888888888888888888888888888888G88888G888888E8888N8888C888808888D88888888888888888888888888888888888r:   c                    t          dt          d          fdt          d          fdt          d          fdt          d          fd	t          d          fg          } | j        }d }||u}|st          j        d
|fd||f          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}}| j        }d}t          |          }||z
  }	t          |	          }
d}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t          j        |          dt          j                    v st          j        t                    rt          j        t                    ndt          j        |          t          j        |          t          j        |
          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}	x}
x}x}}d S )Nz
2008-01-01iz
2008-03-01i
  z
2008-10-30i  z
2009-02-15i  z
2009-04-01is notz1%(py2)s
{%(py2)s = %(py0)s.value
} is not %(py5)sr   rS   rU   rE   z0.373362535z
0.00000001)<)z%(py11)s
{%(py11)s = %(py0)s((%(py3)s
{%(py3)s = %(py1)s.value
} - %(py8)s
{%(py8)s = %(py4)s(%(py6)s)
}))
} < %(py17)s
{%(py17)s = %(py13)s(%(py15)s)
}absr   )
r   rw   rx   r!   r"   r#   ry   rz   r{   r|   zassert %(py19)spy19)r   r   r'   r(   r)   r*   r+   r,   r-   r.   r/   r   )r   r1   r[   r4   r\   rK   r   r2   r3   @py_assert9r   r   @py_assert16r   r   @py_format20s                   r7   4test_xirr_matches_documented_excel_reference_exampler   v   sa   76??+74==)74==)74==)74==)	
 F <#t#<t##########<t############6#####6######<####t###########################|MmMgm44M|44M3455MM8M8MM58MMMMMMMMMMM58MMMMMMMMMMMMM3MMMMM3MMMMMMMMMMMMMvMMMMMvMMMMMM|MMMMMMMMMMMgMMMMMgMMMMMMmMMMM4MMMM5MMMMMMMMMMMMMMMMMMMMMMMMMM8MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMr:   c                    t          dt          d          fdt          d          fdt          d          fg          } | j        }d }||u}|st          j        d|fd||f          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}}| j        }|j        }d}||k    }|st          j        d|fd||f          d	t          j                    v st          j        |           rt          j        |           nd	t          j        |          t          j        |          t          j        |          dz  }dd|iz  }t          t          j
        |                    d x}x}x}}d S )Nz
2024-01-01iz
2024-02-17iz
2025-04-03i  r   r   	irregularrS   rU   rE   rB   r   rC   rD   rF   rG   )r   r   r'   r(   r)   r*   r+   r,   r-   r.   r/   rH   rI   )	r   r1   r[   r4   r\   rK   rJ   r2   rL   s	            r7   &test_xirr_uses_irregular_calendar_daysr      s$   75>>*74==)74==)	
 I ?&$&?$&&&&&&&&&&?$&&&&&&&&&&&&9&&&&&9&&&&&&?&&&&$&&&&&&&&&&&&&&&&&&&&&&&&&&&1#1z1#z1111111111#z11111111111191111191111111111#1111z1111111111111111111111111111111r:   c                    t          dt          d          fdt          d          fg          } | j        }d }||u }|st          j        d|fd||f          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}}| j        }|j        }d}||k    }|st          j        d|fd||f          dt          j                    v st          j        |           rt          j        |           ndt          j        |          t          j        |          t          j        |          dz  }dd|iz  }t          t          j
        |                    d x}x}x}}d S )Nr   
2026-01-01rl   rP   rR   r   rS   rU   rE   )insufficient_cashflowsr   rW   rD   rF   rG   r   r   r'   r(   r)   r*   r+   r,   r-   r.   r/   rH   rY   rZ   s	            r7   ,test_xirr_without_sign_change_is_unavailabler      s   |WT]]3lGCLL5QRSSF<4<4<466<4>@>!@%@@!%@@@@@@@@@@@!%@@@@@@@@@@@@@6@@@@@6@@@@@@>@@@@!@@@@%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@r:   c                    t          dt          d          fdt          d          fdt          d          fg          } | j        }d }||u }|st          j        d|fd||f          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}}| j        }|j        }d}||k    }|st          j        d|fd||f          d	t          j                    v st          j        |           rt          j        |           nd	t          j        |          t          j        |          t          j        |          dz  }dd|iz  }t          t          j
        |                    d x}x}x}}d S )Nr   r   z
2025-06-01   r   i`rP   rR   r   rS   rU   rE   )mwr_multiple_solutionsr   rW   rD   rF   rG   r   rZ   s	            r7   4test_xirr_with_ambiguous_sign_pattern_is_unavailabler      s%   
	&ws||(D|U\]aUbUbFcd F <4<4<466<4>@>!@%@@!%@@@@@@@@@@@!%@@@@@@@@@@@@@6@@@@@6@@@@@@>@@@@!@@@@%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@r:   c                     t          dt          d          t          d          fidt          d          t          d          fi          } t          d          t          d          f}| |k    }|st          j        d|fd	| |f          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}}d S )Npositionr   z0.9r   z1.0z9.0z11.0r   )z%(py0)s == %(py3)sr   )r   rx   assert %(py5)srT   )
r   r   r(   r)   r*   r+   r,   r-   r.   r/   )r   r   r1   @py_format4r\   s        r7   =test_price_fx_interaction_is_deterministically_assigned_to_fxr      s!   $	gcllGENN34	gcllGENN34 F enngfoo666666666666666666666666666666666666666666666666666666666666666666666r:   c                 	   t          t          d          t          d          t          d          t          d          t          d          t          d          t          d          t          d                    } | d	         }d
}t          |          }||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        |          dz  }dd|iz  }t          t          j	        |                    d x}x}x}}| d         }d}t          |          }||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        |          dz  }dd|iz  }t          t          j	        |                    d x}x}x}}| d         }d}| }t          |          }||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        |          dz  }dd|iz  }	t          t          j	        |	                    d x}x}x}x}}| d         }d}| }t          |          }||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        |          dz  }dd|iz  }	t          t          j	        |	                    d 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}}
d S )Nr   x   r               opening_valueclosing_valuenet_external_cashflowsmarket_pricefxdividends_and_interestfeestaxesinvestment_result   r   z0%(py1)s == %(py7)s
{%(py7)s = %(py3)s(%(py5)s)
}r   rw   rx   rT   rE   rF   rG   unattributed_residualr   )z1%(py1)s == %(py8)s
{%(py8)s = %(py3)s(-%(py5)s)
})rw   rx   rT   r#   r$   r%   r   rI   rB   z%(py1)s == %(py4)srw   r!   assert %(py6)sr"   
r   r   r(   r)   r-   r*   r+   r,   r.   r/   )bridge@py_assert0r[   rJ   r   rK   rL   r3   r5   r6   r4   @py_format5@py_format7s                r7   8test_attribution_value_bridge_reconciles_within_one_centr      s+   "cllcll&qzzR[[1::&qzzQZZajj	 	 	F %&5"5'"++5&+5555555555&+55555&55555555555'55555'555555"5555+55555555555555555555555555555)*8a8gajj8*j8888888888*j88888*88888888888g88888g888888a8888j88888888888888888888888888888&>(a(aR(WR[[(>[((((((((((>[(((((>(((((((((((W(((((W((((((a(((([((((((((((((((((((((((((((((((('?)q)qb)gbkk)?k))))))))))?k)))))?)))))))))))g)))))g))))))q))))k)))))))))))))))))))))))))))))))()z)z))))))))))z)))))))))z)))))))))))))))))))))))))))))r:   c                    t                      } t          |            |                     d           |                     d           |                     d                                          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}}|                     d
                                          d         }|                     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         }||k    }|st	          j        d|fd||f          t	          j        |          dt          j                    v st	          j        |          rt	          j        |          nddz  }dd|iz  }t          t	          j        |                    d x}}|                     d                                          d         }||k    }|st	          j        d|fd||f          t	          j        |          dt          j                    v st	          j        |          rt	          j        |          nddz  }dd|iz  }t          t	          j        |                    d x}}d S )NzINSERT INTO platforms(platform_id,name,platform_type,default_currency,created_at) VALUES ('p','Bank','bank','CHF','2026-01-01T00:00:00Z')zINSERT INTO accounts(account_id,platform_id,account_name,account_type,currency,created_at) VALUES ('a','p','New household','bank','CHF','2026-01-01T00:00:00Z')>SELECT performance_included FROM accounts WHERE account_id='a'r   r   r   r   r   r"   zSELECT COUNT(*) FROM audit_logz6SELECT COUNT(*) FROM performance_scope_classifications1   z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)sr   connr   rw   rx   r"   assert %(py8)sr#   z%(py1)s == %(py3)saudit_beforerw   rx   r   rT   classification_before)r   r   executefetchoner(   r)   r-   r.   r/   r   r*   r+   r,   )r   r   r4   r   r   r   r   r   r2   r[   r5   r   r\   s                r7   Ktest_schema_46_defaults_new_accounts_out_of_performance_and_repeats_as_noopr      s5   DTLL 	T   	LL 	j   	UVV__aabcdd	      d    	e                            << @AAJJLLQOL LL@ hjj Td##)r)#r))))))))))#r))))))))))))))))))))))))))))))d)))))d))))))#))))r)))))))))))))))))))))))))))<<899BBDDQGWG<WWWWWWWWWWG<WWWWWGWWWWWWWWWWW<WWWWW<WWWWWWWWWWWWWWWWWWWWWWWWWWWMNNWWYYZ[\\ 	!      \     	]        !    !                          r:   c                    t          t          d          t          d          t          d          d d t          d          t          d          t          d                    } | d         }d}t          |          }||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        |          dz  }dd|iz  }t          t          j	        |                    d 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}}d S )Nr   r   r      r   r   r      r   r   r   r   rF   rG   rI   partialr   r   r   r"   r   )
r   r   r[   rJ   r   rK   rL   r4   r   r   s
             r7   Btest_attribution_unexplained_remainder_remains_visible_and_partialr      s   "cllcll&qzz&qzzQZZajj	 	 	F )*9b9gbkk9*k9999999999*k99999*99999999999g99999g999999b9999k99999999999999999999999999999((y(y((((((((((y(((((((((y(((((((((((((((((((((((((((((r:   c                    t          t          d          t          d          t          d          d d t          d          t          d          t          d                    } | d         }d }||u }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }d	d
|iz  }t          t          j        |                    d x}x}}| d         }d }||u }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }d	d
|iz  }t          t          j        |                    d x}x}}| d         }d}t          |          }||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        |          dz  }dd|iz  }	t          t          j        |	                    d x}x}x}}d S )Nr   r   r   r   r   rP   )z%(py1)s is %(py4)sr   r   r"   r   r   rp   r   r   r   r   rF   rG   )
r   r   r(   r)   r-   r.   r/   r*   r+   r,   )
r   r   r4   r   r   r   r[   rJ   rK   rL   s
             r7   ?test_total_value_account_does_not_invent_price_or_fx_componentsr      s   "cllcll&qzz&qzzQZZajj	 	 	F .!)T)!T))))))))))!T)))))!))))T)))))))))))))))))))))))))))$<4<4<4<4)*9b9gbkk9*k9999999999*k99999*99999999999g99999g999999b9999k9999999999999999999999999999999r:   c            	     ^   dddgd} t          |           }t          |           }||k    }|sxt          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        |          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        |          d	z  }d
d|iz  }t          t          j        |                    d x}x}}d S )Nz2026-07-27T12:00:00Z100110)cutoffvaluesr   )zN%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py8)s
{%(py8)s = %(py5)s(%(py6)s)
}r	   payload)r   rw   rx   rT   r"   r#   r$   r%   )	r	   r(   r)   r*   r+   r,   r-   r.   r/   )r   r   r3   r[   r5   r6   s         r7   7test_identical_cutoff_payload_has_identical_fingerprintr      s   /E5>JJG#G,,Q0H0Q0QQ,0QQQQQQQQQQQ,0QQQQQQQQQQQQQ#QQQQQ#QQQQQQQQQQQQQGQQQQQGQQQQQQ,QQQQQQQQQQQ0HQQQQQ0HQQQQQQQQQQQQQQQQQQQQQQQQ0QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQr:   c            
        t                      } t          |            |                     d           |                     d           |                     d                                          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}}t          |                     d
                    }t          |            | j        }d
} ||          }t          |          }	|	|k    }
|
sVt	          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        |          t	          j        |          t	          j        |	          dt          j                    v st	          j        |          rt	          j        |          nddz  }dd|iz  }t          t	          j        |                    d x}x}x}x}	}
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         }d}||k    }|slt	          j        d|fd||f          t	          j        |          t	          j        |          dz  }dd	|iz  }t          t	          j        |                    d x}x}}d S )NzhINSERT INTO platforms(platform_id,name,platform_type,created_at) VALUES ('p','Bank','bank','2026-01-01')zINSERT INTO accounts(account_id,platform_id,account_name,account_type,created_at) VALUES ('a','p','Household','cash','2026-01-01')r   r   r   r   r   r   r"   z;SELECT version,name FROM schema_migrations ORDER BY version)zl%(py9)s
{%(py9)s = %(py0)s(%(py7)s
{%(py7)s = %(py3)s
{%(py3)s = %(py1)s.execute
}(%(py5)s)
})
} == %(py11)slistr   before)r   rw   rx   rT   rE   rG   ry   zassert %(py13)srz   r   r   r   r   r   r#   zPRAGMA integrity_checkok)r   r   r   r   r(   r)   r-   r.   r/   r   r*   r+   r,   r   )r   r   r4   r   r   r   r   r[   rJ   r   r   @py_format12@py_format14r2   r5   s                  r7   Vtest_performance_scope_migration_defaults_new_accounts_to_excluded_and_repeats_as_noopr      s   DTLLr   	LL 	M   	UVV__aabcdd	      d    	e                            $,,\]]^^FT\W\WXXXYYY]cc      Y]c         	    	                      X   Y   	Z        ^d    ^d                               d##)r)#r))))))))))#r))))))))))))))))))))))))))))))d)))))d))))))#))))r)))))))))))))))))))))))))))<<011::<<Q?G4G?4GGGGGGGGGG?4GGGGG?GGGG4GGGGGGGGGGGGGGGGGGGGGGGGGGGGGr:   c                 	   t                      } t          |            t          | t          dddddd                    }|                     d|j        f                                          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}}|                     d|j        f                                          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}}t          | d          }|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}}|                     d                                          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}}|                     d                                          d	         }t          | d           |                     d                                          d	         }	|	|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 }
t!          j        t$          d          5  |                     d|                     d                                          d	         f           d d d            d S # 1 swxY w Y   d S )NzOrdinary household accountbankzSynthetic BankCHFtestT)account_nameaccount_typeplatform_namecurrencynoteconfirmz<SELECT performance_included FROM accounts WHERE account_id=?r   r   r   r   r   r"   zISELECT COUNT(*) FROM performance_scope_classifications WHERE account_id=?)
created_bycreated   zSSELECT COUNT(*) FROM accounts WHERE account_type='cash' AND performance_included<>0zeSELECT group_concat(account_id || ':' || performance_included, ',') FROM accounts ORDER BY account_id)z%(py0)s == %(py2)safterr   )r   r    zassert %(py4)sr!   z.new accounts default outside performance scopematchzINSERT INTO accounts(account_id,platform_id,account_name,account_type,currency,
                 performance_included,created_at)
               VALUES('bypass',?,'Bypass','brokerage','CHF',1,'2026-01-01')z)SELECT platform_id FROM platforms LIMIT 1)r   r   r   r   r   	entity_idr   r(   r)   r-   r.   r/   r   r*   r+   r,   pytestraises	Exception)r   manualr   r4   r   r   r   ensuredr   r   r1   @py_format3s               r7   Etest_new_account_paths_are_excluded_until_audited_role_classificationr     s   DT5*	
 	
 	

 
F <<F		  hjj                      q                          <<S		  hjj                      q                         
 -TfEEEG9""""""""""""""""""""""""""""""""""""""""""""""""<<] hjj                q                         \\o hjjF #4F;;;;LLo hjjE F?5F55FF	y(X	Y	Y	Y 
 
O \\EFFOOQQRSTV		
 	
 	

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
s   1ARRRc                 #   t                      } t          |            |                     d           dD ]}|                     d||f           t          j        t
          d          5  t          | dddd	d
d           d d d            n# 1 swxY w Y   d}d}d}d	}d}d}t          | ||||||          }|s2d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        |          t          j        |          t          j        |          t          j        |          t          j        |          t          j        |          d	z  }	t          t          j        |	                    d x}x}x}x}x}x}}|                     d                                          d         }
d}d}d}d	}d}d}t          | ||||||          }| }|s2d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        |          t          j        |          t          j        |          t          j        |          t          j        |          t          j        |          d	z  }t          t          j        |                    d x}x}x}x}x}x}x}}|                     d                                          d         }||
k    }|st          j        d|fd||
f          t          j        |          dt          j                    v st          j
        |
          rt          j        |
          nddz  }dd|iz  }t          t          j        |                    d x}}d}d}d }d	}d!}d"}t          | ||||||          }|s2d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        |          t          j        |          t          j        |          t          j        |          t          j        |          t          j        |          d	z  }	t          t          j        |	                    d x}x}x}x}x}x}}d}d}d}d	}d#}d$}t          | ||||||          }|s2d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        |          t          j        |          t          j        |          t          j        |          t          j        |          t          j        |          d	z  }	t          t          j        |	                    d x}x}x}x}x}x}}|                     d                                          d         }d%}|
|z   }||k    }|st          j        d|fd&||f          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}}d*D ]\  }}d}d	}d+}d,|d-k    rd.nd/ d0}t          | ||||||          }|sd1d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d2t          j                    v st          j
        |          rt          j        |          nd2t          j        |          d3t          j                    v st          j
        |          rt          j        |          nd3t          j        |          t          j        |          t          j        |          t          j        |          d4	z  }t          t          j        |                    d x}x}x}x}}| j        }d5} ||          }t!          |          }d6d6d6d7}||k    }|s+t          j        d|fd8||f          d9t          j                    v st          j
        t                     rt          j        t                     nd9dt          j                    v st          j
        |           rt          j        |           ndt          j        |          t          j        |          t          j        |          t          j        |          t          j        |          d:z  }d;d<|iz  }t          t          j        |                    d x}x}x}x}x}}t          j        t
          d=          5  t          | dddd	d
>           d d d            n# 1 swxY w Y   |                     d?           |                     d@           t          j        t"          dA          5  |                     dB           d d d            n# 1 swxY w Y   t          j        t"          dC          5  |                     dD           d d d            n# 1 swxY w Y   t          j        t"          dE          5  |                     dF           d d d            n# 1 swxY w Y   t          j        t"          dG          5  |                     dH           d d d            n# 1 swxY w Y   |                     dI                                          d         }d6}||k    }|slt          j        d|fdJ||f          t          j        |          t          j        |          dKz  }dLdM|iz  }t          t          j        |                    d x}x}}d}dN}dO}dP}dQ}dR}dS}t%          | |||||||T          }|sEdUdVt          j                    v st          j
        t$                    rt          j        t$                    ndVdt          j                    v st          j
        |           rt          j        |           ndt          j        |          t          j        |          t          j        |          t          j        |          t          j        |          t          j        |          t          j        |          t          j        |          dW
z  }t          t          j        |                    d x}x}x}x}x}x}x}}|                     dX                                          d         }d}dN}dO}dP}dQ}dY}dZ}t%          | |||||||T          }| }|sEd[dVt          j                    v st          j
        t$                    rt          j        t$                    ndVdt          j                    v st          j
        |           rt          j        |           ndt          j        |          t          j        |          t          j        |          t          j        |          t          j        |          t          j        |          t          j        |          t          j        |          dW
z  }t          t          j        |                    d x}x}x}x}x}x}x}x}}|                     dX                                          d         }||k    }|st          j        d|fd||f          t          j        |          d\t          j                    v st          j
        |          rt          j        |          nd\dz  }dd|iz  }t          t          j        |                    d x}}t          j        t"          dE          5  |                     d]           d d d            d S # 1 swxY w Y   d S )^NznINSERT INTO platforms(platform_id,name,platform_type,created_at) VALUES('p','Synthetic','broker','2026-01-01'))pftwcryptozINSERT INTO accounts(account_id,platform_id,account_name,account_type,currency,
                 performance_included,created_at) VALUES(?, 'p', ?, 'brokerage', 'CHF', 0, '2026-01-01')zapproved investment roler   r  Tordinary_bank_accountr   z	must failz2026-01-01T00:00:00Z)
account_idincludedclassification_rolesourcer   classified_atpostfinance_etrading_depotapprovedz2026-01-01T00:00:01Zzassert %(py15)s
{%(py15)s = %(py0)s(%(py1)s, account_id=%(py3)s, included=%(py5)s, classification_role=%(py7)s, source=%(py9)s, note=%(py11)s, classified_at=%(py13)s)
}r   r   rv   zfSELECT COUNT(*) FROM audit_log WHERE entity_type='performance_scope_classification' AND entity_id='pf'r   repeatz2026-01-01T00:00:02Zzassert not %(py15)s
{%(py15)s = %(py0)s(%(py1)s, account_id=%(py3)s, included=%(py5)s, classification_role=%(py7)s, source=%(py9)s, note=%(py11)s, classified_at=%(py13)s)
}r   r   audit_countr   r   rT   F#not_in_investment_performance_scopeexcludedz2026-01-01T00:00:03Zzincluded againz2026-01-01T00:00:04Zr   )z%(py1)s == (%(py3)s + %(py5)s))rw   rx   rT   r   r#   ))r   canonical_truewealth_total_value)r  crypto_portfoliozapproved rolez2026-01-01T00:00:0r     r   Zzassert %(py13)s
{%(py13)s = %(py0)s(%(py1)s, account_id=%(py2)s, included=%(py4)s, classification_role=%(py5)s, source=%(py7)s, note=%(py9)s, classified_at=%(py11)s)
}r  role)	r   rw   r    r!   rT   rE   rG   ry   rz   zHSELECT account_id,performance_included FROM accounts ORDER BY account_idr   )r  r  r  )zl%(py9)s
{%(py9)s = %(py0)s(%(py7)s
{%(py7)s = %(py3)s
{%(py3)s = %(py1)s.execute
}(%(py5)s)
})
} == %(py12)sdictr}   r   r   zapproved non-investment role)r  r  r  r	  r   zINSERT INTO accounts(account_id,platform_id,account_name,account_type,currency,
             performance_included,created_at) VALUES('bogus','p','Bogus','brokerage','CHF',0,'2026-01-01')a  INSERT INTO audit_log(audit_id,timestamp,source,action,entity_type,entity_id,
             old_values_json,new_values_json,user_text_note,created_by,created_at)
           VALUES('bogus-audit','2026-01-01','test','other','other','bogus','{}',
             '{"performance_included":1,"classification_role":"postfinance_etrading_depot"}',
             'invalid audit','test','2026-01-01')zinvalid or unauditeda"  INSERT INTO performance_scope_classifications(
                 account_id,included,classification_role,decision_version,audit_id,classified_at)
               VALUES('bogus',1,'postfinance_etrading_depot','investment_performance_scope_v1',
                      'bogus-audit','2026-01-01')znew matching auditz]UPDATE performance_scope_classifications SET classified_at='2026-02-01' WHERE account_id='pf'zcannot be deletedzCDELETE FROM performance_scope_classifications WHERE account_id='pf'z&flag must match audited classificationz@UPDATE accounts SET performance_included=0 WHERE account_id='pf'z?SELECT performance_included FROM accounts WHERE account_id='pf'r   r   r   r"   r   r   rB   synthetic_ledger_reconciliationz(Complete source-to-ledger reconciliationz2026-01-02T00:00:00Z)r  coverage_fromcoverage_torI   r	  r   recorded_atzassert %(py17)s
{%(py17)s = %(py0)s(%(py1)s, account_id=%(py3)s, coverage_from=%(py5)s, coverage_to=%(py7)s, status=%(py9)s, source=%(py11)s, note=%(py13)s, recorded_at=%(py15)s)
}r   )
r   rw   rx   rT   rE   rG   ry   rz   r{   r|   zPSELECT COUNT(*) FROM audit_log WHERE entity_type='performance_cashflow_coverage'zIdempotent repeatz2026-01-03T00:00:00Zzassert not %(py17)s
{%(py17)s = %(py0)s(%(py1)s, account_id=%(py3)s, coverage_from=%(py5)s, coverage_to=%(py7)s, status=%(py9)s, source=%(py11)s, note=%(py13)s, recorded_at=%(py15)s)
}coverage_auditsz?DELETE FROM performance_cashflow_coverage WHERE account_id='pf')r   r   r   r   r   
ValueErrorr   r*   r+   r(   r,   r-   r.   r/   r   r)   r  r   r   )r   r  r   r[   rJ   r   r   r   r   r   r  r   @py_format17r   r   r\   r   r5   r  r4   r   r   r   r   r   r   r  @py_assert18@py_format19s                                r7   Ntest_scope_classification_is_role_gated_idempotent_and_every_change_is_auditedr   ;  s'   DTLLx   - 
 

l$	
 	
 	
 	

 
z)C	D	D	D 	
 	
, 70	
 	
 	
 	
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
   9	
   -/8,             0     0           	    	          	 9	         -                              ,,p hjjK
   9	
   -38,                4     4           	    	          	 9	         -                                <<p hjj # "# # # # #"# # # # "# # # #" # # # #"# # # # #
"{# # # #"{# # # # # # # # # # # # # # # #"# # # # # # # # # #   B	
   -/A,             0     0           	    	          	 B	         -                                9	
   -/8,             0     0           	    	          	 9	         -                              <<p hjj '%&'"Q' &' ' ' ' '&' ' ' ' &' ' ' '& ' ' ' ' &' ' ' ' '&{' ' ' '&{' ' ' ' '&Q' ' ' ' ' ' ' ' ' ' ' ' ' '&' ' ' ' ' ' ' ' ' ' ' ' ' ' 
 

D 	

 	
 !	
 QJ$4F4FqqAPPP	
3! $ P
 
 
 	
 
 	
 	
 	
 	
 
	
 	
 	
 	
 	
 4 	
 	
 	
 	
 
 4 	
 	
 	
 	
 	
 	
 
	
 	
 	
 	
 	
 	
 	
 	
 	
 
 	
 	
 	
 	
 	
 	
 
	
 	
 	
 	
 	
 "	
 	
 	
 	
 
 "	
 	
 	
 	
 	
 
 	
 	
 	
 	
 
	
 	
 	
 	
 	
	 !%		
 	
 	
 	
 
	 !%		
 	
 	
 	
 	
 
 	
 	
 	
 
 !	
 	
 	
 
 Q	
 	
 	
 

 	
 	
 	
 	
 	
 	
 	
 	
	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	
 	)_)_``)4`  )Qa	(	() 	() ) ) ) )() ) ) ) 	() ) ) ) )"() ) ) ) )(  ) ) ) )(  ) ) ) ) ) )"() ) ) ) )( 	) ) ) )( 	) ) ) ) )( 	) ) )( `) ) )( 	a) ) )( ) ) )(	() ) ) ) ) ) ) ) ) ) ) ) ) )() ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) 
z)G	H	H	H 
 
, 7	
 	
 	
 	

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 	LL	n   	LL	5   
y(>	?	?	? 
 
5	
 	
 	

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
y(<	=	=	= 
 
k	
 	
 	

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
y(;	<	<	< \ \Z[[[\ \ \ \ \ \ \ \ \ \ \ \ \ \ \	y(P	Q	Q	Q Y YWXXXY Y Y Y Y Y Y Y Y Y Y Y Y Y Y<<I hjj                q                         	 #	 !		
 	 1	 8	 +	," 07*	 	 	 	 	 	 	 	 		 	 	 	 	 - 	 	 	 	 - 	 	 	 	 	 		 	 	 	 	 		 	 	 	 		 	 	 	 	 	 	 	 #	 	 	 !		 	 		 	 	 	 1	 	 	 8	 	 	 +	 	 		 	 	 	 	 	 	 	 		 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 llZ hjjO
 	 #	 !		
 	 1	 !	 +	0" 0 *	 	 	 	 	 	 	 	 	 	 	 		 	 	 	 	 1 	 	 	 	 1 	 	 	 	 	 		 	 	 	 	 		 	 	 	 		 	 	 	 	 	 	 	 #	 	 	 !		 	 		 	 	 	 1	 	 	 !	 	 	 +	 	 		 	 	 	 	 	 	 	 		 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 <<Z hjj ' &' ' ' ' '&' ' ' ' &' ' ' '& ' ' ' ' &' ' ' ' '&' ' ' '&' ' ' ' ' ' ' ' ' ' ' ' ' ' ' '&' ' ' ' ' ' ' ' ' ' 
y(;	<	<	< X XVWWWX X X X X X X X X X X X X X X X X Xs   +BBB*nnno>>pp$qq
q
,rrr4sssF!AGGAGGAG)8
__future__r   builtinsr*   _pytest.assertion.rewrite	assertionrewriter(   decimalr   r   $jarvis_finance.api.schemas.positionsr   !jarvis_finance.ledger.performancer   r   r   r	   r
   r   $jarvis_finance.services.cash_servicer   ,jarvis_finance.services.manual_entry_servicer   )jarvis_finance.services.performance_scoper   r   jarvis_finance.storage.databaser   !jarvis_finance.storage.migrationsr   r   r8   r@   rM   r]   ra   rg   rj   rn   rr   rt   r   r   r   r   r   r   r   r   r   r   r   r   r   r    r:   r7   <module>r/     s   " " " " " "                      H H H H H H                P O O O O O H H H H H H        ; : : : : : R R R R R R R R* * *
* * */ / /
D 
D 
D* * *	+ 	+ 	+E E E@ @ @L L L* * *
9 9 9
N N N	2 	2 	2A A AA A A7 7 7* * *$  4) ) ): : : R R R
H H H,+
 +
 +
\YX YX YX YX YXr:   