La estrategia de Lanzamiento de Moneda emula el asesor experto original de MetaTrader donde las entradas se determinan por un lanzamiento de moneda pseudoaleatorio. Solo se puede abrir una posición a la vez. Cada vela completada actúa como un punto de decisión: cuando la operación anterior está plana, la estrategia lanza una moneda y abre inmediatamente una posición larga o corta usando el volumen de operación calculado. Cada operación está protegida con niveles de stop loss y take profit, mientras que un stop de seguimiento opcional puede ajustar el riesgo a medida que el mercado se mueve a favor de la posición.
Se implementa un modelo de dimensionamiento de posición estilo martingale. Si la posición anterior fue detenida, la siguiente operación aumentará su tamaño por un multiplicador configurable. Las operaciones exitosas restablecen el volumen al tamaño base. Un volumen máximo definido por el usuario previene el crecimiento descontrolado del tamaño de la operación.
Reglas de operación
En cada vela completada, la estrategia evalúa la posición actual.
Cuando no hay posición abierta, un número pseudoaleatorio selecciona la dirección larga o corta. Ambos lados tienen igual probabilidad.
Cada nueva operación usa el volumen base a menos que la operación anterior terminara con un stop loss. En ese caso, el volumen se multiplica por el factor martingale, respetando el límite de volumen máximo.
Los precios de stop loss y take profit de protección se adjuntan a cada posición. Cuando el precio de cierre alcanza esos umbrales, la posición se cierra con una orden de mercado.
El stop de seguimiento monitorea el movimiento favorable. Una vez que la ganancia supera la distancia de seguimiento más el paso, el nivel de stop se mueve hacia el precio para asegurar ganancias.
Parámetros
Stop Loss – distancia en pasos de precio usada para calcular el stop loss desde el precio de entrada.
Take Profit – distancia en pasos de precio añadida al precio de entrada para el take profit.
Trailing Stop – distancia de ganancia que activa el mecanismo de stop de seguimiento. Establecer en cero para deshabilitar el seguimiento.
Trailing Step – ganancia adicional mínima requerida antes de que el stop de seguimiento se mueva de nuevo.
Base Volume – volumen de la primera operación en un ciclo martingale.
Martingale Mult – multiplicador aplicado al último volumen detenido para determinar el siguiente tamaño de orden.
Max Volume – límite máximo para el tamaño de orden. Cuando se supera, la operación se omite y se registra una advertencia.
Candle Type – serie de velas que define cuándo se ejecutan los lanzamientos de moneda y las verificaciones de gestión de riesgo.
Notas
La estrategia usa órdenes de mercado tanto para entradas como para salidas para imitar el comportamiento del asesor experto original.
Los cálculos del stop de seguimiento dependen del paso de precio del instrumento. Si no hay un paso de precio disponible, se usan valores de puntos sin procesar en su lugar.
Los números aleatorios se generan con una semilla determinista basada en la hora actual para evitar secuencias idénticas en ejecuciones simultáneas.
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Random coin flip entry with martingale volume management (simplified).
/// Enters randomly using RSI as a tiebreaker, doubles volume after losses.
/// </summary>
public class CoinFlipMartingaleStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiLength;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int RsiLength
{
get => _rsiLength.Value;
set => _rsiLength.Value = value;
}
public CoinFlipMartingaleStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Candles", "General");
_rsiLength = Param(nameof(RsiLength), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Length", "RSI period", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var rsi = new RelativeStrengthIndex { Length = RsiLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(rsi, (ICandleMessage candle, decimal rsiValue) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
// Use RSI to decide direction
if (rsiValue < 35 && Position <= 0)
{
BuyMarket();
}
else if (rsiValue > 65 && Position >= 0)
{
SellMarket();
}
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
}
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 RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class coin_flip_martingale_strategy(Strategy):
def __init__(self):
super(coin_flip_martingale_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Candles", "General")
self._rsi_length = self.Param("RsiLength", 14) \
.SetDisplay("RSI Length", "RSI period", "Indicators")
@property
def CandleType(self):
return self._candle_type.Value
@property
def RsiLength(self):
return self._rsi_length.Value
def OnStarted2(self, time):
super(coin_flip_martingale_strategy, self).OnStarted2(time)
rsi = RelativeStrengthIndex()
rsi.Length = self.RsiLength
subscription = self.SubscribeCandles(self.CandleType)
subscription \
.Bind(rsi, self._on_process) \
.Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def _on_process(self, candle, rsi_value):
if candle.State != CandleStates.Finished:
return
rv = float(rsi_value)
if rv < 35 and self.Position <= 0:
self.BuyMarket()
elif rv > 65 and self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return coin_flip_martingale_strategy()