A estratégia de Lançamento de Moeda emula o consultor especialista original do MetaTrader onde as entradas são determinadas por um lançamento de moeda pseudoaleatório. Apenas uma posição pode ser aberta de cada vez. Cada vela concluída atua como um ponto de decisão: quando a operação anterior está plana, a estratégia lança uma moeda e abre imediatamente uma posição comprada ou vendida usando o volume de operação calculado. Cada operação é protegida com níveis de stop loss e take profit, enquanto um stop de seguimento opcional pode ajustar o risco à medida que o mercado se move a favor da posição.
Um modelo de dimensionamento de posição estilo Martingale é implementado. Se a posição anterior foi stoppada, a próxima operação aumentará seu tamanho por um multiplicador configurável. Operações bem-sucedidas redefinem o volume para o tamanho base. Um volume máximo definido pelo usuário previne o crescimento descontrolado do tamanho da operação.
Regras de operação
Em cada vela concluída, a estratégia avalia a posição atual.
Quando nenhuma posição está aberta, um número pseudoaleatório seleciona a direção comprada ou vendida. Ambos os lados têm igual probabilidade.
Cada nova operação usa o volume base, a menos que a operação anterior tenha terminado com um stop loss. Nesse caso, o volume é multiplicado pelo fator Martingale, respeitando o limite de volume máximo.
Preços de stop loss e take profit de proteção são anexados a cada posição. Quando o preço de fechamento atinge esses limites, a posição é encerrada com uma ordem a mercado.
O stop de seguimento monitora o movimento favorável. Uma vez que o lucro excede a distância de seguimento mais o passo, o nível de stop é movido em direção ao preço para assegurar ganhos.
Parâmetros
Stop Loss – distância em passos de preço usada para calcular o stop loss a partir do preço de entrada.
Take Profit – distância em passos de preço adicionada ao preço de entrada para o take profit.
Trailing Stop – distância de lucro que ativa o mecanismo de stop de seguimento. Definir como zero para desabilitar o seguimento.
Trailing Step – lucro adicional mínimo necessário antes que o stop de seguimento seja movido novamente.
Base Volume – volume da primeira operação em um ciclo Martingale.
Martingale Mult – multiplicador aplicado ao último volume stoppado para determinar o próximo tamanho de ordem.
Max Volume – limite máximo para o tamanho da ordem. Quando excedido, a operação é ignorada e um aviso é registrado.
Candle Type – série de velas que define quando os lançamentos de moeda e as verificações de gestão de risco são executados.
Notas
A estratégia usa ordens a mercado tanto para entradas quanto para saídas para imitar o comportamento do consultor especialista original.
Os cálculos do stop de seguimento dependem do passo de preço do instrumento. Se um passo de preço não estiver disponível, valores de pontos brutos são usados em seu lugar.
Os números aleatórios são gerados com uma semente determinista baseada na hora atual para evitar sequências idênticas em execuções 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()