La estrategia AMA Trader v2.1 es una conversión del asesor experto MetaTrader 4 AMA_TRADER_v2_1.mq4 que combina las ráfagas de media móvil adaptativa (AMA) de Kaufman con un filtro Heiken Ashi de doble suavizado y comprobaciones de impulso RSI.
Lógica principal
Filtro de tendencia adaptativo: un motor AMA personalizado reproduce el indicador original, incluidas las constantes rápidas/lentas, la relación de eficiencia y el parámetro de potencia. El algoritmo busca ráfagas de impulso en las que el valor de AMA salta más de AmaThreshold pasos de precio en comparación con la barra anterior.
Confirmación de Heiken Ashi: las velas de precios se suavizan dos veces: primero mediante un promedio móvil configurable en los precios brutos de OHLC, luego mediante un segundo promedio móvil en los buffers de Heiken Ashi. Una barra suavizada alcista (cerrada sobre abierta) permite operaciones largas, mientras que una barra bajista permite operaciones cortas.
RSI Comprobación de impulso: un RSI clásico con período configurable confirma el impulso: las posiciones largas requieren que el RSI retroceda desde un valor anterior mientras se mantiene por debajo de 70, las posiciones cortas requieren un rebote mientras el oscilador permanece por encima de 30.
Gestión de posiciones: la estrategia abre una única posición a la vez, aplica distancias opcionales de stop-loss y take-profit (en pasos de precio) y puede seguir el stop una vez que el precio se mueve en la dirección comercial. Cuando RSI cruza los extremos 70/30, se realiza un cierre parcial opcional antes de que se produzca una salida completa en el siguiente cruce.
Parámetros
Nombre
Predeterminado
Descripción
CandleType
velas de 15 minutos
Plazo para todos los cálculos.
TradeVolume
0.1
Volumen de orden de mercado base.
AmaLength
9
Lookback utilizado por la media móvil adaptativa.
AmaFastPeriod
2
Constante rápida en barras para el suavizado AMA.
AmaSlowPeriod
30
Constante lenta en barras para el suavizado de AMA.
AmaPower
2
Exponente aplicado a la constante de suavizado (coincide con G en el código MQ4).
AmaThreshold
2 pasos
Cambio mínimo de AMA (en pasos de precio) para activar una señal.
FirstMaMethod
alisado
Primer método de alisado para la construcción Heiken Ashi.
FirstMaPeriod
6
Longitud de la primera media móvil de suavizado.
SecondMaMethod
Lineal ponderado
Segundo método de suavizado aplicado a los buffers Heiken Ashi.
SecondMaPeriod
2
Longitud de la segunda media móvil de suavizado.
RsiPeriod
14
RSI período utilizado por el filtro de impulso.
PartialClosePercent
70%
Parte de la posición activa que se cerrará cuando RSI cruce un extremo. Establezca en 0 para desactivar.
StopLossSteps
50
Distancia de stop-loss expresada en pasos de precio del instrumento. Establezca en 0 para desactivar.
TakeProfitSteps
100
Distancia de obtención de beneficios expresada en incrementos de precio. Establezca en 0 para desactivar.
TrailingSteps
30
Distancia del trailing stop en pasos de precio. Establezca en 0 para deshabilitar el seguimiento.
Reglas de trading
Entrada larga: cuando el salto de AMA es positivo y supera AmaThreshold, la última vela Heiken Ashi suavizada es alcista y RSI retrocede (valor anterior mayor que el valor actual) mientras se mantiene en 70 o por debajo.
Entrada corta: cuando el salto de AMA es negativo más allá de AmaThreshold, la vela Heiken Ashi suavizada es bajista y RSI aumenta (el valor anterior es menor que el actual) mientras se mantiene en 30 o por encima.
Cierre parcial: si está habilitado, cierre PartialClosePercent de la posición cuando RSI cruce por encima de 70 (largos) o por debajo de 30 (cortos).
Salida completa: cierre toda la posición en el extremo opuesto RSI, en stop-loss, take-profit o cuando se alcance el trailing stop.
La implementación utiliza el StockSharp API de alto nivel: una suscripción de vela alimenta la calculadora AMA personalizada, el canal de suavizado Heiken Ashi y el indicador RSI. Todos los comentarios en el código fuente están en inglés, lo que refleja los requisitos de las pautas de conversión.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class AmaTraderV21Strategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevFast; private decimal _prevSlow; private bool _hasPrev;
private int _cooldown;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public AmaTraderV21Strategy()
{
_fastPeriod = Param(nameof(FastPeriod), 10).SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 30).SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(fast, slow, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished) return;
if (!_hasPrev) { _prevFast = fast; _prevSlow = slow; _hasPrev = true; return; }
if (_cooldown > 0) { _cooldown--; _prevFast = fast; _prevSlow = slow; return; }
if (_prevFast <= _prevSlow && fast > slow && Position <= 0)
{ if (Position < 0) BuyMarket(); BuyMarket(); _cooldown = 140; }
else if (_prevFast >= _prevSlow && fast < slow && Position >= 0)
{ if (Position > 0) SellMarket(); SellMarket(); _cooldown = 140; }
_prevFast = fast; _prevSlow = slow;
}
protected override void OnReseted()
{
base.OnReseted();
_prevFast = 0;
_prevSlow = 0;
_hasPrev = false;
_cooldown = 0;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import CandleStates
from StockSharp.Algo.Indicators import ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
from datatype_extensions import *
class ama_trader_v21_strategy(Strategy):
"""
AMA Trader V2.1: dual EMA crossover strategy.
"""
def __init__(self):
super(ama_trader_v21_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 10) \
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 30) \
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators")
self._candle_type = self.Param("CandleType", tf(5)) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
@property
def FastPeriod(self): return self._fast_period.Value
@FastPeriod.setter
def FastPeriod(self, v): self._fast_period.Value = v
@property
def SlowPeriod(self): return self._slow_period.Value
@SlowPeriod.setter
def SlowPeriod(self, v): self._slow_period.Value = v
@property
def CandleType(self): return self._candle_type.Value
@CandleType.setter
def CandleType(self, v): self._candle_type.Value = v
def OnReseted(self):
super(ama_trader_v21_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(ama_trader_v21_strategy, self).OnStarted2(time)
self._has_prev = False
fast = ExponentialMovingAverage()
fast.Length = self.FastPeriod
slow = ExponentialMovingAverage()
slow.Length = self.SlowPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast, slow, self.ProcessCandle).Start()
def ProcessCandle(self, candle, fast, slow):
if candle.State != CandleStates.Finished:
return
if not self._has_prev:
self._prev_fast = fast
self._prev_slow = slow
self._has_prev = True
return
if self._prev_fast <= self._prev_slow and fast > slow and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif self._prev_fast >= self._prev_slow and fast < slow and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_fast = fast
self._prev_slow = slow
def CreateClone(self):
"""!! REQUIRED!! Creates a new instance of the strategy."""
return ama_trader_v21_strategy()