Ir al contenido

Modelos alfa

Un modelo alfa se encarga de convertir el estado del mercado en posibles insights. No debe gestionar todo el ciclo de vida de las órdenes. Su función es decidir cuándo existe una oportunidad y devolver un Insight.

AQE llama a los modelos alfa mediante un ciclo de vida específico:

  • 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;
}

Usa start() para la configuración de todo el entorno de ejecución:

  • registrar indicadores
  • establecer las velas de calentamiento
  • configurar el estado necesario antes de cualquier inicialización específica por símbolo

Usa init() para la configuración por activo:

  • inicializar variables específicas por símbolo
  • leer los metadatos del activo
  • preparar el estado de ejecución por símbolo

Usa generate_insights() para:

  • leer el historial más reciente
  • inspeccionar indicadores o variables
  • comprobar los metadatos del activo
  • crear y devolver un nuevo Insight

EmaPriceCrossover es un modelo alfa concreto de AQE. Este modelo:

  • registra ATR y EMA
  • lee el historial
  • comprueba la vela más reciente y la anterior
  • usa los metadatos del activo para decidir si se permiten señales de venta en corto
  • devuelve un insight con ajustes de entrada, TP, SL y 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 muestra una estructura alfa más sencilla:

  • lee el estado reciente del precio
  • cuenta los insights activos por símbolo
  • emite un nuevo insight de compra o venta cuando se cumplen las condiciones

Por eso resulta una referencia útil para tu propio código cuando buscas un punto de partida sencillo.

Los modelos alfa no deben convertirse en gestores completos del entorno de ejecución. En la mayoría de los casos, evita incluir estas responsabilidades dentro del modelo alfa:

  • dimensionamiento final de la cantidad
  • envío de operaciones
  • lógica de cierre
  • comprobaciones de activación del stop-loss
  • filtrado por ventana temporal

Estas funciones encajan mejor en los pipes de 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