Files
BoursePython/app/templates/analyse.html
T

389 lines
25 KiB
HTML

{% extends "base.html" %}
{% block title %}Analyse technique - Bolsa{% endblock %}
{% block header_title %}Analyse technique{% endblock %}
{% block content %}
<div class="flex flex-col items-center justify-start py-4 px-2 w-full h-full overflow-y-auto">
<!-- Toasts -->
<div id="toast-container" class="fixed top-6 left-1/2 transform -translate-x-1/2 z-50 space-y-3 w-full max-w-md px-4 pointer-events-none">
{% set messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="toast-message pointer-events-auto flex items-center justify-center px-4 py-3 rounded-xl shadow-2xl text-white text-sm font-medium transition-all duration-300
{% if category == 'success' %}bg-emerald-600 border border-emerald-500{% else %}bg-rose-600 border border-rose-500{% endif %}">
<span>{{ message }}</span>
</div>
{% endfor %}
{% endif %}
</div>
<!-- Barre de recherche ISIN -->
<div class="bg-gray-900 border border-gray-800 rounded-2xl shadow-2xl w-full max-w-[98%] p-4 mb-4">
<form method="GET" action="{{ url_for('analyse.analyse') }}" class="flex items-center gap-3 flex-wrap">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<div class="flex-1 min-w-[200px]">
<label class="block text-xs font-medium text-gray-400 mb-1">Entrer un ISIN</label>
<input type="text" name="isin" id="input-isin-analyse" required
value="{{ isin_recherche or '' }}"
placeholder="Ex : FR0000120271"
class="w-full bg-gray-950 border border-gray-800 rounded-lg px-3 py-2 text-white text-sm focus:outline-none focus:border-blue-500 uppercase" />
</div>
<button type="submit" class="px-5 py-2.5 bg-blue-600 hover:bg-blue-500 text-white text-sm font-semibold rounded-lg transition cursor-pointer self-end">
<i class="fa-solid fa-magnifying-glass-chart"></i> Analyser
</button>
<a
href="{{ url_for('menu.menu') }}"
class="px-5 py-2.5 bg-gray-800 hover:bg-gray-700 text-gray-200 text-sm font-semibold rounded-lg transition duration-200 cursor-pointer self-end"
>
<i class="fa-solid fa-house"></i> Retour au menu
</a>
</form>
</div>
{% if resultat %}
{% if resultat.erreur %}
<!-- Message d'erreur -->
<div class="bg-rose-950 border border-rose-800 rounded-xl p-6 text-center w-full max-w-[98%]">
<i class="fa-solid fa-triangle-exclamation text-rose-400 text-3xl mb-3"></i>
<p class="text-rose-300 text-sm">{{ resultat.erreur }}</p>
{% if resultat.action %}
<p class="text-gray-400 text-xs mt-2">Action : {{ resultat.action.company_name }} ({{ resultat.isin }})</p>
{% endif %}
</div>
{% else %}
<!-- ===================== EN-TÊTE FICHE ACTION ===================== -->
<div class="bg-gray-900 border border-gray-800 rounded-2xl shadow-2xl w-full max-w-[98%] p-6 mb-4">
<div class="flex flex-wrap items-start justify-between gap-4">
<div>
<h2 class="text-3xl font-extrabold text-white">{{ resultat.action.company_name }}</h2>
<p class="text-gray-400 text-sm font-mono mt-1">{{ resultat.isin }}
{% if resultat.action.ticker %} · {{ resultat.action.ticker }}{% endif %}
</p>
<div class="flex items-center gap-4 mt-3">
<span class="text-2xl font-bold text-white">{{ "{:,.2f}".format(resultat.cours) }} {{ resultat.action.currency or '€' }}</span>
{% set vj = resultat.variation_jour %}
<span class="text-lg font-semibold {% if vj and vj >= 0 %}text-emerald-400{% elif vj %}text-rose-400{% else %}text-gray-400{% endif %}">
{% if vj %}{{ "{:+,.2f}".format(vj) }} %{% else %}--{% endif %}
</span>
</div>
<p class="text-gray-500 text-xs mt-1">Dernier cours : {{ resultat.derniere_date_cours }}</p>
</div>
<div class="text-right">
<div class="inline-block bg-gray-950 border border-gray-800 rounded-xl px-5 py-3">
<p class="text-xs text-gray-400 uppercase tracking-wider">Score</p>
<p class="text-4xl font-extrabold
{% if resultat.score >= 65 %}text-emerald-400{% elif resultat.score <= 35 %}text-rose-400{% else %}text-amber-400{% endif %}">
{{ resultat.score }}/100
</p>
</div>
<p class="mt-2 text-sm font-semibold
{% if resultat.tendance == 'haussiere' %}text-emerald-400{% elif resultat.tendance == 'baissiere' %}text-rose-400{% else %}text-amber-400{% endif %}">
{% if resultat.tendance == 'haussiere' %}🟢 Haussière{% elif resultat.tendance == 'baissiere' %}🔴 Baissière{% else %}🟡 Neutre{% endif %}
</p>
</div>
</div>
</div>
<!-- ===================== CARTES INDICATEURS ===================== -->
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-7 gap-3 w-full max-w-[98%] mb-4">
<!-- RSI -->
{% set rsi14 = resultat.rsi.RSI14 %}
<div class="bg-gray-900 border border-gray-800 rounded-xl p-3 text-center">
<p class="text-xs text-gray-400 uppercase tracking-wider mb-1">RSI 14</p>
<p class="text-2xl font-bold {% if rsi14.valeur and rsi14.valeur < 30 %}text-emerald-400{% elif rsi14.valeur and rsi14.valeur > 70 %}text-rose-400{% else %}text-white{% endif %}">
{{ rsi14.valeur if rsi14.valeur is not none else '--' }}
</p>
<p class="text-[10px] {% if rsi14.zone == 'survente' %}text-emerald-400{% elif rsi14.zone == 'surachat' %}text-rose-400{% else %}text-gray-500{% endif %} uppercase">{{ rsi14.zone }}</p>
</div>
<!-- MACD -->
{% set macd = resultat.macd %}
<div class="bg-gray-900 border border-gray-800 rounded-xl p-3 text-center">
<p class="text-xs text-gray-400 uppercase tracking-wider mb-1">MACD</p>
<p class="text-2xl font-bold {% if macd.histogramme and macd.histogramme > 0 %}text-emerald-400{% elif macd.histogramme and macd.histogramme < 0 %}text-rose-400{% else %}text-white{% endif %}">
{{ "{:+.2f}".format(macd.histogramme) if macd.histogramme is not none else '--' }}
</p>
<p class="text-[10px] {% if macd.croisement == 'haussier' %}text-emerald-400{% elif macd.croisement == 'baissier' %}text-rose-400{% else %}text-gray-500{% endif %} uppercase">{{ macd.croisement }}</p>
</div>
<!-- ATR14 -->
<div class="bg-gray-900 border border-gray-800 rounded-xl p-3 text-center">
<p class="text-xs text-gray-400 uppercase tracking-wider mb-1">ATR 14</p>
<p class="text-2xl font-bold text-white">{{ resultat.atr.ATR14 if resultat.atr.ATR14 is not none else '--' }}</p>
<p class="text-[10px] text-gray-500">{{ resultat.atr.ATR14_pct if resultat.atr.ATR14_pct is not none else '--' }}% du cours</p>
</div>
<!-- Volatilité -->
<div class="bg-gray-900 border border-gray-800 rounded-xl p-3 text-center">
<p class="text-xs text-gray-400 uppercase tracking-wider mb-1">Volatilité 20j</p>
<p class="text-2xl font-bold text-white">{{ resultat.volatilite.actuelle if resultat.volatilite.actuelle is not none else '--' }}%</p>
<p class="text-[10px] text-gray-500">Moy 1an : {{ resultat.volatilite.moyenne_1an if resultat.volatilite.moyenne_1an is not none else '--' }}%</p>
</div>
<!-- Bollinger -->
<div class="bg-gray-900 border border-gray-800 rounded-xl p-3 text-center">
<p class="text-xs text-gray-400 uppercase tracking-wider mb-1">Bollinger</p>
<p class="text-2xl font-bold text-white">{{ resultat.bollinger.position if resultat.bollinger.position is not none else '--' }}%</p>
<p class="text-[10px] text-gray-500">position dans les bandes</p>
</div>
<!-- Volume relatif -->
<div class="bg-gray-900 border border-gray-800 rounded-xl p-3 text-center">
<p class="text-xs text-gray-400 uppercase tracking-wider mb-1">Volume relatif</p>
<p class="text-2xl font-bold {% if resultat.volumes.exceptionnel %}text-amber-400{% else %}text-white{% endif %}">
{{ resultat.volumes.volume_relatif if resultat.volumes.volume_relatif is not none else '--' }}x
</p>
<p class="text-[10px] {% if resultat.volumes.exceptionnel %}text-amber-400{% else %}text-gray-500{% endif %}">{% if resultat.volumes.exceptionnel %}Exceptionnel{% else %}Normal{% endif %}</p>
</div>
<!-- Drawdown -->
<div class="bg-gray-900 border border-gray-800 rounded-xl p-3 text-center">
<p class="text-xs text-gray-400 uppercase tracking-wider mb-1">Drawdown</p>
<p class="text-2xl font-bold {% if resultat.drawdown.actuel and resultat.drawdown.actuel < -10 %}text-rose-400{% else %}text-white{% endif %}">
{{ "{:.1f}".format(resultat.drawdown.actuel) if resultat.drawdown.actuel is not none else '--' }}%
</p>
<p class="text-[10px] text-gray-500">Max : {{ "{:.1f}".format(resultat.drawdown.maximum) if resultat.drawdown.maximum is not none else '--' }}%</p>
</div>
</div>
<!-- ===================== GRAPHIQUE PRINCIPAL ===================== -->
<div class="bg-gray-900 border border-gray-800 rounded-2xl shadow-2xl w-full max-w-[98%] p-4 mb-4">
<div class="flex items-center justify-between mb-3">
<h3 class="text-sm font-semibold text-gray-300 uppercase tracking-wider"><i class="fa-solid fa-chart-line text-blue-500"></i> Cours & Moyennes mobiles</h3>
<div class="flex gap-2 text-xs">
<label class="flex items-center gap-1 cursor-pointer"><input type="checkbox" id="toggle-mm20" checked class="accent-blue-500"> MM20</label>
<label class="flex items-center gap-1 cursor-pointer"><input type="checkbox" id="toggle-mm50" checked class="accent-emerald-500"> MM50</label>
<label class="flex items-center gap-1 cursor-pointer"><input type="checkbox" id="toggle-mm200" checked class="accent-amber-500"> MM200</label>
</div>
</div>
<div style="height: 380px;"><canvas id="chartCours"></canvas></div>
</div>
<!-- ===================== GRAPHIQUE VOLUME ===================== -->
<div class="bg-gray-900 border border-gray-800 rounded-2xl shadow-2xl w-full max-w-[98%] p-4 mb-4">
<h3 class="text-sm font-semibold text-gray-300 uppercase tracking-wider mb-3"><i class="fa-solid fa-chart-column text-blue-500"></i> Volumes</h3>
<div style="height: 180px;"><canvas id="chartVolume"></canvas></div>
</div>
<!-- ===================== GRAPHIQUE VOLATILITÉ ===================== -->
<div class="bg-gray-900 border border-gray-800 rounded-2xl shadow-2xl w-full max-w-[98%] p-4 mb-4">
<h3 class="text-sm font-semibold text-gray-300 uppercase tracking-wider mb-3"><i class="fa-solid fa-wave-square text-blue-500"></i> Volatilité 20j annualisée</h3>
<div style="height: 180px;"><canvas id="chartVolatilite"></canvas></div>
</div>
<!-- ===================== SUPPORTS & RÉSISTANCES ===================== -->
<div class="bg-gray-900 border border-gray-800 rounded-2xl shadow-2xl w-full max-w-[98%] p-4 mb-4">
<h3 class="text-sm font-semibold text-gray-300 uppercase tracking-wider mb-3"><i class="fa-solid fa-arrows-up-down text-blue-500"></i> Supports & Résistances</h3>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Tableau -->
<div>
<table class="w-full text-sm text-gray-300">
<thead><tr class="text-gray-400 text-xs uppercase border-b border-gray-800"><th class="py-2 px-3 text-left">Fenêtre</th><th class="py-2 px-3 text-right">Plus Haut</th><th class="py-2 px-3 text-right">Plus Bas</th></tr></thead>
<tbody>
{% for fenetre in ['20j', '50j', '100j', '250j'] %}
<tr class="border-b border-gray-800/50">
<td class="py-2 px-3">{{ fenetre }}</td>
<td class="py-2 px-3 text-right text-emerald-400">{{ "{:,.2f}".format(resultat.supports_resistances.plus_haut[fenetre]) if resultat.supports_resistances.plus_haut[fenetre] is not none else '--' }}</td>
<td class="py-2 px-3 text-right text-rose-400">{{ "{:,.2f}".format(resultat.supports_resistances.plus_bas[fenetre]) if resultat.supports_resistances.plus_bas[fenetre] is not none else '--' }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="mt-3 space-y-1 text-xs">
<p class="text-gray-400">Support proche : <span class="text-emerald-400 font-bold">{{ "{:,.2f}".format(resultat.supports_resistances.support_proche) if resultat.supports_resistances.support_proche is not none else '--' }} {{ resultat.action.currency or '€' }}</span></p>
<p class="text-gray-400">Résistance proche : <span class="text-rose-400 font-bold">{{ "{:,.2f}".format(resultat.supports_resistances.resistance_proche) if resultat.supports_resistances.resistance_proche is not none else '--' }} {{ resultat.action.currency or '€' }}</span></p>
</div>
</div>
<!-- Barre visuelle 52 sem -->
<div>
{% set pb52 = resultat.supports_resistances.plus_bas['250j'] %}
{% set ph52 = resultat.supports_resistances.plus_haut['250j'] %}
{% set cours = resultat.cours %}
{% if pb52 is not none and ph52 is not none and ph52 > pb52 %}
{% set pct_pos = ((cours - pb52) / (ph52 - pb52) * 100) | float %}
<div class="relative h-8 bg-gray-950 rounded-lg border border-gray-800 overflow-hidden">
<div class="absolute top-0 left-0 h-full bg-gradient-to-r from-rose-900 via-amber-900 to-emerald-900 opacity-30" style="width: 100%"></div>
<div class="absolute top-0 h-full w-1 bg-white" style="left: {{ pct_pos }}%;"></div>
</div>
<div class="flex justify-between text-xs mt-1">
<span class="text-rose-400">{{ "{:,.2f}".format(pb52) }}</span>
<span class="text-gray-400">Cours : {{ "{:,.2f}".format(cours) }}</span>
<span class="text-emerald-400">{{ "{:,.2f}".format(ph52) }}</span>
</div>
{% endif %}
</div>
</div>
</div>
<!-- ===================== ANALYSE DES GAPS ===================== -->
<div class="bg-gray-900 border border-gray-800 rounded-2xl shadow-2xl w-full max-w-[98%] p-4 mb-4">
<h3 class="text-sm font-semibold text-gray-300 uppercase tracking-wider mb-3"><i class="fa-solid fa-arrows-left-right-to-line text-blue-500"></i> Analyse des gaps</h3>
<div class="grid grid-cols-1 md:grid-cols-4 gap-3 mb-3">
<div class="bg-gray-950 border border-gray-800 rounded-lg p-3 text-center">
<p class="text-xs text-gray-400">Total gaps</p>
<p class="text-xl font-bold text-white">{{ resultat.gap.nb_total }}</p>
</div>
<div class="bg-gray-950 border border-gray-800 rounded-lg p-3 text-center">
<p class="text-xs text-gray-400">Taux comblés</p>
<p class="text-xl font-bold text-emerald-400">{{ resultat.gap.taux_combles }}%</p>
</div>
<div class="bg-gray-950 border border-gray-800 rounded-lg p-3 text-center">
<p class="text-xs text-gray-400">Gap moyen</p>
<p class="text-xl font-bold text-white">{{ resultat.gap.gap_moyen }}%</p>
</div>
<div class="bg-gray-950 border border-gray-800 rounded-lg p-3 text-center">
<p class="text-xs text-gray-400">Plus gros gap</p>
<p class="text-xl font-bold text-amber-400">{{ resultat.gap.plus_gros_gap }}%</p>
</div>
</div>
{% if resultat.gap.derniers %}
<table class="w-full text-sm text-gray-300">
<thead><tr class="text-gray-400 text-xs uppercase border-b border-gray-800">
<th class="py-2 px-3 text-left">Date</th><th class="py-2 px-3 text-left">Type</th><th class="py-2 px-3 text-right">Taille</th><th class="py-2 px-3 text-center">Comblé</th>
</tr></thead>
<tbody>
{% for g in resultat.gap.derniers %}
<tr class="border-b border-gray-800/50">
<td class="py-2 px-3">{{ g.date }}</td>
<td class="py-2 px-3 {% if g.type == 'haussier' %}text-emerald-400{% else %}text-rose-400{% endif %}">Gap {{ g.type }}</td>
<td class="py-2 px-3 text-right">{{ "{:+.2f}".format(g.taille) }}%</td>
<td class="py-2 px-3 text-center">{% if g.comble %}<span class="text-emerald-400">✓ Oui ({{ g.jours_combles }}j)</span>{% else %}<span class="text-rose-400">✗ Non</span>{% endif %}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p class="text-gray-500 text-sm text-center py-4">Aucun gap significatif détecté.</p>
{% endif %}
</div>
<!-- ===================== SIGNAL SYNTHÉTIQUE ===================== -->
<div class="bg-gray-900 border border-gray-800 rounded-2xl shadow-2xl w-full max-w-[98%] p-4 mb-4">
<h3 class="text-sm font-semibold text-gray-300 uppercase tracking-wider mb-3"><i class="fa-solid fa-clipboard-check text-blue-500"></i> Analyse automatique</h3>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<!-- Points positifs -->
<div class="bg-emerald-950/30 border border-emerald-800/50 rounded-xl p-4">
<p class="text-emerald-400 font-semibold mb-2">🟢 Points positifs</p>
{% if resultat.points_positifs %}
{% for p in resultat.points_positifs %}
<p class="text-emerald-300 text-sm flex items-start gap-2 mb-1"><i class="fa-solid fa-check text-emerald-500 mt-0.5"></i> {{ p }}</p>
{% endfor %}
{% else %}
<p class="text-gray-500 text-sm">Aucun point positif détecté.</p>
{% endif %}
</div>
<!-- Points négatifs -->
<div class="bg-rose-950/30 border border-rose-800/50 rounded-xl p-4">
<p class="text-rose-400 font-semibold mb-2">🔴 Points négatifs</p>
{% if resultat.points_negatifs %}
{% for n in resultat.points_negatifs %}
<p class="text-rose-300 text-sm flex items-start gap-2 mb-1"><i class="fa-solid fa-xmark text-rose-500 mt-0.5"></i> {{ n }}</p>
{% endfor %}
{% else %}
<p class="text-gray-500 text-sm">Aucun point négatif détecté.</p>
{% endif %}
</div>
</div>
<!-- Conclusion -->
<div class="mt-4 bg-gray-950 border border-gray-800 rounded-xl p-4 text-center">
<p class="text-gray-300 text-sm">
<strong>Conclusion :</strong>
Tendance
{% if resultat.tendance == 'haussiere' %}<span class="text-emerald-400 font-bold">positive</span>
{% elif resultat.tendance == 'baissiere' %}<span class="text-rose-400 font-bold">négative</span>
{% else %}<span class="text-amber-400 font-bold">neutre</span>{% endif %}
— Score {{ resultat.score }}/100.
{% if resultat.points_negatifs and resultat.points_positifs %}Des signaux contradictoires sont présents, prudence recommandée.{% endif %}
</p>
</div>
</div>
<!-- ===================== DÉTAILS : PERFORMANCES + MOYENNES + SÉRIES ===================== -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 w-full max-w-[98%] mb-4">
<!-- Performances -->
<div class="bg-gray-900 border border-gray-800 rounded-2xl p-4">
<h3 class="text-sm font-semibold text-gray-300 uppercase tracking-wider mb-3">Performances</h3>
<table class="w-full text-sm text-gray-300">
{% for fenetre, val in resultat.performances.fenetres.items() %}
<tr class="border-b border-gray-800/50">
<td class="py-1.5 px-2">{{ fenetre }}</td>
<td class="py-1.5 px-2 text-right font-bold {% if val and val >= 0 %}text-emerald-400{% elif val %}text-rose-400{% else %}text-gray-500{% endif %}">
{{ "{:+.2f}".format(val) if val is not none else '--' }}%
</td>
</tr>
{% endfor %}
{% if resultat.performances.ytd is not none %}
<tr class="border-b border-gray-800/50">
<td class="py-1.5 px-2">YTD</td>
<td class="py-1.5 px-2 text-right font-bold {% if resultat.performances.ytd >= 0 %}text-emerald-400{% else %}text-rose-400{% endif %}">{{ "{:+.2f}".format(resultat.performances.ytd) }}%</td>
</tr>
{% endif %}
</table>
</div>
<!-- Moyennes mobiles + Séries -->
<div class="bg-gray-900 border border-gray-800 rounded-2xl p-4">
<h3 class="text-sm font-semibold text-gray-300 uppercase tracking-wider mb-3">Moyennes mobiles & Séries</h3>
<table class="w-full text-sm text-gray-300 mb-3">
{% for mm, val in resultat.moyennes_mobiles.sma.items() %}
{% if mm.endswith('_distance') %}{% else %}
<tr class="border-b border-gray-800/50">
<td class="py-1.5 px-2">{{ mm }}</td>
<td class="py-1.5 px-2 text-right">{{ "{:,.2f}".format(val) if val is not none else '--' }}</td>
<td class="py-1.5 px-2 text-right text-xs {% if resultat.moyennes_mobiles.sma[mm + '_distance'] and resultat.moyennes_mobiles.sma[mm + '_distance'] >= 0 %}text-emerald-400{% elif resultat.moyennes_mobiles.sma[mm + '_distance'] %}text-rose-400{% else %}text-gray-500{% endif %}">
{{ "{:+.2f}".format(resultat.moyennes_mobiles.sma[mm + '_distance']) if resultat.moyennes_mobiles.sma.get(mm + '_distance') is not none else '' }}%
</td>
</tr>
{% endif %}
{% endfor %}
</table>
<div class="border-t border-gray-800 pt-3 space-y-1 text-xs text-gray-400">
<p>Hausse consécutive : <span class="text-emerald-400 font-bold">{{ resultat.series.jours_hausse_consecutifs }}j</span> · Baisse : <span class="text-rose-400 font-bold">{{ resultat.series.jours_baisse_consecutifs }}j</span></p>
<p>Plus forte hausse : <span class="text-emerald-400">{{ "{:+.2f}".format(resultat.series.plus_forte_hausse) if resultat.series.plus_forte_hausse is not none else '--' }}%</span> · Plus forte baisse : <span class="text-rose-400">{{ "{:.2f}".format(resultat.series.plus_forte_baisse) if resultat.series.plus_forte_baisse is not none else '--' }}%</span></p>
</div>
</div>
</div>
<!-- ===================== CHANDELIERS JAPONAIS ===================== -->
<div class="bg-gray-900 border border-gray-800 rounded-2xl shadow-2xl w-full max-w-[98%] p-4 mb-4">
<h3 class="text-sm font-semibold text-gray-300 uppercase tracking-wider mb-3"><i class="fa-solid fa-chart-simple text-blue-500"></i> Chandeliers japonais</h3>
<p class="text-gray-400 text-sm mb-2">Pattern actuel : <span class="text-amber-400 font-bold">{{ resultat.chandeliers.pattern_actuel }}</span></p>
{% if resultat.chandeliers.derniers_detectes %}
<table class="w-full text-sm text-gray-300">
<thead><tr class="text-gray-400 text-xs uppercase border-b border-gray-800"><th class="py-2 px-3 text-left">Date</th><th class="py-2 px-3 text-left">Pattern</th></tr></thead>
<tbody>
{% for c in resultat.chandeliers.derniers_detectes %}
<tr class="border-b border-gray-800/50"><td class="py-2 px-3">{{ c.date }}</td><td class="py-2 px-3 text-amber-400">{{ c.pattern }}</td></tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p class="text-gray-500 text-sm">Aucun pattern significatif détecté récemment.</p>
{% endif %}
</div>
<!-- Données JSON pour les graphiques (passées au JS) -->
<script id="data-cours" type="application/json">{{ resultat.graphique_cours | tojson | safe }}</script>
<script id="data-volumes" type="application/json">{{ resultat.graphique_volumes | tojson | safe }}</script>
<script id="data-volatilite" type="application/json">{{ resultat.graphique_volatilite | tojson | safe }}</script>
{% endif %}
{% else %}
<!-- Message d'accueil quand aucune recherche -->
<div class="bg-gray-900 border border-gray-800 rounded-2xl shadow-2xl w-full max-w-[98%] p-8 text-center">
<i class="fa-solid fa-chart-line text-gray-700 text-5xl mb-4"></i>
<h2 class="text-xl font-bold text-white mb-2">Analyse technique</h2>
<p class="text-gray-400 text-sm">Saisissez un ISIN ci-dessus pour afficher la fiche d'analyse complète.</p>
</div>
{% endif %}
</div>
<!-- Chart.js + charts.js -->
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
<script src="{{ url_for('static', filename='js/charts.js') }}"></script>
<script>
// Disparition des toasts
document.addEventListener("DOMContentLoaded", () => {
document.querySelectorAll(".toast-message").forEach(t => setTimeout(() => {
t.style.opacity = "0"; t.style.transform = "translateY(-10px)";
setTimeout(() => t.remove(), 300);
}, 4000));
});
</script>
{% endblock %}