Team Ai
Apppublic

Deepvest/ProfilingAI

sourceHugging Faceupdated 2y agoView on Hugging Face
0likes
profiling.cpython-310.pyc723 linesDownload Raw Back to __pycache__
1o

2@�g��@s�ddlmZddlZddlZddlZddlZddlZddlZddlm	Z	m3Z4mZddlmZm
Z
ddlmZddlmZmZmZmZmZmZmZddlZddlZddlmZmZzddlmZWn	eyiYnwz5dd	l m!Z!m"Z"Wn	ey}Ynwej#ej$d6d�e�%d�Z&e7Gd
d�d��Z'e8Gdd�d��Z(e9Gdd�d��Z)e10Gdd�d��Z*e11Gdd�d��Z+e12Gdd�d��Z,Gdd�d�Z-Gdd�d�Z.Gdd�d�Z/dS)�)�annotationsN)�asdict�	dataclass�field)�datetime�	timedelta)�	lru_cache)�Any�Dict�List�Optional�Tuple�Union�Set)�
AutoTokenizer�AutoModelForCausalLM��PhiForCausalLM��	PeftModel�13PeftConfigz4%(asctime)s - %(name)s - %(levelname)s - %(message)s)�level�format�DeepVestc@s�eZdZUdZdZded<dZded<dZd	ed14<dZded<dZ	ded
<dZ15d	ed<dZd	ed<dZd	ed<dZ
ded<dZd	ed<dZded<dZded<dZded<dZded<dZded<dd�ZdS) �DeepVestConfigz%Configuration for the DeepVest system�financial_profiler_model�str�16model_pathT�bool�use_quantization�d�int�17cache_sizeZprofiles_db�db_path�use_persistent_storage��default_horizon��default_risk_tolerance�min_recommendation_count�enable_caching��18batch_size�parallel_processingF�fetch_market_dataN�
Optional[str]�market_data_api_key�19debug_mode�log_promptscCs |jrt�d��tj�dSdS)z+Validate configuration after initializationrN)r1�logging�	getLogger�setLevel�DEBUG��self�r9�5/Users/sandrine/Deepvest_system/src/core/profiling.py�
__post_init__@s�zDeepVestConfig.__post_init__)�__name__�20__module__�__qualname__�__doc__r�__annotations__rr"r#r$r&r(r)r*r,r-r.r0r1r2r;r9r9r9r:r"s$21rc@s�eZdZUdZdZded<dZded<dZded<dZded	<dZ	ded22<dZ23ded
<dZded<ee
d�Zded<ee
d�Zded<ee
d�Zded<dZded<dZded<d$dd�Zd%dd�Zd%d d!�Zd%d"d#�ZdS)&�FinancialAnalysisz2Detailed financial analysis of an investor profile��?�float�income_stability��24debt_ratio�savings_capacity�@�emergency_fund_months�
risk_capacityr%r!�investment_horizon皙�����?�liquidity_needs��default_factory�Dict[str, float]�income_sources�fixed_expenses�variable_expensesNz
Optional[int]�credit_scorezOptional[float]�tax_bracket�returnrc25Cszmd|jkodkn|jdkd|jkodkn|jdkd|jko+dkn|jdkd|jko;dkng}|jdurT|�d|jkoPdkn�|j	duri|�d|j	koedkn�t26|�WSty�}zt�
d|���WYd}~dSd}~ww)z&Validate financial analysis attributesr�Ni,iRz%Error validating financial analysis: F)rDrFrGrIrJrKrMrT�appendrU�all�	Exception�logger�error�r8�validations�er9r9r:�validateVs&�27	 28 29��zFinancialAnalysis.validatecCst|j���t|j���S)z Calculate total monthly expenses)�sumrR�valuesrSr7r9r9r:�calculate_total_expensesls��z*FinancialAnalysis.calculate_total_expensescCs$t|j���}|dkr
dS|j|S)z0Calculate savings rate as a percentage of incomer)rarQrbrG)r8Ztotal_incomer9r9r:�calculate_savings_ratess30z(FinancialAnalysis.calculate_savings_ratec	Csvd}d}d}d}tdd|jd�}td|jd�}td|jd�}||j||||||}tdtd|��S)	z.Calculate overall financial health score (0-1)�333333�?��?rLrrWrB�r')�maxrF�minrIrGrD)	r8Zstability_weightZdebt_weightZsavings_weightZemergency_weightZ31debt_scoreZemergency_scoreZ
savings_scoreZhealth_scorer9r9r:�get_financial_health_scorezs ����z,FinancialAnalysis.get_financial_health_score�rVr�rVrC)r<r=r>r?rDr@rFrGrIrJrKrMr�dictrQrRrSrTrUr`rcrdrjr9r9r9r:rAFs$32333435rAc@s�eZdZUdZdZded<dZded<dZded	<ee	d36�Z37ded<d
Zded<eed38�Z
ded<eed39�Zded<eed40�Zded<eed41�Zded<eed42�Zded<d#dd�Zd$dd�Zd%dd�Zd$d d!�Zd"S)&�FamilyAnalysisz%Detailed analysis of family situationrWr!�family_sizer�43dependents�	undefinedr�44life_stagerN�45List[Dict]�
future_eventsrErC�monthly_obligationsrP�insurance_coverage�education_needs�healthcare_needs�Dict[str, Any]�retirement_plans�estate_plansrVrc46Cs�z4|jdk|jdk|jdktdd�|j��D��tdd�|j��D��tdd�|j��D��g}t|�WStyO}zt	�47d|���WYd}~d	Sd}~ww)48z#Validate family analysis attributesrWrcs��|]}|dkVqdS�rNr9��.0�valuer9r9r:�	<genexpr>���z*FamilyAnalysis.validate.<locals>.<genexpr>csr|r}r9r~r9r9r:r��r�csr|r}r9r~r9r9r:r��r�z"Error validating family analysis: NF)rorprurYrvrbrwrxrZr[r\r]r9r9r:r`�s�49��zFamilyAnalysis.validatecCs0|jt|j���t|j���t|j���S)z#Calculate total monthly obligations)rurarvrbrwrxr7r9r9r:�calculate_total_obligations�s����z*FamilyAnalysis.calculate_total_obligations�Optional[Dict]cCs2|jsdSdd�|jD�}|sdSt|dd�d�S)z Get the next upcoming life eventNcSsg|]}d|vr|�qS)�dater9)rr_r9r9r:�50<listcomp>��z6FamilyAnalysis.get_next_life_event.<locals>.<listcomp>cS�|dS�Nr�r9��xr9r9r:�<lambda>��z4FamilyAnalysis.get_next_life_event.<locals>.<lambda>��key)rtri)r8rtr9r9r:�get_next_life_event�sz"FamilyAnalysis.get_next_life_eventcCsvtd|jdd�}td|jd�}tdt|j�d�}t|j�dkp)t|j�dk}|r.dnd}td||||�S)z+Calculate family situation complexity (0-1)rWrLrB皙�����?re皙�����?r)rirorp�lenrtrxrw)r8Zbase_complexityZdependent_complexityZevents_complexityZ
special_needsZspecial_complexityr9r9r:�calculate_family_complexity�sz*FamilyAnalysis.calculate_family_complexityNrkrl)rVr�)r<r=r>r?ror@rprrr�listrtrurmrvrwrxrzr{r`r�r�r�r9r9r9r:rn�s 51525354	rnc@s�eZdZUdZeed�Zded<eed�Z	ded<eed�Z55ded<eed�Zd	ed56<eed�Zded<eed�Z
ded<eed�Zded
<eed�Zded<d*dd�Zd+dd�Zd,dd�Zd+dd�Zd-dd�Zd.d/d#d$�Zd0d'd(�Zd)S)1�InvestmentGoalszDetailed investment goalsrNrs�
primary_goals�Dict[str, int]�57timeframesrP�required_returns�	List[str]�priority_order�target_amounts�
goal_progress�risk_tolerance_by_goalzDict[str, List[Dict]]�58milestonesrVrc59Cs�zK|jrtdd�|j��D��rWdS|jr%tdd�|j��D��r%WdS|jr7tdd�|j��D��r7WdS|jrItdd�|j��D��rIWdSWdStyf}zt�d|���WYd	}~dSd	}~ww)60z$Validate investment goals attributescss�|]}|dkVqdSr}r9)r�amountr9r9r:r��r�z+InvestmentGoals.validate.<locals>.<genexpr>Fcs� �|]}|dkp|dkVqdS)������Nr9)r�retr9r9r:r����csr�)rWr%Nr9)r�tolr9r9r:r��r�csr�)rrWNr9)r�progr9r9r:r��r�Tz#Error validating investment goals: N)	r��anyrbr�r�r�rZr[r\�r8r_r9r9r:r`�s��zInvestmentGoals.validaterCcCst|j���S)z.Calculate total target amount across all goals)rar�rbr7r9r9r:�calculate_total_target_amount�sz-InvestmentGoals.calculate_total_target_amountr/cCs|jr|jdSdS)zGet the highest priority goalrN)r�r7r9r9r:�get_highest_priority_goal�sz)InvestmentGoals.get_highest_priority_goalcsF�jr�jsdS�����dkrdSt��fdd��j��D��}|S)z0Calculate risk tolerance weighted by goal amountrHrc3s*�|]\}}�j�|d�|�VqdS)r'N)r��get)r�goalr��r8Ztotal_amountr9r:r�s61��62�zDInvestmentGoals.calculate_weighted_risk_tolerance.<locals>.<genexpr>)r�r�r�ra�items)r8Zweighted_tolerancer9r�r:�!calculate_weighted_risk_tolerances�z1InvestmentGoals.calculate_weighted_risk_tolerance�goal_idrcCs,||jvs63||jvrdS|j||j|S)z1Calculate progress percentage for a specific goalrE)r�r�)r8r�r9r9r:�calculate_goal_progresssz'InvestmentGoals.calculate_goal_progress�Z�daysr!c	Cs�g}t��}|t|d�}|j��D]%\}}|D]}|�d�}|r6||kr+|kr6nq|�d|i|��qqt|dd�d�S)z-Get upcoming milestones within specified days�r�r�r�cSr�r�r9r�r9r9r:r�'r�z9InvestmentGoals.get_upcoming_milestones.<locals>.<lambda>r�)r�nowrr�r�r�rX�sorted)	r8r��upcomingr��cutoffr�r�Z	milestoner�r9r9r:�get_upcoming_milestoness64����z'InvestmentGoals.get_upcoming_milestones�monthly_contribution�expected_returncCs�i}|j��D]D\}}|j�|d�}|j�|d�d}|dkr$d||<q|d|d|}|d|d|d|d}	||	}65td|66|�||<q|S)z@Estimate feasibility of goals based on contributions and returnsr�<�rW��?)r�r�r�r�r�ri)r8r�r��feasibilityr��targetZcurrent_amount�monthsZfuture_currentZfuture_contributionsZexpected_amountr9r9r:�estimate_goal_feasibility)s z)InvestmentGoals.estimate_goal_feasibilityNrkrl)rVr/)r�rrVrC)r�)r�r!rVrs)r�rCr�rCrVrP)r<r=r>r?rr�r�r@rmr�r�r�r�r�r�r�r`r�r�r�r�r�r�r9r9r9r:r��s"676869707172r�c@sdeZdZUdZded<ded<ded<ded	<ded73<ded<eed
�Zded<eed
�Zded<eed
�Z	ded<eed
�Z74ded<eed
�Zded<eed
�Zded<ee
d
�Zded<ee
d
�Zded<eed
�Zded<dZded<eed
�Zded<dd�Zd3dd �Zd4d!d"�Zd5d#d$�Zd3d%d&�Zd6d'd(�Zd7d*d+�Zd8d,d-�Zd3d.d/�Zd9d0d1�Zd2S):�ProfileAnalysisResultz'Complete result of LLM profile analysisrC�75risk_scorer!rKr�r�ry�constraints�recommendationsr�explanationrNrP�risk_decomposition�goal_feasibility�investment_style�market_sensitivity�asset_allocation�geographic_allocation�List[Dict[str, Any]]�alerts�attention_points�market_contextrB�adaptability_score�stress_test_resultscCs<d|jkrdkstd��td��|jdkrtd��dS)zPost-initialization validationrrW�"Risk score must be between 0 and 1z#Investment horizon must be positiveN)r��76ValueErrorrKr7r9r9r:r;hs�77�z#ProfileAnalysisResult.__post_init__rVcCs<|jdkrdS|jdkrdS|jdkrdS|jdkrdSd	S)78z&Determine risk category based on scorerL�Très conservateur皙�����?�Conservateur�333333�?�Modéré皙�����?�	Dynamique�Très dynamique�r�r7r9r9r:�get_risk_categoryos79808182z'ProfileAnalysisResult.get_risk_categorycCsdd�|jD�S)zGet critical alerts onlycSsg|]}|�d�dkr|�qS)�severity�critical)r�)rZalertr9r9r:r�~�z=ProfileAnalysisResult.get_critical_alerts.<locals>.<listcomp>)r�r7r9r9r:�get_critical_alerts|sz)ProfileAnalysisResult.get_critical_alertscCsdd�|j��D�S)zIdentify major constraintscSs,g|]\}}t|tttf�r|dkr|�qS)�ffffff�?)�83isinstancerr!rC)r�84constraintr�r9r9r:r��s��z?ProfileAnalysisResult.get_major_constraints.<locals>.<listcomp>)r�r�r7r9r9r:�get_major_constraints�s�z+ProfileAnalysisResult.get_major_constraintscCs$|jsdSt|j��dd�d�dS)z"Determine primary investment styleZBalancedcSr��NrWr9r�r9r9r:r��r�zDProfileAnalysisResult.get_primary_investment_style.<locals>.<lambda>r�r)r�rhr�r7r9r9r:�get_primary_investment_style�sz2ProfileAnalysisResult.get_primary_investment_stylecCs"|jsdSt|j���t|j�S)z"Calculate overall goal feasibilityrB)r�rarbr�r7r9r9r:�calculate_overall_feasibility�sz3ProfileAnalysisResult.calculate_overall_feasibility�List[Tuple[str, float]]cCst|j��dd�dd�S)z*Get main risk factors sorted by importancecSr�r�r9r�r9r9r:r��r�z8ProfileAnalysisResult.get_risk_factors.<locals>.<lambda>T�r��reverse)r�r�r�r7r9r9r:�get_risk_factors�s85�z&ProfileAnalysisResult.get_risk_factorscCs4i}|j��D]\}}t|jd|d�||<q|S)z*Evaluate adaptability to market conditionsrWr�)r�r�rir�)r8�adaptability�	condition�sensitivityr9r9r:�get_market_adaptability�s86�z-ProfileAnalysisResult.get_market_adaptabilitycCs�|��}d|��d|jd�d|j�d�ddgdd	�|jd87d�D��d�d�d
d	�t|j��dd�dd�D��d�d�dd	�|��d88d�D��d�d�dd	�|jd89d�D��d�d�dd	�|j	d90d�D��}d�91|�S)z3Generate a concise one-page summary of the analysisz# Profil d'Investissement: zScore de risque: �.2fz/1.00 | Horizon: z ans�z## Objectifs PrincipauxcS�g|]}d|���qS��- r9)rr�r9r9r:r���zCProfileAnalysisResult.generate_one_page_summary.<locals>.<listcomp>Nr'u### Allocation d'Actifs RecommandéecS�"g|]
\}}d|�d|d���qS�r��: �.1%r9)r�asset�weightr9r9r:r���"cSr�r�r9r�r9r9r:r��r�zAProfileAnalysisResult.generate_one_page_summary.<locals>.<lambda>Tr�z ## Facteurs de Risque PrincipauxcSr�r�r9)r�factor�scorer9r9r:r��ru## Recommandations CléscSr�r�r9)r�recr9r9r:r��r�z## Points d'AttentioncSr�r�r9)r�pointr9r9r:r��r��92)r�r�rKr�r�r�r�r�r�r��join)r8�
risk_category�summaryr9r9r:�generate_one_page_summary�sF������93���
������94z/ProfileAnalysisResult.generate_one_page_summarycCsd|j|��|j|jd�|j|j|j|jd�|j|j	|j95d�|j|j|j
d�|j|jd�|j|jd�S)zConvert analysis to dictionary)r�category�
decompositionZstress_tests)�horizon�styler�r�)r�r�r�)Zsuggestionsr�r�)ZassetsZ	geography)�risk_profile�investment_profileZgoals_analysisr�Zallocationsr�r�)r�r�r�r�rKr�r�r�r�r�r�r�r�r�r�r�r�r�r7r9r9r:�to_dict�s0������zProfileAnalysisResult.to_dictN�rVr)rVr�)rVr�rl)rVr��rVrP�rVry)r<r=r>r?r@rrmr�r�r�r�r�r�r�r�r�r�r�r�r;r�r�r�r�r�r�r�r96rr9r9r9r:r�Hs:979899
100101102103104105 106r�c@s�eZdZUdZdZded<eejd�Z	ded<eejd�Z107ded<d	Zd108ed<dZd109ed
<dZ
d110ed<dZd111ed<dZd112ed<eed�Zded<dZded<eed�Zded<dZd113ed<dZded<dZded<dZded <dZded!<d"Zd#ed$<d"Zd#ed%<d"Zd#ed&<d'Zd#ed(<d)Zd114ed*<d"Zd#ed+<d,Z d#ed-<dZ!d.ed/<dZ"d0ed1<dZ#d2ed3<dZ$ded4<eed�Z%d5ed6<eed�Z&d5ed7<eed�Z'd8ed9<dZ(d:ed;<ed<d=�d�Z)ded><dZ*d?ed@<dAZ+dedB<dAZ,dedC<dAZ-dedD<dEdF�Z.dgdHdI�Z/dJdK�Z0dhdLdM�Z1didNdO�Z2didPdQ�Z3didRdS�Z4didTdU�Z5djdXdY�Z6dkdZd[�Z7dldmd]d^�Z8dndodadb�Z9dpdcdd�Z:e;dqdedf��Z<dS)r�PersonalProfilez<Complete and dynamic investor profile with advanced analysisNr/�idrNr�115created_at�last_updatedrWr!�versionr'�risk_tolerancer%rKrD�financial_knowledger��investment_goalsFr�esg_preferencesryr���agegj�@rC�
annual_incomerE�total_assets�116total_debt�monthly_savingsr�r�117occupation�industry�education_level�single�marital_statusr�number_of_dependents�118tax_status�owner�residential_statuszOptional[FinancialAnalysis]�financial_analysiszOptional[FamilyAnalysis]�family_analysiszOptional[InvestmentGoals]�investment_objectives�profile_descriptionrP�risk_metrics�performance_metricsr��historical_changeszOptional[datetime]�last_reviewcCsgggggd�S)N)�
asset_classes�sectors�regionsZ119strategiesZexcluded_investmentsr9r9r9r9r:r�s�zPersonalProfile.<lambda>�investment_preferenceszOptional[ProfileAnalysisResult]�llm_analysis_resultsrBr�r��complexity_tolerancecCsV|jdur120|��|_|jdurt�|_|jdurt�|_|jdur%t�|_|��dS)zPost-initialization setupN)	r�_generate_profile_idr-rAr.rnr/r��_validate_profiler7r9r9r:r;s121122123124125zPersonalProfile.__post_init__rVcCsTt|j�t|j�t|j�|jt����g}d�|�}dt	�126|�����dd���S)zGenerate unique profile ID�_ZPROFILE_N�)
rrr rr$rr��	isoformatr�hashlib�sha256�encode�	hexdigest)r8�127componentsZ
unique_stringr9r9r:r;.s128�129 z$PersonalProfile._generate_profile_idc
Cs�d|jko130dkndfd|jkodkndfd|jko&dkndfd|jko4dkndfd|jkoBd	knd131f|jdkdf|jdkd
f|jdkdfd|jkobdkndfd|j	kopdkndfd|j132ko~dkndfg}|jr�|j�dg�D]}t
|t�s�td��q�|jr�t|j�dkr�td��|D]133\}}|s�t|��q�|jr�|j��s�td��|jr�|j��s�td��|jr�|j��s�td��dSdS)z Comprehensive profile validationrWr%z&Risk tolerance must be between 1 and 5�2z1Investment horizon must be between 1 and 50 yearsz(Income stability must be between 1 and 5z+Financial knowledge must be between 1 and 5��xzAge must be between 18 and 120rz Annual income cannot be negativezTotal assets cannot be negativezTotal debt cannot be negativer�z*Adaptability score must be between 0 and 1z,Complexity tolerance must be between 0 and 1r5zInvalid asset class formatz.At least one investment goal must be specifiedzInvalid financial analysiszInvalid family analysiszInvalid investment objectivesN)rrKrDrrr r!r"r�r�r:r8r�r�rr�rr�r-r`r.r/)r8r^�asset_class�134validation�messager9r9r:r<:s<�135���z!PersonalProfile._validate_profilec136Cszm|jdkr|j|jntd�|jr|jjdnd|jr |jjnd|jr+t|j�dnd|��|�	�|�137�|��d�}|jrJ|�
|jj|jjd��|jrR|j��nd}|ddd	|d138d|d|d
<||_|WSty�}zt�d|���iWYd}~Sd}~ww)z$Calculate comprehensive risk metricsr�infrgrBr%)�total_debt_ratioZemergency_fund_ratiorJZinvestment_diversificationZdebt_service_ratioZsavings_rateZliquidity_ratioZinvestment_concentration)Zllm_risk_scorer�rJrWrLrerLZoverall_risk_capacityz Error calculating risk metrics: N)r r"rCr-rIrJrr��_calculate_debt_service_ratio�_calculate_savings_rate�_calculate_liquidity_ratio�#_calculate_investment_concentrationr9�updater�r�rjr1rZr[r\)r8r1Zfinancial_healthr_r9r9r:�$calculate_comprehensive_risk_metricsbs:��139�����z4PersonalProfile.calculate_comprehensive_risk_metricsc140Cs�zI|jr	|jdkrWdSt|jjt�r4d|jjvr4t|jjdt�r-t|jjd���}n|jjd}n|jd}|jd}|dkrG||WSdWStyd}zt	�141d|���WYd}~dSd}~ww)zCalculate debt service ratiorrEZ
debt_payments�{�G�z�?r�z&Error calculating debt service ratio: N)r-r r�rRrmrarbr"rZr[r\)r8Zmonthly_debt_paymentZmonthly_incomer_r9r9r:rM�s142143��z-PersonalProfile._calculate_debt_service_ratioc144Csbz|jr	|jdkrWdS|jjd|jWSty0}zt�d|���WYd}~dSd}~ww)zCalculate savings raterrEr�z Error calculating savings rate: N)r-r rGrZr[r\r�r9r9r:rN�s��z'PersonalProfile._calculate_savings_ratec145Cstz|jr	|jdkrWdStdd�|jj��D��}||jWSty9}zt�d|���WYd}~dSd}~ww)zCalculate liquidity ratiorrEcss �|]\}}|dvr|VqdS))ZsavingsZinvestments�cashNr9)r�type_r�r9r9r:r��s���z=PersonalProfile._calculate_liquidity_ratio.<locals>.<genexpr>z#Error calculating liquidity ratio: N)r-r!rarQr�rZr[r\)r8Z
liquid_assetsr_r9r9r:rO�s146���z*PersonalProfile._calculate_liquidity_ratioc147Cs�z&|jr148|j�d�s
WdS|jd}dt|�gt|�}tdd�|D��WStyA}zt�d|���WYd}~dSd}~ww)z,Calculate investment concentration using HHIr5r�rWcss�|]}||VqdS�Nr9)r�wr9r9r:r��r�zFPersonalProfile._calculate_investment_concentration.<locals>.<genexpr>z,Error calculating investment concentration: N)r8r�r�rarZr[r\)r8r5�weightsr_r9r9r:rP�s149��z3PersonalProfile._calculate_investment_concentration�updates�'PersonalProfile'c150Cs�z7t|�}|�|�|��D]\}}||vr|||<q|dd7<t��|d<|jdi|��}|��|WStyL}z	t�	d|����d}~ww)z#Update profile with new informationrrWrzError updating profile: Nr9)151r�_save_change_historyr�rr��	__class__r<rZr[r\)r8rYZcurrent_datar�r��updated_profiler_r9r9r:rQ�s"152���zPersonalProfile.updatecs:t����|�fdd�|��D��jd�}�j�|�dS)zRecord change historycs"i|]
}t�|�r|t�|��qSr9)�hasattr�getattr)rr�r7r9r:�153<dictcomp>�s�154�z8PersonalProfile._save_change_history.<locals>.<dictcomp>)�	timestamp�changesZprevious_valuesrN)rr�r?�keysrr3rX)r8rYZ
change_recordr9r7r:r[�s155156��157z$PersonalProfile._save_change_historyrcs�r�fdd�|jD�S|jS)z%Get change history for optional fieldcsg|]158}�|dvr|�qS)rbr9)r�change�rr9r:r��s159�z6PersonalProfile.get_change_history.<locals>.<listcomp>)r3)r8rr9rer:�get_change_history�s160161�z"PersonalProfile.get_change_history�filepath�include_detailed_analysisc162Cs�z?tjtj�|�dd�t|ddd��}tj|rt|�n|��|ddt	d�Wd	�n1s0wYt163�d164|���Wd	StyW}zt165�
d|�d|����d	}~ww)
zExport profile to JSON fileT)�exist_okrW�utf-8��encodingFr�)�ensure_ascii�indent�defaultNz!Profile exported successfully to zError exporting profile to r�)�os�makedirs�path�dirname�open�json�dumprrrr[�inforZr\)r8rgrh�fr_r9r9r:�export_json�s����zPersonalProfile.export_jsoncCsp|j|j|j��|j��|j|j|j|j|j	|j166d�|j|j|j
|j|j|jd�|j|jr4|j��d�Sdd�S)z,Convert profile to dictionary representation)rr r!r"r(rp)rrKrrD�goalsrN)rrrr�167basic_inforr1�llm_analysis)rrrr?rrr r!r"r(r)rrKrrDrrr1r9rr7r9r9r:r168s.�	���zPersonalProfile.to_dictc169CsJz�t|ddd��
}t�|�}Wd�n1swYdD]}||vr2||r2t�||�||<qd|vrF|drFtdi|d��|d<d|vrY|drYtdi|d��|d<d|vrl|drltdi|d��|d<d	|vr|d	rtdi|d	��|d	<|di|��}|�	�|WSt170y�}zt�d171|�d|����d}~ww)
zLoad profile from JSON file�rrjrkN)rrr4r-r.r/r9�Error loading profile from r�r9)
rtru�loadr�
fromisoformatrArnr�r�r<rZr[r\)�clsrgrx�dataZ172date_field�profiler_r9r9r:�	from_json%s0����zPersonalProfile.from_jsonrrrl)rYryrVrZ)rYryrV)rr/rVr��F)rgrrhrr)rgrrVrZ)=r<r=r>r?rr@rrr�rrrrrKrDrr�rrrmr�rr r!r"r#r$r%r&r(r)r*r,r-r.r/r0r1r2r3r4r8r9r�r�r:r;r;r<rRrMrNrOrPrQr[rfryr�classmethodr�r9r9r9r:r�sj173	174175(176$177178 179 180181182	183rc@sveZdZdZd#dd�Zd$dd	�Zd%dd�Zd&dd�Zdd�Zd'd(dd�Z	d&dd�Z184d)dd�Zd)dd�Zd'd*d!d"�Z
d185S)+�DeepVestLLMzAAdvanced LLM integration using fine-tuned financial advisor model�configrcCsl||_t�d�|_d|_d|_|��|_tj	�186|j�r"|�|j�n|j�
d|j�d��i|_|j|_dS)zInitialize with configurationzDeepVest.LLMNzModel path z not found, using fallback mode)r�r3r4r[�model�	tokenizer�_detect_optimal_device�devicerprr�existsr�187load_model�warning�generation_cacher"�max_cache_entries�r8r�r9r9r:�__init__Ks188zDeepVestLLM.__init__rVrcCsRtj��r
|j�d�dSttjd�r!tjj��r!|j�d�dS|j�d�dS)z-Detect the optimal device for model inferencezCUDA GPU available, using CUDA�cuda�mps�Apple MPS available, using MPSzNo GPU available, using CPU�cpu)�torchr��is_availabler[rwr^�backendsr�r7r9r9r:r�_s189z"DeepVestLLM._detect_optimal_deviceNcCsj�z�|r|n|jj}|j�d|���tj��r!|j�d�d}nttjd�r6tjj	��r6|j�d�d}n|j�d�d}t190j�|d�}t191j�
|�r�t|d	��
}t�|�}Wd192�n1s`wYd|vr�|j�d�d
|d<d|vr|dg|d<t|d��}tj||dd�Wd193�n1s�wYn3|j�d|�d��d
dgddddddd�}t|d��}tj||dd�Wd194�n1s�wYztj|dd�|_tj|dtjddd�|_Wn�t�y�}z�|j�d|���zdd lm}tj|dd�|_|j|dtjddd�|_Wnet�yv}	zX|j�d!|	���z%dd"lm}195m}d#}tj|dtjdd$�}
tj|dd�|_|196�|
|�|_Wn#t�yk}z|j�d%|���td&|�d'|	�d'|����d197}~wwWYd198}	~	nd199}	~	wwWYd200}~nd201}~ww|jj d202u�r�|jj!|j_ |j�d(�WdSt�y�}z|j�d)|���WYd203}~d*Sd204}~ww)+z2Load the fine-tuned model from the configured pathzLoading fine-tuned model from zCUDA available, using GPUr�r�r�z	Using CPUr�zconfig.jsonr}N�205model_typez(Adding missing model_type to config.json�phi�
architecturesrrWr�)rnzconfig.json not found in z, creating onerWrii��float16)r�r�Zbos_token_id�eos_token_id�pad_token_idZhidden_sizeZ206vocab_size�torch_dtypeT)�trust_remote_code�auto)r�r��207device_mapZlow_cpu_mem_usagezFirst loading attempt failed: rzSecond loading attempt failed: rzmicrosoft/phi-1_5)r�r�r�z)All loading attempts failed. Last error: zCould not load model: z -> zModel loaded successfullyzError loading model: F)"r�rr[rwr�r�r�r^r�r�rprrrr�rtrurr�rvrZfrom_pretrainedr�rr�r�rZ�transformersr�peftrrr\Z	pad_tokenZ	eos_token)r8rZpath_to_user�Zconfig_filerxr�Zmodel_errorrZspecific_errorrrZbase_model_pathZ208base_modelZ209peft_errorr_r9r9r:r�ks�210�211���212������������)��zDeepVestLLM.load_model�promptcCst�|�����S)zGenerate cache key for a prompt)r@�md5rBrC)r8r�r9r9r:�_get_cache_key�szDeepVestLLM._get_cache_keycCszt|j�|jkr;t|j��dd�d�}t|jd�}t|�D]}|t|�kr.|j||d=q|j�d|�d��dSdS)	zManage cache sizecS�|ddS�NrWrar9r�r9r9r:r���z+DeepVestLLM._manage_cache.<locals>.<lambda>r�rLrzCache cleanup: removed z entriesN)	r�r�r�r�r�r!�ranger[�debug)r8Zsorted_entriesZentries_to_remove�ir9r9r:�
_manage_cache�s���zDeepVestLLM._manage_cache���213max_lengthr!c	
�s��|jjr$|�|�}||jvr$|j|}t��|d<|j�d�|dS|jjr1|j�d|���t	|d�r�|j214r�|jr�|jr�zt|j|dddd	�}t	|jd215�r^|jj
��fdd�|��D�}t���|jjdi|�|dd
dddd|jjd���}Wd�n1s�wY|jj|ddd�}d|vr�|�d�d��}|jjr�|t��d�|j|<|��|WSty�}z|j�d|���|�|�IdHWYd}~Sd}~ww|j�d�|�|�IdHS)z$Generate text using the loaded modelrazUsing cached response�responsezPrompt: �model_loaded�ptT�)�return_tensors�216truncationr�r�csi|]217\}}||����qSr9)�to�r�k�v�r�r9r:r`�z-DeepVestLLM.generate_text.<locals>.<dictcomp>r��q=218ףp�?rE�ffffff�?r+)r��	do_sample�temperature�top_p�top_k�repetition_penaltyZ	num_beamsr�Nr�Zskip_special_tokens�[/INST]r�)r�razError generating text: �Using fallback generationr9)r�r*r�r�rr�r[r�r2r^r�r�r�r�r�r��no_grad�generater��decode�split�stripr�rZr\�_fallback_generationrw)	r8r�r��	cache_keyZcache_entry�inputs�outputsr�r_r9r�r:�
generate_text�s\�219220221222223���
���zDeepVestLLM.generate_textc�s��|j�d�d}d}t�d|�}|rt|�d��}t�d|�}|r)t|�d��}|d}d|d�d	|�d224t|d��dtd|d
��dtd|d��d�}|S)z-Fallback generation when model is unavailabler�r'r%z[Rr]isque.*?(\d+)rWz[Hh]orizon.*?(\d+)z1. Score de risque: r�uZ - Basé sur la tolérance au risque déclarée.2252. Horizon d'investissement recommandé: u� ans.2263. Objectifs prioritaires: Épargne générale, Croissance du capital.2274. Contraintes: Limitation classique de diversification.228 2295. Recommandations d'allocation:230   - Actions: r z%231   - Obligations: �Pu%232   - Liquidités: �uQ%233 2346. Recommandations:235   - Diversifier votre portefeuille236   - Investir régulièrement237   - Maintenir une épargne de sécurité suffisante238 2397. Points d'attention:240   - Réévaluer régulièrement votre profil de risque241   - Ajuster votre allocation selon l'évolution de votre situation242   - Prévoir une réserve d'urgence adéquate243)r[rw�re�searchr!�group)r8r�rrKZ244risk_matchZ
horizon_matchr�Zfallback_responser9r9r:r�3s*�245�246���z DeepVestLLM._fallback_generation�profile_dataryc247CsLd�gd�|�dd���d�|�dd���d�|�dd���d	�|�d248d���d�|�d
d���d�|�dd���d�|�dd���d�d�|�dg����d�|�dd���d�|�dd���d�|�dd���d�|�dd���d�|�d d!�r|d"nd#��d$�d�|�d%i��d&g����d'�d�d(d)�|�d*i���D����d+��S),z)Prepare analysis prompt from profile datar�u�[INST] Je suis un conseiller financier expert. Analyse ce profil d'investisseur de manière exhaustive.249 250Profil détaillé :251- Âge: r�Non spécifié� ans252- Revenu annuel: r �€253- Situation familiale: r(u254- Dépendants: r)ru255- Épargne mensuelle: r#u€256- Dette totale: r"u€257- Patrimoine total: r!u€258- Objectifs: �, ru259- Tolérance au risque (1-5): rr'z260- Horizon d'investissement: rKr%u) ans261- Connaissances financières (1-5): r�262- Stabilité professionnelle: rDu263- Préférences ESG: rFZOuiZNonu264- Secteurs préférés: r8r6u265- Contraintes spécifiques: css �|]\}}|rt|�VqdSrV)rr�r9r9r:r�qr�z6DeepVestLLM.prepare_analysis_prompt.<locals>.<genexpr>r�u�266 267Format de réponse requis:2681. Score de risque (entre 0 et 1): [score] - Justification détaillée2692. Horizon d'investissement recommandé: [années] - Justification2703. Objectifs prioritaires: Liste ordonnée avec justification2714. Contraintes et limitations: Analyse détaillée des contraintes2725. Recommandations d'allocation:273   - Par classe d'actifs (%)274   - Par zone géographique (%)275   - Par stratégie d'investissement2766. Analyse des risques:277   - Décomposition des risques278   - Points de vigilance279   - Stress tests recommandés2807. Plan d'action détaillé:281   - Court terme (0-2 ans)282   - Moyen terme (2-5 ans)283   - Long terme (5+ ans)2848. Recommandations spécifiques:285   - Investissements recommandés286   - Stratégies de diversification287   - Protection du capital2889. Explication détaillée:289   - Raisonnement complet290   - Points d'attention particuliers291   - Opportunités identifiées292 293Analyse complète: [/INST])rr�r��r8r�r9r9r:�prepare_analysis_prompt^s>294295�296�297�298�299�300�301	�302�303�304�305
�306����z#DeepVestLLM.prepare_analysis_promptcCs�d|�dd��d|�dd��d|�dd��dd	�|�d307g���d|�dd
��d|�dd��d|�dd
��d|�dd��d|�dd��d|�dd��d|�dd��d|�dd
��d�S)z,Prepare description prompt from profile datau�[INST] En tant que conseiller financier expert, génère une description détaillée et professionnelle de ce profil d'investisseur.308 309Profil complet:310- Âge: rr�r�r r�r(z311- Objectifs: r�ru312- Tolérance au risque: rr'z/5313- Horizon: rKr%u# ans314- Connaissances financières: ru/5315- Épargne mensuelle: r#u€316- Patrimoine: r!u
€317- Dette: r"u€318- Secteur d'activité: r%r�rDu�/5319 320La description doit couvrir:3211. Analyse du profil de risque et des objectifs3222. Evaluation de la capacité financière3233. Identification des contraintes et opportunités3244. Recommandations d'investissement personnalisées3255. Points de vigilance et attention particulière3266. Stratégie de diversification recommandée3277. Projection et scénarios d'évolution328 329Description: [/INST]�r�rr�r9r9r:�prepare_description_prompt�s2330�331�332��333�334�335	�336 337�338�339�340
�341�z&DeepVestLLM.prepare_description_prompt�promptsr�c
�s��jr�js�fdd�|D�IdHSg}�jj}tdt|�|�D]k}||||�}�j|ddddd�}�fd	d342�|��D�}t����jj	di|�|dddd
d�jj343d���}Wd�n1sdwYt|�D]\}	}344�jj|345dd�}d|vr�|�
d�d��}|�|�qmq!|S)z3Generate responses for multiple prompts in parallelc�s�g|]346}��|�IdH�qSrV)r�)rr�r7r9r:r����z.DeepVestLLM.generate_batch.<locals>.<listcomp>Nrr�Tr�)r��paddingr�r�csi|]\}}||��j��qSr9)r�r�r�r7r9r:r`�r�z.DeepVestLLM.generate_batch.<locals>.<dictcomp>r�r�rEr�)r�r�r�r�r�r�r�r�r�r�r9)r�r�r�r,r�r�r�r�r�r�r��	enumerater�r�r�rX)r8r�r��	responsesr,r�Z
batch_promptsZbatch_inputsr��j�outputr�r9r7r:�generate_batch�sF��347348����zDeepVestLLM.generate_batch)r�rrrV)r�rrVr)r�)r�rr�r!rVr�r�ryrVr)r�r�r�r!rVr�)r<r=r>r?r�r�r�r�r�r�r�r�r�r�r9r9r9r:r�Hs349350351352v353>354+3551r�c@sFeZdZdZdWdXdd�ZdYdd�Zd
d�ZdZdd�Zd[dd�Zd\dd�Z	d]dd�Z356d^d d!�ZdZd"d#�Zd_d'd(�Z
d`d)d*�Zdad-d.�Zdbd0d1�Zdcd2d3�Zddd4d5�Zdcd6d7�Zded8d9�Zdfd:d;�Zdfd<d=�Zdfd>d?�Zdfd@dA�ZdfdBdC�ZdfdDdE�ZdgdFdG�ZdcdHdI�ZdddJdK�ZdadLdM�ZdhdOdP�ZdfdQdR�Z dYdSdT�Z!dYdUdV�Z"dS)i�LLMProfileAnalyzerz8Advanced profile analyzer using fine-tuned financial LLMNr��Optional[DeepVestConfig]cCs8|pt�|_t�d�|_t|j�|_i|_|jj|_	dS)NzDeepVest.Analyzer)357rr�r3r4r[r��llm�analysis_cacher"�max_cache_sizer�r9r9r:r��s358zLLMProfileAnalyzer.__init__r�ryrVrcCs�t|�dd��t|�dd��t|�dd��d�|�dg��t|�dd��t|�dd��t|�d	d��g}t�d359�|������S)z'Generate unique cache key for a profilerr�rrK�,rr r!r"r=)rr�rr@r�rBrC)r8r�Zkey_componentsr9r9r:r��s�	z!LLMProfileAnalyzer._get_cache_keycCsft|j�|jkr/t|j��dd�d�}t|jd�}t|�D]}|t|�kr.|j||d=qdSdS)z,Manage cache size by removing oldest entriescSr�r�r9r�r9r9r:r��r�z2LLMProfileAnalyzer._manage_cache.<locals>.<lambda>r�rLrN)r�r�r�r�r�r!r�)r8r�Z
num_to_remover�r9r9r:r��s���z LLMProfileAnalyzer._manage_cacher�c360�s(�zr|�|�}||jvr!|jjr!|j�d|���|j|dWS|j�d|�dd����|j�|�}|j�	|�IdH}|�361||�}|�|�sS|j�d�|�
|�}|�||�}|jjrk|t��d�|j|<|��|j�d	�|WSty�}z|j�d362|���|�
|�WYd}~Sd}~ww)z3Comprehensive profile analysis with recommendationsz"Using cached analysis for profile �resultz"Starting profile analysis for ID: r�unknownNz8Analysis results validation failed, using default values�r�raz'Profile analysis completed successfullyzError in profile analysis: )r�r�r�r*r[rwr�r�r�r��_parse_response�_validate_resultsr��_get_default_analysis�_enrich_analysisrr�r�rZr\)r8r�r�r�r��analysis_result�enriched_analysisr_r9r9r:�analyze_profile�s4�363364365���z"LLMProfileAnalyzer.analyze_profile�profilesr��List[ProfileAnalysisResult]c�s�z�g}g}g}t|�D]'\}}��|�}|�jvr)�jjr)|��j|d�q|�|�|�|�q|s9|WS�fdd�|D�}�j�|�IdH}	tt||	��D]p\}\}}366zD��	|367|�}��368|�si��|�}��||�}�jjr���|�}|t
��d��j|<||}
t|�|
kr�|�d�t|�|
ks�|||
<WqRty�}z�j�d|�d|���|���|��WYd}~qRd}~ww�jjrˈ��t|�D]\}}|dur���||�||<q�|WSt�y}z�j�d|����fd	d�|D�WYd}~Sd}~ww)369z"Analyze multiple profiles in batchr�csg|]}�j�|��qSr9)r�r��rr�r7r9r:r�;r�z=LLMProfileAnalyzer.batch_analyze_profiles.<locals>.<listcomp>Nr�zError processing profile r��!Error in batch profile analysis: csg|]}��|��qSr9)r�r�r7r9r:r�lr�)r�r�r�r�r*rXr�r��zipr�r�r�r�rr�r�rZr[r\r�)r8r��resultsZuncached_profilesZuncached_indicesr�r�r�r�r�r�r�r�Zinsert_indexr_r�r9r7r:�batch_analyze_profiles&s`�370371372373374�375������z)LLMProfileAnalyzer.batch_analyze_profilesr��
original_datac376Cs,zu|�d�}|�|�}|�|�}tdid|�|��d|�|��d|�|��d|�|��d|�|��d|�	|��d|�377|��d	|�|��d378|�|��d|�
|��d|�|��d
|�|��d|�|��d|�|��d|�|��d|�d|��WSty�}z|j�d|���|�|�WYd}~Sd}~ww)z'Parse LLM response into structured datarr�rKr�r�r�r�r�r�r�r�r�r�r�r�r�r�r�zError parsing response: Nr9)r��_extract_asset_allocation�_extract_geographic_allocationr��_extract_risk_score�_extract_horizon�_extract_goals�_extract_constraints�_extract_recommendations�_extract_explanation�_extract_risk_decomposition�_extract_goal_feasibility�_extract_investment_style�_extract_market_sensitivity�_extract_alerts�_extract_attention_points�_extract_market_context�_calculate_adaptability_score�_extract_stress_test_resultsrZr[r\r�)r8r�r�sectionsr�Zgeo_allocationr_r9r9r:r�nsX379380381382�383�384�385�386�387�388�389�390	�391 392�393�394�395
�396�397�����z"LLMProfileAnalyzer._parse_responser�rc398Cs�zCd|jkrdksntt|jd�d�|_|jdkrd|_|js%WdS|js+WdS|jdkrA|jdkrA|j�d�|j�	d�WdSt399y_}z|j�d	|���WYd400}~dSd401}~ww)z)Validate analysis results for consistencyrrWr%Fr�z4Inconsistency detected: high risk with short horizonuMAttention: profil à risque élevé avec horizon court, prudence recommandéeTz#Error validating analysis results: N)r�rirhrKr�r�r[r�r�rXrZr\)r8r�r_r9r9r:r��s(402���z$LLMProfileAnalyzer._validate_results�analysisc403Cs�z�|j}g}|�dd�}tdd|d�d}|�|�|�dd�}|dd}|�|�|�d	d�}	|�d404d�}405|	dkrN|406|	}|dkrGdnd}|�|�tt|�d
g��dd�}
|�|
�|}|D]}tdtd||��}qd||_|j�||dt�vr�|nd|
d��|j	s�|�407|�|_	|js�|��|_|j
s�|ddtdd|d�d|dtdd|d�d�|_
|js�|�d�r�|�d�}t|d�r�|�dd�}d|d}|j||d�|_|WSty�}z|j�d|���|WYd}~Sd}~ww)z,Enrich analysis with additional calculationsrrr�ArLrr'r�r r"r�皙������rr�rW�financial_adjustment)Z408age_factorZknowledge_factorZfinancial_stability�goals_diversificationr�r�rer���market_beta�
interest_rate�economic_cycle�	inflationr/�calculate_goal_feasibilityr#���Q��?�{�G�z�?)r�r�zError enriching analysis: N)r�r�rhrXrir�r�rQ�localsr��_generate_default_allocationr�� _generate_default_geo_allocationr�r�r^rrZr[r\)r8rr�Zbase_risk_scoreZadjustmentsrZage_adjustmentZ	knowledgeZknowledge_adjustment�incomeZdebtrFrrZfinal_risk_score�adjZ409objectivesr�r�r_r9r9r:r��sh410411412413�414415416�417418���z#LLMProfileAnalyzer._enrich_analysisc419CsH|�dd�d}t||�dd�|�ddg�igd�d|�|�|��d	�S)420z(Generate default analysis when LLM failsrr'r%rKruÉpargne générale)u&Construire un portefeuille diversifiéu Maintenir une réserve d'urgence�Investir régulièrementu5Analyse par défaut basée sur les données fournies.)r�rKr�r�r�r�r�r�)r�r�r#r$)r8r�r�r9r9r:r��s421�z(LLMProfileAnalyzer._get_default_analysisr�rCrPcCs(|}d|d}d|d}|||d�S)z5Generate default asset allocation based on risk scorerWr�rL��Actions�Obligations�Liquiditésr9)r8r��stocks�bondsrTr9r9r:r#
s�z/LLMProfileAnalyzer._generate_default_allocationcCsddddd�S)z&Generate default geographic allocationr�rerLr�)�Europe�Amérique du Nord�Asie-PacifiqueuMarchés émergentsr9r7r9r9r:r$s422�z3LLMProfileAnalyzer._generate_default_geo_allocationrr�c	Cs`tdd�|D�d�}zt�d|�}|rt|d�nd}tt|d�d�WSttfy/YdSw)zExtract risk score from textcs��|]423}|�d�r|VqdS)z1. Score de risqueN��424startswith�r�sr9r9r:r�&r�z9LLMProfileAnalyzer._extract_risk_score.<locals>.<genexpr>r�z(\d*\.?\d+)rrBrW)�nextr��findallrCrirh�425IndexErrorr�)r8rZ	risk_line�matchesrr9r9r:r$s�z&LLMProfileAnalyzer._extract_risk_scorer!c	CsRtdd�|D�d�}zt�d|�}|rt|d�WSdWSttfy(YdSw)zExtract investment horizoncsr1)z4262. HorizonNr2r4r9r9r:r�0r�z6LLMProfileAnalyzer._extract_horizon.<locals>.<genexpr>r�z(\d+)rr%)r6r�r7r!r8r�)r8rZhorizon_liner9r9r9r:r.s�z#LLMProfileAnalyzer._extract_horizoncCsbtdd�|D�d�}|sgSz|�d�d��}t�d|�}dd�|D�WSty0gYSw)	zExtract prioritized goalscsr1)z3. ObjectifsNr2r4r9r9r:r�9r�z4LLMProfileAnalyzer._extract_goals.<locals>.<genexpr>r��:r��[•\-\d]+\.?\s*cSsg|]427}|��r|���qSr9)r�)r�gr9r9r:r�@r�z5LLMProfileAnalyzer._extract_goals.<locals>.<listcomp>)r6r�r�r�rZ)r8r�
goals_sectionZ428goals_textrzr9r9r:r7s�z!LLMProfileAnalyzer._extract_goalscCs�tdd�|D�d�}|siSi}zT|�d�d��}t�d|tj�r&d|d<t�d	|tj�r2d|d429<t�d|tj�r>d|d<t�d
|tj�rJd|d<t�d|tj�rVd|d<t�d|tj�rbd|d<|WStyoiYSw)z#Extract constraints and limitationscsr1)z4. ContraintesNr2r4r9r9r:r�Fr�z:LLMProfileAnalyzer._extract_constraints.<locals>.<genexpr>r�r:r�uliquidité|liquide|court termeT�liquidity_neededu esg|durable|responsable|éthiqueZ	esg_focuszrevenu|dividende|rente�income_focuszprotection|capital|garantiZcapital_protectionufiscalité|impôt|tax�tax_optimizationu!succession|transmission|héritageZinheritance_planning)r6r�r�r�r��IrZ)r8rZconstraints_sectionr��textr9r9r:rDs,�z'LLMProfileAnalyzer._extract_constraintscCs�g}tdd�|D�d�}|r)t�d|�}|D]}|��}|r(|�d�s(|�|�q|sRtdd�|D�d�}|rRt�d|�}|D]}|��}|rQ|�d�sQ|�|�q?|sXgd�}|S)	z Extract specific recommendationscsr1)�8. RecommandationsNr2r4r9r9r:r�hr�z>LLMProfileAnalyzer._extract_recommendations.<locals>.<genexpr>r�r;rCcsr1)z7. Plan d'actionNr2r4r9r9r:r�sr�z7. Plan��5Diversifier le portefeuille selon le profil de risque�$Maintenir une épargne de sécuritéu1Adopter une stratégie d'investissement régulier)r6r�r�r�r3rX)r8rr�Zrec_section�parts�partZ430clean_partZplan_sectionr9r9r:r	es*431�432�z+LLMProfileAnalyzer._extract_recommendationscsztdd�|D�d�}|r|�dd�d��}|r|Sg}dD]�t�fdd�|D�d�}|r3|�|�q|r;d	�|�Sd433S)zExtract detailed explanationcsr1)z9. ExplicationNr2r4r9r9r:r��r�z:LLMProfileAnalyzer._extract_explanation.<locals>.<genexpr>r�r:rWr�)rWr�r'r+�c3s$�|]
}|���d��r|VqdS)�.Nr2r4�Zsection_numr9r:r����"z434 435u3Analyse basée sur le profil d'investisseur fourni.)r6r�r�rXr)r8rZexplanation_sectionr�Zcombined_explanation�sectionr9rKr:r436�s437�438z'LLMProfileAnalyzer._extract_explanationc	�439tdd�|D�d�}i}|r1t�d|�}|D]}|�d���}t|�d��dd��}|d	||<q|sc|D]-}t�d440|tj�rbt�d|�}|D]}|�d���}t|�d��dd��}|d	||<qGq5t	|�441���d�krsdksxn�d
kr��fdd�|��D�}|S)z(Extract asset allocation recommendationscs� �|]}d|��vr|VqdS)zclasse d'actifsN��lowerr4r9r9r:r��r�z?LLMProfileAnalyzer._extract_asset_allocation.<locals>.<genexpr>r��/([A-Za-zÀ-ÖØ-öø-ÿ\s]+)[\s:]+([\d.,]+)\s*%rWr�r�rJr u$allocation|répartition|portefeuiller�G�z��?�)\���(�?c�i|]	\}}||��qSr9r9r���totalr9r:r`��z@LLMProfileAnalyzer._extract_asset_allocation.<locals>.<dictcomp>�r6r��finditerr�r�rC�replacer�rArarbr�)	r8rZallocation_section�442allocationr9�matchrH�443percentagerMr9rVr:r��*�z,LLMProfileAnalyzer._extract_asset_allocationc	rN)z-Extract geographic allocation recommendationscsrO)u
géographiqueNrPr4r9r9r:r��r�zDLLMProfileAnalyzer._extract_geographic_allocation.<locals>.<genexpr>r�rRrWr�r�rJr uzone|région|international|paysrrSrTcrUr9r9r�rVr9r:r`�rXzELLMProfileAnalyzer._extract_geographic_allocation.<locals>.<dictcomp>rY)	r8rZgeo_sectionr\r9r]�regionr^rMr9rVr:r�r_z1LLMProfileAnalyzer._extract_geographic_allocationcCsbtdd�|D�d�}i}|r�z�t�d|�}|r2t|�d��dkr)t|�d��dnt|�d��|d<t�d|�}|rUt|�d��dkrLt|�d��dnt|�d��|d	<t�d444|�}|rxt|�d��dkrot|�d��dnt|�d��|d<t�d|�}|r�t|�d��dkr�t|�d��dnt|�d��|d
<Wn	ty�Ynw|s�ddddd�}|S)zExtract risk decompositioncs��|]	}d|vr|VqdS)zAnalyse des risquesNr9r4r9r9r:r����zALLMProfileAnalyzer._extract_risk_decomposition.<locals>.<genexpr>r�umarché[^\d]*(\d+(?:\.\d+)?)rWr �market_riskucrédit[^\d]*(\d+(?:\.\d+)?)�credit_riskuliquidité[^\d]*(\d+(?:\.\d+)?)�liquidity_risku"opérationnel[^\d]*(\d+(?:\.\d+)?)�operational_riskr�rL)rcrdrerf)r6r�r�rCr�r�)r8rZrisk_sectionrrcrdrerfr9r9r:r�s66666���z.LLMProfileAnalyzer._extract_risk_decompositioncCsvtdd�|D�d�}i}|r9t�d|�}|D]"}|�d���}t|�d��}tt|dkr0|dn|d�d�||<q|S)	z#Extract goal feasibility assessmentcsra)zObjectifs prioritairesNr9r4r9r9r:r��rbz?LLMProfileAnalyzer._extract_goal_feasibility.<locals>.<genexpr>r�z([^:]+):\s*(\d+(?:\.\d+)?)rWr�r r)r6r�rZr�r�rCrirh)r8rr=r�Zgoal_matchesr]r�rr9r9r:r�s&z,LLMProfileAnalyzer._extract_goal_feasibilitycs�dddddd�}tdd�|D�d�}|rott�d|tj��d|d<tt�d	|tj��d|d445<tt�d|tj��d|d<tt�d
|tj��d|d<tt�d|tj��d|d<t|�����dkro�fdd�|��D�}|S)z&Determine recommended investment stylerE)r��growthr%�momentum�qualitycsra)ZRecommandationsNr9r4r9r9r:r�rbz?LLMProfileAnalyzer._extract_investment_style.<locals>.<genexpr>r�uvaleur|sous-évalué|valuerLr�zcroissance|growth|innovationrgzrevenu|dividende|incomer%zmomentum|tendance|trendrhuqualité|quality|soliderircrUr9r9r�rVr9r:r`rXz@LLMProfileAnalyzer._extract_investment_style.<locals>.<dictcomp>)r6r�r�r7rArarbr�)r8rZ
style_weightsr�r9rVr:r
s"�z,LLMProfileAnalyzer._extract_investment_stylecs�ddddd�}d�|�}d|��vr%t�d|tj�}|r%t|�d��|d<d|��vr9tt�d	|tj��d446|d<d|��vrMtt�d
|tj��d447|d<d|��vratt�d|tj��d448|d<t	|�449����dkrv�fdd�|��D�}|S)z(Analyze sensitivity to market conditionsrErr�betazbeta[^\d]*(\d+(?:\.\d+)?)rWrZtauxz	taux|rater�r�cycleucycle|économiquerrzinflation|prixrcrUr9r9r���	max_valuer9r:r`<rXzBLLMProfileAnalyzer._extract_market_sensitivity.<locals>.<dictcomp>)rrQr�r�rArCr�r�r7rhrbr�)r8rr�Z
analysis_textZ450beta_matchr9rlr:rs(�451z.LLMProfileAnalyzer._extract_market_sensitivityc	Cstg}tdd�|D�d�}|r8gd�}|D]#\}}t�||tj�}|D]}|�||�d���t���	�d��q"q|S)z,Extract alerts and critical attention pointscsra)�Points de vigilanceNr9r4r9r9r:r�Crbz5LLMProfileAnalyzer._extract_alerts.<locals>.<genexpr>r�))z(!+|ATTENTION|ALERTE)[^\n]*r�)zattention|vigilance[^\n]*r�)znoter|remarquer[^\n]*rwr)r�rJra)452r6r�rZrArXr�r�rr�r?)	r8rr��attention_sectionZalert_patterns�patternr�r9r]r9r9r:r@s453454��z"LLMProfileAnalyzer._extract_alertscCs:g}tdd�|D�d�}|rt�d|�}dd�|D�}|S)z!Extract specific attention pointscs�$�|]
}d|vsd|vr|VqdS)zPoints d'attentionrnNr9r4r9r9r:r�ZrLz?LLMProfileAnalyzer._extract_attention_points.<locals>.<genexpr>r�r;cSs&g|]}|��r|�d�s|���qS)ZPoints)r�r3�r�pr9r9r:r�^s&z@LLMProfileAnalyzer._extract_attention_points.<locals>.<listcomp>)r6r�r�)r8rr�ro�pointsr9r9r:rWsz,LLMProfileAnalyzer._extract_attention_pointscCs�i}tdd�|D�d�}|rQt�d|tj�rd|d<nt�d|tj�r(d|d<nd	|d<t�d455|tj�r9d|d<nt�d
|tj�rFd|d<nd|d<|�|�|d<|S)zExtract relevant market contextcsrq)uContexte de marchéuconditions de marchéNr9r4r9r9r:r�erLz=LLMProfileAnalyzer._extract_market_context.<locals>.<genexpr>r�ubaiss|bear|négatifZbearZ
market_regimezhauss|bull|positif�bull�neutralzvolatile|instable�high�456volatilityzstable|calme�lowZmoderate�	sentiment)r6r�r�rA�_analyze_market_sentiment)r8r�contextZmarket_sectionr9r9r:rbs457458459460z*LLMProfileAnalyzer._extract_market_contextcCsXd}d�|�}gd�}gd�}||D]\}}t�||tj�r)tt||d�d�}q|S)z$Calculate profile adaptability scorerBr))zflex|adapt|ajustr�)udivers|équilibrr�)zlong terme|patientr�)uexpérience|connaissancer�)ustable|régulierr�))zrigid|fix|strictr)zrisqu|peur|craintr)zcourt terme|urgentr)ulimité|contraintr)uinstable|irrégulierrrrW)rr�r�rArirh)r8rrrBZpositive_factorsZnegative_factorsrprr9r9r:r|s461		�z0LLMProfileAnalyzer._calculate_adaptability_scorerBcCsDtt�d|tj��}tt�d|tj��}||krdS||kr dSdS)zAnalyze market sentimentz"positif|optimiste|favorable|hausseu'négatif|pessimiste|défavorable|baisse�positive�negativerv)r�r�r7rA)r8rBZpositive_countZnegative_countr9r9r:r{�sz,LLMProfileAnalyzer._analyze_market_sentimentc462Cs�i}tdd�|D�d�}|rAt�d|�}|D]*}|�d���}ztt�d|�d���d��}|d||<Wqttfy@Yqw|sJd	d463ddd
�}|S)zExtract stress test resultscsra)zStress testsNr9r4r9r9r:r��rbzBLLMProfileAnalyzer._extract_stress_test_results.<locals>.<genexpr>r�z([^:]+):\s*-?\d+(?:\.\d+)?%rWz-?\d+(?:\.\d+)?rr g333333ӿ�333333ÿg������ɿr)Zmarket_crashZinterest_rate_shockZcurrency_crisisZinflation_shock)	r6r�rZr�r�rCr�r��AttributeError)r8rrZstress_section�	scenariosZscenario�name�impactr9r9r:r�s&��z/LLMProfileAnalyzer._extract_stress_test_resultsc464�sx�z|j�|�}|j�|�IdH}|�dd���}|WSty;}z|j�d|���|�|�WYd}~Sd}~ww)z%Generate detailed profile descriptionNr�r�z&Error generating profile description: )	r�r�r�r[r�rZr[r\�_generate_default_description)r8r�r��descriptionr_r9r9r:�generate_profile_description�s���z/LLMProfileAnalyzer.generate_profile_descriptioncCs�|�dd�}|�dd�}d�|�ddg��}|�dd�}|�d	d465�}|dkr(dn|dkr.d
nd}d|�d|�d|�d|�d|�d|�d|�d�S)z0Generate default description if generation failsrr�r r�ruépargne généralerr'rKr%r�ZprudentumodéréZ	dynamiquezProfil investisseur de z ans avec un revenu annuel de u3€. 466Ce profil présente une tolérance au risque z	 (niveau z&/5) et un horizon d'investissement de z% ans.467Ses principaux objectifs sont: uc.468 469Une stratégie d'investissement diversifiée est recommandée, adaptée à son niveau de risque u{. 470L'allocation d'actifs devra tenir compte de ses objectifs spécifiques tout en respectant son horizon d'investissement.471r�)r8r�rr%rzZriskr
rr9r9r:r��s"�����z0LLMProfileAnalyzer._generate_default_descriptionrV�r�r�r�)r�ryrVr�)r�r�rVr�)r�rrryrVr�)r�r�rVr)rr�r�ryrVr�)r�rCrVrPr)rr�rVrC)rr�rVr!)rr�rVr�)rr�rVry)rr�rVr)rr�rVrP)rr�rVr�)rBrrVr)#r<r=r>r?r�r�r�r�rr�r�r�r�r#r$rrrrr	r472rrrrr
rrrrrr{rr�r�r9r9r9r:r��sB473	
474475+476H477!478479O480481
482 483 484 485 486	487
488!489 490491492493$494495496!497498499500501502r�c@s>eZdZdZdddedd�Zdd�Zdfd
d�Zdgdd�Zdhdd�Zdidd�Z	djdd�Z503dkdd �Zdld"d#�Zdmd$d%�Z
dddnd)d*�Zdod,d-�Zd.d/�Zdpd2d3�Zdqd7d8�Zdqd9d:�Zdrd<d=�Zdsd?d@�ZdtdudFdG�ZdvdHdI�ZdwdLdM�ZdwdNdO�ZdxdQdR�ZdvdSdT�ZdydWdX�ZdzdZd[�Zdvd\d]�Zd{d^d_�Zd|d`da�Z dvdbdc�Z!dS)}�DeepVestProfilerz9Advanced investor profiler with fine-tuned AI integrationNr�r�cCsB|pt�|_t�d�|_t|j�|_i|_|jjr|�	�dSdS)z&Initialize profiler with configurationzDeepVest.ProfilerN)504rr�r3r4r[r��llm_analyzerr�r$�_ensure_db_directoryr�r9r9r:r��s�zDeepVestProfiler.__init__cCs<tj�|jj�st�|jj�|j�d|jj���dSdS)z Ensure database directory existszCreated database directory: N)rprrr�r�r#rqr[rwr7r9r9r:r��s�z%DeepVestProfiler._ensure_db_directoryr�ryrVrc�s(�z�|j�d�|��}d|vr|�d�|d<nd|vr#|�d�|d<|j�|�IdH}|j�|�IdH}td'id|�d��d|�dd��d	|�d	d505��d|�dd��d|�dd��d
|�d
g��d|�dd��d|�di��d|�dd��d|�dd��d|�dd��d|�dd��d|�dd��d|�dd��d|�dd��d|�dd��d|�dd��d|�d|�dd���d|�d |j	�d!|j506�d"|�d"d#��d$|��}|�||�IdH|��|�
�||j|j<|jjr�|�|�|j�d%|j���|WSt�y}z507|j�d&|����d}~ww)(z2Create complete investor profile with LLM analysiszCreating new investor profile�épargne_mensueller#�épargne mensuelleNrrr'rKr%rDrrrFr�rrr rr!r"r$r�r%r&r(r'r)rpr9r�r�r:rBr0z&Profile created successfully with ID: zError creating profile: r9)r[rw�copy�popr�r�r�rr�r�r��_add_detailed_analysisr<rRr�rr�r$�_save_profile_to_dbrZr\)r8r��processed_datar|r0r�r_r9r9r:�create_profile�s��508�����	�509�����������������"510��zDeepVestProfiler.create_profiler�r�c�s&�zTt|�dd�d|jdkr|j|jnd|�dd�dkr,|�dd�|�dd�dnd|�d	d�|jr9|jjnd511|j|�dd�|�d
i�|�di�|�di�d�512|_Wntyp}z|j	�513d|���WYd}~nd}~wwz<td|�d�dvr}dnd|�dd�|�dd�|�|j
�|�dg�|�dd�|�di�|�di�|�di�d�|_Wnty�}z|j	�514d|���WYd}~nd}~wwz,tdd�t|j�D�|�di�|�d i�|j|�d!i�|�d"i�|�d#i�d$�|_WdSt�y}z|j	�515d%|���WYd}~dSd}~ww)&z Add detailed analyses to profilerDr'r%rr r#rWr�rIrBrMrLrQrRrS)516rDrFrGrIrJrKrMrQrRrSz,Error creating detailed financial analysis: Nr()�marriedZ	partneredrprtrurvrwrx)rorprrrtrurvrwrxz)Error creating detailed family analysis: cSsg|]\}}||dd��qS)rW)r��priorityr9)rr�r�r9r9r:r�ir�z;DeepVestProfiler._add_detailed_analysis.<locals>.<listcomp>Zgoal_timeframesr�Zgoal_amountsr�Zrisk_by_goal)r�r�r�r�r�r�r�z/Error creating detailed investment objectives: )rAr�r r"r9r�rKr-rZr[r�rn�_determine_life_stagerr.r�r�rr/)r8r�r�r_r9r9r:r�Ds^�.517518519520521���$522523524525526527528�529��530531532533534�	 ��z'DeepVestProfiler._add_detailed_analysisrr!rcCs@|dkrdS|dkrdS|dkrdS|dkrdS|d	krd535SdS)z!Determine life stage based on age�Zearly_career�#Zcareer_building�-Zfamily_building�7Zpeak_earningrZpre_retirementZ536retirementr9)r8rr9r9r:r�tsz&DeepVestProfiler._determine_life_stagec537Cs~z"|j�d�}tj�|jj|�}|j|dd�|j�d|���WdSt	y>}z|j�538d|���WYd}~dSd}~ww)z"Save profile to persistent storage�.jsonT)rhzProfile saved to database: z"Error saving profile to database: N)rrprrrr�r#ryr[rwrZr\)r8r��filenamergr_r9r9r:r��s ��z$DeepVestProfiler._save_profile_to_db�539profile_id�Optional[PersonalProfile]c540�s��zO||jvr|j�d|�d��|j|WS|jjrDtj�|jj|�d��}tj�	|�rD|j�541d|�d��t�|�}||j|<|WS|j�
d|�d��WdStyo}z|j�d|�d	|���WYd}~dSd}~ww)542u Récupérer un profil par son ID�Profile z found in memory cacher�zLoading profile z from disk storage�543 not foundNzError retrieving profile r�)r�r[r�r�r$rprrrr#r�rwrr�r�rZr\)r8r�rgr�r_r9r9r:�get_profile�s&�544545546��zDeepVestProfiler.get_profilerYc547�sv�z�|�|�IdH}|std|�d���|��}d|vr$|�d�|d<nd|vr/|�d�|d<ddlm}||�}d	g}|D]	}||vrG||=q>|��D]\}	}548|	|vrX|549||	<qLdd550lm}|t	�j551��fdd�|��D�}t	di|��}
t|
d
�r|
��|j
�|
�IdH}||
_|�|
�IdH|j�d|�d��|
WSty�}z|j�d|�dt|�����d}~ww)u=Met à jour un profil existant avec de nouvelles informationsNzProfile with ID r�r�r#r�r)rr{)�	signaturecsi|]\}}|�vr||�qSr9r9r��Zprofile_paramsr9r:r`�r�z3DeepVestProfiler.update_profile.<locals>.<dictcomp>r<r�z updated successfullyzError updating profile r�r9)r�r�r�r��dataclassesrr��inspectr�r�552parametersr^r<�analyzerr�r9Z
_save_profiler[rwrZr\r)r8r�rYr�Zprocessed_updatesrZprofile_dictZfields_to_removerr�r�r�Z
filtered_dictr]r�r_r9r�r:�update_profile�sJ���553554��zDeepVestProfiler.update_profilercshd�}t�fdd�|D��S)z0Determine if profile changes require re-analysis>555r"r rrrKrrr(r)r!c3s�|]}|�vVqdSrVr9)rr�rYr9r:r��r�z<DeepVestProfiler._are_changes_significant.<locals>.<genexpr>)r�)r8rYZsignificant_fieldsr9r�r:�_are_changes_significant�sz)DeepVestProfiler._are_changes_significantc556�s��z1||jvr|j|=|jjr&tj�|jj|�d��}tj�|�r&t�|�|j	�557d|�d��WdStyQ}z|j	�d|�d|���WYd}~dSd}~ww)	zSupprimer un profilr�r�z deleted successfullyTzError deleting profile r�NF)
r�r�r$rprrrr#r��remover[rwrZr\)r8r�rgr_r9r9r:�delete_profile�s�558559��zDeepVestProfiler.delete_profile�filter_criteria�Optional[Dict[str, Any]]r�c560�s��z:g}|jjr|��|j��D]'\}}|r|�||�sq|j|j|j|j	|j561��|j��|j
d�}|�|�q|WStyX}z|j�d|���gWYd}~Sd}~ww)uHListe tous les profils disponibles avec critères de filtrage optionnels)rrr�rKZ
creation_daterrzzError listing profiles: N)r�r$�_load_all_profiles_to_memoryr�r��_profile_matches_criteriarrr�rKrr?rrrXrZr[r\)r8r�Z
profiles_listr�r�Zprofile_infor_r9r9r:�
list_profiles	s.��	��zDeepVestProfiler.list_profiles�criteriacCs�|��D]M\}}t||�sdSt||�}t|t�r=d|vs"d|vr=d|vr/||dkr/dSd|vr<||dkr<dSqt|t�rJ||vrIdSq||krQdSqdS)u8Vérifie si un profil correspond aux critères de filtreFrirhT)r�r^r_r�rmr�)r8r�r�rr�Z
profile_valuer9r9r:r� 	s$562563�564��z*DeepVestProfiler._profile_matches_criteriacCs*|jjsdSzr|jj}tj�|�s|j�d|�d��WdSdd�t�|�D�}|j�	dt565|��d��|D]?}|�dd	�}||jvrutj�
||�}zt�|�}||j|<Wq6tyt}z|j�d566|�d|���WYd}~q6d}~wwq6WdSty�}z|j�d|���WYd}~dSd}~ww)
uFCharge tous les profils depuis le stockage persistant vers la mémoireNzDatabase directory r�cSsg|]	}|�d�r|�qS)r�)�endswith)rrxr9r9r:r�D	rXzADeepVestProfiler._load_all_profiles_to_memory.<locals>.<listcomp>zFound z profile files in databaser�r�r~r�z"Error loading profiles from disk: )r�r$r#rprrr�r[r��listdirrwr�r[r�rrr�rZr\)r8r#Z567json_filesZ	json_filer�rgr�r_r9r9r:r�8	s4568569$����570 ��z-DeepVestProfiler._load_all_profiles_to_memory�profile_idsr�c571�s��zQg}i}|D]}|�|�IdH}|r|�|�|||<q|s)|j�d�iWS|�|�}|�|�}|�|�}i}	t|�dkrH|�|�IdH}	||||	t|�d�WSt	ys}572z|j�573d|574���dt|575�iWYd}576~577Sd}578~579ww)uBAnalyse par lots de plusieurs profils pour détection de tendancesNz*No valid profiles found for batch analysisr%)�580age_groups�risk_distribution�goal_trendsZprofile_clustersZtotal_profiles_analyzedr�r\)r�rXr[r��_group_profiles_by_age�_group_profiles_by_risk�_analyze_goal_trendsr��_cluster_profilesrZr\r)r8r�r�Zprofile_mapr�r�r��risk_groupsr��clustersr_r9r9r:rU	s<�581�582583584���z'DeepVestProfiler.batch_analyze_profilesr��List[PersonalProfile]r�cCs�ddddddd�}|D]N}|j}|dkr|dd7<q|dkr*|dd7<q|dkr7|d	d7<q|d585krD|dd7<q|dkrQ|d
d7<q|dd7<q|S)u%Groupe les profils par tranche d'âger)�18-25�26-35�36-45�46-55�56-65�65+r�r�rWr�r�r�r�r�r�rr�r�)r)r8r�r�r�rr9r9r:r�|	s*�	z'DeepVestProfiler._group_profiles_by_agecCs�dddddd�}|D]A}|j}|dkr|dd7<q586|dkr)|dd7<q587|dkr6|d	d7<q588|d589krC|dd7<q590|dd7<q591|S)
z'Groupe les profils par niveau de risquer)r�r�r�r�r�rLr�rWr�r�r�r�r�r�r�r�)r8r�r�r�r�r9r9r:r��	s$�z(DeepVestProfiler._group_profiles_by_risk�Dict[str, Dict[str, Any]]cCs�i}|D]?}|jD]9}||vrdddgd�||<||dd7<||d|j7<||d|j7<||d�|j�q	q|��D]&\}}|d}|dkrn|d|<|d|<|t|�d|d	<qH|S)592z9Analyse les tendances dans les objectifs d'investissementr)�count�avg_risk_score�avg_investment_horizonr�r�rWr�r�r�r r^)rr�rKrXrr�r�)r8r�Z	all_goalsr�r�r�r�r9r9r:r��	s,593594���z%DeepVestProfiler._analyze_goal_trends�Dict[str, List[str]]c595�s��z�g}g}|D]=}|j|jd|jd|jd|jd|jdkr&|jdnd|jdkr1|jdndt|j�dg}|�	|�|�	|j596�qt|�dkrQd|iWSddlm}dd	l
m}|�}|�|�}	ttd597t|�d�d�}598||599ddd�}|�|	�}i}
t|�D]\}}d
|d��}||
vr�g|
|<|
|�	||�q�|
WSty�}z|j�d|���ddd�|D�iWYd}~Sd}~ww)uCRegroupe les profils en clusters basés sur leurs caractéristiques�600r r%ri@Br'Z	cluster_1)�KMeans)�StandardScalerr��*)�601n_clusters�random_state�n_initZcluster_rWzError in profile clustering: Z
cluster_errorcSsg|]}|j�qSr9)rrrr9r9r:r�602sz6DeepVestProfiler._cluster_profiles.<locals>.<listcomp>N)r�rKrrrDr!r"r�rrXrZsklearn.clusterr�Zsklearn.preprocessingr��
fit_transformrirh�fit_predictr�rZr[r\)r8r��featuresr�r�Zfeature_vectorr�r��scalerZfeatures_scaledr��kmeansr�Zcluster_dictr�Z603cluster_idZcluster_namer_r9r9r:r��	sJ��604605606607��z"DeepVestProfiler._cluster_profilesFr�rCrKrc608sz�|}|dkr|d}d}|dkrd}n|dkrd}n|dkr"d	}n	|d609kr)d}nd}i}|dkr8d
ddd�}n'|dkrCddd
d�}n|d	krNdddd�}n|dkrYdddd�}ndddd�}d}|dkrhd}n|dkrnd}|dkr�t|dt|��|dkr�dnd}|d|7<|}	|	d}610|	d}|d|6117<|d|7<|r�t|dd�}|d|8<||d <d!d"�|��D�}t|�����fd#d"�|��D�}|||d$�d%�WSt�y}
z|j�d&t|
����dddd�dd	d$�d%�WYd'}
~
Sd'}
~
ww)(u�Génère une allocation d'actifs basée sur le profil de risque et l'horizon612        613        Args:614            risk_score: Score de risque (1-5 ou 0-1)615            investment_horizon: Horizon d'investissement en années616            esg_preferences: Indique si l'investisseur a des préférences ESG617            618        Returns:619            Dictionnaire contenant l'allocation d'actifs et le profil de risque620        rWg@r�rLr�r�r�r�r�r�r�r��333333�?g�������?r(reg�������?rBr�r�rfr�g333333�?rr%r�r)r�r*r+�Actions ESGcSsi|]621\}}|td|��qS)r)rhr�r9r9r:r`e622r�z>DeepVestProfiler.generate_asset_allocation.<locals>.<dictcomp>crUr9r9r�rVr9r:r`i623rX�rr)r�rz#Error generating asset allocation: N)	ri�absr�rarbrZr[r\r)r8r�rKrZnormalized_riskrr\Zhorizon_factorZaction_shiftZremaining_shiftZobligation_shiftZliquidity_shiftZesg_allocationr_r9rVr:�generate_asset_allocation624s������"��625���z*DeepVestProfiler.generate_asset_allocationc626�s$�z�|r|jstd��t|dd�}|dkr$t|d�r$t|jd�r$|jj}d|jkr/dkr4nn|jnd}|j||j|j	d�}g}|�627d	�|jd628krW|�629d�|�630d�n|jd
krg|�631d�|�632d�n633|�634d�|�635d�d|jvr{|�636d�d|jvr�|�637d�d|jvr�|�638d�|j
|jkr�|�639d�||jddkr�|�640d�t|�dkr�|dd�}|jt����|d|d|t|jdd|�|jd d!�|�||�d"�}|j�d#|j���|WSt�y}z|j�d$t|����d%d&id'd(dd)�gd*�d+�WYd}~Sd}~ww),uFGénère une stratégie d'investissement personnalisée pour un profilzInvalid profiler#rr-rWr%r')r�rKrrEru@Privilégier les investissements à fort potentiel de croissanceu7Adopter une stratégie d'investissement régulier (DCA)rEu:Équilibrer croissance et sécurité dans votre allocationu.Réviser annuellement votre stratégie fiscaleu(Sécuriser progressivement votre capitalu0Optimiser votre stratégie en vue de la retraite�Retraitez3Maximiser les versements sur votre plan de retraitezAchat immobilierz1Constituer un apport pour votre projet immobilieruÉtudes des enfantsu=Mettre en place une épargne dédiée aux études des enfantsu5Prioriser le remboursement des dettes à taux élevér�r�u'Augmenter votre taux d'épargne mensuelNrr�r�rg)r#Zemergency_fund)r�rarr�r��targetsZinvestment_productsz*Generated investment strategy for profile z&Error generating investment strategy: rr�r�rer(rD)rr�r�)rr�r_r^r-r#rr�rKrrXrrr"r r�rr�r?rhZ_recommend_productsr[rwrZr\r)r8r�r#r�r�r��strategyr_r9r9r:�generate_investment_strategy|641sn�642$�643644645646647648649650651652653654655656657658�659�
660���z-DeepVestProfiler.generate_investment_strategyr\rPcs|��}|jr!d|vr!|�dd�}|dkr!|d|d<|d|d<t|d�rl|jrl|jj}|dkrld|vrltd|�}|d|krl||d}t|���D]\}}	|dkrg|	|d	|d}661td|	|662�||<qL||d<t	|�663���t�d664�dkr��fdd
�|��D�}|S)uIRaffine l'allocation d'actifs basée sur des contraintes supplémentairesr)rrer�r�r-r+r�rWr�rScrUr9r9r�rVr9r:r`�665rXz=DeepVestProfiler._refine_asset_allocation.<locals>.<dictcomp>)r�rr�r^r-rMrhr�r�rarbr�)r8r\r��refinedZregular_stocksrMZmin_cashZ	shortfallr�r�	reductionr9rVr:�_refine_asset_allocation�666s,667�z)DeepVestProfiler._refine_asset_allocationcs|s	ddddd�}|��}|jdkr4d|vr3|d}|d|d<dD]}||vr2|||d	7<q"n3|jd668krgd|vrg|ddkrgtdd|d�}|d|7<dD]}||vrf|||d8<qVt|����t�d�d
kr��fdd�|��D�}|S)uNRaffine l'allocation géographique basée sur des contraintes supplémentairesr�rerLr��r.r/r0�Pays émergentsr�rB)r.r/rfr�r�r�rScrUr9r9r�rVr9r:r`rXzBDeepVestProfiler._refine_geographic_allocation.<locals>.<dictcomp>)r�r�rirarbr�r�)r8r\r�r�Zemergingr`�increaser9rVr:�_refine_geographic_allocation�669s6�670�671�z.DeepVestProfiler._refine_geographic_allocationr�cCs�g}|�dddgd�d��|�di�}g}|��D]\}}|�d|d�d	|�d672��q|�ddd
|d��|�dddgd�d��|�dddgd�d��|S)uCGénère des étapes d'implémentation pratiques pour la stratégierWzMise en place des comptesu?Ouvrir les comptes nécessaires pour implémenter la stratégie)uEOuvrir un compte-titres classique pour les investissements générauxu4Mettre en place un PEA pour les actions européennesuDConsidérer une assurance-vie pour les investissements à long terme)�order�titler��actionsr�zAllouer r�u( du portefeuille à la classe d'actifs "�"r�zAllocation initiale des actifsuFRépartir les investissements selon l'allocation d'actifs recommandéer'uCalendrier d'implémentationuIÉtablir un calendrier progressif pour l'implémentation de la stratégie)zEMois 1: Mise en place des comptes et investissement de 25% du capitalu0Mois 2-3: Investissement de 25% supplémentairesz+Mois 4-6: Investissement du capital restantuETrimestriel: Rééquilibrage du portefeuille selon l'allocation cibler+zSuivi et ajustementsu9Établir un processus de suivi régulier de la stratégie)z3Suivre mensuellement la performance du portefeuilleu@Vérifier trimestriellement l'alignement avec l'allocation cibleu0Réévaluer annuellement la stratégie complètez<Ajuster en fonction des changements de situation personnelle)rXr�r�)r8r��stepsr�Zallocation_actionsr�rr9r9r:�_generate_implementation_stepss<���
�z/DeepVestProfiler._generate_implementation_stepscCsn|jdks673|jdkrd}d}n|jdks|jdkrd}d}nd	}d674}|||jdkr+dnd
t��|�|�d�S)u3Détermine le calendrier de rééquilibrage optimalr�r+�
Trimestrieller�rer��Annueller��Semestrielleg333333�?r'zThreshold-basedzCalendar-based)�	frequencyZdrift_threshold�methodZnext_scheduled)r�rrr��_frequency_to_timedelta)r8r�r��	thresholdr9r9r:�_determine_rebalancing_scheduleUs�z0DeepVestProfiler._determine_rebalancing_scheduler�rcCsR|dkr	tdd�S|dkrtdd�S|dkrtdd�S|dkr$td	d�Stdd�S)675u5Convertit une fréquence textuelle en objet timedeltaZ	Mensuellerr�r�r�r��r�im)r)r8r�r9r9r:r�is676677678679680z(DeepVestProfiler._frequency_to_timedelta�yearsc	681Cs�ddd�ddd�ddd�ddd�d	d	d�d682dd�d683dd�dd
d�d�}d}d}|��D]\}}||vrG|||d|7}|||d|7}q+|dkrQ|d9}n|dkrY|d9}d||d}||||d||dd�||d�d�S)uHCalcule les performances attendues basées sur l'allocation et l'horizong�Q���?g684ףp=685�?)rVrxg�p=686ף�?g��(\���?r r�r�rSr!g{�G�z�?rLr�)r)r�r*Z687Immobilierr+�OruMatières premièresZCryptomonnaiesrrVrxr�g�������?r%gffffff�?rWr�g�������?)�conservative�expectedZ688optimistic)Ztime_horizonZasset_assumptions)Zexpected_annual_return�expected_volatilityZexpected_total_returnr��assumptions)r�)	r8r\r�r�r�r�r�rZcompound_returnr9r9r:�_calculate_expected_performancevs@��689���z0DeepVestProfiler._calculate_expected_performancec�sb�|�|�}ddddd�}gd�}gd�}|jd|�|jd�d	�|j|jd690d�||||d�S)
uKGénère une stratégie de repli lorsque l'analyse LLM n'est pas disponibler�rerLr�r�)z;Diversifier votre portefeuille selon votre profil de risqueuJMaintenir une épargne de sécurité équivalente à 3-6 mois de dépensesuFInvestir régulièrement pour lisser l'exposition au risque de marchéuSRééquilibrer périodiquement votre portefeuille pour maintenir l'allocation cible)uCSurveiller l'évolution de votre tolérance au risque avec le tempsu^Ajuster votre stratégie en fonction des changements importants de votre situation personnelleu3Rester discipliné face aux fluctuations du marchér%r�Nr')rrKr�r�r�r�r�)r#r�_get_risk_categoryrKr)r8r�r�r�r�r�r9r9r:�_generate_fallback_strategy�s&�691���z,DeepVestProfiler._generate_fallback_strategycCsX|jd}|}d|d}d|d}|dkr&|d}||8}||||d�S|||d�S)	uBGénère une allocation par défaut basée sur le profil de risquer%rWr�rLr�r�)r)r*r+zActifs alternatifsr()r)r8r�r�r,r-rT�alternativesr9r9r:r#�s 692��z-DeepVestProfiler._generate_default_allocationcCs4|dkrdS|dkrdS|dkrdS|dkrdSd	S)693u6Détermine la catégorie de risque basée sur le scorerLr�r�r�r�r�r�r�r�r9)r8r�r9r9r:r��sz#DeepVestProfiler._get_risk_categorycCsf|j}|dkrdddd�}n|dkrdddd�}nd	ddd�}|d694|�|d695�d�|j|gd�d
�S)u3Génère une stratégie simplifiée en cas d'erreurr�rerBrLr(r'r�r�r�r%r�)zDiversifier votre portefeuiller'rF)rrKr�r�)rr�rK)r8r�Z696risk_levelr\r9r9r:�"_generate_simple_fallback_strategy�s��z3DeepVestProfiler._generate_simple_fallback_strategyrVr�)r�ryrVr)r�rr�ry)rr!rVr)r�r)r�rrVr�)r�rrYryrVr)rYryrVr)r�rrVr)r�r�rVr�)r�rr�ryrVr)r�r�rVry)r�r�rVr�)r�r�rVr�)r�r�rVr�r�)r�rCrKr!rrrVry)r�rrVry)r\rPr�rrVrP)r�ryrVr�)r�rrVr)r\rPr�r!rVry)r�rrVrP)r�rCrVr)"r<r=r>r?r�r�r�r�r�r�r�r�r�r�r�r�r�rr�r�r�r�r�r�r�r�r�r�r�r�r�r#r�rr9r9r9r:r��s@697698M69907007017027039704	705 706707'7087097109711t712U713"714)7159716717
7180719)720
r�)0�721__future__r�asyncior@rur3rpr�r�rrrrr�	functoolsr�typingr	r722rrr
rr�numpy�npr�r�rrr�ImportErrorr�rr�basicConfig�INFOr4r[rrArnr�r�rr�r�r�r9r9r9r:�<module>sp$���723#NDmh