
    \Xj                       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mZmZmZmZmZ d dlmZ d dlmZmZ d dlmZmZmZmZ d dlmZ d d	lmZ d
 Z d4d5dZ!d6dZ"d7dZ#d7dZ$d7dZ%d7dZ&d7dZ'd7dZ(d7dZ)d7dZ*d7dZ+d7dZ,d7dZ-d7dZ. G d  d!          Z/d7d"Z0d7d#Z1d7d$Z2d7d%Z3d7d&Z4d7d'Z5d7d(Z6d7d)Z7d7d*Z8d7d+Z9d7d,Z:d7d-Z;d7d.Z<d7d/Z=d7d0Z>d7d1Z?d7d2Z@d7d3ZAdS )8    )annotationsN)Decimal)add_equity_initial_snapshotadd_equity_transaction add_manual_position_from_catalogcreate_manual_catalog_entryget_equity_management_optionssearch_instrument_candidates)calculate_positions)CatalogSearchResultinstrument_provider_statuses)FmpEquityPriceProviderMockEquityPriceProviderrefresh_market_pricesstore_market_price)connect_memory)apply_migrationsc                 @    t                      } t          |            | S N)r   r   )conns    I/home/agent/.hermes/repos/FinanceManager/tests/unit/test_equity_manage.py
setup_connr      s     DTK    Synthetic PostFinanceplatform_namestrreturnc                :   d|                                                     dd           }d|                                                     dd           }|                     d||f           |                     d||f           |                                  |S )Nz	platform- -zaccount-zINSERT INTO platforms(platform_id, name, platform_type, country, default_currency, created_at) VALUES (?, ?, 'broker', 'CH', 'CHF', '2026-01-01')zINSERT INTO accounts(account_id, platform_id, account_name, account_type, currency, created_at) VALUES (?, ?, 'Synthetic Depot', 'brokerage', 'CHF', '2026-01-01'))lowerreplaceexecutecommit)r   r   platform_id
account_ids       r   seed_accountr'      s    Gm1133;;CEEGGKEM//1199#sCCEEJLL 	\	m$   	LL 	m	[!   	KKMMMr   actionintc                `    |                      d|f                                          d         S )Nz2SELECT COUNT(*) AS c FROM audit_log WHERE action=?c)r#   fetchone)r   r(   s     r   audit_countr-   +   s+    <<LviXXaaccdghhr   Nonec                 H   t                      } t          |           }t          | |ddddddddd	d
dd          }|                     d|j        f                                          }|                     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         }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}||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}||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}||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}||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}||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
}||k    }|slt          j        d|fd||f          t          j	        |          t          j	        |          dz  }dd|iz  }	t          t          j        |	                    d x}x}}d }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	        |
          t          j	        |          d%z  }d&d'|iz  }t          t          j        |                    d x}x}
x}}|j        }g }
||
k    }|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}}
d S )-NstockzSynthetic NestleCH0038863350NESNSIXCHFz3.5z350.00
2025-12-31Corez%synthetic incomplete history acceptedTr&   asset_classnameisintickerexchangecurrencyquantity_textcost_basis_original_textsnapshot_datecategorynoteconfirm1SELECT * FROM transactions WHERE transaction_id=?/SELECT * FROM instruments WHERE instrument_id=?transaction_typeinitial_position_snapshot==z%(py1)s == %(py4)spy1py4assert %(py6)spy6quantitygross_amount_originalfx_rate_to_chf1	fx_status
not_neededr:   r8   position_category equity_initial_position_snapshot   z9%(py5)s
{%(py5)s = %(py0)s(%(py1)s, %(py3)s)
} == %(py8)sr-   r   py0rL   py3py5py8assert %(py10)spy10)z0%(py2)s
{%(py2)s = %(py0)s.warnings
} == %(py5)sresultr[   py2r]   assert %(py7)spy7)r   r'   r   r#   transaction_idr,   instrument_id
@pytest_ar_call_reprcompare	_safereprAssertionError_format_explanationr-   @py_builtinslocals_should_repr_global_namewarnings)r   r&   ra   tx
instrument@py_assert0@py_assert3@py_assert2@py_format5@py_format7@py_assert4@py_assert7@py_assert6@py_format9@py_format11@py_assert1@py_format6@py_format8s                     r   Htest_add_stock_initial_snapshot_creates_instrument_transaction_and_auditr   /   s   <<Dd##J(!)"4  F" 
IFLaKc	d	d	m	m	o	oBORXRfQhiirrttJ !@%@@!%@@@@@@@@@@@!%@@@@@@!@@@@%@@@@@@@@@@@@@@@@@@@@@@@@@@@@j>"U">U"""""""""">U""""">""""U"""""""""""""""""""""""""""%&2(2&(2222222222&(22222&2222(222222222222222222222222222&3&3&&&&&&&&&&3&&&&&&&&&3&&&&&&&&&&&&&&&&&&&&&&&&&&&k?*l*?l**********?l*****?****l***************************f////////////////////////////////////////////////m$//$//////////$/////$///////////////////////////////)*4f4*f4444444444*f44444*4444f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4?E;t?@@EAE@AEEEEEEEEEE@AEEEEEEEEEEEE;EEEEE;EEEEEEEEEEEEEtEEEEEtEEEEEE?EEEE@EEEEAEEEEEEEEEEEEEEEEEEEEEEEEEEEEE? b ?b          ?b            6     6      ?    b                             r   c                 	   t                      } t          | d          }t          | fi 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)|j        f                                          }|                     d*|j        f                                          }|d+         }d}||k    }|slt          j        d,|fd-||f          t          j	        |          t          j	        |          d.z  }d/d0|iz  }	t          t          j        |	                    d x}x}}|d         }d }||k    }|slt          j        d,|fd-||f          t          j	        |          t          j	        |          d.z  }d/d0|iz  }	t          t          j        |	                    d x}x}}|d!         }d"}||k    }|slt          j        d,|fd-||f          t          j	        |          t          j	        |          d.z  }d/d0|iz  }	t          t          j        |	                    d x}x}}|d#         }d$}||k    }|slt          j        d,|fd-||f          t          j	        |          t          j	        |          d.z  }d/d0|iz  }	t          t          j        |	                    d x}x}}|d%         }d&}||k    }|slt          j        d,|fd-||f          t          j	        |          t          j	        |          d.z  }d/d0|iz  }	t          t          j        |	                    d x}x}}|d1         }d}||k    }|slt          j        d,|fd-||f          t          j	        |          t          j	        |          d.z  }d/d0|iz  }	t          t          j        |	                    d x}x}}|d2         }d}||k    }|slt          j        d,|fd-||f          t          j	        |          t          j	        |          d.z  }d/d0|iz  }	t          t          j        |	                    d x}x}}|d3         }d4}||k    }|slt          j        d,|fd-||f          t          j	        |          t          j	        |          d.z  }d/d0|iz  }	t          t          j        |	                    d x}x}}d S )5NzSynthetic True Wealthr&   r8   ETFr9   zSynthetic World ETFr:   IE00B4L5Y983r;   SWLDr<   LSEr=   USDr>   10r?   z1000.00r@   r5   rA   r6   rB   z$synthetic ETF snapshot with known FXfx_rate_to_chf_textz0.91	fx_sourcezsynthetic fixtureter_textz0.20distribution_policyaccumulating
index_namezMSCI World Syntheticfund_domicileIE	benchmarkzSynthetic BenchmarkrC   TrE   rD   terrH   rJ   rK   rN   rO   currency_originalrR   gross_amount_chfz910.0000)r   r'   r   r#   rg   r,   rf   rh   ri   rj   rk   rl   )
r   r&   ra   rr   rq   rs   rt   ru   rv   rw   s
             r   :test_add_etf_initial_snapshot_prepares_optional_etf_fieldsr   R   s   <<Dd$;<<J(  : E #"	
 ^ v   d "+ #l  43 #F &%  !" +N#$ *)%& d'( (')* +F0 ORXRfQhiirrttJ	IFLaKc	d	d	m	m	o	oBe&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&+,>>,>>>>>>>>>>,>>>>>,>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>l#='==#'===========#'======#===='============================o&.$.&$..........&$.....&....$...........................k";&;;"&;;;;;;;;;;;"&;;;;;;";;;;&;;;;;;;;;;;;;;;;;;;;;;;;;;;;!"+e+"e++++++++++"e+++++"++++e+++++++++++++++++++++++++++)6)6))))))))))6)))))))))6))))))))))))))))))))))))))) !/Z/!Z//////////!Z/////!////Z/////////////////////////////r   c                    t                      } t          | d          }t          | |ddddddd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         }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}|j        }	||	v }|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}}	|                     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 )$NzSynthetic Raiffeisenr0   zSynthetic US StockUS0378331005AAPLNASDAQr   2z400.00r5   Opportunity(synthetic missing FX accepted for reviewmissingT)r&   r8   r9   r:   r;   r<   r=   r>   r?   r@   rA   rB   rT   rC   rD   rT   rH   rJ   rK   rN   rO   r   isz%(py1)s is %(py4)s
missing_fxinz0%(py1)s in %(py5)s
{%(py5)s = %(py3)s.warnings
}ra   rL   r\   r]   rd   re   z;SELECT COUNT(*) AS c FROM alerts WHERE rule_id='missing_fx'r+   rX   )r   r'   r   r#   rf   r,   rh   ri   rj   rk   rl   rp   rm   rn   ro   )r   r&   ra   rq   rs   rt   ru   rv   rw   rx   r~   r   s               r   ;test_usd_stock_requires_fx_or_explicit_missing_status_alertr   z   s}   <<Dd$:;;J(!!)"7  F$ 
IFLaKc	d	d	m	m	o	oBk?'i'?i''''''''''?i'''''?''''i''''''''''''''''''''''''''' !)T)!T))))))))))!T)))))!))))T)))))))))))))))))))))))))))*6?*<?**********<?*****<***********6*****6******?***************************<<UVV__aabefkjkkfjkkkkkkkkkkkfjkkkkkkfkkkkjk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                      } t          |           }t          | |ddddddddd	d
dd          }t          | ||j        ddddddd
  
         t          |           j        ||j        f         }|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}}t#          j        t&          d          5  t          | ||j        dddd dd!d
  
         d d d            d S # 1 swxY w Y   d S )"Nr0   zSynthetic SellableCH0000000001SYNr3   r4   5500r5   Unknownsynthetic initialTr7   partial_sell
2026-01-10r   220zsynthetic partial sell	r&   rg   rF   
trade_dater>   gross_amount_original_textr=   rB   rC   3rH   zN%(py2)s
{%(py2)s = %(py0)s.quantity
} == %(py8)s
{%(py8)s = %(py4)s(%(py6)s)
}positionr   r[   rc   rM   rO   r^   r_   r`   negativematch
2026-01-11r   1000zsynthetic oversell)r   r'   r   r   rg   r   	positionsrP   r   rh   ri   rm   rn   ro   rj   rk   rl   pytestraises
ValueError)
r   r&   snapr   r}   @py_assert5ry   rt   r{   r|   s
             r   .test_sell_reduces_position_and_blocks_negativer      s   <<Dd##J&!!&"   D" ('#(%    #4((2J@R3STH,,,,,,,,,,,,,,,,,,,,,,,,,8,,,,,8,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,	z	4	4	4 
 
!,+#'-%	
 	
 	
 	

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
s   G//G36G3c                    t                      } t          |           }t          | |ddddddddd	d
dd          }t          | ||j        ddddddd
  
         t          |           j        ||j        f         }|j        }d}t          |          }||k    }|st          j
        d|fd||f          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}}t#          j        t&          d          5  t          | ||j        ddddddd
  
         d d d            d S # 1 swxY w Y   d S ) Nr   zSynthetic Income ETFIE0000000001INCr3   r4   7700r5   r6   r   Tr7   dividend
2026-02-010z12.50synthetic dividendr   rH   zN%(py3)s
{%(py3)s = %(py1)s.quantity
} == %(py9)s
{%(py9)s = %(py5)s(%(py7)s)
}r   rL   r\   r]   re   py9assert %(py11)spy11rB   r   manual_adjustmentz
2026-02-02rS    )r   r'   r   r   rg   r   r   rP   r   rh   ri   rj   rm   rn   ro   rk   rl   r   r   r   )
r   r&   r   rs   ru   rz   @py_assert8rx   @py_format10@py_format12s
             r   Jtest_dividend_does_not_change_quantity_and_manual_adjustment_requires_noter      s   <<Dd##J&#!&"   D" (##*!    t$$.
D<N/OPiPYiehi]deh]i]iiY]iiiiiiiiiiiY]iiiiiiPiiiiYiiiiiiiiiii]diiiii]diiiiiiehiiii]iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii	z	0	0	0 
 
!,0#'*	
 	
 	
 	

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
s   GG	G	c                 J   t                      } t          |           }t          | |ddddddddd	d
dd          }t          j        t
          d          5  t          | ||j        ddddddd
  
         d d d            n# 1 swxY w Y   t          | ||j        ddddddd
  
         t          |           j	        ||j        f         }|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!}
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        |          t          j        |          d&z  }dd |iz  }	t%          t          j        |	                    d x}
x}x}}d S )'Nr0   zSynthetic Full SellCH0000000002FULr3   r4   4400r5   r   r   Tr7   zfull_sell quantityr   	full_sellr   r   330zsynthetic wrong full sellr   r   440zsynthetic full sellr   rH   r   r   r   r   r_   r`   equity_full_sellrX   rY   r-   r   rZ   )r   r'   r   r   r   r   r   rg   r   r   rP   r   rh   ri   rm   rn   ro   rj   rk   rl   r-   )r   r&   r   r   r}   r   ry   rt   r{   r|   ru   rx   rz   s                r   Atest_full_sell_requires_exact_current_quantity_and_zeros_positionr      s   <<Dd##J&"!&"   D" 
z)=	>	>	> 
 
!,(#',,	
 	
 	
 	

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 ($#("    #4((2J@R3STH,,,,,,,,,,,,,,,,,,,,,,,,,8,,,,,8,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,/5;t/005A50A55555555550A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5t55555t555555/555505555A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5s   BBBc                    t                      } t          | d           t          |           }|d         }|s:ddt          j        |          iz  }t          t          j        |                    d }ddlm} d}d |D             }||v }|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   accountsassert %(py1)srL   r   )PAGESzEquity/ETF Managec                    g | ]	}|j         
S  )
PAGE_TITLE).0pages     r   
<listcomp>zLtest_equity_management_options_and_dashboard_page_import.<locals>.<listcomp>5  s    "E"E"Et4?"E"E"Er   r   )z%(py1)s in %(py4)srK   rN   rO   )
r   r'   r	   rh   rj   rk   rl   jarvis_finance.dashboard.pagesr   ri   )	r   optionsrs   @py_format2r   rt   ru   rv   rw   s	            r   8test_equity_management_options_and_dashboard_page_importr   .  sG   <<D.///+D11G:444444E"E"Eu"E"E"EE"EEEEEEEEEEE"EEEEEEEEEE"EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEr   c                 |   t                      } t          | d          }t          | ddddddd	          }t          | dd
ddddd	           t          | d          }|d         }t	          |          }d}||k    }|st          j        d|fd||f          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}}|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          }|d         }t	          |          }d}||k    }|st          j        d |fd!||f          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}}|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}}t          | d          }|d         }t	          |          }d}||k    }|st          j        d |fd!||f          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}}|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'         }
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          j        t"          d()          5  t%          | ||d*d+d,dd-d./	  	         d d d            n# 1 swxY w Y   t%          | ||d*d+d,dd d0d#1
  
        }|                     d2|j        f                                          }|d3         }
d4}|
|k    }|slt          j        d|fd|
|f          t          j
        |
          t          j
        |          dz  }dd|iz  }t          t          j        |                    d x}
x}}|d5         }
d+}|
|k    }|slt          j        d|fd|
|f          t          j
        |
          t          j
        |          dz  }dd|iz  }t          t          j        |                    d x}
x}}|d6         }
d7}|
|k    }|slt          j        d|fd|
|f          t          j
        |
          t          j
        |          dz  }dd|iz  }t          t          j        |                    d x}
x}}d8}
|j        }|
|v }|st          j        d9|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}}|                     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 S )ANzSynthetic Manual Brokerr0   zSynthetic Alpha AGr4   CH1111111111ALPr3   zsynthetic catalog sourcer8   r9   r=   r:   r;   r<   rB   zSynthetic Alpha US Listingr   US1111111111r   )queryresultsrX   rH   z0%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} == %(py7)slenr[   rc   rM   re   assert %(py9)sr   r   mapping_statusexact_isin_matchrJ   rK   rN   rO   zSynthetic Alpha   >=z0%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} >= %(py7)sselection_requiredTr   r   z&SELECT COUNT(*) AS c FROM transactionsr+   rC   r   initial_snapshotz1.25r5   z"synthetic review must be confirmedF)catalog_entry_idr&   position_typer>   r   r=   rB   rC   z,synthetic manually reviewed initial snapshot	r  r&   r  r>   r   r=   r?   rB   rC   rD   rF   rG   rP   rQ   r   cost_basis_uncertainr   r   ra   r   rd   re   zFSELECT COUNT(*) AS c FROM audit_log WHERE action='manual_position_add'zESELECT COUNT(*) AS c FROM alerts WHERE rule_id='cost_basis_uncertain')r   r'   r   r
   r   rh   ri   rm   rn   ro   rj   rk   rl   r#   r,   r   r   r   r   rf   rp   )r   r&   firstisin_resultr}   rt   rz   r   r   r   rs   ru   rv   rw   name_resultticker_resultra   rq   rx   r~   s                       r   4test_manual_instrument_search_and_wizard_safety_flowr
  8  s   <<Dd$=>>J'!'	 	 	E  )'	 	 	 	 /t>JJJK9%+3%&&+!+&!++++++++++&!++++++++++++3+++++3++++++%++++&++++!+++++++++++++++++++++++++++++y!!$%56L:LL6:LLLLLLLLLLL6:LLLLLL6LLLL:LLLLLLLLLLLLLLLLLLLLLLLLLLLL.t;LMMMK9%+3%&&+!+&!++++++++++&!++++++++++++3+++++3++++++%++++&++++!++++++++++++++++++++++++++++++,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44444444444444444444440UCCCMY'-3'((-A-(A----------(A------------3-----3------'----(----A------------------------------.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666666666666666<<@AAJJLLSQVUVVQUVVVVVVVVVVVQUVVVVVVQVVVVUV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	z	3	3	3 
 
("!, #5
	
 
	
 
	
 
	

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 .(!%;  F 
IFLaKc	d	d	m	m	o	oB !@%@@!%@@@@@@@@@@@!%@@@@@@!@@@@%@@@@@@@@@@@@@@@@@@@@@@@@@@@@j>#V#>V##########>V#####>####V###########################%&-#-&#----------&#-----&----#---------------------------!4V_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4V44444V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4444444<<`aajjllmpqvuvvquvvvvvvvvvvvquvvvvvvqvvvvuv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<<_``iikkloputuuptuuuuuuuuuuuptuuuuuupuuuutuuuuuuuuuuuuuuuuuuuuuuuuuuuuuus   (WWWc                 b   t                      } t          | d          }t          | ddddddd	          }t          | ||d
dd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         }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}||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d d!d"d#	          }
t          | |
|d$d%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         }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.}|j        }||v }|st          j        d/|fd0||f          t          j	        |          d(t          j                    v st          j        |          rt          j	        |          nd(t          j	        |          d1z  }d2d3|iz  }t          t          j        |                    d x}x}}d S )4NzSynthetic FX BrokeretfzSynthetic USD ETFr   IE2222222222USDENYSEzsynthetic manual ETF sourcer   r  r   r5   z100.00z0.90zsynthetic fx sourcezsynthetic USD ETF with FXT)r  r&   r  r>   r   r=   r?   r   r   rB   rC   rD   r   rH   rJ   rK   rN   rO   rR   r   z90.0000r0   zSynthetic EUR StockEURDE3333333333EURSXETRAzsynthetic manual stock sourcebuyrS   
2026-01-05z50.00r   r   
r  r&   r  r>   r   r=   r?   rT   rB   rC   rT   r   r   r   r   r   r   rd   re   )r   r'   r   r   r#   rf   r,   rh   ri   rj   rk   rl   rp   rm   rn   ro   )r   r&   
catalog_idra   rq   rs   rt   ru   rv   rw   missing_fx_catalogr   
tx_missingrx   r~   r   s                   r   1test_manual_catalog_entry_and_foreign_fx_handlingr    sn   <<Dd$9::J, *	 	 	J .#(!)"'(  F 
IFLaKc	d	d	m	m	o	oB!"+e+"e++++++++++"e+++++"++++e+++++++++++++++++++++++++++)6)6))))))))))6)))))))))6))))))))))))))))))))))))))) !.Y.!Y..........!Y.....!....Y...........................4",	 	 	 /+!(7  G QT[TjSlmmvvxxJk"/i/"i//////////"i/////"////i///////////////////////////()1T1)T1111111111)T11111)1111T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+7++<+++++++++++<++++++<+++++++++++7+++++7++++++++++++++++++++++++++++++++++++r   c                 	   t                      } t          | d          }t          | ddddddd	          }t          | ||d
dddddd
  
        }t          | ||ddddddd
  
         t          | ||ddddddd
  
         t          | ||ddddddd
  
         t	          |           j        ||j        f         }|j        }d }t          |          }||k    }|st          j
        d!|fd"||f          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}}d'd(lm}  |d)                                          }d*}||v }|st          j
        d+|fd,||f          t          j        |          d-t          j                    v st          j        |          rt          j        |          nd-d.z  }d/d0|iz  }t          t          j        |                    d x}}d1}||v }|st          j
        d+|fd,||f          t          j        |          d-t          j                    v st          j        |          rt          j        |          nd-d.z  }d/d0|iz  }t          t          j        |                    d x}}|                    d2d3          d'         }d4}||v}|st          j
        d5|fd6||f          t          j        |          d7t          j                    v st          j        |          rt          j        |          nd7d.z  }d/d0|iz  }t          t          j        |                    d x}}d8}||v}|st          j
        d5|fd6||f          t          j        |          d7t          j                    v st          j        |          rt          j        |          nd7d.z  }d/d0|iz  }t          t          j        |                    d x}}d S )9NzSynthetic Trading Brokerr0   zSynthetic Tradabler4   CH4444444444TRDr3   zsynthetic tradable sourcer   r  r   r5   r   zsynthetic starting pointTr  r  rS   r  110zsynthetic buyr   r   r   r   zsynthetic sellr   r   r   z4.50r   r   rH   r   r   r   r   r   r   )Pathz;src/jarvis_finance/dashboard/views/page_13_equity_manage.pyzsearch_instrument_candidates(r   z%(py1)s in %(py3)sr   rL   r\   assert %(py5)sr]   zProvider-Suche explizitzwith tabs[1]:rX   zst.write({"instrument_id"not inz%(py1)s not in %(py3)swizard_sourcezst.write({"catalog_entry_id")r   r'   r   r   r   r   rg   rP   r   rh   ri   rj   rm   rn   ro   rk   rl   pathlibr  	read_textsplit)r   r&   r  r   rs   ru   rz   r   rx   r   r   r  r   @py_format4r~   r&  s                   r   Ntest_manual_wizard_supports_buy_sell_dividend_and_no_dashboard_live_api_or_idsr+    s#   <<Dd$>??J,!(	 	 	J ,D:Zd  uG  WZ  gs  ~C  ^c  jD  NR  S  S  SD$TJS]mr  CF  S_  jo  JO  Ve  os  t  t  t  t$TJS]m{  LO  \h  sx  SX  _o  y}  ~  ~  ~  ~$TJS]mw  HK  Xd  ot  OU  \p  z~        t$$.
D<N/OPiPYiehi]deh]i]iiY]iiiiiiiiiiiY]iiiiiiPiiiiYiiiiiiiiiii]diiiii]diiiiiiehiiii]iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii4MNNXXZZD*2*d2222222222*d22222*22222222222d22222d222222222222222222222222222$,$,,,,,,,,,,$,,,,,$,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,JJ2215M(=(==========(=====(===========================================+@+=@@@@@@@@@@+=@@@@@+@@@@@@@@@@@=@@@@@=@@@@@@@@@@@@@@@@@@@@@@@@@@@@@r   c                L   ddl m}m}m} d  |            D             }g 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d           |                     dt          |                     |dz                                   |dz  dz                      dd            |            }|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z  dz                                    ||
d |            g          \  }}g }||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!}||v }|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}} G d& d'|          } ||
d( |d)*          g          \  }}g }||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         }|j        }d+}||k    }|st	          j        d|fd,||f          t	          j        |          t	          j        |          t	          j        |          d-z  }	d.d/|	iz  }t          t	          j        |                    d x}x}x}}|
                    d0                                          d1         }d2}||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 )3Nr   )OpenFigiLookupProvider#default_instrument_lookup_providerssearch_instrumentsc                    g | ]	}|j         
S r   )r9   )r   ps     r   r   zTtest_provider_lookup_classes_skip_missing_keys_and_cache_results.<locals>.<listcomp>  s    BBBqAFBBBr   )openfigifmpfinnhub
twelvedatamassiverH   rJ   rK   rN   rO   OPENFIGI_API_KEYFraisingJARVIS_OPENFIGI_API_KEYJARVIS_FINANCE_RUNTIME_DIRsecrets.envz"OPENFIGI_API_KEY=runtime-file-key
utf-8encodingruntime-file-keyzF%(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s()
}.api_key
} == %(py7)sr-  r   r   r   r   	providersz%(py0)s == %(py3)sr   r[   r\   r"  r]   openfigi_api_key_missingr   r   rp   r!  c                      e Zd ZddZdS )Vtest_provider_lookup_classes_skip_missing_keys_and_cache_results.<locals>.FakeOpenFigir   r   c                    dddddddgS )Nz	Apple Incr   USzCommon StockEquityBBG000B9XRY4)r9   r;   exchCodesecurityTypemarketSecDescompositeFIGIr   )selfr   s     r   _requestz_test_provider_lookup_classes_skip_missing_keys_and_cache_results.<locals>.FakeOpenFigi._request  s2    (F^l  G  Zh  i  i  j  jr   Nr   r   __name__
__module____qualname__rS  r   r   r   FakeOpenFigirI    s.        	j 	j 	j 	j 	j 	jr   rY  Applezruntime-only-keyapi_keyr2  )z.%(py3)s
{%(py3)s = %(py1)s.source
} == %(py6)srL   r\   rO   assert %(py8)sr^   zNSELECT COUNT(*) AS c FROM instrument_catalog_entries WHERE provider='openfigi'r+   rX   )"jarvis_finance.market_data.catalogr-  r.  r/  rh   ri   rj   rk   rl   r   delenvsetenvr   mkdir
write_textr\  rm   rn   ro   unlinksourcer#   r,   )monkeypatchtmp_pathr-  r.  r/  rs   rt   ru   rv   rw   r   r}   rz   r   r   r   r   rp   r*  r~   rY  rx   r{   s                          r   @test_provider_lookup_classes_skip_missing_keys_and_cache_resultsrh    s$    C  C  C  C  C  C  C  C  C  CBB??AABBB}F}F}F}}BF}}}}}}}}}}}BF}}}}}}B}}}}F}}}}}}}}}}}}}}}}}}}}}}}}}}}}<<D)59990%@@@3S]]CCC	  """	F"../Ydk.lll!!##A#+A/AA+/AAAAAAAAAAA+/AAAAAAAAAAAAA!AAAAA!AAAAAA#AAAA+AAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA	F"**,,,**4LbLbLdLdKefffGX7b=7b77b%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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j j j j j- j j j +*4\\ZlEmEmEmDnoooGX8r>8r88r1:*:*
*
**********
*****:********
*****************************<<hiirrttuxy~}~~y}~~~~~~~~~~~y}~~~~~~y~~~~}~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~r   c                  	
 ddl m} ddlm	 t	                      }ddi G 	fdd          
|                     |d
fd           t          |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	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}||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   )manager   nc                  &    e Zd ZdZdd fd
ZdS )[test_search_candidates_uses_external_providers_only_on_explicit_click.<locals>.FakeProviderfake_providerNr8   c               T    dxx         dz  cc<    d |pddddddd	d
d
  
        gS )Nrl  rX   r0   zSynthetic Provider AGCH5555555555SPVr3   r4   fakemediumro  )r:   r;   r<   trading_currencyprovider
confidencere  r   )rR  r   r8   r   callss      r   searchzbtest_search_candidates_uses_external_providers_only_on_explicit_click.<locals>.FakeProvider.search  su    #JJJ!OJJJ''k.DWF]dr  |A  LQ  di  tz  GO  Xg  h  h  h  i  ir   rV  rW  rX  r9   rz  )r   ry  s   r   FakeProviderrn    sO        /3 	i 	i 	i 	i 	i 	i 	i 	i 	i 	ir   r|  r.  c                                   gS r   r   )r|  s   r   <lambda>zWtest_search_candidates_uses_external_providers_only_on_explicit_click.<locals>.<lambda>  s    P\P\P^P^O_ r   rs  F)r   include_externalrH   rJ   rK   rN   rO   TrX   r   data_sourcero  )jarvis_finance.equityrj  r_  r   r   setattrr
   rh   ri   rj   rk   rl   )rf  rj  r   rs   rt   ru   rv   rw   ra   r   r|  ry  s            @@@r   Etest_search_candidates_uses_external_providers_only_on_explicit_clickr    s   ,,,,,,FFFFFF<<D!HEi i i i i i i i i i i  EG_G_G_G_``` UUKKKK::?::)$edSSSF::?::)Q.A/A./AAAAAAAAAA./AAAAA.AAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAr   c                  (    e Zd ZdZddZddddZdS )CountingProvidercountingr   r.   c                    d| _         d S )Nr   )ry  )rR  s    r   __init__zCountingProvider.__init__
  s    


r   Nrp  r   r   r8   
str | Nonec               ^    | xj         dz  c_         t          d |pddddddddd	dd
          gS )NrX   r  zProvider Test ETFUS9229087690VTIr  r   r  ru  zsynthetic provider result)	r:   r;   r<   rv  rw  provider_symbolrx  re  evidence_note)ry  r   rR  r   r8   s      r   rz  zCountingProvider.search  su    

a

#D+*>@SZhqv  BH  [`  ku  GL  Ya  jt  D_  `  `  `  a  	ar   r   r.   )r   r   r8   r  )rV  rW  rX  r9   r  rz  r   r   r   r  r    sY        D    ?C a a a a a a a ar   r  c            
        t                      } t          | ddddddd           t          | dd	dddd
d           t          | dd          }|d         }|s:ddt          j        |          iz  }t          t          j        |                    d }|d         d         d         }|j        }d} ||          }|ssdt          j        |          t          j        |          t          j        |          t          j        |          dz  }t          t          j        |                    d x}x}x}}d |d         D             }t          |          }	|	sddt          j
                    v st          j        t                    rt          j        t                    ndt          j        |          t          j        |	          dz  }
t          t          j        |
                    d x}}	d |d         D             }t          |          }	|	sddt          j
                    v st          j        t                    rt          j        t                    ndt          j        |          t          j        |	          dz  }
t          t          j        |
                    d x}}	t          | dd          }|d         }t          |          }	d}|	|k    }|st          j        d|fd|	|f          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}}|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}}	t          | dd          }|d         }t          |          }	d}|	|k    }|st          j        d|fd|	|f          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}}|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         D             }t          |          }	|	sddt          j
                    v st          j        t                    rt          j        t                    ndt          j        |          t          j        |	          dz  }
t          t          j        |
                    d x}}	d S )+Nr  Vanguard Total Stock Market ETFr   r  r  r  zsynthetic VTI catalog entryr   z1Vanguard Total Stock Market ETF Secondary ListingARCAzsynthetic VTI alternate listingr   r8   r   r   rL   r   r9   zVanguard Total Stock MarketLassert %(py7)s
{%(py7)s = %(py3)s
{%(py3)s = %(py1)s.startswith
}(%(py5)s)
}rL   r\   r]   re   c              3  F   K   | ]}|d          dk    o|d         dk    V  dS )r;   r  r=   r   Nr   r   rs     r   	<genexpr>zQtest_vti_examples_are_searchable_and_ticker_requires_selection.<locals>.<genexpr>  s9      [[1q{e#>*(>[[[[[[r   ,assert %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}anyr[   rc   rM   c              3  .   K   | ]}|d          dk    V  dS )trust_status	EindeutigNr   r  s     r   r  zQtest_vti_examples_are_searchable_and_ticker_requires_selection.<locals>.<genexpr>  s,      LLAq K/LLLLLLr   allVanguard Total Stockr   r   r   r   r   r   r   r   Tr   r   rK   rN   rO   c              3  .   K   | ]}|d          dk    V  dS )r  u   Manuell prüfenNr   r  s     r   r  zQtest_vti_examples_are_searchable_and_ticker_requires_selection.<locals>.<genexpr>$  s-      TT!q $55TTTTTTr   )r   r   r
   rh   rj   rk   rl   
startswithr  rm   rn   ro   r  r   ri   )r   by_isinrs   r   ru   rx   rz   r   r}   rt   rv   by_namer   r   rw   	by_tickers                   r   >test_vti_examples_are_searchable_and_ticker_requires_selectionr    sr   <<D%>_jo  wE  NS  ^d  kH  I  I  I  I%>q  }B  IW  `e  pv  }^  _  _  _  _*4~SXYYYG99a (R(3R4QR334QRRRRRRRR(RRRR3RRRR4QRRRRRRRRRRRRRRRRRRRRRRRRRRRR[[PYHZ[[[[3[[[[[[[[[[[[[[[[3[[[[[3[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[LL9KLLLL3LLLLLLLLLLLLLLLL3LLLLL3LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL*47M[`aaaGy!'3!""'a'"a''''''''''"a''''''''''''3'''''3''''''!''''"''''a''''''''''''''''''''''''''''''(0D0(D0000000000(D00000(0000D000000000000000000000000000,TERRRI#)3#$$))$))))))))))$))))))))))))3)))))3))))))#))))$))))))))))))))))))))))))))))))))))*2d2*d2222222222*d22222*2222d222222222222222222222222222TTy?STTTT3TTTTTTTTTTTTTTTT3TTTTT3TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTr   c                    t                      } t                      }ddlm} t	          | ddd          }|d         }g }||k    }|slt          j        d|fd	||f          t          j        |          t          j        |          d
z  }dd|iz  }t          t          j	        |                    d x}x}}|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        |
          dz  }dd|iz  }t          t          j	        |                    d x}	x}}
 || dd|g          \  }}g }||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}	}|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        |
          dz  }dd|iz  }t          t          j	        |                    d x}	x}}
|d         }|j        }d}||k    }
|
st          j        d|
fd||f          t          j        |          t          j        |          t          j        |          dz  }dd|iz  }t          t          j	        |                    d x}x}x}
}t	          | ddd          }|d         }|s:ddt          j        |          iz  }t          t          j	        |                    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 S )"Nr   r/  r  r  Fr   r8   r  r   rH   rJ   rK   rN   rO   )z-%(py2)s
{%(py2)s = %(py0)s.calls
} == %(py5)srw  rb   rd   re   rC  rE  rp   rF  r"  r]   rX   r  )z.%(py3)s
{%(py3)s = %(py1)s.ticker
} == %(py6)sr]  r^  r^   r   rL   r  local_catalog)r   r  r_  r/  r
   rh   ri   rj   rk   rl   ry  rm   rn   ro   r;   )r   rw  r/  
local_onlyrs   rt   ru   rv   rw   r}   rx   r~   r   r   rp   r*  r   r{   cachedr   s                       r   Ktest_online_provider_is_only_used_when_explicitly_enabled_and_caches_resultr  '  sk   <<D!!HEEEEEE-d.V[nstttJi &B& B&&&&&&&&&& B&&&&& &&&&B&&&&&&&&&&&&&&&&&&&&&&&&&&&>Q>Q>Q88>Q**4S[R\]]]GX8r>8r88r>Q>Q>Q88>Q1:%:%%%%%%%%%%%%%%%%%:%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%)$nRWjopppF))Q.A/A./AAAAAAAAAA./AAAAA.AAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAr   c                `   dD ]}|                      |d           |                     dt          |                     t                      }d |D             }h 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         }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          |	          }| }
|
sddt          j                    v st	          j        t                    rt	          j        t                    ndt	          j        |	          t	          j        |          dz  }t          t	          j        |                    d x}	x}}
d S )N)r7  r:  FINNHUB_API_KEYJARVIS_FINNHUB_API_KEYFMP_API_KEYJARVIS_FMP_API_KEYFr8  r;  c                    h | ]
}|d          S Providerr   r   rows     r   	<setcomp>zStest_provider_statuses_report_missing_keys_without_secret_values.<locals>.<setcomp>>  s    000C
O000r   >   Lokale SucheManuelle AnlageFMPFinnhubOpenFIGIr   )z%(py1)s >= %(py4)srK   rN   rO   c              3  2   K   | ]}|d          dk    |V  dS r  r  Nr   r  s     r   r  zStest_provider_statuses_report_missing_keys_without_secret_values.<locals>.<genexpr>?  0      II3z?j+H+H+H+H+H+HIIr   StatuszAPI-Key fehltrH   rJ   c              3  ~   K   | ]8}d t          |                                          v pdt          |          v V  9dS )secretrA  N)r   r!   r  s     r   r  zStest_provider_statuses_report_missing_keys_without_secret_values.<locals>.<genexpr>@  sI      ffVY8s3xx~~///Q3ES3Qffffffr   0assert not %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}r  r  )r`  ra  r   r   rh   ri   rj   rk   rl   nextr  rm   rn   ro   )rf  rg  keystatusesrs   rt   ru   rv   rw   r}   r   r~   s               r   @test_provider_statuses_report_missing_keys_without_secret_valuesr  9  s    Q / /3....3S]]CCC+--H00x000u4u4u4uu04uuuuuuuuuuu04uuuuuu0uuuu4uuuuuuuuuuuuuuuuuuuuuuuuuuuuIIxIIIII(SfWffSWfffffffffffSWffffffSffffWffffffffffffffffffffffffffffff]effffsfffffffffffffffffffsfffffsfffffffffffffffffffffffffffffffffffr   c                    t                      } t          | d          }t          | ddddddd	          }t          | ||d
d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 S )NzSynthetic Category Brokerr  zSynthetic Core ETFr4   rr  COREr3   zsynthetic core entryr   r  rS   r5   100zsynthetic category testr6   T)
r  r&   r  r>   r   r=   r?   rB   rA   rC   z?SELECT position_category FROM instruments WHERE instrument_id=?rV   rH   rJ   rK   rN   rO   )r   r'   r   r   r#   rg   r,   rh   ri   rj   rk   rl   )
r   r&   r  ra   r  rs   rt   ru   rv   rw   s
             r   7test_category_is_saved_for_manual_position_from_catalogr  C  s   <<Dd$?@@J,TuK_jo  wE  NT  _d  kA  B  B  BJ-dZ\f  wI  Y\  iu  @E  `e  lE  PV  `d  e  e  eF
,,X[a[oZq
r
r
{
{
}
}C"#-v-#v----------#v-----#----v-----------------------------r   c                 	   ddl m} m}  G d d|          } G d d|           } |d          } |d          }|                    d	d
          }|                    dd
          }|d         }|j        }	d	}
|	|
k    }|st          j        d|fd|	|
f          t          j        |          t          j        |	          t          j        |
          dz  }dd|iz  }t          t          j	        |                    d x}x}	x}}
|d         }|j
        }	d}
|	|
k    }|st          j        d|fd|	|
f          t          j        |          t          j        |	          t          j        |
          dz  }dd|iz  }t          t          j	        |                    d x}x}	x}}
|d         }|j        }	d}
|	|
k    }|st          j        d|fd|	|
f          t          j        |          t          j        |	          t          j        |
          dz  }dd|iz  }t          t          j	        |                    d x}x}	x}}
|d         }|j        }	d}
|	|
k    }|st          j        d|fd|	|
f          t          j        |          t          j        |	          t          j        |
          dz  }dd|iz  }t          t          j	        |                    d x}x}	x}}
|d         }|j        }	d	}
|	|
k    }|st          j        d|fd|	|
f          t          j        |          t          j        |	          t          j        |
          dz  }dd|iz  }t          t          j	        |                    d x}x}	x}}
|d         }|j
        }	d}
|	|
k    }|st          j        d|fd|	|
f          t          j        |          t          j        |	          t          j        |
          dz  }dd|iz  }t          t          j	        |                    d x}x}	x}}
|d         }|j        }	d}
|	|
k    }|st          j        d|fd|	|
f          t          j        |          t          j        |	          t          j        |
          dz  }dd|iz  }t          t          j	        |                    d x}x}	x}}
d S )Nr   )FmpSearchProviderr-  c                      e Zd ZddZdS )Vtest_openfigi_isin_and_fmp_name_search_candidates_are_structured.<locals>.FakeOpenFigir   r   c                f   d}||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d	d
dddddgigS )Nr  rH   rE  r   rF  r"  r]   datar  r  rK  r   r   BBG000PSKYX7r9   r;   rN  r=   rO  rQ  rh   ri   rm   rn   ro   rj   rk   rl   rR  r   ru   r}   r*  r~   s         r   rS  z_test_openfigi_isin_and_fmp_name_search_candidates_are_structured.<locals>.FakeOpenFigi._requestP  s   **5N**********5N************5*****5******N*************************'HTYgky~  QV  iw  x  x  y  z  {  {r   NrT  rU  r   r   r   rY  r  O  s.        	{ 	{ 	{ 	{ 	{ 	{r   rY  c                      e Zd Zd	dZd
dZdS )Qtest_openfigi_isin_and_fmp_name_search_candidates_are_structured.<locals>.FakeFmpr   r   r   list[dict[str, object]]c                \   d}||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d	d
ddgS )Nr  rH   rE  r   rF  r"  r]   r  r  AMEXr   symbolr9   exchangeShortNamer=   r  r  s         r   _request_manyz_test_openfigi_isin_and_fmp_name_search_candidates_are_structured.<locals>.FakeFmp._request_manyU  s    2252222222222252222222222222522222522222222222222222222222222222222$.Oflz  A  A  B  Br   r  c                    ddddddS )Nr  r   TrK  p=
Co@)r:   r=   isEtfcountrypricer   )rR  r  s     r   _profilezZtest_openfigi_isin_and_fmp_name_search_candidates_are_structured.<locals>.FakeFmp._profileX  s    *Y]hnooor   N)r   r   r   r  )r  r   )rV  rW  rX  r  r  r   r   r   FakeFmpr  T  sF        	B 	B 	B 	B	p 	p 	p 	p 	p 	pr   r  ztest-keyr[  r  r  r  r  rH   z,%(py3)s
{%(py3)s = %(py1)s.isin
} == %(py6)sr]  r^  r^   r2  z0%(py3)s
{%(py3)s = %(py1)s.provider
} == %(py6)sr  )z7%(py3)s
{%(py3)s = %(py1)s.provider_symbol
} == %(py6)shighz2%(py3)s
{%(py3)s = %(py1)s.confidence
} == %(py6)sr3  ru  )r_  r  r-  rz  r:   rh   ri   rj   rk   rl   rw  r  rx  )r  r-  rY  r  r2  r3  	figi_rowsfmp_rowsrs   ru   r   rx   rw   r{   s                 r   @test_openfigi_isin_and_fmp_name_search_candidates_are_structuredr  L  s3   \\\\\\\\{ { { { {- { { {
p p p p p# p p p |J///H
'*
%
%
%Cn%HHIzz 6EzJJHQ<.<.................<.....................................Q<.< .J. J.......... J.....<.... ....J.............................Q<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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Q<,<",f,"f,,,,,,,,,,"f,,,,,<,,,,",,,,f,,,,,,,,,,,,,,,,,,,,,,,,,,,,,A;-;-~-~----------~-----;--------~-----------------------------A;(;(5(5((((((((((5(((((;((((((((5(((((((((((((((((((((((((((((A;-;!-X-!X----------!X-----;----!----X-------------------------------r   c                    ddl m}   G d d          } G d d          } G d d          }t                      } | |d	d
 |             |            g          \  }}g }||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}}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         }|j        }d}||k    }|st          j        d|fd||f          t          j        |          t          j        |          t          j        |          dz  }dd|iz  }t          t          j
        |                    d x}x}x}}|d         }|j        }d}||k    }|st          j        d|fd||f          t          j        |          t          j        |          t          j        |          dz  }dd|iz  }t          t          j
        |                    d x}x}x}}t                      } | |d	d
 |             |            g          \  }}g }||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}}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         }|j        }d}||k    }|st          j        d|fd||f          t          j        |          t          j        |          t          j        |          dz  }dd|iz  }t          t          j
        |                    d x}x}x}}t          |d	d
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 S ))Nr   r  c                      e Zd ZdZdddZdS )\test_provider_merge_raises_confidence_and_conflict_needs_manual_review.<locals>.FakeOpenFigir2  Nrp  c               <    t          d |pddddddddd	d
          gS )Nr  r  r  r  rK  r   r2  r  r  r:   r;   r<   rv  rw  r  rx  re  rk  r  s      r   rz  zctest_provider_merge_raises_confidence_and_conflict_needs_manual_review.<locals>.FakeOpenFigi.searchm  sc    'k.BUDelz  DI  TX  kp  {E  We  rx  AK  L  L  L  M  Mr   r{  r   r   r   rY  r  k  s<        /3 	M 	M 	M 	M 	M 	M 	Mr   rY  c                      e Zd ZdZdddZdS )[test_provider_merge_raises_confidence_and_conflict_needs_manual_review.<locals>.FakeFmpSamer3  Nrp  c               <    t          d |pdddddddddd	          gS )
Nr  r  r  r  rK  r   r3  ru  r  rk  r  s      r   rz  zbtest_provider_merge_raises_confidence_and_conflict_needs_manual_review.<locals>.FakeFmpSame.searchr  sc    'k.BUDelz  DI  TX  kp  {@  RW  dl  uz  {  {  {  |  |r   r{  r   r   r   FakeFmpSamer  p  s<        /3 	| 	| 	| 	| 	| 	| 	|r   r  c                      e Zd ZdZdddZdS )_test_provider_merge_raises_confidence_and_conflict_needs_manual_review.<locals>.FakeFmpConflictr3  Nrp  c               <    t          d |pdddddddddd	          gS )
Nr  r  r  VTIXrK  r   r3  ru  r  rk  r  s      r   rz  zftest_provider_merge_raises_confidence_and_conflict_needs_manual_review.<locals>.FakeFmpConflict.searchw  sc    'k.BUDelz  DJ  UY  lq  |A  SY  fn  w|  }  }  }  ~  ~r   r{  r   r   r   FakeFmpConflictr  u  s<        /3 	~ 	~ 	~ 	~ 	~ 	~ 	~r   r  r  r  rC  rH   rE  rp   rF  r"  r]   rX   z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)sr   mergedr[   rL   r\   rO   r^  r^   zfmp+openfigir  r]  r  r  
conflictedlowFr  r   Tr   r   rK   rN   rO   )r_  r/  r   rh   ri   rm   rn   ro   rj   rk   rl   r   rw  rx  r
   )r/  rY  r  r  r   r  rp   ru   r}   r*  r~   r   rx   rw   r{   rs   r  ra   rt   rv   s                       r   Ftest_provider_merge_raises_confidence_and_conflict_needs_manual_reviewr  h  s   EEEEEEM M M M M M M M
| | | | | | | |
~ ~ ~ ~ ~ ~ ~ ~
 <<D))$R^R^R`R`bmbmboboQpqqqFH8r>8r88rv;;!;!;!33vv;!!9/9/////////////////9/////////////////////////////////////!9)9)6)6))))))))))6)))))9))))))))6)))))))))))))))))))))))))))))<<D--dNEVbVbVdVdfufufwfwUxyyyJ8r>8r88rz??a?a?a33zz?aa=,=#,u,#u,,,,,,,,,,#u,,,,,=,,,,#,,,,u,,,,,,,,,,,,,,,,,,,,,,,,,,,,,)$nRWjopppF&'/4/'4//////////'4/////'////4/////////////////////////////r   c                    ddl m}  t                      }t          |d          }t	          |dddddd	d
          }t          |||ddddddd
d          }t          ||j        dt          d          ddd           t          |d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}||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         } | |          }||v }|st          j        d!|fd"||f          t          j        |          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}x}}d'd(d)} | |          }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-}d'd(d)} | |          }||v}|st          j        d.|fd/||f          t          j        |          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}x}}d S )0Nr   )_price_previewzSynthetic Price Brokerr  r  r   r  r  rK  zsynthetic price previewr   r  rS   
2026-01-01r  r   Tr  
2026-01-02z250.12r3  )rg   
price_datecloser=   rw  r  r  r   
last_pricerH   rJ   rK   rN   rO   price_sourcez
250.12 USDr   )z0%(py1)s in %(py7)s
{%(py7)s = %(py3)s(%(py5)s)
}r  r  r   r   zNo Pricer   )r9   r
  u   Preis noch nicht verfügbarr   r   r   r#  )z4%(py1)s not in %(py7)s
{%(py7)s = %(py3)s(%(py5)s)
})3jarvis_finance.dashboard.views.page_17_position_addr  r   r'   r   r   r   rg   r   r
   rh   ri   rj   rk   rl   rm   rn   ro   )r  r   r&   r  ra   rowsrs   rt   ru   rv   rw   rx   rz   r   r   r}   r   s                    r   Itest_price_preview_uses_local_market_prices_and_missing_price_is_not_zeror    s   RRRRRR<<Dd$<==J,TuKlw|  DR  [`  ko  vO  P  P  PJ-dZ\f  wI  Y\  iu  @E  `e  qz  AZ  dh  i  i  iFt6+?L`ghp`q`q  }B  MR  di  j  j  j  j'NPUVVVW`aD7< ,H, H,,,,,,,,,, H,,,,, ,,,,H,,,,,,,,,,,,,,,,,,,,,,,,,,,7>"+e+"e++++++++++"e+++++"++++e+++++++++++++++++++++++++++2$q'2>>'222<22222222222<222222<22222222222>22222>222222'2222222222222222222222222222222222#-R@@b>>@AAbEbbAEbbbbbbbbbbbAEbbbbbbbbbbbbb>bbbbb>bbbbbb@bbbbAbbbbEbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbLj%K%KLnn%KLLL3LLLLLLLLLLL3LLLLLL3LLLLLLLLLLLnLLLLLnLLLLLL%KLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLr   c                    t                      } t          | d          }t          | ddddddddd	

  
        }t          | ||ddddddd	d          }t	          | t          ddi          dd          }|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        |          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}}|
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 )$NzSynthetic Update Brokerr  r  r   r  r  rK  r3  zsynthetic price update)	r8   r9   r=   r:   r;   r<   rw  r  rB   r  rS   r  r  r   Tr  251.34r  )rw  r8   r  rX   rH   )z5%(py2)s
{%(py2)s = %(py0)s.updated_count
} == %(py5)ssummaryrb   rd   re   z?SELECT close, provider FROM market_prices WHERE instrument_id=?r	  rJ   rK   rN   rO   rw  mock)r   r'   r   r   r   r   updated_countrh   ri   rm   rn   ro   rj   rk   rl   r#   rg   r,   )r   r&   r  ra   r  r}   rx   rt   r~   r   r  rs   ru   rv   rw   s                  r   Etest_update_equity_prices_cli_workflow_uses_explicit_provider_mappingr    sH   <<Dd$=>>J,TuKlw|  DR  [`  ko  z  QV  ]u  v  v  vJ-dZ\f  wI  Y\  iu  @E  `e  qz  AY  cg  h  h  hF#D3JES[K\3]3]kp  ~J  K  K  KG %A% A%%%%%%%%%% A%%%%%%%%%%%%7%%%%%7%%%%%% %%%%A%%%%%%%%%%%%%%%%%%%%%%%%%%%
,,X[a[oZq
r
r
{
{
}
}Cw<#8#<8##########<8#####<####8###########################z?$f$?f$$$$$$$$$$?f$$$$$?$$$$f$$$$$$$$$$$$$$$$$$$$$$$$$$$$$r   c                >   |                      dd           |                     dt          |                     t                                          d          }|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}||k    }|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}}d}|j        }||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}	}d S )Nr  Fr8  r;  r  r   )z-%(py2)s
{%(py2)s = %(py0)s.close
} is %(py5)squoterb   rd   re   fmp_api_key_missingrH   )z5%(py2)s
{%(py2)s = %(py0)s.error_message
} == %(py5)s)z7%(py1)s == %(py5)s
{%(py5)s = %(py3)s.provider_symbol
}r   )r`  ra  r   r   	get_pricer	  rh   ri   rm   rn   ro   rj   rk   rl   error_messager  )
rf  rg  r  r}   rx   rt   r~   r   rs   ru   s
             r   0test_fmp_price_provider_missing_key_is_sanitizedr    s   }e4443S]]CCC"$$..u55E;$;$;$55;$7"77"77777777777"777777777777757777757777777777"7777777777777777777777777777)E))5)))))))))))5))))))5)))))))))))E)))))E))))))))))))))))))))))))))))))))))))r   c                   ddl m}m}m} dD ]}|                     |d           |dz  }|dz  }|                    d	           |d
z                      dd           |                     dt          |                     d} ||          }	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}}
 |            }|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}}
 |            }|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}}
t%                      }|j        }	d}
|	|
k    }|st          j
        d|fd|	|
f          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}}
t'                      }t)          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# |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+          |          }	|	 }|sd'd(t          j                    v st          j        t*                    rt          j        t*                    nd(t          j        |          t          j        |	          d)z  }t          t          j        |                    d x}x}	}d S )*Nr   )r  r-  _runtime_secret_value)r7  r:  r  r  Fr8  runtimer<  Tparentsr=  z6OPENFIGI_API_KEY=dummy-openfigi
FMP_API_KEY=dummy-fmp
r>  r?  r;  )r7  r:  dummy-openfigirH   r   r  r   r   r   rB  r-  	dummy-fmpr  r   c              3  2   K   | ]}|d          dk    |V  dS r  r   r  s     r   r  zFtest_runtime_secret_file_is_loaded_without_repo_env.<locals>.<genexpr>  r  r   r  aktivrJ   rK   rN   rO   c              3  2   K   | ]}|d          dk    |V  dS )r  r  Nr   r  s     r   r  zFtest_runtime_secret_file_is_loaded_without_repo_env.<locals>.<genexpr>  s0      DD3z?e+C+C+C+C+C+CDDr   	Kategorie
key_loadedc              3  Z   K   | ]&}d t          |          v pdt          |          v V  'dS )r   r!  N)r   r  s     r   r  zFtest_runtime_secret_file_is_loaded_without_repo_env.<locals>.<genexpr>  s>      __s#s3xx/J;#c((3J______r   r  r  r  )r_  r  r-  r  r`  rb  rc  ra  r   rh   ri   rm   rn   ro   rj   rk   rl   r\  r   r   r  r  )rf  rg  r  r-  r  r  r  r<  r}   rt   rz   r   r   r   r  rs   ru   rv   rw   r~   s                       r   3test_runtime_secret_file_is_loaded_without_repo_envr(    s0   ssssssssssc / /3...."G	!GMM$Mv!!"kv}!~~~3S\\BBB!Pe  !PQQeUeeQUeeeeeeeeeeeQUeeeeeeeeeeeee eeeee eeeeee!PeeeeQeeeeUeeeeeeeeeeeeeeeeeeeeeeeeeeeeee!!##?#+?/??+/???????????+/?????????????!?????!??????#????+????/??????????????????????????????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!##:#+:{:+{::::::::::+{::::::::::::!:::::!::::::#::::+::::{:::::::::::::::::::::::::::::+--HIIxIIIII(S^W^^SW^^^^^^^^^^^SW^^^^^^S^^^^W^^^^^^^^^^^^^^^^^^^^^^^^^^^^DDxDDDDD[QaUaaQUaaaaaaaaaaaQUaaaaaaQaaaaUaaaaaaaaaaaaaaaaaaaaaaaaaaaa__V^____s___________________s_____s___________________________________r   c            	        ddl m}  i  G fdd|           } |d                              dd	          }|sed
ddt          j                    v st          j        |          rt          j        |          ndiz  }t          t          j	        |                    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          |	          }
|
j        } |            }||v}|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        |          t          j        |          dz  }dd|iz  }t          t          j	        |                    d x}x}x}	x}
x}}d         }ddi}||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-  c                       e Zd Zdd fd
ZdS )Ntest_openfigi_key_is_sent_as_header_not_query_param.<locals>.CapturingOpenFigiNheadersc               @    |d<   |d<   |pi d<   dddddd	d
dgigS )Nurlpayloadr.  r  r  r  rK  r   r   r  r  r   )rR  r0  r1  r.  captureds       r   
_post_jsonzYtest_openfigi_key_is_sent_as_header_not_query_param.<locals>.CapturingOpenFigi._post_json  se    !HUO")HY")-RHY'HTYgky~  QV  iw  x  x  y  z  {  {r   rV  rW  rX  r3  r2  s   r   CapturingOpenFigir,    sD        6: 	{ 	{ 	{ 	{ 	{ 	{ 	{ 	{ 	{r   r6  r   r[  r  r  r  assert %(py0)sr[   r  r0  z#https://api.openfigi.com/v3/mappingrH   rJ   rK   rN   rO   apikeyr#  )zh%(py1)s not in %(py11)s
{%(py11)s = %(py9)s
{%(py9)s = %(py7)s
{%(py7)s = %(py3)s(%(py5)s)
}.lower
}()
}r   )rL   r\   r]   re   r   r   zassert %(py13)spy13r.  zX-OPENFIGI-APIKEY)r_  r-  rz  rm   rn   rh   ro   rj   rk   rl   ri   r   r!   )r-  r6  r  @py_format1rs   rt   ru   rv   rw   rx   rz   r   @py_assert10r   @py_format14r2  s                  @r   3test_openfigi_key_is_sent_as_header_not_query_paramr=    ss   IIIIII"$H{ { { { { { {2 { { { %5666==N`e=ffDKKKKKKKKKKKK4KKKKK4KKKKKKKKKKKKKKKKE?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CCCCCCC7x73//7/5755777877777777777877777787777777777737777737777777777/7777577777777777777777777777777777777777777II#68H"II"IIIIIIIIIII"IIIIIIIIII"IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIr   c                    ddl m} m} ddlm} g  G fdd|          } |d                              dd	
          }|sedddt          j                    v st          j	        |          rt          j
        |          ndiz  }t          t          j        |                     |  |d                   j                  }|d         }dg}||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g}||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   parse_qsurlparser  c                       e Zd Zdd fd
ZdS );test_fmp_key_is_sent_as_api_parameter.<locals>.CapturingFmpNr-  c               V                         |           d|v rdddddgS ddd	dd
gS )N/stable/profiler  r   Tr  )r:   r=   r  r  r  r  r  r  appendrR  r0  r.  r2  s      r   	_get_jsonzEtest_fmp_key_is_sent_as_api_parameter.<locals>.CapturingFmp._get_json  sZ    OOC    C''!/UT\bccdd$.Oflz  A  A  B  Br   rV  rW  rX  rJ  r5  s   r   CapturingFmprD    sD        ,0 	B 	B 	B 	B 	B 	B 	B 	B 	Br   rL  r!  r[  r  r  r  r7  r[   r  r8  rH   rJ   rK   rN   rO   r   )urllib.parser@  rA  r_  r  rz  rm   rn   rh   ro   rj   rk   rl   r   ri   )r@  rA  r  rL  r  r:  parsedrs   rt   ru   rv   rw   r2  s               @r   %test_fmp_key_is_sent_as_api_parameterrO    s`   ////////DDDDDDHB B B B B B B( B B B <,,,33:P^c3ddDKKKKKKKKKKKK4KKKKK4KKKKKKKKKKKKKKKKXhhx{++122F(,},},,,,,,,,,,},,,,,,,,,},,,,,,,,,,,,,,,,,,,,,,,,,,,'?65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66666666666666666666r   c                   dd l mc m} ddlm  G fdd          } G fdd          } G d d          }|                     |d	|           |                     |d
|           |                     |d|           |                    d          }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}||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         }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         }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   LookupUnavailablec                  (    e Zd ZdZdZdd fd
ZdS )Utest_provider_status_probe_distinguishes_error_categories.<locals>.AuthFailedProviderr2  dummyNrp  c                    d          )Nopenfigi_auth_failedr   rR  r   r8   rR  s      r   rz  z\test_provider_status_probe_distinguishes_error_categories.<locals>.AuthFailedProvider.search  s    ##$:;;;r   rV  rW  rX  r9   r\  rz  rQ  s   r   AuthFailedProviderrT    sE        /3 	< 	< 	< 	< 	< 	< 	< 	< 	<r   rZ  c                  (    e Zd ZdZdZdd fd
ZdS )Xtest_provider_status_probe_distinguishes_error_categories.<locals>.NetworkFailedProviderr3  rU  Nrp  c                    d          )Nfmp_network_errorr   rX  s      r   rz  z_test_provider_status_probe_distinguishes_error_categories.<locals>.NetworkFailedProvider.search  s    ##$7888r   rY  rQ  s   r   NetworkFailedProviderr\    sE        /3 	9 	9 	9 	9 	9 	9 	9 	9 	9r   r_  c                  "    e Zd ZdZdZdddZdS )Ttest_provider_status_probe_distinguishes_error_categories.<locals>.NoResultsProviderr4  rU  Nrp  c                   g S r   r   r  s      r   rz  z[test_provider_status_probe_distinguishes_error_categories.<locals>.NoResultsProvider.search  s    Ir   rY  r   r   r   NoResultsProviderra    s:        /3 	 	 	 	 	 	 	r   rc  r-  r  FinnhubSymbolLookupProviderT)probec                     i | ]}|d          |S r  r   r  s     r   
<dictcomp>zMtest_provider_status_probe_distinguishes_error_categories.<locals>.<dictcomp>  s    <<<C3z?C<<<r   r  r%  auth_failedrH   rJ   rK   rN   rO   r  zAuth fehlgeschlagenr  network_errorNetzwerkfehlerr  
no_resultszKeine Treffer)r_  market_datacatalog%jarvis_finance.market_data.candidatesrR  r  r   rh   ri   rj   rk   rl   )rf  rm  rZ  r_  rc  r  by_providerrs   rt   ru   rv   rw   rR  s               @r   9test_provider_status_probe_distinguishes_error_categoriesrp    sW   888888888GGGGGG< < < < < < < < < <9 9 9 9 9 9 9 9 9 9        !9;MNNN!46KLLL!>@QRRR33$3??H<<8<<<Kz";/@=@/=@@@@@@@@@@/=@@@@@/@@@@=@@@@@@@@@@@@@@@@@@@@@@@@@@@z"8,E0EE,0EEEEEEEEEEE,0EEEEEE,EEEE0EEEEEEEEEEEEEEEEEEEEEEEEEEEEuk*=o=*o==========*o=====*====o===========================uh';+;;'+;;;;;;;;;;;'+;;;;;;';;;;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;y!+.>,>.,>>>>>>>>>>.,>>>>>.>>>>,>>>>>>>>>>>>>>>>>>>>>>>>>>>y!(+>>+>>>>>>>>>>+>>>>>+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>r   c                *   |dz  }|dz  }|                     d           |dz                      dd           |                     d	t          |                     |                     d
d           |                     dd           t                      }|                                }t          |          |j        z   |j        z   }d}||v}	|	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}||v}	|	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 )Nr  r<  Tr  r=  zDOPENFIGI_API_KEY=super-secret-openfigi
FMP_API_KEY=super-secret-fmp
r>  r?  r;  r7  Fr8  r  zsuper-secret-openfigir#  r%  textr!  r"  r]   zsuper-secret-fmp)rb  rc  ra  r   r`  r   
readouterrouterrrh   ri   rj   rm   rn   ro   rk   rl   )rf  rg  capsysr  r<  r  r2  rr  rs   ru   r*  r~   s               r   9test_provider_status_does_not_log_or_return_secret_valuesrw    sl   "G	!GMM$Mv!!"y  EL!  M  M  M3S\\BBB)5999}e444+--H  ""Hx==8<'(,6D"."$.........."$....."...........$.....$...........................)T))))))))))T))))))))))))))))T)))))T)))))))))))))))))))))))))))))r   c                    ddl m} m} ddlm} g  G fdd|          } |d                              dd	
          } |d                              dd	
          } |d                              dd	
          }g }|}|r|}|r|}|sOdddt          j                    v st          j	        |          rt          j
        |          ndiz  }	|                    |	           |rdddt          j                    v st          j	        |          rt          j
        |          ndiz  }
|                    |
           |rYdddt          j                    v st          j	        |          rt          j
        |          ndiz  }|                    |           t          j        |d          i z  }dd|iz  }t          t          j        |                    d x}}|d         }|j        }d}||k    }|st          j        d|fd||f          t          j
        |          t          j
        |          t          j
        |          dz  }dd|iz  }t          t          j        |                    d x}x}x}}|d         }|j        }d}||k    }|st          j        d|fd||f          t          j
        |          t          j
        |          t          j
        |          dz  }dd|iz  }t          t          j        |                    d x}x}x}}|d         }|j        }d}||k    }|st          j        d|fd ||f          t          j
        |          t          j
        |          t          j
        |          dz  }dd|iz  }t          t          j        |                    d x}x}x}}d! D             }t'          |          }|sd"d#t          j                    v st          j	        t&                    rt          j
        t&                    nd#t          j
        |          t          j
        |          d$z  }
t          t          j        |
                    d x}}d% D             }t'          |          }|sd"d#t          j                    v st          j	        t&                    rt          j
        t&                    nd#t          j
        |          t          j
        |          d$z  }
t          t          j        |
                    d x}}d& D             }t'          |          }|sd"d#t          j                    v st          j	        t&                    rt          j
        t&                    nd#t          j
        |          t          j
        |          d$z  }
t          t          j        |
                    d x}} |  |d                   j                  }|d'         }dg}||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?  rB  c                       e Zd Zdd fd
ZdS )\test_fmp_stable_isin_symbol_name_and_profile_price_preview_are_normalized.<locals>.StableFmpNr-  c                                        |           d|v r	ddddddgS d|v rddddd	gS d
|v rddddd	gS d|v rddddd	gS d|v r
dddddddgS g S )N/stable/search-isinr  r  r  r  r   )r  r9   r  r:   r=   /stable/search-symbolr  z /stable/search-exchange-variants/stable/search-namerF  TrK  {Gjo@)r  r:   r=   r  r  r  rG  rI  s      r   rJ  zftest_fmp_stable_isin_symbol_name_and_profile_price_preview_are_normalized.<locals>.StableFmp._get_json$  s$   OOC   $++#(2Sjp  {I  W\  ]  ]  ^  ^&#--#(2Sjp  D  E  E  F  F1S88#(2Sjp  D  E  E  F  F$++#(2Sjp  D  E  E  F  F C''#(.e^bos  E  F  F  G  GIr   rK  r5  s   r   	StableFmprz  #  s;        ,0 	 	 	 	 	 	 	 	 	r   r  r!  r[  r  r  r  r  r  z%(py2)src   	isin_rowsz%(py4)srM   	name_rowsz%(py6)srO   ticker_rowsr   r   rH   r  r]  r^  r^   r  )z2%(py3)s
{%(py3)s = %(py1)s.last_price
} == %(py6)szfmp profile)z4%(py3)s
{%(py3)s = %(py1)s.price_source
} == %(py6)sc              3     K   | ]}d |v V  	dS )r|  Nr   r   r0  s     r   r  z\test_fmp_stable_isin_symbol_name_and_profile_price_preview_are_normalized.<locals>.<genexpr>9  (      @@$+@@@@@@r   r  r  r  c              3     K   | ]}d |v V  	dS )r}  Nr   r  s     r   r  z\test_fmp_stable_isin_symbol_name_and_profile_price_preview_are_normalized.<locals>.<genexpr>:  s(      BB#&#-BBBBBBr   c              3     K   | ]}d |v V  	dS )r~  Nr   r  s     r   r  z\test_fmp_stable_isin_symbol_name_and_profile_price_preview_are_normalized.<locals>.<genexpr>;  r  r   r8  rJ   rK   rN   )rM  r@  rA  r_  r  rz  rm   rn   rh   ro   rj   rH  _format_booloprk   rl   r:   ri   r
  r  r  r   )r@  rA  r  r  r  r  r  r}   rs   @py_format3rv   rw   r   r   ru   r   rx   r{   rt   first_qsr2  s                       @r   Itest_fmp_stable_isin_symbol_name_and_profile_price_preview_are_normalizedr    s   ////////DDDDDDH      %    	+...55NX]5^^I	+...55<R`e5ffI)K00077eQV7WWK22929222{2222222222222292222292222222222222292222222222222222222222222222222222222222222{22222{222222222222222222222222222222222222222222Q<.<.................<.....................................Q<.<".h."h.........."h.....<...."....h.............................Q<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@@x@@@@3@@@@@@@@@@@@@@@@3@@@@@3@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@BBBBBB3BBBBBBBBBBBBBBBB3BBBBB3BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB@@x@@@@3@@@@@@@@@@@@@@@@3@@@@@3@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@x!--344HH.+.................................................r   c                    ddl m} m} ddlm} g  G fdd|          } |d                              d          }|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        }
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        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}
x}x}}|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        |          dz  }dd|iz  }	t          t          j        |	                    d x}x}}d         }|j        }
d} |
|          }|ssdt          j        |          t          j        |
          t          j        |          t          j        |          dz  }	t          t          j        |	                    d x}x}
x}}d S )Nr   r?  )r   c                      e Zd Zd fdZdS )Ttest_fmp_price_provider_uses_stable_profile_without_logging_key.<locals>.StablePricepathr   paramsdict[str, str]c           
                              |dz   d                    d t          |                                          D                       z              ddddgS )N?&c              3  *   K   | ]\  }}| d | V  dS )=Nr   )r   kvs      r   r  zqtest_fmp_price_provider_uses_stable_profile_without_logging_key.<locals>.StablePrice._get_json.<locals>.<genexpr>H  s0      1`1`AQ****1`1`1`1`1`1`r   r  r  r   )r  r  r=   )rH  joinsorteditems)rR  r  r  r2  s      r   rJ  z^test_fmp_price_provider_uses_stable_profile_without_logging_key.<locals>.StablePrice._get_jsonG  sa    OOD3J1`1`PVP\P\P^P^I_I_1`1`1`)`)``aaa$v5IIJJr   N)r  r   r  r  rK  r5  s   r   StablePricer  F  s;        	K 	K 	K 	K 	K 	K 	K 	Kr   r  r!  r[  r  )is not)z1%(py2)s
{%(py2)s = %(py0)s.close
} is not %(py5)sr  rb   rd   re   r  rH   )zK%(py5)s
{%(py5)s = %(py0)s(%(py3)s
{%(py3)s = %(py1)s.close
})
} == %(py8)sr   rZ   r_   r`   r   )z0%(py2)s
{%(py2)s = %(py0)s.currency
} == %(py5)sz/stable/profile?r  r  )rM  r@  rA  !jarvis_finance.market_data.pricesr   r  r	  rh   ri   rm   rn   ro   rj   rk   rl   r   r=   r  )r@  rA  r   r  r  r}   rx   rt   r~   r   ru   ry   rz   r{   r|   rs   r2  s                   @r   ?test_fmp_price_provider_uses_stable_profile_without_logging_keyr  @  s;   ////////HHHHHHHK K K K K K K, K K K
 K,,,66u==E;"d";d"""""""""";d""""""""""""5"""""5"""""";""""d"""""""""""""""""""""""""""{'3{'x'x''''''''''x''''''''''''3'''''3'''''''''''''u'''''u''''''{''''''''x'''''''''''''''''''''''''''''>"U">U"""""""""">U""""""""""""5"""""5"""""">""""U"""""""""""""""""""""""""""A;5;!5"45!!"455555555;5555!5555"4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5r   c                   ddl m} ddlm} ddlm} ddlm  G fdd|          }	  |d	                              d
d           t          d          # $ r+}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}t          |          }||v}|st          j        d|fd||f          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}}Y d }~d S d }~ww xY w)Nr   )	HTTPError)BytesIOr*  rQ  c                       e Zd Zdd fd
ZdS )Ytest_openfigi_429_is_reported_as_rate_limited_without_secret.<locals>.RateLimitedOpenFigiNr-  c                    d          )Nopenfigi_rate_limitedr   )rR  r0  r1  r.  rR  s       r   r3  zdtest_openfigi_429_is_reported_as_rate_limited_without_secret.<locals>.RateLimitedOpenFigi._post_jsonY  s    ##$;<<<r   r4  rQ  s   r   RateLimitedOpenFigir  X  s;        6: 	= 	= 	= 	= 	= 	= 	= 	= 	=r   r  r   r[  r  r  r  zexpected rate limitr  rH   r  r   excr   r^  r^   r#  )z4%(py1)s not in %(py6)s
{%(py6)s = %(py3)s(%(py4)s)
})rL   r\   rM   rO   )urllib.errorr  ior  r_  r-  rn  rR  rz  rk   r   rh   ri   rm   rn   ro   rj   rl   )rf  r  r  r-  r  r  ru   r   rx   rw   r{   rs   rR  s               @r   <test_openfigi_429_is_reported_as_rate_limited_without_secretr  R  s/   &&&&&&IIIIIIGGGGGG= = = = = = =4 = = =4$4555<<>_d<eee
 2333	  0 0 03xx222x22222222222x2222222222222s22222s22222222222223222223222222x22222222222222222222222222222222/s3xx/x//////////x////////////////s/////s/////////////3/////3//////x/////////////////////////////////0s   !A J!H JJc                    ddl m} m}  G d d          }t                      } ||ddg           \  }}g }||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}}g }||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 )Nr   )r   r/  c                      e Zd ZdZdddZdS )Ttest_online_search_not_called_when_include_external_false.<locals>.ExplodingProvidershould_not_runNrp  c                    t          d          )Nz,provider was called during local-only search)rk   r  s      r   rz  z[test_online_search_not_called_when_include_external_false.<locals>.ExplodingProvider.searchj  s     !OPPPr   r{  r   r   r   ExplodingProviderr  h  s<        /3 	Q 	Q 	Q 	Q 	Q 	Q 	Qr   r  r  r  rC  rH   rE  rp   rF  r"  r]   r  )r_  r   r/  r   rh   ri   rm   rn   ro   rj   rk   rl   )
r   r/  r  r   r  rp   ru   r}   r*  r~   s
             r   9test_online_search_not_called_when_include_external_falser  e  s   ZZZZZZZZQ Q Q Q Q Q Q Q
 <<D''eUbIIIND(8r>8r88r42:42442r   )r   )r   r   r   r   )r(   r   r   r)   r  )B
__future__r   builtinsrm   _pytest.assertion.rewrite	assertionrewriterh   decimalr   r   jarvis_finance.equity.manager   r   r   r   r	   r
   jarvis_finance.ledger.positionsr   r_  r   r   r  r   r   r   r   jarvis_finance.storage.databaser   !jarvis_finance.storage.migrationsr   r   r'   r-   r   r   r   r   r   r   r   r
  r  r+  rh  r  r  r  r  r  r  r  r  r  r  r  r(  r=  rO  rp  rw  r  r  r  r  r   r   r   <module>r     sF   " " " " " "                                     @ ? ? ? ? ? ` ` ` ` ` ` ` ` I  I  I  I  I  I  I  I  I  I  I  I : : : : : : > > > > > >      i i i i !  !  !  !F%0 %0 %0 %0Pl l l l:/
 /
 /
 /
d.
 .
 .
 .
b16 16 16 16hF F F FDv Dv Dv DvN:, :, :, :,zA A A A8   4B B B B*a a a a a a a aU U U U*B B B B$g g g g. . . .. . . .80 0 0 0DM M M M 	% 	% 	% 	%* * * *` ` ` `*J J J J&7 7 7 7( ?  ?  ?  ?F* * * * /  /  /  /F6 6 6 6$4 4 4 4&     r   