
    j                    `   d dl mZ d dlmZ d dlmZmZmZmZ d dlm	Z	 e	d         Z
e	d         Z ed          Z ed	          Z ed
          Z ed          ZdZ ed           G d d                      Zd5dZd6dZd7dZd8dZd9dZd:d"Zd#d$d#d%d;d-Zd#ed$d.d<d1Zd=d4Zd#S )>    )annotations)	dataclass)UTCdatedatetime	timedelta)Literal)freshstalepartialunavailableunknown)genericmarketcrypto_24_7bank_balancemanaged_portfolio   days         T)frozenc                  8    e Zd ZU ded<   ded<   ded<   ded<   d	S )
FreshnessAssessmentFreshnessStatusstatusstrreason_code
str | Noneexpected_as_ofFreshnessSourceKindsource_kindN)__name__
__module____qualname____annotations__     o/home/agent/.hermes/worktrees/FinanceManager-current-import-performance/src/jarvis_finance/quality/freshness.pyr   r      sB         $$$$$$r*   r   valuer!   returndatetime | Nonec                   | sdS |                                  }	 t          |          dk    rJt          j        t	          j        |          t          j                                        t                    S t          j        |	                    dd                    }n# t          $ r Y dS w xY w|j        |	                    t                    n|                    t                    S )zDParse a source date/time as UTC without substituting a receive time.N
   tzinfoZz+00:00)striplenr   combiner   fromisoformatmintimer   replace
ValueErrorr2   
astimezone)r,   rawparseds      r+   parse_source_timer?      s     t
++--Cs88r>>#D$6s$;$;X\=N=N=P=PY\]]]]'C(B(BCC   tt)/)>6>>>%%%FDUDUVYDZDZZs   AB  7(B   
B.-B.yearintr   c                R   | dz  }| dz  }| dz  }|dz  }|dz  }|dz   dz  }||z
  dz   dz  }d|z  |z   |z
  |z
  dz   d	z  }|dz  }	|dz  }
d
d|z  z   d|	z  z   |z
  |
z
  dz  }|d|z  z   d|z  z   dz  }||z   d|z  z
  dz   dz  }||z   d|z  z
  dz   dz  dz   }t          | ||          S )zFAnonymous Gregorian algorithm, used only for the SIX holiday calendar.   d            r                r   r         i  r   r   )r   )r@   abcdefghiklengthmmonthdays                  r+   _easter_sundayr]   -   s   r	AAs
A	QA	AA	
Q2A	
QqA	a!a!	b	 B&A	QA	AA1q5j1q5 1$q(A-F	
R!Vb6k	!c)AZ!a%#%",Ev:A#r
)A
-CeS!!!r*   frozenset[date]c                   t          |           }t          t          | dd          t          | dd          |t          d          z
  |t          d          z   t          | dd          |t          d          z   |t          d          z   t          | dd          t          | dd	          t          | dd
          t          | dd          t          | dd          h          S )zDeterministic Swiss Stock Exchange full-day closures.

    The policy mirrors the recurring SIX holiday calendar. Weekend dates are
    harmless because market-day evaluation excludes weekends independently.
    r   r   r      '   2   rF         rG      r   )r]   	frozensetr   r   )r@   easters     r+   six_market_holidaysrh   @   s     D!!Fq!q!YA&&&&YA&&&&q!YB''''YB''''q!r2r2r2r2	
  r*   r\   boolc                ^    |                                  dk     o| t          | j                  vS )Nr`   )weekdayrh   r@   )r\   s    r+   _is_market_dayrl   Y   s*    ;;==1I,?,I,I!IIr*   	referencec                l    | }t          |          s"|t          d          z  }t          |          "|S )Nr   r   )rl   r   )rm   	candidates     r+   _latest_market_dayrp   ]   sD    IY'' 'YA&&&&	 Y'' 'r*   sourceexpectedc                    | |k    rdS d}| t          d          z   }||k    r-t          |          r|dz  }|t          d          z  }||k    -|S )Nr   r   r   )r   rl   )rq   rr   sessionscursors       r+   _market_sessions_afterrv   d   sy    qHiQ''''F
H

&!! 	MH)#### H

 Or*   Nr   )nowr$   max_age	availableas_ofrw   r$   r#   rx   timedelta | Nonec                   | st          ddd |          S t          |          }|t          ddd |          S |pt          j        t                    }|j        |                    t                    n|                    t                    }||k    r6t          dd|                                	                                |          S |dk    rt          |                                          }t          |                                |          }t          |t          k    rdnd	|t          k    rd
nd|	                                |          S t          ddft          ddft          ddf|pt           ddfd|         \  }	}
}||z
  |	k    }t          |rdnd	|r|n|
|                                	                                |          S )Nr   value_unavailabler   business_date_missingr1   source_date_in_futurer   r   r
   market_session_overduewithin_market_session_lagwithin_crypto_update_rhythmcrypto_update_overduewithin_bank_update_rhythmbank_update_overduewithin_managed_update_rhythmmanaged_update_overduewithin_generic_age_limitgeneric_update_overdue)r   r   r   r   )r   r?   r   rw   r   r2   r:   r<   r   	isoformatrp   rv   MARKET_MAX_SESSION_LAGCRYPTO_MAX_AGEBANK_BALANCE_MAX_AGEMANAGED_PORTFOLIO_MAX_AGEDEFAULT_FRESHNESS_MAX_AGE)ry   rz   rw   r$   rx   source_timerm   rr   lag
policy_agefresh_reasonstale_reasonr   s                r+   assess_freshnessr   p   s     Z"=2Et[YYY#E**K"9.Et[YYY(x|C((I # 	%%%!!#&& 
 Y".	0@0@0J0J0L0Lk
 
 	
 h%inn&6&677$[%5%5%7%7BB"333GG(+.D(D(D$$Je  	
 
 	
 '(EG^_-/JLab%*$
 00&$
. . .*Jl #j0E%g/<""$$	  r*   )rw   rx   r$   r   r   c                4    t          | ||||          j        S )N)ry   rz   rw   r$   rx   )r   r   )ry   rz   rw   rx   r$   s        r+   freshness_statusr      s/        r*   statuseslist[FreshnessStatus]c                    d | D             }|sdS t          |          t          |           k    sd|v rdS d|v rdS d|v rdS dS )zICollapse read-model sources without claiming availability that is absent.c                    g | ]
}|d k    |S )r   r)   ).0r   s     r+   
<listcomp>z&combined_freshness.<locals>.<listcomp>   s"    HHH&-0G0Gv0G0G0Gr*   r   r   r   r   r
   )r5   )r   presents     r+   combined_freshnessr      sm    HHHHHHG }
7||s8}}$$	W(<(<y'wGy7r*   )r,   r!   r-   r.   )r@   rA   r-   r   )r@   rA   r-   r^   )r\   r   r-   ri   )rm   r   r-   r   )rq   r   rr   r   r-   rA   )ry   ri   rz   r!   rw   r.   r$   r#   rx   r{   r-   r   )ry   ri   rz   r!   rw   r.   rx   r   r$   r#   r-   r   )r   r   r-   r   )
__future__r   dataclassesr   r   r   r   r   typingr	   r   r#   r   r   r   r   r   r   r?   r]   rh   rl   rp   rv   r   r   r   r)   r*   r+   <module>r      s    " " " " " " ! ! ! ! ! ! 3 3 3 3 3 3 3 3 3 3 3 3      OP  &I1---  ya((( %I2... """  $% % % % % % % %[ [ [ [" " " "&   2J J J J   	 	 	 	   '0 $6 6 6 6 6 6z  2'0     "     r*   