TugbaGold es un asesor experto en promedios basado en cuadrículas que se origina en MetaTrader 5. La estrategia convertida recrea su lógica de gestión de canasta y tamaño de posición de martingala utilizando API de alto nivel de StockSharp. El sistema coloca nuevas órdenes cada vez que la vela anterior cierra con impulso direccional y construye progresivamente una cuadrícula de posiciones espaciadas por una distancia configurable. Las salidas promedio se ejecutan bloqueando ganancias en las posiciones extremas o cerrando parcialmente la cesta según el modo seleccionado.
como funciona
La estrategia evalúa las velas completadas desde el parámetro CandleType. Las señales utilizan la vela anterior, que coincide con la lógica MT5 original.
Una vela alcista permite la colocación de una nueva orden de compra. Una vela bajista permite una nueva orden de venta.
Las órdenes se agregan solo si la distancia desde el mejor precio existente en esa dirección excede PointOrderStepPips.
El primer pedido utiliza StartVolume. Las entradas posteriores duplican el volumen de la posición más favorable respetando MaxVolume y los límites del corredor.
Una vez que existen al menos dos posiciones, la estrategia calcula los precios objetivo que incluyen el buffer MinimalProfitPips. El cálculo difiere según el modo de salida:
Promedio – promedio ponderado de las posiciones extremas más el colchón de ganancias.
Parcial: combinación de los peores y mejores tickets, donde el peor ticket usa StartVolume y el mejor usa su tamaño real.
Cuando se alcanzan los objetivos, la estrategia cierra las órdenes correspondientes:
Modo promedio: cierra ambas entradas extremas por completo.
Modo parcial: cierra completamente la peor entrada y reduce la mejor entrada en StartVolume.
Las posiciones independientes individuales utilizan TakeProfitPips para salir una vez que el precio alcanza la distancia configurada.
Parámetros
Parámetro
Descripción
TakeProfitPips
Distancia de toma de ganancias que se aplica cuando solo hay una posición abierta. Establezca en 0 para desactivar.
StartVolume
Volumen inicial para el primer pedido en una secuencia de cuadrícula.
MaxVolume
Volumen máximo de pedido. 0 mantiene la secuencia de duplicación ilimitada.
CloseMode
Modo de salida: Average (cierre ambos extremos) o Partial (cierre parcial + total).
PointOrderStepPips
Distancia mínima en pips antes de que se pueda agregar una nueva orden promedio.
MinimalProfitPips
Se agregó un colchón de ganancias adicional a los objetivos promedio.
CandleType
Serie de velas utilizadas para la evaluación de señales.
Gestión de posiciones
Los incrementos de precios se derivan de Security.PriceStep. Si no está disponible, se utiliza un valor predeterminado de 0.0001.
Los volúmenes se normalizan automáticamente según las restricciones mínimas, máximas y de pasos del corredor.
La estrategia rastrea las posiciones ocupadas internamente y emite órdenes de mercado (BuyMarket / SellMarket) al cerrar partes de la cesta.
La protección se habilita automáticamente a través de StartProtection() una vez que comienza la estrategia.
Notas y limitaciones
La implementación supone ejecución inmediata de órdenes de mercado, similar al entorno MT5.
Las señales promedio se basan en las mejores cotizaciones actuales de oferta y demanda; Asegúrese de que los datos de Nivel 1 estén disponibles para una ejecución precisa.
Debido a que las salidas están impulsadas por la lógica estratégica, los niveles de stop-loss del experto original no se recrean.
Utilice una gestión de riesgos cautelosa: el tamaño de la martingala puede generar una gran exposición si las tendencias persisten.
Detalles de conversión
Las fórmulas promedio y los ajustes de la canasta reflejan el código fuente original.
La selección de posición (mejores/peores boletos) se reproduce mediante el seguimiento de los precios de apertura más altos y más bajos dentro de cada dirección.
Toda la lógica se ejecuta dentro de la suscripción de vela utilizando el nivel alto API de StockSharp sin recurrir al acceso a datos de bajo nivel.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// TugbaGold strategy: candle direction + EMA trend filter with martingale-style averaging.
/// Buys on bullish candle above EMA, sells on bearish candle below EMA.
/// </summary>
public class TugbaGoldStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _emaPeriod;
private bool _wasBullishSignal;
private bool _hasPrevSignal;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
public TugbaGoldStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_emaPeriod = Param(nameof(EmaPeriod), 50)
.SetGreaterThanZero()
.SetDisplay("EMA Period", "EMA trend filter period", "Indicators");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_wasBullishSignal = false;
_hasPrevSignal = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_wasBullishSignal = false;
_hasPrevSignal = false;
var ema = new ExponentialMovingAverage { Length = EmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(ema, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal emaValue)
{
if (candle.State != CandleStates.Finished) return;
var bullish = candle.ClosePrice > candle.OpenPrice;
var bearish = candle.ClosePrice < candle.OpenPrice;
var bullishSignal = bullish && candle.ClosePrice > emaValue;
var bearishSignal = bearish && candle.ClosePrice < emaValue;
var crossedUp = bullishSignal && (!_hasPrevSignal || !_wasBullishSignal);
var crossedDown = bearishSignal && (!_hasPrevSignal || _wasBullishSignal);
if (crossedUp && Position <= 0)
BuyMarket();
else if (crossedDown && Position >= 0)
SellMarket();
if (bullishSignal || bearishSignal)
{
_wasBullishSignal = bullishSignal;
_hasPrevSignal = true;
}
}
}
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 DataType, CandleStates
from StockSharp.Algo.Indicators import ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class tugba_gold_strategy(Strategy):
def __init__(self):
super(tugba_gold_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60)))
self._ema_period = self.Param("EmaPeriod", 50)
self._was_bullish_signal = False
self._has_prev_signal = False
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def EmaPeriod(self):
return self._ema_period.Value
@EmaPeriod.setter
def EmaPeriod(self, value):
self._ema_period.Value = value
def OnReseted(self):
super(tugba_gold_strategy, self).OnReseted()
self._was_bullish_signal = False
self._has_prev_signal = False
def OnStarted2(self, time):
super(tugba_gold_strategy, self).OnStarted2(time)
self._was_bullish_signal = False
self._has_prev_signal = False
ema = ExponentialMovingAverage()
ema.Length = self.EmaPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(ema, self._process_candle).Start()
def _process_candle(self, candle, ema_value):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
open_price = float(candle.OpenPrice)
ema_val = float(ema_value)
bullish = close > open_price
bearish = close < open_price
bullish_signal = bullish and close > ema_val
bearish_signal = bearish and close < ema_val
crossed_up = bullish_signal and (not self._has_prev_signal or not self._was_bullish_signal)
crossed_down = bearish_signal and (not self._has_prev_signal or self._was_bullish_signal)
if crossed_up and self.Position <= 0:
self.BuyMarket()
elif crossed_down and self.Position >= 0:
self.SellMarket()
if bullish_signal or bearish_signal:
self._was_bullish_signal = bullish_signal
self._has_prev_signal = True
def CreateClone(self):
return tugba_gold_strategy()