
    {jk+                    p   d dl mZ d dlZd dlmc mZ d dlZd dl	m
Z
 d dlmZ d dlmZ d dlZd dlmZ d dlmZmZ d dlmZmZmZmZmZmZ d d	lmZ d d
lmZ d dl m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z' d dl(m)Z) d dl*m+Z+  G d d          Z,d Z-ddZ.ddZ/ddZ0ddZ1ddZ2ddZ3ddZ4ddZ5ddZ6ddZ7ddZ8ddZ9dS )     )annotationsN)Decimal)BytesIO)	HTTPError)main)FrankfurterFxProviderTwelveDataFxProvider)MassiveLookupProviderOpenFigiLookupProviderTwelveDataLookupProvider_runtime_secret_value#default_instrument_lookup_providersinstrument_provider_statuses)LookupUnavailable) confirm_instrument_price_mapping)EodhdEquityPriceProviderCompositeEquityPriceProviderFinnhubEquityPriceProviderMassiveEquityPriceProviderTwelveDataEquityPriceProviderequity_price_provider_by_namerefresh_market_prices)connect_memory)apply_migrationsc                  ,    e Zd ZdddZd	 Zd
 ZddZdS )FakeResponseNpayloadobjectheadersdict[str, str] | NonereturnNonec                &    || _         |pi | _        d S N)r   r   )selfr   r   s      S/home/agent/.hermes/repos/FinanceManager/tests/unit/test_provider_integration_v2.py__init__zFakeResponse.__init__$   s    }"    c                    | S r$    r%   s    r&   	__enter__zFakeResponse.__enter__(   s    r(   c                    dS )NFr*   )r%   argss     r&   __exit__zFakeResponse.__exit__+   s    ur(   bytesc                Z    t          j        | j                                      d          S )Nutf-8)jsondumpsr   encoder+   s    r&   readzFakeResponse.read.   s"    z$,''..w777r(   r$   )r   r   r   r    r!   r"   )r!   r0   )__name__
__module____qualname__r'   r,   r/   r6   r*   r(   r&   r   r   #   s_        % % % % %    8 8 8 8 8 8r(   r   c                     t                      } t          |            |                     d           |                     d           |                     d           | S )Nz|INSERT INTO platforms(platform_id,name,platform_type,default_currency,created_at) VALUES('p1','Broker','broker','CHF','now')zINSERT INTO accounts(account_id,platform_id,account_name,account_type,currency,created_at) VALUES('a1','p1','Account','brokerage','CHF','now')zINSERT INTO instruments(instrument_id,asset_class,name,ticker,isin,exchange,currency,created_at) VALUES('usd1','ETF','USD ETF','VTI','US9229087690','NYSE','USD','now'))r   r   execute)conns    r&   
setup_connr=   2   s}    DTLL  P  Q  Q  QLL  b  c  c  cLL  {  |  |  |Kr(   r!   r"   c                   |                      dd           |                     dt          |                     |dz  }|                                 |dz  }|                    d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}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}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 S )NOPENFIGI_API_KEYF)raisingJARVIS_FINANCE_RUNTIME_DIRsecretsz.envzHTWELVEDATA_API_KEY=td
MASSIVE_API_KEY=mass
JARVIS_OPENFIGI_API_KEY=figi
r2   )encodingi  )TWELVEDATA_API_KEYTWELVE_DATA_API_KEYtd==)z0%(py4)s
{%(py4)s = %(py0)s(%(py2)s)
} == %(py7)sr   )py0py2py4py7assert %(py9)spy9)MASSIVE_API_KEYJARVIS_MASSIVE_API_KEYmass)r?   JARVIS_OPENFIGI_API_KEYfigi)delenvsetenvstrmkdir
write_textchmodr   
@pytest_ar_call_reprcompare@py_builtinslocals_should_repr_global_name	_safereprAssertionError_format_explanation)
monkeypatchtmp_pathrB   env_file@py_assert1@py_assert3@py_assert6@py_assert5@py_format8@py_format10s
             r&   :test_runtime_secret_aliases_include_new_provider_key_namesrk   ;   s   )59993S]]CCC"GMMOOOH~  JQ  R  R  RNN5!NW !NOOWSWWOSWWWWWWWWWWWOSWWWWWWWWWWWWW WWWWW WWWWWW!NWWWWOWWWWSWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW!NY !NOOYSYYOSYYYYYYYYYYYOSYYYYYYYYYYYYY YYYYY YYYYYY!NYYYYOYYYYSYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY!P[ !PQQ[U[[QU[[[[[[[[[[[QU[[[[[[[[[[[[[ [[[[[ [[[[[[!P[[[[Q[[[[U[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[r(   c                    d }|                      d|           t          dd          }t          j        t          d          5  |                    dd	
           d d d            d S # 1 swxY w Y   d S )Nc                 @    t          dddi t                                )Nz#https://api.openfigi.com/v3/mappingi  Unauthorized)r   r   )r.   kwargss     r&   failz<test_openfigi_401_is_auth_failed_without_crash.<locals>.failJ   s!    =sNTVX_XaXabbbr(   z2jarvis_finance.market_data.catalog.request.urlopen	syntheticr   api_keymin_interval_secondsopenfigi_auth_failed)matchUS9229087690etfqueryasset_class)setattrr   pytestraisesr   search)rb   rp   providers      r&   .test_openfigi_401_is_auth_failed_without_crashr   I   s    c c c LdSSS%kPQRRRH	(0F	G	G	G A An%@@@A A A A A A A A A A A A A A A A A As   A++A/2A/c                   t          d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}||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 )Nrq   r   rr   
_post_jsonc                     dddddddgigS )NdataBBG000VTIVanguard Total Stock Market ETFUSUSD)rS   tickernameexchCodecurrencyr*   aks     r&   <lambda>zCtest_openfigi_isin_mapping_mock_returns_candidate.<locals>.<lambda>V   sD    &T\hm  xY  gk  y~  L  L  K@  BA  AB r(   rw   rx   ry   zassert %(py0)srI   resultsopenfigirG   )z0%(py3)s
{%(py3)s = %(py1)s.provider
} == %(py6)s)py1py3py6assert %(py8)spy8r   )z.%(py3)s
{%(py3)s = %(py1)s.ticker
} == %(py6)s)r   r|   r   r\   r]   rZ   r^   r_   r`   ra   r   r[   r   )
rb   r   r   @py_format1@py_assert0@py_assert2rh   @py_assert4@py_format7@py_format9s
             r&   1test_openfigi_isin_mapping_mock_returns_candidater   T   s,   %kPQRRRH,  1B  1B  C  C  CooNoFFGNNNNNNNNNNNN7NNNNN7NNNNNNNNNNNNNNNN1:,:,*,*,,,,,,,,,,*,,,,,:,,,,,,,,*,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1:%:%%%%%%%%%%%%%%%%%:%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%r(   c                	   |                      dt          |                     d t                      D             }g 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}}t          d
          }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}|	|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}}t          j        |          }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        |
          t          j        |          dz  }dd |iz  }t          t          j
        |                    d x}	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        |
          t          j        |          dz  }dd |iz  }t          t          j
        |                    d x}	x}x}
}d S )"NrA   c                    g | ]	}|j         
S r*   r   .0ps     r&   
<listcomp>zPtest_provider_priority_and_dashboard_status_without_key_leak.<locals>.<listcomp>a   s    GGGAGGGr(   )r   fmpfinnhub
twelvedatamassiverG   )z%(py0)s == %(py3)s	providers)rI   r   zassert %(py5)spy5F)probec                     i | ]}|d          |S Providerr*   )r   rows     r&   
<dictcomp>zPtest_provider_priority_and_dashboard_status_without_key_leak.<locals>.<dictcomp>e   s    333sc*os333r(   EODHDHinweiszEODHD_API_KEY; Low-volumezLassert %(py7)s
{%(py7)s = %(py3)s
{%(py3)s = %(py1)s.startswith
}(%(py5)s)
})r   r   r   rL   zFrankfurter FXStatusaktivz%(py1)s == %(py4)sr   rK   assert %(py6)sr   Stooqu
   verfügbarapikeynot in)zH%(py1)s not in %(py7)s
{%(py7)s = %(py5)s
{%(py5)s = %(py3)s.lower
}()
}renderedrM   rN   rq   )rU   rV   r   rZ   r[   r\   r]   r^   r_   r`   ra   r   
startswithr3   r4   lower)rb   rc   r   r   re   @py_format4@py_format6rowslabelsr   r   rg   ri   rf   @py_format5r   r   rj   s                     r&   <test_provider_priority_and_dashboard_status_without_key_leakr   _   sN   3S]]CCCGG!D!F!FGGGIOOOO9OOOOOOOOOOO9OOOOOOOOOOOOO9OOOOO9OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO'e444D33d333F'?9%M%0M1LM001LMMMMMMMM%MMMM0MMMM1LMMMMMMMMMMMMMMMMMMMMMMMMMMMM"#H-88-8888888888-88888-8888888888888888888888888888888'?8$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z$H+8>+>>+++8+++++++++++8++++++8+++++++++++8+++++8++++++>++++++++++++++++++++++++++++++++++.hn.nn...;...........;......;...........h.....h......n....................................r(   c                H   g dfd}|                      d|           ddlm}  |dd                              d	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}}|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}}|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}}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 S )NurlrV   c                n                         |           d|v rddddgiS d|v rddd	d
S d|v rddiS i S )Nz/search?resultr   r   )symboldescriptionz/stock/profile2?r   	NYSE ARCAr   )r   exchangecountry/quote?cp=
Co@)append)r%   r   ro   callss      r&   fake_get_jsonzJtest_finnhub_lookup_mock_enriches_profile_and_quote.<locals>.fake_get_jsonq   sl    S%@abbcdd$$ %;4PPP= 	r(   zHjarvis_finance.market_data.catalog.FinnhubSymbolLookupProvider._get_jsonr   )FinnhubSymbolLookupProviderrq   rr   r   rx   ry   r   rG   z0%(py2)s
{%(py2)s = %(py0)s.provider
} == %(py5)sr   rI   rJ   r   assert %(py7)srL   r   z0%(py2)s
{%(py2)s = %(py0)s.exchange
} == %(py5)s250.12)z2%(py2)s
{%(py2)s = %(py0)s.last_price
} == %(py5)s   )z0%(py3)s
{%(py3)s = %(py0)s(%(py1)s)
} == %(py6)slenr   )rI   r   r   r   r   r   )r   rV   )r|   "jarvis_finance.market_data.catalogr   r   r   rZ   r[   r\   r]   r^   r_   r`   ra   r   
last_pricer   )rb   r   r   r   re   r   rf   r   ri   r   rh   r   r   r   s                @r&   3test_finnhub_lookup_mock_enriches_profile_and_quoter   n   s>   E      bdqrrrNNNNNN((STUUU\\chv{\||}~F?'i'?i''''''''''?i''''''''''''6'''''6''''''?''''i'''''''''''''''''''''''''''?)k)?k))))))))))?k))))))))))))6)))))6))))))?))))k)))))))))))))))))))))))))))((((((((((((((((((((((((6(((((6(((((((((((((((((((((((((((((((((((((u:::?:33uu:r(   c                <   |                      dd           |                     dd            t          d                              d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}}|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}}|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 S )NrD   rq   zEjarvis_finance.market_data.catalog.TwelveDataLookupProvider._get_jsonc                    ddddddddgiS )	Nr   r   zVanguard Total StockNYSEr   zUnited StatesETF)r   instrument_namer   r   r   instrument_typer*   r%   r   ro   s      r&   r   z=test_twelvedata_symbol_lookup_and_key_alias.<locals>.<lambda>   sQ      E  SX  mC  QW  ej  wF  [`  Ha  Ha  Gb  ~c r(   r   )rt   r   rx   ry   r   rG   r   r   r   r   rL   z.%(py2)s
{%(py2)s = %(py0)s.ticker
} == %(py5)sr   )z8%(py2)s
{%(py2)s = %(py0)s.trading_currency
} == %(py5)s)rU   r|   r   r   r   rZ   r[   r\   r]   r^   r_   r`   ra   r   trading_currency)rb   r   re   r   rf   r   ri   s          r&   +test_twelvedata_symbol_lookup_and_key_aliasr      s   +[999_  bc  bc  d  d  d%1===DD5^cDddefgF?*l*?l**********?l************6*****6******?****l***************************=!E!=E!!!!!!!!!!=E!!!!!!!!!!!!6!!!!!6!!!!!!=!!!!E!!!!!!!!!!!!!!!!!!!!!!!!!!!"+e+"e++++++++++"e++++++++++++6+++++6++++++"++++e+++++++++++++++++++++++++++++r(   c                &   ddd}|                      t          d|           t          dd                              d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}}|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}}|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 S )NpathrV   c                2    |dk    r
ddddddgiS dddd	d
iS )Nz/v3/reference/tickersr   r   r   ARCXr   )r   r   primary_exchangetyper   us)r   currency_namelocaler*   )r%   r   paramss      r&   fake_massive_jsonz=test_massive_reference_lookup_mock.<locals>.fake_massive_json   sS    ***5:[qw  BG  !H  !H   I  J  JeetTTUUr(   _massive_jsonrq   r   rr   r   rx   ry   r   rG   r   r   r   r   rL   r   r   r   r$   )r   rV   )r|   r
   r   r   rZ   r[   r\   r]   r^   r_   r`   ra   r   r   )rb   r   r   re   r   rf   r   ri   s           r&   "test_massive_reference_lookup_mockr      s   V V V V V
 -@QRRR";QOOOVV]bpuVvvwxyF?'i'?i''''''''''?i''''''''''''6'''''6''''''?''''i'''''''''''''''''''''''''''=!E!=E!!!!!!!!!!=E!!!!!!!!!!!!6!!!!!6!!!!!!=!!!!E!!!!!!!!!!!!!!!!!!!!!!!!!!!?$f$?f$$$$$$$$$$?f$$$$$$$$$$$$6$$$$$6$$$$$$?$$$$f$$$$$$$$$$$$$$$$$$$$$$$$$$$$$r(   c                   |                      t          dd            |                      t          dd            |                      t          dd            d}t          |          }|j        }d} ||          }|j        }d	}t          |          }||k    }	|	snt          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        |          t          j        |          t          j        |          t          j        |          dt          j
                    v st          j        t                    rt          j        t                    ndt          j        |          t          j        |          d
z  }
dd|
iz  }t          t          j        |                    d x}x}x}x}x}x}x}	x}}d}t          |          }|j        }d} ||          }|j        }d}t          |          }||k    }	|	snt          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        |          t          j        |          t          j        |          t          j        |          dt          j
                    v st          j        t                    rt          j        t                    ndt          j        |          t          j        |          d
z  }
dd|
iz  }t          t          j        |                    d x}x}x}x}x}x}x}	x}}d}t          |          }|j        }d} ||          }|j        }d}t          |          }||k    }	|	snt          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        |          t          j        |          t          j        |          t          j        |          dt          j
                    v st          j        t                    rt          j        t                    ndt          j        |          t          j        |          d
z  }
dd|
iz  }t          t          j        |                    d x}x}x}x}x}x}x}	x}}d}t          |          }t!          |t                    }|s8ddt          j
                    v st          j        t                     rt          j        t                     nddt          j
                    v st          j        t                    rt          j        t                    ndt          j        |          t          j        |          dt          j
                    v st          j        t                    rt          j        t                    ndt          j        |          dz  }t          t          j        |                    d x}x}}d}t          |          }t!          |t"                    }|s8ddt          j
                    v st          j        t                     rt          j        t                     nddt          j
                    v st          j        t                    rt          j        t                    ndt          j        |          t          j        |          dt          j
                    v st          j        t"                    rt          j        t"                    ndt          j        |          dz  }t          t          j        |                    d x}x}}d S )N	_json_urlc                    d|v rddinddiS )Nr   r   r   r   r   r*   r   s      r&   r   z9test_equity_price_providers_mock_quotes.<locals>.<lambda>   s1    nw{~n~n~^aci]j]j  FP  RW  EX r(   c                    ddddS )N250.13r   
2026-05-16)closer   datetimer*   r   s      r&   r   z9test_equity_price_providers_mock_quotes.<locals>.<lambda>   s#    jr  AF  T`  aa  aa r(   r   c                    dddigiS )Nr   r   gGzDo@r*   )r%   r   s     r&   r   z9test_equity_price_providers_mock_quotes.<locals>.<lambda>   s    YbfikqerdsXt r(   rq   rs   r   r   rG   )z%(py12)s
{%(py12)s = %(py10)s
{%(py10)s = %(py6)s
{%(py6)s = %(py4)s
{%(py4)s = %(py0)s(api_key=%(py2)s)
}.get_price
}(%(py8)s)
}.close
} == %(py18)s
{%(py18)s = %(py14)s(%(py16)s)
}r   r   
rI   rJ   rK   r   r   py10py12py14py16py18assert %(py20)spy20r   r   z250.14r   r   Sassert %(py8)s
{%(py8)s = %(py0)s(%(py5)s
{%(py5)s = %(py1)s(%(py3)s)
}, %(py6)s)
}
isinstancer   rI   r   r   r   r   r   autor   )r|   r   r   r   	get_pricer   r   rZ   r[   r\   r]   r^   r_   r`   ra   r   r  r   )rb   re   rf   rh   @py_assert7@py_assert9@py_assert11@py_assert15@py_assert17@py_assert13@py_format19@py_format21r   r   r   s                  r&   'test_equity_price_providers_mock_quotesr     s   2K  BX  BX  Y  Y  Y5{  Ea  Ea  b  b  b2OEtEtuuu.9f%k:::f:DfUfDDUKKfKQf]efU\]eUfUffQUfffffffffffQUfffffffffffff%fffff%ffffffkffff:ffffDffffUffffKffffQfffffffffffU\fffffU\ffffff]effffUf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fffff1<i(===i=GiiGGNNiNTi`hiX_`hXiXiiTXiiiiiiiiiiiTXi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GiiiiiiiiNiiiiTiiiiiiiiiiiX_iiiiiX_iiiiii`hiiiiXi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.9f%k:::f:DfUfDDUKKfKQf]efU\]eUfUffQUfffffffffffQUfffffffffffff%fffff%ffffffkffff:ffffDffffUffffKffffQfffffffffffU\fffffU\ffffff]effffUf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fffff4@a3LAAa:AC`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3aaaaa3aaaaaaLaaaaAaaaaaaaaaaaC`aaaaaC`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a4:Z3F;;Z:;=YZZZZZZZZZZZZZZZ:ZZZZZ:ZZZZZZZZZZZZZ3ZZZZZ3ZZZZZZFZZZZ;ZZZZZZZZZZZ=YZZZZZ=YZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZr(   c                    ddl m  G fdd          }  G fdd          }t           |              |            g                              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}}|j        }d}t          |          }	||	k    }|st          j        d	|fd||	f          dt          j                    v st          j	        |          rt          j
        |          ndt          j
        |          dt          j                    v st          j	        t                    rt          j
        t                    ndt          j
        |          t          j
        |	          dz  }
dd|
iz  }t          t          j        |                    d x}x}x}}	d S )Nr   EquityPriceQuotec                  &    e Zd ZdZddd	 fdZdS )
Qtest_composite_equity_price_provider_uses_priority_order.<locals>.MissingProviderr   N
price_dateprovider_symbolrV   r  
str | Nonec               0     |dd | j         dd          S )N missingrestricted_endpoint)r   r   r   r   quality_statuserror_messager   r%   r   r  r  s      r&   r  z[test_composite_equity_price_provider_uses_priority_order.<locals>.MissingProvider.get_price   s<    ##ObX\gkgp  BK  [p  q  q  q  qr(   r   rV   r  r!  r7   r8   r9   r   r  r  s   r&   MissingProviderr     sO        NR 	q 	q 	q 	q 	q 	q 	q 	q 	q 	qr(   r+  c                  &    e Zd ZdZddd	 fdZdS )
Otest_composite_equity_price_provider_uses_priority_order.<locals>.FreshProviderr   Nr  r   rV   r  r!  c               H     |dt          d          | j        d          S )Nr   250.15freshr   r   r   r   r&  )r   r   r(  s      r&   r  zYtest_composite_equity_price_provider_uses_priority_order.<locals>.FreshProvider.get_price   sB    ##Oe[bck[l[lw{  xA  RY  Z  Z  Z  Zr(   r)  r*  r  s   r&   FreshProviderr-     sO        NR 	Z 	Z 	Z 	Z 	Z 	Z 	Z 	Z 	Z 	Zr(   r2  r   r   rG   r   quoter   r   rL   r/  )zK%(py2)s
{%(py2)s = %(py0)s.close
} == %(py8)s
{%(py8)s = %(py4)s(%(py6)s)
}r   )rI   rJ   rK   r   r   zassert %(py10)sr  )!jarvis_finance.market_data.pricesr  r   r  r   rZ   r[   r\   r]   r^   r_   r`   ra   r   r   )r+  r2  r3  re   r   rf   r   ri   rh   r  r   @py_format11r  s               @r&   8test_composite_equity_price_provider_uses_priority_orderr6     s   BBBBBBq q q q q q q q q q
Z Z Z Z Z Z Z Z Z Z
 )//*;*;]]__)MNNXXY^__E>)\)>\))))))))))>\))))))))))))5)))))5))))))>))))\)))))))))))))))))))))))))));+(+'(+++;+++++++++++;+++++++++++++5+++++5++++++;+++++++++++'+++++'++++++(++++++++++++++++++++++++++++++++++++r(   c           	     ~   d}d t                      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}t          |          }t          |t                    }|s8dd	t          j
                    v st          j        t                    rt          j        t                    nd	d
t          j
                    v st          j        t                    rt          j        t                    nd
t          j        |          t          j        |          dt          j
                    v st          j        t                    rt          j        t                    ndt          j        |          dz  }t	          t          j        |                    d x}x}}t          j        t                    5  t          g d           d d d            d S # 1 swxY w Y   d S )Neodhdc                    g | ]	}|j         
S r*   r   r   s     r&   r   zJtest_eodhd_is_explicit_low_volume_provider_not_default.<locals>.<listcomp>   s    QQQa16QQQr(   r   )z%(py1)s not in %(py4)sr   r   r   r  r  r   r   r  )zupdate-equity-pricesz
--providerr8  z	--dry-runz--limit0)r   rZ   r[   r_   r`   ra   r   r  r   r\   r]   r^   r}   r~   
SystemExitr   )	rb   r   rf   r   r   r   r   r  r   s	            r&   6test_eodhd_is_explicit_low_volume_provider_not_defaultr<     s   QQQ+N+P+PQQQQ7QQQQQQQQQQQ7QQQQQQ7QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ4;W3G<<W:<>VWWWWWWWWWWWWWWW:WWWWW:WWWWWWWWWWWWW3WWWWW3WWWWWWGWWWW<WWWWWWWWWWW>VWWWWW>VWWWWWWWWWWWWWWWWWWWWWWWWWWWW	z	"	" [ [YYYZZZ[ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [s   H22H69H6c            	        t                      } t          | dddddd            G fdd	          t          |              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}}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         }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 )Nusd1r   r   r   manualztest mapping)instrument_idr   r   provider_market
confidencenotec                  *    e Zd ZdZdZddd
 fd	ZdS )Htest_refresh_market_prices_uses_explicit_provider_only.<locals>.Providerr   r   Nr  r   rV   r  r!  c               j    xj         dz  c_         ddlm}  ||dt          d          dd          S )	N   r   r  r   r   r   r0  r1  )r   r4  r  r   )r%   r   r  r  r   s       r&   r  zRtest_refresh_market_prices_uses_explicit_provider_only.<locals>.Provider.get_price   sa    NNaNNJJJJJJ##Oe[bck[l[l  xD  U\  ]  ]  ]  ]r(   r)  )r7   r8   r9   r   r   r  r   s   r&   r   rE     sT        NR 	] 	] 	] 	] 	] 	] 	] 	] 	] 	]r(   r   rx   r   )r   r{   r  rG  rG   )z5%(py2)s
{%(py2)s = %(py0)s.updated_count
} == %(py5)sr   r   r   rL   )z-%(py2)s
{%(py2)s = %(py0)s.calls
} == %(py5)szDSELECT provider, close FROM market_prices WHERE instrument_id='usd1'r   r   r   r   r   )r=   r   r   updated_countrZ   r[   r\   r]   r^   r_   r`   ra   r   r;   fetchone)r<   r   re   r   rf   r   ri   r   r   r   r   r   s              @r&   6test_refresh_market_prices_uses_explicit_provider_onlyrJ     s   <<D$T,hm  @F  S[  bp  q  q  q  q] ] ] ] ] ] ] ] ] ] #4((**%\hiiiF$1$1$$$$$$$$$$1$$$$$$$$$$$$6$$$$$6$$$$$$$$$$1$$$$$$$$$$$$$$$$$$$$$$$$$$$>Q>Q>Q88>Q<<^__hhjjkuv  G  {G  Gv  {G  G  G  G  G  G  G  G  G  G  Gv  {G  G  G  G  G  Gv  G  G  G  G  {G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  G  Gr(   c                   g fd}|                      d|           t                      }|j        }d}d}d} ||||          }d}t          |          }	||	k    }
|
snt	          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	        |          t	          j	        |          t	          j	        |          t	          j	        |          d
t          j                    v st	          j        t                    rt	          j	        t                    nd
t	          j	        |          t	          j	        |	          d
z  }dd|iz  }t          t	          j        |                    d x}x}x}x}x}x}x}
x}}	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}}g }d}d         }||v }|}|rd}d         }
||
v }|}|st	          j        d|fd||f          t	          j	        |          t	          j	        |          dz  }dd|iz  }|                    |           |r`t	          j        d|fd||
f          t	          j	        |          t	          j	        |
          dz  }dd|iz  }|                    |           t	          j        |d          i z  }dd |iz  }t          t	          j        |                    d x}x}x}x}x}x}x}}
|                      dd!            d"}t          |#          }|j        }d}d}d} ||||          }
d$}	t          |	          }|
|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	        |          t	          j	        |          t	          j	        |          t	          j	        |          t	          j	        |
          d
t          j                    v st	          j        t                    rt	          j	        t                    nd
t	          j	        |	          t	          j	        |          d'z  }d(d)|iz  }t          t	          j        |                    d x}x}x}x}x}x}x}
x}x}	}d"}t          |#          }|j        }d}d}d} ||||          }
d*}	t          |	          }|
|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	        |          t	          j	        |          t	          j	        |          t	          j	        |          t	          j	        |
          d
t          j                    v st	          j        t                    rt	          j	        t                    nd
t	          j	        |	          t	          j	        |          d'z  }d(d)|iz  }t          t	          j        |                    d x}x}x}x}x}x}x}
x}x}	}d S )+Nc                b                         | j                   t          dddddg          S )Nz
2026-05-20r   CHFg{Gz?)datebaser3  rate)r   full_urlr   )reqr.   ro   	seen_urlss      r&   fake_frankfurterzBtest_frankfurter_and_twelvedata_fx_mocks.<locals>.fake_frankfurter   s7    &&&lEE[_``abbbr(   z+jarvis_finance.fx.providers.request.urlopenr   rM  latestz0.89rG   )z%(py12)s
{%(py12)s = %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s()
}.get_rate
}(%(py6)s, %(py8)s, %(py10)s)
} == %(py18)s
{%(py18)s = %(py14)s(%(py16)s)
}r   r   r  r	  r
  zapi.frankfurter.dev/v2/ratesr   )in)z%(py1)s in %(py4)sr   r   r   zbase=USDz
quotes=CHF)z%(py3)s in %(py6)s)r   r   z%(py8)sr   )z%(py11)s in %(py14)s)py11r  z%(py16)sr  zassert %(py19)spy19c                 $    t          ddi          S )NrP  0.90)r   r   s     r&   r   z:test_frankfurter_and_twelvedata_fx_mocks.<locals>.<lambda>   s    WcekmsdtWuWu r(   rq   r  rZ  )z%(py14)s
{%(py14)s = %(py6)s
{%(py6)s = %(py4)s
{%(py4)s = %(py0)s(api_key=%(py2)s)
}.get_rate
}(%(py8)s, %(py10)s, %(py12)s)
} == %(py20)s
{%(py20)s = %(py16)s(%(py18)s)
}r	   )rI   rJ   rK   r   r   r  r  r  r  r  r
  zassert %(py22)spy221)r|   r   get_rater   rZ   r[   r\   r]   r^   r_   r`   ra   r   _format_boolopr	   )rb   rT  re   rf   rh   r  r  r  r  r  r  r  r  r   r   r   r   r   @py_assert10@py_assert12r   @py_format15@py_format17@py_format18@py_format20@py_assert19@py_format23rS  s                              @r&   (test_frankfurter_and_twelvedata_fx_mocksrg     s{   Ic c c c c EGWXXX ""V"+VEV5V(V++E5(CCVvVwvVCVVVVVVVVVVCVVVVVVVVVVVV VVVVV VVVVVV"VVVV+VVVVEVVVV5VVVV(VVVVCVVVVVVVVVVVwVVVVVwVVVVVVvVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV)9Yq\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FF:F1F:%FFFFF,F)A,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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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FFFFFFFFFFFFFFFEGuGuvvv(3h444h4=hehUhHh==eUHUUhaghY`agYhYhhUYhhhhhhhhhhhUYhhhhhhhhhhhhhhhhhhhhhhhhhhhh4hhhh=hhhhehhhhUhhhhHhhhhUhhhhhhhhhhhY`hhhhhY`hhhhhhaghhhhYhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh(3e444e4=eeeUeHe==eUHUUeadeY`adYeYeeUYeeeeeeeeeeeUYe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4eeee=eeeeeeeeeUeeeeHeeeeUeeeeeeeeeeeY`eeeeeY`eeeeeeadeeeeYe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(   )r!   r"   ):
__future__r   builtinsr\   _pytest.assertion.rewrite	assertionrewriterZ   r3   decimalr   ior   urllib.errorr   r}   jarvis_finance.cli.mainr   jarvis_finance.fx.providersr   r	   r   r
   r   r   r   r   r   %jarvis_finance.market_data.candidatesr   #jarvis_finance.market_data.mappingsr   r4  r   r   r   r   r   r   r   jarvis_finance.storage.databaser   !jarvis_finance.storage.migrationsr   r   r=   rk   r   r   r   r   r   r   r  r6  r<  rJ  rg  r*   r(   r&   <module>rv     s   " " " " " "                           " " " " " "  ( ( ( ( ( ( S S S S S S S S                D C C C C C P P P P P P                  ; : : : : : > > > > > >8 8 8 8 8 8 8 8  \ \ \ \A A A A& & & &/ / / /   0, , , ,% % % %	[ 	[ 	[ 	[, , , ,&[ [ [ [G G G G(f f f f f fr(   