Aller au contenu

Modèles alpha

Un modèle alpha transforme l’état de marché en insights candidats. Ce n’est pas l’endroit où gérer tout le cycle de vie des ordres. Son rôle est de décider quand une opportunité existe et de retourner un Insight.

AQE appelle les modèles alpha via un cycle de vie dédié :

  • start()
  • init(asset)
  • generate_insights(symbol)
aq-engine/src/core/alpha/mod.rs
pub trait AlphaModel {
fn version(&self) -> &str;
fn start(&mut self, ctx: &mut dyn StrategyContext);
fn init(&mut self, ctx: &mut dyn StrategyContext, asset: &Asset);
fn generate_insights(&mut self, ctx: &mut dyn StrategyContext, symbol: &str) -> AlphaResult;
}

Utilisez start() pour la configuration globale du runtime :

  • enregistrer les indicateurs
  • définir les barres de warm-up
  • configurer l’état nécessaire avant toute initialisation propre à un symbole

Utilisez init() pour la configuration par actif :

  • initialiser les variables propres au symbole
  • lire les métadonnées de l’actif
  • préparer l’état runtime par symbole

Utilisez generate_insights() pour :

  • lire le dernier historique
  • inspecter des indicateurs ou variables
  • vérifier les métadonnées de l’actif
  • créer et retourner un nouvel Insight

EmaPriceCrossover est un alpha concret dans AQE. Il :

  • enregistre ATR et EMA
  • lit l’historique
  • vérifie les barres récente et précédente
  • utilise les métadonnées de l’actif pour décider si les signaux short sont autorisés
  • retourne un insight avec paramètres d’entrée, TP, SL et TTL
aq-engine/src/core/alpha/ema_price_crossover.rs
fn generate_insights(&mut self, ctx: &mut dyn StrategyContext, symbol: &str) -> AlphaResult {
let Some(asset) = self.get_asset(ctx, symbol) else {
return AlphaResult::new(None, false, Some(format!("Asset {} not found", symbol)), self.name().to_string());
};
let history = match self.get_history(ctx, symbol) {
Some(history) if history.height() >= 2 => history,
_ => return AlphaResult::new(None, true, Some("Not enough history".to_string()), self.name().to_string()),
};
// derive signal, tp, sl, entry ...
let mut insight = Insight::new(
side,
symbol.to_string(),
StrategyType::Custom(self.name().to_string()),
ctx.timeframe().clone(),
confidence,
None,
);
insight
.set_limit_price(Some(entry))
.set_take_profit_levels(Some(vec![tp]))
.set_stop_loss(Some(sl))
.set_period_unfilled(Some(ttluf as u32))
.set_period_till_tp(Some(ttlf as u32));
AlphaResult::new(Some(insight), true, None, self.name().to_string())
}

TestEntry montre une forme d’alpha plus simple :

  • lit l’état récent des prix
  • compte les insights actifs par symbole
  • émet un nouvel insight buy ou sell quand les conditions sont remplies

C’est une référence utile pour le code utilisateur quand vous voulez un point de départ léger.

Les modèles alpha ne doivent pas devenir des gestionnaires complets du runtime. Dans la plupart des cas, évitez de placer ces responsabilités dans l’alpha :

  • sizing final de quantité
  • soumission de trade
  • logique de clôture
  • vérifications de déclenchement stop-loss
  • filtrage de fenêtres horaires

Ces responsabilités conviennent mieux aux pipelines d’insights.

  • aq-engine/src/core/alpha/mod.rs
  • aq-engine/src/core/alpha/ema_price_crossover.rs
  • aq-engine/src/core/alpha/test_entry.rs