0.7.33
This commit is contained in:
@@ -63,3 +63,4 @@
|
|||||||
0.7.30 - Ajout d’une taxonomie DEX plus fine pour les événements décodés : `eventLifecycleKind`, `eventActionability`, `nonTradeUseful`, compteurs diagnostics des événements non-trade utiles, trades non actionnables et classifications inconnues ; ajout du profil `0.7.30_non_trade_event_classification` sans modification volontaire de la matérialisation trade/candle.
|
0.7.30 - Ajout d’une taxonomie DEX plus fine pour les événements décodés : `eventLifecycleKind`, `eventActionability`, `nonTradeUseful`, compteurs diagnostics des événements non-trade utiles, trades non actionnables et classifications inconnues ; ajout du profil `0.7.30_non_trade_event_classification` sans modification volontaire de la matérialisation trade/candle.
|
||||||
0.7.31 - Application de la politique Option B : les transactions failed restent traçables dans les événements décodés mais ne peuvent plus alimenter `trade_events`, metrics ou candles ; le replay local réinitialise les tables de matérialisation marché avant reconstruction pour supprimer les anciennes lignes dérivées non actionnables.
|
0.7.31 - Application de la politique Option B : les transactions failed restent traçables dans les événements décodés mais ne peuvent plus alimenter `trade_events`, metrics ou candles ; le replay local réinitialise les tables de matérialisation marché avant reconstruction pour supprimer les anciennes lignes dérivées non actionnables.
|
||||||
0.7.32 - Clarification de la sémantique des diagnostics locaux : séparation des gaps littéraux de paires et des gaps bloquants/actionnables, ajout des compteurs de matérialisation par paire, résumé `pairActionabilitySummaries`, profil `0.7.32_validation_report_semantics` et garde-fous sur la matrice DEX sans modification de la matérialisation trade/candle.
|
0.7.32 - Clarification de la sémantique des diagnostics locaux : séparation des gaps littéraux de paires et des gaps bloquants/actionnables, ajout des compteurs de matérialisation par paire, résumé `pairActionabilitySummaries`, profil `0.7.32_validation_report_semantics` et garde-fous sur la matrice DEX sans modification de la matérialisation trade/candle.
|
||||||
|
0.7.33 - Ajout de la classification diagnostique `pairTradingReadiness` pour les paires, avec `quoteAssetClass`, `tradingRouteRequired`, résumé `pairTradingReadinessSummaries`, profil de validation `0.7.33_pair_trading_readiness` et mise à jour de la sélection UI Demo Pipeline 2 sans modifier la matérialisation trade/candle.
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ members = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.7.32"
|
version = "0.7.33"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://git.sasedev.com/Sasedev/khadhroony-bobobot"
|
repository = "https://git.sasedev.com/Sasedev/khadhroony-bobobot"
|
||||||
|
|||||||
29
README.md
29
README.md
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
`khadhroony-bobobot` est un workspace Rust destiné à la détection, au décodage, à l’analyse et, à terme, au trading semi-automatisé de tokens Solana.
|
`khadhroony-bobobot` est un workspace Rust destiné à la détection, au décodage, à l’analyse et, à terme, au trading semi-automatisé de tokens Solana.
|
||||||
|
|
||||||
Le README précédent décrivait surtout l’état `0.3.1`. Ce fichier reflète l’état de reprise autour de `0.7.32` : le socle transport HTTP/WS, la résolution transactionnelle, le modèle SQLite, plusieurs connecteurs DEX, les candles, les signaux analytiques, la validation locale et une matrice DEX commune existent déjà.
|
Le README précédent décrivait surtout l’état `0.3.1`. Ce fichier reflète l’état de reprise autour de `0.7.33` : le socle transport HTTP/WS, la résolution transactionnelle, le modèle SQLite, plusieurs connecteurs DEX, les candles, les signaux analytiques, la validation locale et une matrice DEX commune existent déjà.
|
||||||
|
|
||||||
## 1. Objectif
|
## 1. Objectif
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ Le workspace contient deux crates principales.
|
|||||||
|
|
||||||
La logique métier doit rester dans `kb_lib`. `kb_demo_app` doit rester une façade UI/Tauri et ne doit pas récupérer de logique Solana ou DEX profonde.
|
La logique métier doit rester dans `kb_lib`. `kb_demo_app` doit rester une façade UI/Tauri et ne doit pas récupérer de logique Solana ou DEX profonde.
|
||||||
|
|
||||||
## 3. État actuel autour de `0.7.32`
|
## 3. État actuel autour de `0.7.33`
|
||||||
|
|
||||||
### 3.1. Socle stabilisé à ne pas refactorer maintenant
|
### 3.1. Socle stabilisé à ne pas refactorer maintenant
|
||||||
|
|
||||||
@@ -101,6 +101,8 @@ Depuis `0.7.30`, les événements décodés reçoivent aussi une classification
|
|||||||
|
|
||||||
Depuis `0.7.32`, les diagnostics distinguent explicitement les gaps littéraux de catalogue (`literalPairWithoutTradeCount`, `literalPairWithoutCandleCount`) des gaps bloquants/actionnables (`blockingPairWithoutTradeCount`, `blockingPairWithoutCandleCount`). Les anciens champs `pairWithoutTradeCount` et `pairWithoutCandleCount` restent exposés comme alias de compatibilité pour les gaps bloquants/actionnables.
|
Depuis `0.7.32`, les diagnostics distinguent explicitement les gaps littéraux de catalogue (`literalPairWithoutTradeCount`, `literalPairWithoutCandleCount`) des gaps bloquants/actionnables (`blockingPairWithoutTradeCount`, `blockingPairWithoutCandleCount`). Les anciens champs `pairWithoutTradeCount` et `pairWithoutCandleCount` restent exposés comme alias de compatibilité pour les gaps bloquants/actionnables.
|
||||||
|
|
||||||
|
Depuis `0.7.33`, les diagnostics ajoutent une classification `pairTradingReadiness` au niveau des paires et des résumés agrégés `pairTradingReadinessSummaries`. Cette classification sépare les paires directement lisibles/tradables contre WSOL ou stable, les paires inversées avec WSOL/stable en base, les paires cross-quote nécessitant un routeur/aggregator, les paires non matérialisées en trade et les cas de quote inconnue. Elle reste purement diagnostique : elle ne modifie ni le replay, ni les `trade_events`, ni les candles.
|
||||||
|
|
||||||
| Code cible | Type | Statut `0.7.29` | Prochaine action |
|
| Code cible | Type | Statut `0.7.29` | Prochaine action |
|
||||||
|---|---:|---|---|
|
|---|---:|---|---|
|
||||||
| `pump_fun` | Launch + bonding curve | partiel | verrouiller le rattachement mint initial -> pools migrés |
|
| `pump_fun` | Launch + bonding curve | partiel | verrouiller le rattachement mint initial -> pools migrés |
|
||||||
@@ -217,17 +219,18 @@ Les tests peuvent rester plus souples lorsque cela clarifie le test.
|
|||||||
|
|
||||||
La reprise doit suivre cet ordre :
|
La reprise doit suivre cet ordre :
|
||||||
|
|
||||||
1. conserver la sémantique `0.7.32` : les gaps littéraux de catalogue ne doivent pas être confondus avec les gaps bloquants/actionnables utilisés par la validation ;
|
1. conserver la classification `0.7.33` : les paires matérialisées doivent être classées par readiness trading sans transformer les paires cross-quote ou inversées en erreurs bloquantes ;
|
||||||
2. conserver la non-régression `0.7.31` : transactions failed traçables mais exclues des `trade_events`, metrics et candles ;
|
2. conserver la sémantique `0.7.32` : les gaps littéraux de catalogue ne doivent pas être confondus avec les gaps bloquants/actionnables utilisés par la validation ;
|
||||||
3. utiliser la matrice `0.7.29` comme source commune pour le catalogue, la classification et les protocol candidates ;
|
3. conserver la non-régression `0.7.31` : transactions failed traçables mais exclues des `trade_events`, metrics et candles ;
|
||||||
4. relier progressivement les événements non-trade aux tables existantes : lifecycle, liquidité, fees, rewards, admin ;
|
4. utiliser la matrice `0.7.29` comme source commune pour le catalogue, la classification et les protocol candidates ;
|
||||||
4. consolider Meteora, surtout `meteora_dlmm` et le cas partiel `meteora_damm_v1` ;
|
5. relier progressivement les événements non-trade aux tables existantes : lifecycle, liquidité, fees, rewards, admin ;
|
||||||
5. ajouter les launch surfaces manquantes comme origines de mint : LaunchLab/Launchpad, LetsBonk/Bonk.fun, Boop.fun, Moonshot/Moonit, Believe, Bags ;
|
6. consolider Meteora, surtout `meteora_dlmm` et le cas partiel `meteora_damm_v1` ;
|
||||||
6. traiter Heaven ;
|
7. ajouter les launch surfaces manquantes comme origines de mint : LaunchLab/Launchpad, LetsBonk/Bonk.fun, Boop.fun, Moonshot/Moonit, Believe, Bags ;
|
||||||
7. consolider Orca/FluxBeam/DexLab ;
|
8. traiter Heaven ;
|
||||||
8. isoler Raydium AMM v4 legacy ;
|
9. consolider Orca/FluxBeam/DexLab ;
|
||||||
9. effectuer une validation DEX v1 consolidée ;
|
10. isoler Raydium AMM v4 legacy ;
|
||||||
10. reprendre ensuite l’UI analytique et les vues token/pair/pool.
|
11. effectuer une validation DEX v1 consolidée ;
|
||||||
|
12. reprendre ensuite l’UI analytique et les vues token/pair/pool.
|
||||||
|
|
||||||
## 9. Fichiers utiles pour reprendre dans une nouvelle session
|
## 9. Fichiers utiles pour reprendre dans une nouvelle session
|
||||||
|
|
||||||
|
|||||||
52
ROADMAP.md
52
ROADMAP.md
@@ -861,7 +861,20 @@ Réalisé :
|
|||||||
|
|
||||||
Repoussé après cette clarification : consolider les transactions inconnues et protocol candidates sans polluer les trades/candles.
|
Repoussé après cette clarification : consolider les transactions inconnues et protocol candidates sans polluer les trades/candles.
|
||||||
|
|
||||||
### 6.065. Version `0.7.33` — Événements non-trade v1 : liquidité et cycle de vie pool
|
### 6.065. Version `0.7.33` — Readiness trading des paires
|
||||||
|
Réalisé :
|
||||||
|
|
||||||
|
- ajouter une classification diagnostique `pairTradingReadiness` pour chaque paire inspectée localement ;
|
||||||
|
- distinguer `direct_wsol_quote`, `direct_stable_quote`, `inverse_wsol_base`, `inverse_stable_base`, `cross_quote_requires_router`, `unknown_quote` et `non_trade_materialized` ;
|
||||||
|
- exposer `quoteAssetClass` et `tradingRouteRequired` dans les diagnostics par paire ;
|
||||||
|
- ajouter `pairTradingReadinessSummaries` dans le résumé local du pipeline ;
|
||||||
|
- ajouter le profil `0.7.33_pair_trading_readiness` ;
|
||||||
|
- valider que les résumés de readiness couvrent toutes les paires et restent cohérents avec les compteurs `tradeMaterializedPairCount`, `tradeEventCount` et `pairCandleCount` ;
|
||||||
|
- ne pas modifier la logique de replay, `trade_events`, metrics ou candles.
|
||||||
|
|
||||||
|
Objectif : préparer la future couche d’achat/vente en distinguant les paires immédiatement exploitables contre WSOL/stable des paires qui nécessitent inversion de lecture ou routeur/aggregator.
|
||||||
|
|
||||||
|
### 6.066. Version `0.7.34` — Événements non-trade v1 : liquidité et cycle de vie pool
|
||||||
Objectif : exploiter les événements utiles à l’analyse et au trading semi-automatique sans les mélanger avec les swaps/candles.
|
Objectif : exploiter les événements utiles à l’analyse et au trading semi-automatique sans les mélanger avec les swaps/candles.
|
||||||
|
|
||||||
À faire :
|
À faire :
|
||||||
@@ -874,7 +887,7 @@ Objectif : exploiter les événements utiles à l’analyse et au trading semi-a
|
|||||||
- alimenter les diagnostics locaux avec les compteurs liquidité/lifecycle,
|
- alimenter les diagnostics locaux avec les compteurs liquidité/lifecycle,
|
||||||
- garantir qu’un événement de liquidité ou de cycle de vie ne produit jamais de candle directement.
|
- garantir qu’un événement de liquidité ou de cycle de vie ne produit jamais de candle directement.
|
||||||
|
|
||||||
### 6.066. Version `0.7.34` — Événements non-trade v2 : fees, rewards et administration
|
### 6.067. Version `0.7.35` — Événements non-trade v2 : fees, rewards et administration
|
||||||
Objectif : conserver les événements utiles au risque, au scoring, à l’économie du pool et à la traçabilité opérationnelle.
|
Objectif : conserver les événements utiles au risque, au scoring, à l’économie du pool et à la traçabilité opérationnelle.
|
||||||
|
|
||||||
À faire :
|
À faire :
|
||||||
@@ -888,7 +901,7 @@ Objectif : conserver les événements utiles au risque, au scoring, à l’écon
|
|||||||
- rattacher ces événements aux transactions, decoded events, pools, paires et wallets observés lorsque les comptes le permettent,
|
- rattacher ces événements aux transactions, decoded events, pools, paires et wallets observés lorsque les comptes le permettent,
|
||||||
- documenter clairement que ces événements ne sont ni des trades ni des candles.
|
- documenter clairement que ces événements ne sont ni des trades ni des candles.
|
||||||
|
|
||||||
### 6.067. Version `0.7.35` — Meteora : DBC / DAMM v1 / DAMM v2 / DLMM
|
### 6.068. Version `0.7.36` — Meteora : DBC / DAMM v1 / DAMM v2 / DLMM
|
||||||
Objectif : consolider Meteora comme famille multi-programmes au lieu de traiter chaque variante comme un cas isolé incomplet.
|
Objectif : consolider Meteora comme famille multi-programmes au lieu de traiter chaque variante comme un cas isolé incomplet.
|
||||||
|
|
||||||
À faire :
|
À faire :
|
||||||
@@ -902,7 +915,7 @@ Objectif : consolider Meteora comme famille multi-programmes au lieu de traiter
|
|||||||
- vérifier l’idempotence du replay local sur un corpus Meteora mixte,
|
- vérifier l’idempotence du replay local sur un corpus Meteora mixte,
|
||||||
- documenter les limites connues des variantes insuffisamment couvertes.
|
- documenter les limites connues des variantes insuffisamment couvertes.
|
||||||
|
|
||||||
### 6.068. Version `0.7.36` — Launch surfaces : LaunchLab, LetsBonk, Bags, Moonshot/Moonit, Boop.fun, Believe
|
### 6.069. Version `0.7.37` — Launch surfaces : LaunchLab, LetsBonk, Bags, Moonshot/Moonit, Boop.fun, Believe
|
||||||
Objectif : détecter la première source de mint/lancement des tokens même lorsque le swap final se fait ailleurs.
|
Objectif : détecter la première source de mint/lancement des tokens même lorsque le swap final se fait ailleurs.
|
||||||
|
|
||||||
À faire :
|
À faire :
|
||||||
@@ -917,7 +930,7 @@ Objectif : détecter la première source de mint/lancement des tokens même lors
|
|||||||
- rattacher les launch origins aux pools et paires lorsque les comptes permettent un matching fiable,
|
- rattacher les launch origins aux pools et paires lorsque les comptes permettent un matching fiable,
|
||||||
- exposer les origins dans les diagnostics et l’UI d’inspection.
|
- exposer les origins dans les diagnostics et l’UI d’inspection.
|
||||||
|
|
||||||
### 6.069. Version `0.7.37` — Heaven : corpus, launch et AMM
|
### 6.070. Version `0.7.38` — Heaven : corpus, launch et AMM
|
||||||
Objectif : ajouter Heaven sans le classer trop tôt comme simple DEX ou simple launchpad.
|
Objectif : ajouter Heaven sans le classer trop tôt comme simple DEX ou simple launchpad.
|
||||||
|
|
||||||
À faire :
|
À faire :
|
||||||
@@ -929,7 +942,7 @@ Objectif : ajouter Heaven sans le classer trop tôt comme simple DEX ou simple l
|
|||||||
- documenter les limites si le corpus ne permet pas encore de matérialiser tous les événements,
|
- documenter les limites si le corpus ne permet pas encore de matérialiser tous les événements,
|
||||||
- vérifier que Heaven ne crée pas de candles invalides en cas d’événement de launch non pricé.
|
- vérifier que Heaven ne crée pas de candles invalides en cas d’événement de launch non pricé.
|
||||||
|
|
||||||
### 6.070. Version `0.7.38` — Orca / FluxBeam / DexLab : corpus et validation ciblée
|
### 6.071. Version `0.7.39` — Orca / FluxBeam / DexLab : corpus et validation ciblée
|
||||||
Objectif : consolider les connecteurs déjà présents à partir de corpus locaux vérifiables.
|
Objectif : consolider les connecteurs déjà présents à partir de corpus locaux vérifiables.
|
||||||
|
|
||||||
À faire :
|
À faire :
|
||||||
@@ -941,7 +954,7 @@ Objectif : consolider les connecteurs déjà présents à partir de corpus locau
|
|||||||
- marquer explicitement les variantes partiellement supportées ou heuristiques,
|
- marquer explicitement les variantes partiellement supportées ou heuristiques,
|
||||||
- rejouer les corpus plusieurs fois pour vérifier l’idempotence et l’absence de trades/candles invalides.
|
- rejouer les corpus plusieurs fois pour vérifier l’idempotence et l’absence de trades/candles invalides.
|
||||||
|
|
||||||
### 6.071. Version `0.7.39` — Raydium AMM v4 legacy : corpus et validation ciblée
|
### 6.072. Version `0.7.40` — Raydium AMM v4 legacy : corpus et validation ciblée
|
||||||
Objectif : traiter le vrai Raydium AMM v4 historique après les autres Raydium, afin de l’isoler de `raydium_cpmm`, `raydium_clmm` et des labels Raydium génériques.
|
Objectif : traiter le vrai Raydium AMM v4 historique après les autres Raydium, afin de l’isoler de `raydium_cpmm`, `raydium_clmm` et des labels Raydium génériques.
|
||||||
|
|
||||||
À faire :
|
À faire :
|
||||||
@@ -954,7 +967,7 @@ Objectif : traiter le vrai Raydium AMM v4 historique après les autres Raydium,
|
|||||||
- renommer/stabiliser les fonctions internes autour de `raydium_amm_v4` pour éviter l’ambiguïté avec `raydium_cpmm` et `raydium_clmm`,
|
- renommer/stabiliser les fonctions internes autour de `raydium_amm_v4` pour éviter l’ambiguïté avec `raydium_cpmm` et `raydium_clmm`,
|
||||||
- documenter les limites connues si le corpus AMM v4 reste faible.
|
- documenter les limites connues si le corpus AMM v4 reste faible.
|
||||||
|
|
||||||
### 6.072. Version `0.7.40` — Validation DEX v1 consolidée
|
### 6.073. Version `0.7.41` — Validation DEX v1 consolidée
|
||||||
Objectif : rejouer tous les DEX et launch surfaces supportés et valider les invariants du pipeline complet.
|
Objectif : rejouer tous les DEX et launch surfaces supportés et valider les invariants du pipeline complet.
|
||||||
|
|
||||||
À faire :
|
À faire :
|
||||||
@@ -967,7 +980,7 @@ Objectif : rejouer tous les DEX et launch surfaces supportés et valider les inv
|
|||||||
- conserver une matrice de support par DEX, variante, instruction et type d’événement,
|
- conserver une matrice de support par DEX, variante, instruction et type d’événement,
|
||||||
- verrouiller les invariants avant d’ouvrir l’analyse `0.8.x`.
|
- verrouiller les invariants avant d’ouvrir l’analyse `0.8.x`.
|
||||||
|
|
||||||
### 6.073. Version `0.7.41` — `kb_demo_app` : overlays analytiques
|
### 6.074. Version `0.7.42` — `kb_demo_app` : overlays analytiques
|
||||||
Objectif : rendre visibles les signaux analytiques directement sur les graphes et vues de marché.
|
Objectif : rendre visibles les signaux analytiques directement sur les graphes et vues de marché.
|
||||||
|
|
||||||
À faire :
|
À faire :
|
||||||
@@ -978,7 +991,7 @@ Objectif : rendre visibles les signaux analytiques directement sur les graphes e
|
|||||||
- afficher un panneau latéral listant les signaux liés à une paire et à un timeframe,
|
- afficher un panneau latéral listant les signaux liés à une paire et à un timeframe,
|
||||||
- préparer l’extension future vers Ichimoku, Kumo, projections ABCD et égalités temps/prix sans les mélanger au pipeline de décodage DEX.
|
- préparer l’extension future vers Ichimoku, Kumo, projections ABCD et égalités temps/prix sans les mélanger au pipeline de décodage DEX.
|
||||||
|
|
||||||
### 6.074. Version `0.7.42` — `kb_demo_app` : vues consolidées token / pair / pool
|
### 6.075. Version `0.7.43` — `kb_demo_app` : vues consolidées token / pair / pool
|
||||||
Objectif : fournir une lecture métier plus confortable du modèle `0.7.x`.
|
Objectif : fournir une lecture métier plus confortable du modèle `0.7.x`.
|
||||||
|
|
||||||
À faire :
|
À faire :
|
||||||
@@ -990,7 +1003,7 @@ Objectif : fournir une lecture métier plus confortable du modèle `0.7.x`.
|
|||||||
- préparer une navigation transversale entre objets techniques et objets métier,
|
- préparer une navigation transversale entre objets techniques et objets métier,
|
||||||
- rendre explicites les cas `tradeCount = null`, `lastPriceQuotePerBase = null`, tokens non enrichis et événements conservés uniquement pour analyse.
|
- rendre explicites les cas `tradeCount = null`, `lastPriceQuotePerBase = null`, tokens non enrichis et événements conservés uniquement pour analyse.
|
||||||
|
|
||||||
### 6.075. Version `0.7.43` — Finition UI `0.7.x`
|
### 6.076. Version `0.7.44` — Finition UI `0.7.x`
|
||||||
Objectif : stabiliser la couche desktop de validation avant l’ouverture de `0.8.x`.
|
Objectif : stabiliser la couche desktop de validation avant l’ouverture de `0.8.x`.
|
||||||
|
|
||||||
À faire :
|
À faire :
|
||||||
@@ -1001,7 +1014,7 @@ Objectif : stabiliser la couche desktop de validation avant l’ouverture de `0.
|
|||||||
- préparer une base UI suffisamment stable pour la future phase d’analyse et filtrage `0.8.x`,
|
- préparer une base UI suffisamment stable pour la future phase d’analyse et filtrage `0.8.x`,
|
||||||
- vérifier que les commandes Tauri restent de simples façades vers `kb_lib`.
|
- vérifier que les commandes Tauri restent de simples façades vers `kb_lib`.
|
||||||
|
|
||||||
### 6.076. Version `0.7.x` — Couverture DEX v1
|
### 6.077. Version `0.7.x` — Couverture DEX v1
|
||||||
Objectif : structurer les connecteurs DEX autour d’un pipeline complet de résolution, décodage, normalisation métier et classification des événements non-trade.
|
Objectif : structurer les connecteurs DEX autour d’un pipeline complet de résolution, décodage, normalisation métier et classification des événements non-trade.
|
||||||
|
|
||||||
Protocoles et surfaces cibles :
|
Protocoles et surfaces cibles :
|
||||||
@@ -1044,7 +1057,7 @@ Résultat attendu :
|
|||||||
- préparation d’une détection temps réel hybride et d’un backfill ciblé compatible avec les mêmes objets métier,
|
- préparation d’une détection temps réel hybride et d’un backfill ciblé compatible avec les mêmes objets métier,
|
||||||
- préparation d’agrégats DEX plus riches, de candles/OHLCV et d’une UI d’inspection du pipeline `0.7.x`.
|
- préparation d’agrégats DEX plus riches, de candles/OHLCV et d’une UI d’inspection du pipeline `0.7.x`.
|
||||||
|
|
||||||
### 6.077. Version `0.8.x` — Analyse et filtrage
|
### 6.078. Version `0.8.x` — Analyse et filtrage
|
||||||
Objectif : transformer les événements bruts en signaux exploitables.
|
Objectif : transformer les événements bruts en signaux exploitables.
|
||||||
|
|
||||||
À faire :
|
À faire :
|
||||||
@@ -1059,7 +1072,7 @@ Objectif : transformer les événements bruts en signaux exploitables.
|
|||||||
- outils de sélection manuelle de points ABC et projection d’un point D selon des règles temps/prix explicites,
|
- outils de sélection manuelle de points ABC et projection d’un point D selon des règles temps/prix explicites,
|
||||||
- séparation stricte entre signaux analytiques observés, projections hypothétiques et décisions de trading.
|
- séparation stricte entre signaux analytiques observés, projections hypothétiques et décisions de trading.
|
||||||
|
|
||||||
### 6.078. Version `1.x.y` — Wallets et swap préparatoire
|
### 6.079. Version `1.x.y` — Wallets et swap préparatoire
|
||||||
Objectif : préparer la couche d’action.
|
Objectif : préparer la couche d’action.
|
||||||
|
|
||||||
À faire :
|
À faire :
|
||||||
@@ -1070,7 +1083,7 @@ Objectif : préparer la couche d’action.
|
|||||||
- préparation d’ordres et de swaps,
|
- préparation d’ordres et de swaps,
|
||||||
- simulation et garde-fous.
|
- simulation et garde-fous.
|
||||||
|
|
||||||
### 6.079. Version `2.x.y` — Trading semi-automatisé
|
### 6.080. Version `2.x.y` — Trading semi-automatisé
|
||||||
Objectif : brancher l’analyse à l’action tout en gardant des garde-fous explicites.
|
Objectif : brancher l’analyse à l’action tout en gardant des garde-fous explicites.
|
||||||
|
|
||||||
À faire :
|
À faire :
|
||||||
@@ -1081,7 +1094,7 @@ Objectif : brancher l’analyse à l’action tout en gardant des garde-fous exp
|
|||||||
- confirmations explicites ou semi-automatiques,
|
- confirmations explicites ou semi-automatiques,
|
||||||
- journaux d’exécution.
|
- journaux d’exécution.
|
||||||
|
|
||||||
### 6.080. Version `3.x.y` — Yellowstone gRPC
|
### 6.081. Version `3.x.y` — Yellowstone gRPC
|
||||||
Objectif : ajouter le connecteur gRPC dédié.
|
Objectif : ajouter le connecteur gRPC dédié.
|
||||||
|
|
||||||
À faire :
|
À faire :
|
||||||
@@ -1215,9 +1228,10 @@ La priorité immédiate est désormais la suivante :
|
|||||||
|
|
||||||
1. conserver la validation acquise `0.7.31` : transactions failed traçables mais exclues des `trade_events`, metrics et candles, aucun trade/candle candidate sans payload montant/prix exploitable, aucun diagnostic bloquant masqué,
|
1. conserver la validation acquise `0.7.31` : transactions failed traçables mais exclues des `trade_events`, metrics et candles, aucun trade/candle candidate sans payload montant/prix exploitable, aucun diagnostic bloquant masqué,
|
||||||
2. conserver la clarification `0.7.32` entre gaps littéraux de catalogue et gaps bloquants/actionnables,
|
2. conserver la clarification `0.7.32` entre gaps littéraux de catalogue et gaps bloquants/actionnables,
|
||||||
3. utiliser la matrice `0.7.29` (`kb_lib/src/dex_support_matrix.rs`) comme source commune pour le catalogue DEX, les mappings program id -> protocole, la classification transactionnelle et les protocol candidates,
|
3. conserver la classification `0.7.33` des paires par readiness trading : direct WSOL/stable, inverse WSOL/stable, cross-quote avec routeur requis, inconnue ou non matérialisée,
|
||||||
4. garder les clients HTTP/WS et managers réseau hors du refactor DEX tant qu’ils ne bloquent pas le pipeline,
|
4. utiliser la matrice `0.7.29` (`kb_lib/src/dex_support_matrix.rs`) comme source commune pour le catalogue DEX, les mappings program id -> protocole, la classification transactionnelle et les protocol candidates,
|
||||||
5. consolider les événements non-trade sans les confondre avec les trades/candles : lifecycle de pool, liquidité, fees, rewards, admin/config, migration et launch/mint,
|
5. garder les clients HTTP/WS et managers réseau hors du refactor DEX tant qu’ils ne bloquent pas le pipeline,
|
||||||
|
6. consolider les événements non-trade sans les confondre avec les trades/candles : lifecycle de pool, liquidité, fees, rewards, admin/config, migration et launch/mint,
|
||||||
6. rattacher les launch surfaces aux tokens et aux pools migrés : Raydium LaunchLab/Launchpad, LetsBonk/Bonk.fun, Boop.fun, Moonshot/Moonit, Believe, Bags et Heaven,
|
6. rattacher les launch surfaces aux tokens et aux pools migrés : Raydium LaunchLab/Launchpad, LetsBonk/Bonk.fun, Boop.fun, Moonshot/Moonit, Believe, Bags et Heaven,
|
||||||
7. consolider Meteora avec corpus fiable : `meteora_dlmm`, `meteora_damm_v1`, `meteora_damm_v2`, `meteora_dbc` et `meteora_dlc` si le programme est confirmé,
|
7. consolider Meteora avec corpus fiable : `meteora_dlmm`, `meteora_damm_v1`, `meteora_damm_v2`, `meteora_dbc` et `meteora_dlc` si le programme est confirmé,
|
||||||
8. consolider Orca, FluxBeam et DexLab sur corpus,
|
8. consolider Orca, FluxBeam et DexLab sur corpus,
|
||||||
|
|||||||
@@ -166,7 +166,8 @@
|
|||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="demoPipeline2ValidationProfileSelect" class="form-label">Validation profile</label>
|
<label for="demoPipeline2ValidationProfileSelect" class="form-label">Validation profile</label>
|
||||||
<select id="demoPipeline2ValidationProfileSelect" class="form-select">
|
<select id="demoPipeline2ValidationProfileSelect" class="form-select">
|
||||||
<option value="0.7.32_validation_report_semantics" selected>0.7.32 — validation report semantics</option>
|
<option value="0.7.33_pair_trading_readiness" selected>0.7.33 — pair trading readiness</option>
|
||||||
|
<option value="0.7.32_validation_report_semantics">0.7.32 — validation report semantics</option>
|
||||||
<option value="0.7.31_trade_event_actionability_policy">0.7.31 — trade event actionability policy</option>
|
<option value="0.7.31_trade_event_actionability_policy">0.7.31 — trade event actionability policy</option>
|
||||||
<option value="0.7.30_non_trade_event_classification">0.7.30 — non-trade event classification</option>
|
<option value="0.7.30_non_trade_event_classification">0.7.30 — non-trade event classification</option>
|
||||||
<option value="0.7.29_multi_dex_matrix_baseline">0.7.29 — DEX matrix baseline</option>
|
<option value="0.7.29_multi_dex_matrix_baseline">0.7.29 — DEX matrix baseline</option>
|
||||||
|
|||||||
@@ -63,4 +63,16 @@ pairCandleCount: number,
|
|||||||
/**
|
/**
|
||||||
* Last known price.
|
* Last known price.
|
||||||
*/
|
*/
|
||||||
lastPriceQuotePerBase: number | null, };
|
lastPriceQuotePerBase: number | null,
|
||||||
|
/**
|
||||||
|
* Pair trading-readiness class derived from base/quote orientation.
|
||||||
|
*/
|
||||||
|
pairTradingReadiness: string,
|
||||||
|
/**
|
||||||
|
* Quote asset class used by the readiness classifier.
|
||||||
|
*/
|
||||||
|
quoteAssetClass: string,
|
||||||
|
/**
|
||||||
|
* Whether the pair likely requires a router or aggregator before direct execution.
|
||||||
|
*/
|
||||||
|
tradingRouteRequired: boolean, };
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local pair trading-readiness diagnostics summary for the UI.
|
||||||
|
*/
|
||||||
|
export type DemoPipeline2LocalPairTradingReadinessDiagnosticSummary = {
|
||||||
|
/**
|
||||||
|
* Pair trading-readiness class.
|
||||||
|
*/
|
||||||
|
pairTradingReadiness: string,
|
||||||
|
/**
|
||||||
|
* Quote asset class.
|
||||||
|
*/
|
||||||
|
quoteAssetClass: string,
|
||||||
|
/**
|
||||||
|
* Whether a router or aggregator is required before direct execution.
|
||||||
|
*/
|
||||||
|
tradingRouteRequired: boolean,
|
||||||
|
/**
|
||||||
|
* Pair count.
|
||||||
|
*/
|
||||||
|
pairCount: number,
|
||||||
|
/**
|
||||||
|
* Decoded event count.
|
||||||
|
*/
|
||||||
|
decodedEventCount: number,
|
||||||
|
/**
|
||||||
|
* Decoded trade candidate count.
|
||||||
|
*/
|
||||||
|
decodedTradeCandidateCount: number,
|
||||||
|
/**
|
||||||
|
* Trade event count.
|
||||||
|
*/
|
||||||
|
tradeEventCount: number,
|
||||||
|
/**
|
||||||
|
* Pair candle count.
|
||||||
|
*/
|
||||||
|
pairCandleCount: number, };
|
||||||
@@ -10,6 +10,7 @@ import type { DemoPipeline2LocalNonActionablePairDiagnosticSummary } from "./Dem
|
|||||||
import type { DemoPipeline2LocalPairActionabilityDiagnosticSummary } from "./DemoPipeline2LocalPairActionabilityDiagnosticSummary";
|
import type { DemoPipeline2LocalPairActionabilityDiagnosticSummary } from "./DemoPipeline2LocalPairActionabilityDiagnosticSummary";
|
||||||
import type { DemoPipeline2LocalPairDiagnosticSummary } from "./DemoPipeline2LocalPairDiagnosticSummary";
|
import type { DemoPipeline2LocalPairDiagnosticSummary } from "./DemoPipeline2LocalPairDiagnosticSummary";
|
||||||
import type { DemoPipeline2LocalPairGapDiagnosticSample } from "./DemoPipeline2LocalPairGapDiagnosticSample";
|
import type { DemoPipeline2LocalPairGapDiagnosticSample } from "./DemoPipeline2LocalPairGapDiagnosticSample";
|
||||||
|
import type { DemoPipeline2LocalPairTradingReadinessDiagnosticSummary } from "./DemoPipeline2LocalPairTradingReadinessDiagnosticSummary";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Local pipeline diagnostics summary for the UI.
|
* Local pipeline diagnostics summary for the UI.
|
||||||
@@ -184,6 +185,10 @@ pairSummaries: Array<DemoPipeline2LocalPairDiagnosticSummary>,
|
|||||||
* Diagnostics grouped by pair materialization/actionability class.
|
* Diagnostics grouped by pair materialization/actionability class.
|
||||||
*/
|
*/
|
||||||
pairActionabilitySummaries: Array<DemoPipeline2LocalPairActionabilityDiagnosticSummary>,
|
pairActionabilitySummaries: Array<DemoPipeline2LocalPairActionabilityDiagnosticSummary>,
|
||||||
|
/**
|
||||||
|
* Diagnostics grouped by pair trading-readiness class.
|
||||||
|
*/
|
||||||
|
pairTradingReadinessSummaries: Array<DemoPipeline2LocalPairTradingReadinessDiagnosticSummary>,
|
||||||
/**
|
/**
|
||||||
* Diagnostics grouped by decoded event kind.
|
* Diagnostics grouped by decoded event kind.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "kb-demo-app",
|
"name": "kb-demo-app",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.7.32",
|
"version": "0.7.33",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
|
|||||||
@@ -368,6 +368,9 @@ pub(crate) struct DemoPipeline2LocalPipelineDiagnosticSummary {
|
|||||||
/// Diagnostics grouped by pair materialization/actionability class.
|
/// Diagnostics grouped by pair materialization/actionability class.
|
||||||
pub pair_actionability_summaries:
|
pub pair_actionability_summaries:
|
||||||
std::vec::Vec<DemoPipeline2LocalPairActionabilityDiagnosticSummary>,
|
std::vec::Vec<DemoPipeline2LocalPairActionabilityDiagnosticSummary>,
|
||||||
|
/// Diagnostics grouped by pair trading-readiness class.
|
||||||
|
pub pair_trading_readiness_summaries:
|
||||||
|
std::vec::Vec<DemoPipeline2LocalPairTradingReadinessDiagnosticSummary>,
|
||||||
/// Diagnostics grouped by decoded event kind.
|
/// Diagnostics grouped by decoded event kind.
|
||||||
pub decoded_event_summaries: std::vec::Vec<DemoPipeline2LocalDecodedEventDiagnosticSummary>,
|
pub decoded_event_summaries: std::vec::Vec<DemoPipeline2LocalDecodedEventDiagnosticSummary>,
|
||||||
/// Diagnostics grouped by decoded event classification.
|
/// Diagnostics grouped by decoded event classification.
|
||||||
@@ -476,6 +479,12 @@ pub(crate) struct DemoPipeline2LocalPairDiagnosticSummary {
|
|||||||
/// Last known price.
|
/// Last known price.
|
||||||
#[ts(type = "number | null")]
|
#[ts(type = "number | null")]
|
||||||
pub last_price_quote_per_base: std::option::Option<f64>,
|
pub last_price_quote_per_base: std::option::Option<f64>,
|
||||||
|
/// Pair trading-readiness class derived from base/quote orientation.
|
||||||
|
pub pair_trading_readiness: std::string::String,
|
||||||
|
/// Quote asset class used by the readiness classifier.
|
||||||
|
pub quote_asset_class: std::string::String,
|
||||||
|
/// Whether the pair likely requires a router or aggregator before direct execution.
|
||||||
|
pub trading_route_required: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Local pair actionability diagnostics summary for the UI.
|
/// Local pair actionability diagnostics summary for the UI.
|
||||||
@@ -511,6 +520,37 @@ pub(crate) struct DemoPipeline2LocalPairActionabilityDiagnosticSummary {
|
|||||||
pub pair_candle_count: i64,
|
pub pair_candle_count: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Local pair trading-readiness diagnostics summary for the UI.
|
||||||
|
#[derive(Clone, Debug, serde::Serialize, TS)]
|
||||||
|
#[ts(
|
||||||
|
export,
|
||||||
|
export_to = "../frontend/ts/bindings/DemoPipeline2LocalPairTradingReadinessDiagnosticSummary.ts"
|
||||||
|
)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub(crate) struct DemoPipeline2LocalPairTradingReadinessDiagnosticSummary {
|
||||||
|
/// Pair trading-readiness class.
|
||||||
|
pub pair_trading_readiness: std::string::String,
|
||||||
|
/// Quote asset class.
|
||||||
|
pub quote_asset_class: std::string::String,
|
||||||
|
/// Whether a router or aggregator is required before direct execution.
|
||||||
|
pub trading_route_required: bool,
|
||||||
|
/// Pair count.
|
||||||
|
#[ts(type = "number")]
|
||||||
|
pub pair_count: i64,
|
||||||
|
/// Decoded event count.
|
||||||
|
#[ts(type = "number")]
|
||||||
|
pub decoded_event_count: i64,
|
||||||
|
/// Decoded trade candidate count.
|
||||||
|
#[ts(type = "number")]
|
||||||
|
pub decoded_trade_candidate_count: i64,
|
||||||
|
/// Trade event count.
|
||||||
|
#[ts(type = "number")]
|
||||||
|
pub trade_event_count: i64,
|
||||||
|
/// Pair candle count.
|
||||||
|
#[ts(type = "number")]
|
||||||
|
pub pair_candle_count: i64,
|
||||||
|
}
|
||||||
|
|
||||||
/// Local decoded-event diagnostics summary for the UI.
|
/// Local decoded-event diagnostics summary for the UI.
|
||||||
#[derive(Clone, Debug, serde::Serialize, TS)]
|
#[derive(Clone, Debug, serde::Serialize, TS)]
|
||||||
#[ts(
|
#[ts(
|
||||||
@@ -1035,7 +1075,7 @@ pub(crate) async fn demo_pipeline2_validate_local_pipeline(
|
|||||||
let service = kb_lib::LocalPipelineValidationService::new(database.clone());
|
let service = kb_lib::LocalPipelineValidationService::new(database.clone());
|
||||||
let profile_code = match request {
|
let profile_code = match request {
|
||||||
Some(request) => request.profile_code,
|
Some(request) => request.profile_code,
|
||||||
None => "0.7.32_validation_report_semantics".to_string(),
|
None => "0.7.33_pair_trading_readiness".to_string(),
|
||||||
};
|
};
|
||||||
let run_result = match profile_code.as_str() {
|
let run_result = match profile_code.as_str() {
|
||||||
"0.7.27" | "0.7.27_dexes_non_regression" => {
|
"0.7.27" | "0.7.27_dexes_non_regression" => {
|
||||||
@@ -1056,6 +1096,9 @@ pub(crate) async fn demo_pipeline2_validate_local_pipeline(
|
|||||||
"0.7.32" | "0.7.32_validation_report_semantics" => {
|
"0.7.32" | "0.7.32_validation_report_semantics" => {
|
||||||
service.validate_v0_7_32_current_database().await
|
service.validate_v0_7_32_current_database().await
|
||||||
},
|
},
|
||||||
|
"0.7.33" | "0.7.33_pair_trading_readiness" => {
|
||||||
|
service.validate_v0_7_33_current_database().await
|
||||||
|
},
|
||||||
other => Err(kb_lib::Error::InvalidState(format!(
|
other => Err(kb_lib::Error::InvalidState(format!(
|
||||||
"unsupported local pipeline validation profile: {other}"
|
"unsupported local pipeline validation profile: {other}"
|
||||||
))),
|
))),
|
||||||
@@ -1547,6 +1590,14 @@ fn demo_pipeline2_map_local_diagnostics_summary(
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
let mut pair_trading_readiness_summaries = std::vec::Vec::new();
|
||||||
|
for pair_trading_readiness_summary in summary.pair_trading_readiness_summaries {
|
||||||
|
pair_trading_readiness_summaries.push(
|
||||||
|
demo_pipeline2_map_local_pair_trading_readiness_diagnostic_summary(
|
||||||
|
pair_trading_readiness_summary,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
let mut decoded_event_summaries = std::vec::Vec::new();
|
let mut decoded_event_summaries = std::vec::Vec::new();
|
||||||
for decoded_event_summary in summary.decoded_event_summaries {
|
for decoded_event_summary in summary.decoded_event_summaries {
|
||||||
decoded_event_summaries
|
decoded_event_summaries
|
||||||
@@ -1642,6 +1693,7 @@ fn demo_pipeline2_map_local_diagnostics_summary(
|
|||||||
dex_summaries,
|
dex_summaries,
|
||||||
pair_summaries,
|
pair_summaries,
|
||||||
pair_actionability_summaries,
|
pair_actionability_summaries,
|
||||||
|
pair_trading_readiness_summaries,
|
||||||
decoded_event_summaries,
|
decoded_event_summaries,
|
||||||
event_classification_summaries,
|
event_classification_summaries,
|
||||||
missing_trade_event_reason_summaries,
|
missing_trade_event_reason_summaries,
|
||||||
@@ -1689,6 +1741,9 @@ fn demo_pipeline2_map_local_pair_diagnostic_summary(
|
|||||||
invalid_trade_event_count: summary.invalid_trade_event_count,
|
invalid_trade_event_count: summary.invalid_trade_event_count,
|
||||||
pair_candle_count: summary.pair_candle_count,
|
pair_candle_count: summary.pair_candle_count,
|
||||||
last_price_quote_per_base: summary.last_price_quote_per_base,
|
last_price_quote_per_base: summary.last_price_quote_per_base,
|
||||||
|
pair_trading_readiness: summary.pair_trading_readiness,
|
||||||
|
quote_asset_class: summary.quote_asset_class,
|
||||||
|
trading_route_required: summary.trading_route_required,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1707,6 +1762,21 @@ fn demo_pipeline2_map_local_pair_actionability_diagnostic_summary(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn demo_pipeline2_map_local_pair_trading_readiness_diagnostic_summary(
|
||||||
|
summary: kb_lib::LocalPairTradingReadinessDiagnosticSummaryDto,
|
||||||
|
) -> DemoPipeline2LocalPairTradingReadinessDiagnosticSummary {
|
||||||
|
DemoPipeline2LocalPairTradingReadinessDiagnosticSummary {
|
||||||
|
pair_trading_readiness: summary.pair_trading_readiness,
|
||||||
|
quote_asset_class: summary.quote_asset_class,
|
||||||
|
trading_route_required: summary.trading_route_required,
|
||||||
|
pair_count: summary.pair_count,
|
||||||
|
decoded_event_count: summary.decoded_event_count,
|
||||||
|
decoded_trade_candidate_count: summary.decoded_trade_candidate_count,
|
||||||
|
trade_event_count: summary.trade_event_count,
|
||||||
|
pair_candle_count: summary.pair_candle_count,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn demo_pipeline2_map_local_decoded_event_diagnostic_summary(
|
fn demo_pipeline2_map_local_decoded_event_diagnostic_summary(
|
||||||
summary: kb_lib::LocalDecodedEventDiagnosticSummaryDto,
|
summary: kb_lib::LocalDecodedEventDiagnosticSummaryDto,
|
||||||
) -> DemoPipeline2LocalDecodedEventDiagnosticSummary {
|
) -> DemoPipeline2LocalDecodedEventDiagnosticSummary {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://schema.tauri.app/config/2",
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
"productName": "kb-demo-app",
|
"productName": "kb-demo-app",
|
||||||
"version": "0.7.32",
|
"version": "0.7.33",
|
||||||
"identifier": "com.sasedev.kb-demo-app",
|
"identifier": "com.sasedev.kb-demo-app",
|
||||||
"build": {
|
"build": {
|
||||||
"beforeDevCommand": "npm run dev",
|
"beforeDevCommand": "npm run dev",
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ pub use dtos::LocalNonActionablePairDiagnosticSummaryDto;
|
|||||||
pub use dtos::LocalPairActionabilityDiagnosticSummaryDto;
|
pub use dtos::LocalPairActionabilityDiagnosticSummaryDto;
|
||||||
pub use dtos::LocalPairDiagnosticSummaryDto;
|
pub use dtos::LocalPairDiagnosticSummaryDto;
|
||||||
pub use dtos::LocalPairGapDiagnosticSampleDto;
|
pub use dtos::LocalPairGapDiagnosticSampleDto;
|
||||||
|
pub use dtos::LocalPairTradingReadinessDiagnosticSummaryDto;
|
||||||
pub use dtos::LocalPipelineDiagnosticCountersDto;
|
pub use dtos::LocalPipelineDiagnosticCountersDto;
|
||||||
pub use dtos::LocalPipelineDiagnosticSummaryDto;
|
pub use dtos::LocalPipelineDiagnosticSummaryDto;
|
||||||
pub use dtos::ObservedTokenDto;
|
pub use dtos::ObservedTokenDto;
|
||||||
@@ -153,6 +154,7 @@ pub use queries::query_local_multi_trade_signature_pair_diagnostic_list_samples;
|
|||||||
pub use queries::query_local_non_actionable_pair_diagnostic_list_summaries;
|
pub use queries::query_local_non_actionable_pair_diagnostic_list_summaries;
|
||||||
pub use queries::query_local_pair_actionability_diagnostic_list_summaries;
|
pub use queries::query_local_pair_actionability_diagnostic_list_summaries;
|
||||||
pub use queries::query_local_pair_diagnostic_list_summaries;
|
pub use queries::query_local_pair_diagnostic_list_summaries;
|
||||||
|
pub use queries::query_local_pair_trading_readiness_diagnostic_list_summaries;
|
||||||
pub use queries::query_local_pair_without_candle_diagnostic_list_samples;
|
pub use queries::query_local_pair_without_candle_diagnostic_list_samples;
|
||||||
pub use queries::query_local_pair_without_trade_diagnostic_list_samples;
|
pub use queries::query_local_pair_without_trade_diagnostic_list_samples;
|
||||||
pub use queries::query_local_pipeline_diagnostic_get_counters;
|
pub use queries::query_local_pipeline_diagnostic_get_counters;
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ pub(crate) use local_pipeline_diagnostics::LocalNonActionablePairDiagnosticSumma
|
|||||||
pub(crate) use local_pipeline_diagnostics::LocalPairActionabilityDiagnosticSummaryRow;
|
pub(crate) use local_pipeline_diagnostics::LocalPairActionabilityDiagnosticSummaryRow;
|
||||||
pub(crate) use local_pipeline_diagnostics::LocalPairDiagnosticSummaryRow;
|
pub(crate) use local_pipeline_diagnostics::LocalPairDiagnosticSummaryRow;
|
||||||
pub(crate) use local_pipeline_diagnostics::LocalPairGapDiagnosticSampleRow;
|
pub(crate) use local_pipeline_diagnostics::LocalPairGapDiagnosticSampleRow;
|
||||||
|
pub(crate) use local_pipeline_diagnostics::LocalPairTradingReadinessDiagnosticSummaryRow;
|
||||||
pub(crate) use local_pipeline_diagnostics::LocalPipelineDiagnosticCountersRow;
|
pub(crate) use local_pipeline_diagnostics::LocalPipelineDiagnosticCountersRow;
|
||||||
|
|
||||||
pub use analysis_signal::AnalysisSignalDto;
|
pub use analysis_signal::AnalysisSignalDto;
|
||||||
@@ -79,6 +80,7 @@ pub use local_pipeline_diagnostics::LocalNonActionablePairDiagnosticSummaryDto;
|
|||||||
pub use local_pipeline_diagnostics::LocalPairActionabilityDiagnosticSummaryDto;
|
pub use local_pipeline_diagnostics::LocalPairActionabilityDiagnosticSummaryDto;
|
||||||
pub use local_pipeline_diagnostics::LocalPairDiagnosticSummaryDto;
|
pub use local_pipeline_diagnostics::LocalPairDiagnosticSummaryDto;
|
||||||
pub use local_pipeline_diagnostics::LocalPairGapDiagnosticSampleDto;
|
pub use local_pipeline_diagnostics::LocalPairGapDiagnosticSampleDto;
|
||||||
|
pub use local_pipeline_diagnostics::LocalPairTradingReadinessDiagnosticSummaryDto;
|
||||||
pub use local_pipeline_diagnostics::LocalPipelineDiagnosticCountersDto;
|
pub use local_pipeline_diagnostics::LocalPipelineDiagnosticCountersDto;
|
||||||
pub use local_pipeline_diagnostics::LocalPipelineDiagnosticSummaryDto;
|
pub use local_pipeline_diagnostics::LocalPipelineDiagnosticSummaryDto;
|
||||||
pub use observed_token::ObservedTokenDto;
|
pub use observed_token::ObservedTokenDto;
|
||||||
|
|||||||
@@ -105,6 +105,9 @@ pub struct LocalPipelineDiagnosticSummaryDto {
|
|||||||
/// Diagnostics grouped by pair materialization/actionability class.
|
/// Diagnostics grouped by pair materialization/actionability class.
|
||||||
pub pair_actionability_summaries:
|
pub pair_actionability_summaries:
|
||||||
std::vec::Vec<crate::LocalPairActionabilityDiagnosticSummaryDto>,
|
std::vec::Vec<crate::LocalPairActionabilityDiagnosticSummaryDto>,
|
||||||
|
/// Diagnostics grouped by pair trading readiness class.
|
||||||
|
pub pair_trading_readiness_summaries:
|
||||||
|
std::vec::Vec<crate::LocalPairTradingReadinessDiagnosticSummaryDto>,
|
||||||
/// Diagnostics grouped by decoded event kind.
|
/// Diagnostics grouped by decoded event kind.
|
||||||
pub decoded_event_summaries: std::vec::Vec<crate::LocalDecodedEventDiagnosticSummaryDto>,
|
pub decoded_event_summaries: std::vec::Vec<crate::LocalDecodedEventDiagnosticSummaryDto>,
|
||||||
/// Diagnostics grouped by decoded event category, lifecycle kind and actionability.
|
/// Diagnostics grouped by decoded event category, lifecycle kind and actionability.
|
||||||
@@ -187,6 +190,12 @@ pub struct LocalPairDiagnosticSummaryDto {
|
|||||||
pub pair_candle_count: i64,
|
pub pair_candle_count: i64,
|
||||||
/// Last known price.
|
/// Last known price.
|
||||||
pub last_price_quote_per_base: std::option::Option<f64>,
|
pub last_price_quote_per_base: std::option::Option<f64>,
|
||||||
|
/// Pair trading-readiness class derived from base/quote orientation.
|
||||||
|
pub pair_trading_readiness: std::string::String,
|
||||||
|
/// Quote asset class used by the readiness classifier.
|
||||||
|
pub quote_asset_class: std::string::String,
|
||||||
|
/// Whether the pair likely requires a router or aggregator before direct bot execution.
|
||||||
|
pub trading_route_required: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Local pair diagnostics grouped by materialization/actionability class.
|
/// Local pair diagnostics grouped by materialization/actionability class.
|
||||||
@@ -210,6 +219,27 @@ pub struct LocalPairActionabilityDiagnosticSummaryDto {
|
|||||||
pub pair_candle_count: i64,
|
pub pair_candle_count: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Local pair diagnostics grouped by trading readiness class.
|
||||||
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
|
pub struct LocalPairTradingReadinessDiagnosticSummaryDto {
|
||||||
|
/// Pair trading-readiness class.
|
||||||
|
pub pair_trading_readiness: std::string::String,
|
||||||
|
/// Quote asset class attached to this readiness group.
|
||||||
|
pub quote_asset_class: std::string::String,
|
||||||
|
/// Whether the group requires a router or aggregator before direct execution.
|
||||||
|
pub trading_route_required: bool,
|
||||||
|
/// Total pairs in this readiness group.
|
||||||
|
pub pair_count: i64,
|
||||||
|
/// Total decoded events attached to pairs in this readiness group.
|
||||||
|
pub decoded_event_count: i64,
|
||||||
|
/// Total decoded trade candidates attached to pairs in this readiness group.
|
||||||
|
pub decoded_trade_candidate_count: i64,
|
||||||
|
/// Total persisted trade events attached to pairs in this readiness group.
|
||||||
|
pub trade_event_count: i64,
|
||||||
|
/// Total persisted candle buckets attached to pairs in this readiness group.
|
||||||
|
pub pair_candle_count: i64,
|
||||||
|
}
|
||||||
|
|
||||||
/// Local decoded-event diagnostics summary.
|
/// Local decoded-event diagnostics summary.
|
||||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct LocalDecodedEventDiagnosticSummaryDto {
|
pub struct LocalDecodedEventDiagnosticSummaryDto {
|
||||||
@@ -464,6 +494,9 @@ pub(crate) struct LocalPairDiagnosticSummaryRow {
|
|||||||
pub(crate) invalid_trade_event_count: i64,
|
pub(crate) invalid_trade_event_count: i64,
|
||||||
pub(crate) pair_candle_count: i64,
|
pub(crate) pair_candle_count: i64,
|
||||||
pub(crate) last_price_quote_per_base: std::option::Option<f64>,
|
pub(crate) last_price_quote_per_base: std::option::Option<f64>,
|
||||||
|
pub(crate) pair_trading_readiness: std::string::String,
|
||||||
|
pub(crate) quote_asset_class: std::string::String,
|
||||||
|
pub(crate) trading_route_required: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// SQL row for local pair actionability diagnostics.
|
/// SQL row for local pair actionability diagnostics.
|
||||||
@@ -479,6 +512,19 @@ pub(crate) struct LocalPairActionabilityDiagnosticSummaryRow {
|
|||||||
pub(crate) pair_candle_count: i64,
|
pub(crate) pair_candle_count: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// SQL row for local pair trading-readiness diagnostics.
|
||||||
|
#[derive(Debug, Clone, sqlx::FromRow)]
|
||||||
|
pub(crate) struct LocalPairTradingReadinessDiagnosticSummaryRow {
|
||||||
|
pub(crate) pair_trading_readiness: std::string::String,
|
||||||
|
pub(crate) quote_asset_class: std::string::String,
|
||||||
|
pub(crate) trading_route_required: i64,
|
||||||
|
pub(crate) pair_count: i64,
|
||||||
|
pub(crate) decoded_event_count: i64,
|
||||||
|
pub(crate) decoded_trade_candidate_count: i64,
|
||||||
|
pub(crate) trade_event_count: i64,
|
||||||
|
pub(crate) pair_candle_count: i64,
|
||||||
|
}
|
||||||
|
|
||||||
/// SQL row for local decoded-event diagnostics.
|
/// SQL row for local decoded-event diagnostics.
|
||||||
#[derive(Debug, Clone, sqlx::FromRow)]
|
#[derive(Debug, Clone, sqlx::FromRow)]
|
||||||
pub(crate) struct LocalDecodedEventDiagnosticSummaryRow {
|
pub(crate) struct LocalDecodedEventDiagnosticSummaryRow {
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ pub use local_pipeline_diagnostics::query_local_multi_trade_signature_pair_diagn
|
|||||||
pub use local_pipeline_diagnostics::query_local_non_actionable_pair_diagnostic_list_summaries;
|
pub use local_pipeline_diagnostics::query_local_non_actionable_pair_diagnostic_list_summaries;
|
||||||
pub use local_pipeline_diagnostics::query_local_pair_actionability_diagnostic_list_summaries;
|
pub use local_pipeline_diagnostics::query_local_pair_actionability_diagnostic_list_summaries;
|
||||||
pub use local_pipeline_diagnostics::query_local_pair_diagnostic_list_summaries;
|
pub use local_pipeline_diagnostics::query_local_pair_diagnostic_list_summaries;
|
||||||
|
pub use local_pipeline_diagnostics::query_local_pair_trading_readiness_diagnostic_list_summaries;
|
||||||
pub use local_pipeline_diagnostics::query_local_pair_without_candle_diagnostic_list_samples;
|
pub use local_pipeline_diagnostics::query_local_pair_without_candle_diagnostic_list_samples;
|
||||||
pub use local_pipeline_diagnostics::query_local_pair_without_trade_diagnostic_list_samples;
|
pub use local_pipeline_diagnostics::query_local_pair_without_trade_diagnostic_list_samples;
|
||||||
pub use local_pipeline_diagnostics::query_local_pipeline_diagnostic_get_counters;
|
pub use local_pipeline_diagnostics::query_local_pipeline_diagnostic_get_counters;
|
||||||
|
|||||||
@@ -555,7 +555,56 @@ SELECT
|
|||||||
WHERE te_last.pair_id = pair.id
|
WHERE te_last.pair_id = pair.id
|
||||||
ORDER BY te_last.id DESC
|
ORDER BY te_last.id DESC
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
) AS last_price_quote_per_base
|
) AS last_price_quote_per_base,
|
||||||
|
CASE
|
||||||
|
WHEN COUNT(DISTINCT te.id) = 0 THEN 'non_trade_materialized'
|
||||||
|
WHEN quote_token.mint = 'So11111111111111111111111111111111111111112' THEN 'direct_wsol_quote'
|
||||||
|
WHEN quote_token.mint IN (
|
||||||
|
'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
|
||||||
|
'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',
|
||||||
|
'USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB',
|
||||||
|
'JuprjznTrTSp2UFa3ZBUFgwdAmtZCq4MQCwysN55USD'
|
||||||
|
) THEN 'direct_stable_quote'
|
||||||
|
WHEN base_token.mint = 'So11111111111111111111111111111111111111112' THEN 'inverse_wsol_base'
|
||||||
|
WHEN base_token.mint IN (
|
||||||
|
'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
|
||||||
|
'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',
|
||||||
|
'USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB',
|
||||||
|
'JuprjznTrTSp2UFa3ZBUFgwdAmtZCq4MQCwysN55USD'
|
||||||
|
) THEN 'inverse_stable_base'
|
||||||
|
WHEN quote_token.mint IS NULL OR quote_token.mint = '' THEN 'unknown_quote'
|
||||||
|
ELSE 'cross_quote_requires_router'
|
||||||
|
END AS pair_trading_readiness,
|
||||||
|
CASE
|
||||||
|
WHEN quote_token.mint = 'So11111111111111111111111111111111111111112' THEN 'wsol'
|
||||||
|
WHEN quote_token.mint IN (
|
||||||
|
'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
|
||||||
|
'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',
|
||||||
|
'USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB',
|
||||||
|
'JuprjznTrTSp2UFa3ZBUFgwdAmtZCq4MQCwysN55USD'
|
||||||
|
) THEN 'stable'
|
||||||
|
WHEN quote_token.mint IS NULL OR quote_token.mint = '' THEN 'unknown'
|
||||||
|
ELSE 'other'
|
||||||
|
END AS quote_asset_class,
|
||||||
|
CASE
|
||||||
|
WHEN COUNT(DISTINCT te.id) = 0 THEN 0
|
||||||
|
WHEN quote_token.mint IS NULL OR quote_token.mint = '' THEN 1
|
||||||
|
WHEN quote_token.mint = 'So11111111111111111111111111111111111111112' THEN 0
|
||||||
|
WHEN quote_token.mint IN (
|
||||||
|
'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
|
||||||
|
'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',
|
||||||
|
'USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB',
|
||||||
|
'JuprjznTrTSp2UFa3ZBUFgwdAmtZCq4MQCwysN55USD'
|
||||||
|
) THEN 0
|
||||||
|
WHEN base_token.mint = 'So11111111111111111111111111111111111111112' THEN 0
|
||||||
|
WHEN base_token.mint IN (
|
||||||
|
'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
|
||||||
|
'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',
|
||||||
|
'USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB',
|
||||||
|
'JuprjznTrTSp2UFa3ZBUFgwdAmtZCq4MQCwysN55USD'
|
||||||
|
) THEN 0
|
||||||
|
ELSE 1
|
||||||
|
END AS trading_route_required
|
||||||
FROM k_sol_pairs pair
|
FROM k_sol_pairs pair
|
||||||
JOIN k_sol_pools p ON p.id = pair.pool_id
|
JOIN k_sol_pools p ON p.id = pair.pool_id
|
||||||
JOIN k_sol_dexes d ON d.id = p.dex_id
|
JOIN k_sol_dexes d ON d.id = p.dex_id
|
||||||
@@ -605,6 +654,9 @@ ORDER BY pair.id
|
|||||||
invalid_trade_event_count: row.invalid_trade_event_count,
|
invalid_trade_event_count: row.invalid_trade_event_count,
|
||||||
pair_candle_count: row.pair_candle_count,
|
pair_candle_count: row.pair_candle_count,
|
||||||
last_price_quote_per_base: row.last_price_quote_per_base,
|
last_price_quote_per_base: row.last_price_quote_per_base,
|
||||||
|
pair_trading_readiness: row.pair_trading_readiness,
|
||||||
|
quote_asset_class: row.quote_asset_class,
|
||||||
|
trading_route_required: row.trading_route_required != 0,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return Ok(summaries);
|
return Ok(summaries);
|
||||||
@@ -716,6 +768,146 @@ ORDER BY
|
|||||||
return Ok(summaries);
|
return Ok(summaries);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Lists local pair trading-readiness summaries.
|
||||||
|
pub async fn query_local_pair_trading_readiness_diagnostic_list_summaries(
|
||||||
|
database: &crate::Database,
|
||||||
|
) -> Result<std::vec::Vec<crate::LocalPairTradingReadinessDiagnosticSummaryDto>, crate::Error> {
|
||||||
|
match database.connection() {
|
||||||
|
crate::DatabaseConnection::Sqlite(pool) => {
|
||||||
|
let rows_result = sqlx::query_as::<
|
||||||
|
sqlx::Sqlite,
|
||||||
|
crate::db::dtos::LocalPairTradingReadinessDiagnosticSummaryRow,
|
||||||
|
>(
|
||||||
|
r#"
|
||||||
|
WITH pair_state AS (
|
||||||
|
SELECT
|
||||||
|
pair.id AS pair_id,
|
||||||
|
base_token.mint AS base_mint,
|
||||||
|
quote_token.mint AS quote_mint,
|
||||||
|
COUNT(DISTINCT dde.id) AS decoded_event_count,
|
||||||
|
COUNT(DISTINCT CASE WHEN json_extract(dde.payload_json, '$.tradeCandidate') = 1 THEN dde.id END) AS decoded_trade_candidate_count,
|
||||||
|
COUNT(DISTINCT te.id) AS trade_event_count,
|
||||||
|
COUNT(DISTINCT pc.bucket_start_unix || ':' || pc.timeframe_seconds) AS pair_candle_count
|
||||||
|
FROM k_sol_pairs pair
|
||||||
|
JOIN k_sol_pools p ON p.id = pair.pool_id
|
||||||
|
JOIN k_sol_tokens base_token ON base_token.id = pair.base_token_id
|
||||||
|
JOIN k_sol_tokens quote_token ON quote_token.id = pair.quote_token_id
|
||||||
|
LEFT JOIN k_sol_dex_decoded_events dde ON dde.pool_account = p.address
|
||||||
|
LEFT JOIN k_sol_trade_events te ON te.pair_id = pair.id
|
||||||
|
LEFT JOIN k_sol_pair_candles pc ON pc.pair_id = pair.id
|
||||||
|
GROUP BY pair.id, base_token.mint, quote_token.mint
|
||||||
|
), classified AS (
|
||||||
|
SELECT
|
||||||
|
CASE
|
||||||
|
WHEN trade_event_count = 0 THEN 'non_trade_materialized'
|
||||||
|
WHEN quote_mint = 'So11111111111111111111111111111111111111112' THEN 'direct_wsol_quote'
|
||||||
|
WHEN quote_mint IN (
|
||||||
|
'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
|
||||||
|
'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',
|
||||||
|
'USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB',
|
||||||
|
'JuprjznTrTSp2UFa3ZBUFgwdAmtZCq4MQCwysN55USD'
|
||||||
|
) THEN 'direct_stable_quote'
|
||||||
|
WHEN base_mint = 'So11111111111111111111111111111111111111112' THEN 'inverse_wsol_base'
|
||||||
|
WHEN base_mint IN (
|
||||||
|
'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
|
||||||
|
'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',
|
||||||
|
'USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB',
|
||||||
|
'JuprjznTrTSp2UFa3ZBUFgwdAmtZCq4MQCwysN55USD'
|
||||||
|
) THEN 'inverse_stable_base'
|
||||||
|
WHEN quote_mint IS NULL OR quote_mint = '' THEN 'unknown_quote'
|
||||||
|
ELSE 'cross_quote_requires_router'
|
||||||
|
END AS pair_trading_readiness,
|
||||||
|
CASE
|
||||||
|
WHEN quote_mint = 'So11111111111111111111111111111111111111112' THEN 'wsol'
|
||||||
|
WHEN quote_mint IN (
|
||||||
|
'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
|
||||||
|
'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',
|
||||||
|
'USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB',
|
||||||
|
'JuprjznTrTSp2UFa3ZBUFgwdAmtZCq4MQCwysN55USD'
|
||||||
|
) THEN 'stable'
|
||||||
|
WHEN quote_mint IS NULL OR quote_mint = '' THEN 'unknown'
|
||||||
|
ELSE 'other'
|
||||||
|
END AS quote_asset_class,
|
||||||
|
CASE
|
||||||
|
WHEN trade_event_count = 0 THEN 0
|
||||||
|
WHEN quote_mint IS NULL OR quote_mint = '' THEN 1
|
||||||
|
WHEN quote_mint = 'So11111111111111111111111111111111111111112' THEN 0
|
||||||
|
WHEN quote_mint IN (
|
||||||
|
'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
|
||||||
|
'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',
|
||||||
|
'USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB',
|
||||||
|
'JuprjznTrTSp2UFa3ZBUFgwdAmtZCq4MQCwysN55USD'
|
||||||
|
) THEN 0
|
||||||
|
WHEN base_mint = 'So11111111111111111111111111111111111111112' THEN 0
|
||||||
|
WHEN base_mint IN (
|
||||||
|
'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
|
||||||
|
'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',
|
||||||
|
'USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB',
|
||||||
|
'JuprjznTrTSp2UFa3ZBUFgwdAmtZCq4MQCwysN55USD'
|
||||||
|
) THEN 0
|
||||||
|
ELSE 1
|
||||||
|
END AS trading_route_required,
|
||||||
|
pair_id,
|
||||||
|
decoded_event_count,
|
||||||
|
decoded_trade_candidate_count,
|
||||||
|
trade_event_count,
|
||||||
|
pair_candle_count
|
||||||
|
FROM pair_state
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
pair_trading_readiness AS pair_trading_readiness,
|
||||||
|
quote_asset_class AS quote_asset_class,
|
||||||
|
trading_route_required AS trading_route_required,
|
||||||
|
COUNT(pair_id) AS pair_count,
|
||||||
|
SUM(decoded_event_count) AS decoded_event_count,
|
||||||
|
SUM(decoded_trade_candidate_count) AS decoded_trade_candidate_count,
|
||||||
|
SUM(trade_event_count) AS trade_event_count,
|
||||||
|
SUM(pair_candle_count) AS pair_candle_count
|
||||||
|
FROM classified
|
||||||
|
GROUP BY pair_trading_readiness, quote_asset_class, trading_route_required
|
||||||
|
ORDER BY
|
||||||
|
CASE pair_trading_readiness
|
||||||
|
WHEN 'direct_wsol_quote' THEN 1
|
||||||
|
WHEN 'direct_stable_quote' THEN 2
|
||||||
|
WHEN 'inverse_wsol_base' THEN 3
|
||||||
|
WHEN 'inverse_stable_base' THEN 4
|
||||||
|
WHEN 'cross_quote_requires_router' THEN 5
|
||||||
|
WHEN 'unknown_quote' THEN 6
|
||||||
|
ELSE 7
|
||||||
|
END,
|
||||||
|
pair_trading_readiness,
|
||||||
|
quote_asset_class
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.fetch_all(pool)
|
||||||
|
.await;
|
||||||
|
let rows = match rows_result {
|
||||||
|
Ok(rows) => rows,
|
||||||
|
Err(error) => {
|
||||||
|
return Err(crate::Error::Db(format!(
|
||||||
|
"cannot list local pair trading readiness diagnostic summaries on sqlite: {}",
|
||||||
|
error
|
||||||
|
)));
|
||||||
|
},
|
||||||
|
};
|
||||||
|
let mut summaries = std::vec::Vec::new();
|
||||||
|
for row in rows {
|
||||||
|
summaries.push(crate::LocalPairTradingReadinessDiagnosticSummaryDto {
|
||||||
|
pair_trading_readiness: row.pair_trading_readiness,
|
||||||
|
quote_asset_class: row.quote_asset_class,
|
||||||
|
trading_route_required: row.trading_route_required != 0,
|
||||||
|
pair_count: row.pair_count,
|
||||||
|
decoded_event_count: row.decoded_event_count,
|
||||||
|
decoded_trade_candidate_count: row.decoded_trade_candidate_count,
|
||||||
|
trade_event_count: row.trade_event_count,
|
||||||
|
pair_candle_count: row.pair_candle_count,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Ok(summaries);
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lists local decoded-event diagnostic summaries.
|
/// Lists local decoded-event diagnostic summaries.
|
||||||
|
|||||||
@@ -363,6 +363,8 @@ pub use db::LocalPairActionabilityDiagnosticSummaryDto;
|
|||||||
pub use db::LocalPairDiagnosticSummaryDto;
|
pub use db::LocalPairDiagnosticSummaryDto;
|
||||||
/// Sample of a pair gap.
|
/// Sample of a pair gap.
|
||||||
pub use db::LocalPairGapDiagnosticSampleDto;
|
pub use db::LocalPairGapDiagnosticSampleDto;
|
||||||
|
/// Local pair diagnostics grouped by trading readiness class.
|
||||||
|
pub use db::LocalPairTradingReadinessDiagnosticSummaryDto;
|
||||||
/// Internal flat counter row for local diagnostics.
|
/// Internal flat counter row for local diagnostics.
|
||||||
pub use db::LocalPipelineDiagnosticCountersDto;
|
pub use db::LocalPipelineDiagnosticCountersDto;
|
||||||
/// Local pipeline diagnostics summary.
|
/// Local pipeline diagnostics summary.
|
||||||
@@ -577,6 +579,8 @@ pub use db::query_local_non_actionable_pair_diagnostic_list_summaries;
|
|||||||
pub use db::query_local_pair_actionability_diagnostic_list_summaries;
|
pub use db::query_local_pair_actionability_diagnostic_list_summaries;
|
||||||
/// Lists local pair diagnostic summaries.
|
/// Lists local pair diagnostic summaries.
|
||||||
pub use db::query_local_pair_diagnostic_list_summaries;
|
pub use db::query_local_pair_diagnostic_list_summaries;
|
||||||
|
/// Lists local pair trading-readiness summaries.
|
||||||
|
pub use db::query_local_pair_trading_readiness_diagnostic_list_summaries;
|
||||||
/// Lists samples of pairs without candles.
|
/// Lists samples of pairs without candles.
|
||||||
pub use db::query_local_pair_without_candle_diagnostic_list_samples;
|
pub use db::query_local_pair_without_candle_diagnostic_list_samples;
|
||||||
/// Lists samples of pairs without trade events.
|
/// Lists samples of pairs without trade events.
|
||||||
|
|||||||
@@ -42,6 +42,15 @@ impl LocalPipelineDiagnosticsService {
|
|||||||
Ok(summaries) => summaries,
|
Ok(summaries) => summaries,
|
||||||
Err(error) => return Err(error),
|
Err(error) => return Err(error),
|
||||||
};
|
};
|
||||||
|
let pair_trading_readiness_summaries_result =
|
||||||
|
crate::query_local_pair_trading_readiness_diagnostic_list_summaries(
|
||||||
|
self.database.as_ref(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
let pair_trading_readiness_summaries = match pair_trading_readiness_summaries_result {
|
||||||
|
Ok(summaries) => summaries,
|
||||||
|
Err(error) => return Err(error),
|
||||||
|
};
|
||||||
let decoded_event_summaries_result =
|
let decoded_event_summaries_result =
|
||||||
crate::query_local_decoded_event_diagnostic_list_summaries(self.database.as_ref())
|
crate::query_local_decoded_event_diagnostic_list_summaries(self.database.as_ref())
|
||||||
.await;
|
.await;
|
||||||
@@ -182,6 +191,7 @@ impl LocalPipelineDiagnosticsService {
|
|||||||
dex_summaries,
|
dex_summaries,
|
||||||
pair_summaries,
|
pair_summaries,
|
||||||
pair_actionability_summaries,
|
pair_actionability_summaries,
|
||||||
|
pair_trading_readiness_summaries,
|
||||||
decoded_event_summaries,
|
decoded_event_summaries,
|
||||||
event_classification_summaries,
|
event_classification_summaries,
|
||||||
missing_trade_event_reason_summaries,
|
missing_trade_event_reason_summaries,
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ pub struct LocalPipelineValidationConfig {
|
|||||||
pub require_no_non_actionable_trade_events_materialized: bool,
|
pub require_no_non_actionable_trade_events_materialized: bool,
|
||||||
/// Whether the DEX support matrix must satisfy internal semantic invariants.
|
/// Whether the DEX support matrix must satisfy internal semantic invariants.
|
||||||
pub require_dex_support_matrix_semantics: bool,
|
pub require_dex_support_matrix_semantics: bool,
|
||||||
|
/// Whether pair trading-readiness diagnostics must satisfy internal semantic invariants.
|
||||||
|
pub require_pair_trading_readiness_semantics: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for LocalPipelineValidationConfig {
|
impl Default for LocalPipelineValidationConfig {
|
||||||
@@ -62,6 +64,7 @@ impl Default for LocalPipelineValidationConfig {
|
|||||||
require_candles_per_dex: true,
|
require_candles_per_dex: true,
|
||||||
require_no_non_actionable_trade_events_materialized: true,
|
require_no_non_actionable_trade_events_materialized: true,
|
||||||
require_dex_support_matrix_semantics: false,
|
require_dex_support_matrix_semantics: false,
|
||||||
|
require_pair_trading_readiness_semantics: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -90,6 +93,7 @@ impl LocalPipelineValidationConfig {
|
|||||||
require_candles_per_dex: true,
|
require_candles_per_dex: true,
|
||||||
require_no_non_actionable_trade_events_materialized: true,
|
require_no_non_actionable_trade_events_materialized: true,
|
||||||
require_dex_support_matrix_semantics: false,
|
require_dex_support_matrix_semantics: false,
|
||||||
|
require_pair_trading_readiness_semantics: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,6 +127,7 @@ impl LocalPipelineValidationConfig {
|
|||||||
require_candles_per_dex: false,
|
require_candles_per_dex: false,
|
||||||
require_no_non_actionable_trade_events_materialized: true,
|
require_no_non_actionable_trade_events_materialized: true,
|
||||||
require_dex_support_matrix_semantics: false,
|
require_dex_support_matrix_semantics: false,
|
||||||
|
require_pair_trading_readiness_semantics: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,6 +160,7 @@ impl LocalPipelineValidationConfig {
|
|||||||
require_candles_per_dex: false,
|
require_candles_per_dex: false,
|
||||||
require_no_non_actionable_trade_events_materialized: true,
|
require_no_non_actionable_trade_events_materialized: true,
|
||||||
require_dex_support_matrix_semantics: false,
|
require_dex_support_matrix_semantics: false,
|
||||||
|
require_pair_trading_readiness_semantics: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,6 +197,17 @@ impl LocalPipelineValidationConfig {
|
|||||||
config.require_dex_support_matrix_semantics = true;
|
config.require_dex_support_matrix_semantics = true;
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Builds the `0.7.33` pair trading-readiness validation config.
|
||||||
|
///
|
||||||
|
/// This profile keeps the `0.7.32` diagnostics semantics and requires all
|
||||||
|
/// persisted pairs to be covered by the pair trading-readiness summaries.
|
||||||
|
pub fn v0_7_33_pair_trading_readiness() -> Self {
|
||||||
|
let mut config = Self::v0_7_32_validation_report_semantics();
|
||||||
|
config.profile_code = "0.7.33_pair_trading_readiness".to_string();
|
||||||
|
config.require_pair_trading_readiness_semantics = true;
|
||||||
|
return config;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A single local pipeline validation issue.
|
/// A single local pipeline validation issue.
|
||||||
@@ -343,6 +360,14 @@ impl LocalPipelineValidationService {
|
|||||||
let config = crate::LocalPipelineValidationConfig::v0_7_32_validation_report_semantics();
|
let config = crate::LocalPipelineValidationConfig::v0_7_32_validation_report_semantics();
|
||||||
return self.validate_current_database(&config).await;
|
return self.validate_current_database(&config).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Diagnoses the current database with the `0.7.33` pair trading-readiness profile.
|
||||||
|
pub async fn validate_v0_7_33_current_database(
|
||||||
|
&self,
|
||||||
|
) -> Result<crate::LocalPipelineValidationRunDto, crate::Error> {
|
||||||
|
let config = crate::LocalPipelineValidationConfig::v0_7_33_pair_trading_readiness();
|
||||||
|
return self.validate_current_database(&config).await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Validates a diagnostics summary without performing database access.
|
/// Validates a diagnostics summary without performing database access.
|
||||||
@@ -457,6 +482,9 @@ pub fn validate_local_pipeline_diagnostics_summary(
|
|||||||
if config.require_dex_support_matrix_semantics {
|
if config.require_dex_support_matrix_semantics {
|
||||||
validate_dex_support_matrix_semantics(&mut issues);
|
validate_dex_support_matrix_semantics(&mut issues);
|
||||||
}
|
}
|
||||||
|
if config.require_pair_trading_readiness_semantics {
|
||||||
|
validate_pair_trading_readiness_semantics(&mut issues, summary);
|
||||||
|
}
|
||||||
if config.require_all_expected_dexes {
|
if config.require_all_expected_dexes {
|
||||||
for expected_dex_code in &expected_dex_codes {
|
for expected_dex_code in &expected_dex_codes {
|
||||||
if !observed_dex_codes.contains(expected_dex_code) {
|
if !observed_dex_codes.contains(expected_dex_code) {
|
||||||
@@ -532,6 +560,109 @@ pub fn validate_local_pipeline_diagnostics_summary(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn validate_pair_trading_readiness_semantics(
|
||||||
|
issues: &mut std::vec::Vec<crate::LocalPipelineValidationIssueDto>,
|
||||||
|
summary: &crate::LocalPipelineDiagnosticSummaryDto,
|
||||||
|
) {
|
||||||
|
if summary.pair_count > 0 && summary.pair_trading_readiness_summaries.is_empty() {
|
||||||
|
issues.push(crate::LocalPipelineValidationIssueDto {
|
||||||
|
code: "pair_trading_readiness_summary_missing".to_string(),
|
||||||
|
message: "pair trading-readiness summaries are missing".to_string(),
|
||||||
|
subject: None,
|
||||||
|
blocking: true,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let mut readiness_pair_count = 0_i64;
|
||||||
|
let mut readiness_trade_materialized_pair_count = 0_i64;
|
||||||
|
let mut readiness_trade_event_count = 0_i64;
|
||||||
|
let mut readiness_pair_candle_count = 0_i64;
|
||||||
|
for readiness_summary in &summary.pair_trading_readiness_summaries {
|
||||||
|
if readiness_summary.pair_trading_readiness.trim().is_empty() {
|
||||||
|
issues.push(crate::LocalPipelineValidationIssueDto {
|
||||||
|
code: "pair_trading_readiness_empty".to_string(),
|
||||||
|
message: "pair trading-readiness class must not be empty".to_string(),
|
||||||
|
subject: None,
|
||||||
|
blocking: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if readiness_summary.pair_count <= 0 {
|
||||||
|
issues.push(crate::LocalPipelineValidationIssueDto {
|
||||||
|
code: "pair_trading_readiness_empty_group".to_string(),
|
||||||
|
message: format!(
|
||||||
|
"pair trading-readiness group '{}' has no pair",
|
||||||
|
readiness_summary.pair_trading_readiness
|
||||||
|
),
|
||||||
|
subject: Some(readiness_summary.pair_trading_readiness.clone()),
|
||||||
|
blocking: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
readiness_pair_count += readiness_summary.pair_count;
|
||||||
|
readiness_trade_event_count += readiness_summary.trade_event_count;
|
||||||
|
readiness_pair_candle_count += readiness_summary.pair_candle_count;
|
||||||
|
if readiness_summary.pair_trading_readiness != "non_trade_materialized" {
|
||||||
|
readiness_trade_materialized_pair_count += readiness_summary.pair_count;
|
||||||
|
}
|
||||||
|
if readiness_summary.pair_trading_readiness == "unknown_quote"
|
||||||
|
&& readiness_summary.trade_event_count > 0
|
||||||
|
{
|
||||||
|
issues.push(crate::LocalPipelineValidationIssueDto {
|
||||||
|
code: "pair_trading_readiness_unknown_quote_materialized".to_string(),
|
||||||
|
message: format!(
|
||||||
|
"unknown quote readiness group has {} linked trade event(s)",
|
||||||
|
readiness_summary.trade_event_count
|
||||||
|
),
|
||||||
|
subject: Some(readiness_summary.pair_trading_readiness.clone()),
|
||||||
|
blocking: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if readiness_pair_count != summary.pair_count {
|
||||||
|
issues.push(crate::LocalPipelineValidationIssueDto {
|
||||||
|
code: "pair_trading_readiness_pair_count_mismatch".to_string(),
|
||||||
|
message: format!(
|
||||||
|
"pair trading-readiness summaries cover {} pair(s), expected {}",
|
||||||
|
readiness_pair_count, summary.pair_count
|
||||||
|
),
|
||||||
|
subject: None,
|
||||||
|
blocking: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if readiness_trade_materialized_pair_count != summary.trade_materialized_pair_count {
|
||||||
|
issues.push(crate::LocalPipelineValidationIssueDto {
|
||||||
|
code: "pair_trading_readiness_materialized_pair_count_mismatch".to_string(),
|
||||||
|
message: format!(
|
||||||
|
"pair trading-readiness materialized groups cover {} pair(s), expected {}",
|
||||||
|
readiness_trade_materialized_pair_count, summary.trade_materialized_pair_count
|
||||||
|
),
|
||||||
|
subject: None,
|
||||||
|
blocking: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if readiness_trade_event_count != summary.trade_event_count {
|
||||||
|
issues.push(crate::LocalPipelineValidationIssueDto {
|
||||||
|
code: "pair_trading_readiness_trade_event_count_mismatch".to_string(),
|
||||||
|
message: format!(
|
||||||
|
"pair trading-readiness summaries cover {} trade event(s), expected {}",
|
||||||
|
readiness_trade_event_count, summary.trade_event_count
|
||||||
|
),
|
||||||
|
subject: None,
|
||||||
|
blocking: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if readiness_pair_candle_count != summary.pair_candle_count {
|
||||||
|
issues.push(crate::LocalPipelineValidationIssueDto {
|
||||||
|
code: "pair_trading_readiness_candle_count_mismatch".to_string(),
|
||||||
|
message: format!(
|
||||||
|
"pair trading-readiness summaries cover {} candle bucket(s), expected {}",
|
||||||
|
readiness_pair_candle_count, summary.pair_candle_count
|
||||||
|
),
|
||||||
|
subject: None,
|
||||||
|
blocking: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn validate_dex_support_matrix_semantics(
|
fn validate_dex_support_matrix_semantics(
|
||||||
issues: &mut std::vec::Vec<crate::LocalPipelineValidationIssueDto>,
|
issues: &mut std::vec::Vec<crate::LocalPipelineValidationIssueDto>,
|
||||||
) {
|
) {
|
||||||
@@ -728,6 +859,38 @@ mod tests {
|
|||||||
pair_candle_count: 0,
|
pair_candle_count: 0,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
pair_trading_readiness_summaries: vec![
|
||||||
|
crate::LocalPairTradingReadinessDiagnosticSummaryDto {
|
||||||
|
pair_trading_readiness: "direct_wsol_quote".to_string(),
|
||||||
|
quote_asset_class: "wsol".to_string(),
|
||||||
|
trading_route_required: false,
|
||||||
|
pair_count: 20,
|
||||||
|
decoded_event_count: 180,
|
||||||
|
decoded_trade_candidate_count: 180,
|
||||||
|
trade_event_count: 180,
|
||||||
|
pair_candle_count: 200,
|
||||||
|
},
|
||||||
|
crate::LocalPairTradingReadinessDiagnosticSummaryDto {
|
||||||
|
pair_trading_readiness: "direct_stable_quote".to_string(),
|
||||||
|
quote_asset_class: "stable".to_string(),
|
||||||
|
trading_route_required: false,
|
||||||
|
pair_count: 3,
|
||||||
|
decoded_event_count: 30,
|
||||||
|
decoded_trade_candidate_count: 30,
|
||||||
|
trade_event_count: 30,
|
||||||
|
pair_candle_count: 30,
|
||||||
|
},
|
||||||
|
crate::LocalPairTradingReadinessDiagnosticSummaryDto {
|
||||||
|
pair_trading_readiness: "non_trade_materialized".to_string(),
|
||||||
|
quote_asset_class: "other".to_string(),
|
||||||
|
trading_route_required: false,
|
||||||
|
pair_count: 4,
|
||||||
|
decoded_event_count: 0,
|
||||||
|
decoded_trade_candidate_count: 0,
|
||||||
|
trade_event_count: 0,
|
||||||
|
pair_candle_count: 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
decoded_event_summaries: vec![],
|
decoded_event_summaries: vec![],
|
||||||
event_classification_summaries: vec![],
|
event_classification_summaries: vec![],
|
||||||
missing_trade_event_reason_summaries: vec![],
|
missing_trade_event_reason_summaries: vec![],
|
||||||
@@ -778,6 +941,11 @@ mod tests {
|
|||||||
});
|
});
|
||||||
summary.pool_count = 95;
|
summary.pool_count = 95;
|
||||||
summary.pair_count = 95;
|
summary.pair_count = 95;
|
||||||
|
for readiness_summary in &mut summary.pair_trading_readiness_summaries {
|
||||||
|
if readiness_summary.pair_trading_readiness == "non_trade_materialized" {
|
||||||
|
readiness_summary.pair_count = 72;
|
||||||
|
}
|
||||||
|
}
|
||||||
return summary;
|
return summary;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -883,6 +1051,28 @@ mod tests {
|
|||||||
assert_eq!(summary.blocking_pair_without_trade_count, 0);
|
assert_eq!(summary.blocking_pair_without_trade_count, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn validation_accepts_0_7_33_pair_trading_readiness_summary() {
|
||||||
|
let summary = make_0_7_28_summary_with_meteora();
|
||||||
|
let config = crate::LocalPipelineValidationConfig::v0_7_33_pair_trading_readiness();
|
||||||
|
let report = crate::validate_local_pipeline_diagnostics_summary(&summary, &config);
|
||||||
|
assert!(report.validation_passed);
|
||||||
|
assert_eq!(report.validation_profile_code, "0.7.33_pair_trading_readiness");
|
||||||
|
assert_eq!(report.blocking_issue_count, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn validation_rejects_0_7_33_pair_trading_readiness_mismatch() {
|
||||||
|
let mut summary = make_0_7_28_summary_with_meteora();
|
||||||
|
summary.pair_trading_readiness_summaries.retain(|readiness_summary| {
|
||||||
|
return readiness_summary.pair_trading_readiness != "non_trade_materialized";
|
||||||
|
});
|
||||||
|
let config = crate::LocalPipelineValidationConfig::v0_7_33_pair_trading_readiness();
|
||||||
|
let report = crate::validate_local_pipeline_diagnostics_summary(&summary, &config);
|
||||||
|
assert!(!report.validation_passed);
|
||||||
|
assert_eq!(report.issues[0].code, "pair_trading_readiness_pair_count_mismatch");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn validation_rejects_0_7_31_failed_transaction_trade_events() {
|
fn validation_rejects_0_7_31_failed_transaction_trade_events() {
|
||||||
let mut summary = make_0_7_28_summary_with_meteora();
|
let mut summary = make_0_7_28_summary_with_meteora();
|
||||||
|
|||||||
Reference in New Issue
Block a user