Estrategia DoubleUp2 CCI MACD
DoubleUp2 es una estrategia estilo martingala que combina el Commodity Channel Index (CCI) y el MACD. Abre posiciones cortas cuando ambos indicadores muestran valores positivos extremos y posiciones largas cuando ambos son extremadamente negativos. Después de una operación perdedora, el tamaño de la posición se duplica buscando recuperar las pérdidas anteriores. Las operaciones rentables se cierran una vez que el precio avanza un número fijo de puntos.
Detalles
- Criterios de Entrada:
- Largo:
CCI < -ThresholdyMACD < -Threshold. - Corto:
CCI > ThresholdyMACD > Threshold.
- Largo:
- Largo/Corto: Ambos.
- Criterios de Salida:
- Señal opuesta o el precio se mueve
ExitDistancepuntos en ganancia.
- Señal opuesta o el precio se mueve
- Stops: Sin stop-loss explícito.
- Valores predeterminados:
CCI Period= 8MACD Fast= 13MACD Slow= 33MACD Signal= 2Threshold= 230Base Volume= 0.1ExitDistance=120 * price step
- Filtros:
- Categoría: Reversión a la media
- Dirección: Ambos
- Indicadores: CCI, MACD
- Stops: No
- Complejidad: Moderado
- Marco temporal: Corto plazo
- Estacionalidad: No
- Redes neuronales: No
- Divergencia: No
- Nivel de riesgo: Alto
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// DoubleUp2 strategy combining CCI and MACD with volume doubling (martingale).
/// </summary>
public class DoubleUp2Strategy : Strategy
{
private readonly StrategyParam<int> _cciPeriod;
private readonly StrategyParam<int> _macdFastPeriod;
private readonly StrategyParam<int> _macdSlowPeriod;
private readonly StrategyParam<decimal> _threshold;
private readonly StrategyParam<DataType> _candleType;
private decimal _entryPrice;
private int _martingaleStep;
/// <summary>
/// CCI period.
/// </summary>
public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }
/// <summary>
/// MACD fast EMA period.
/// </summary>
public int MacdFastPeriod { get => _macdFastPeriod.Value; set => _macdFastPeriod.Value = value; }
/// <summary>
/// MACD slow EMA period.
/// </summary>
public int MacdSlowPeriod { get => _macdSlowPeriod.Value; set => _macdSlowPeriod.Value = value; }
/// <summary>
/// Threshold for CCI and MACD signals.
/// </summary>
public decimal Threshold { get => _threshold.Value; set => _threshold.Value = value; }
/// <summary>
/// Candle type for calculations.
/// </summary>
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
/// <summary>
/// Constructor.
/// </summary>
public DoubleUp2Strategy()
{
_cciPeriod = Param(nameof(CciPeriod), 8)
.SetDisplay("CCI Period", "Averaging period for CCI", "Indicators")
.SetOptimize(4, 20, 1);
_macdFastPeriod = Param(nameof(MacdFastPeriod), 13)
.SetDisplay("MACD Fast", "Fast EMA period for MACD", "Indicators")
.SetOptimize(5, 20, 1);
_macdSlowPeriod = Param(nameof(MacdSlowPeriod), 33)
.SetDisplay("MACD Slow", "Slow EMA period for MACD", "Indicators")
.SetOptimize(20, 50, 1);
_threshold = Param(nameof(Threshold), 70m)
.SetDisplay("Threshold", "RSI extreme level", "Strategy")
.SetOptimize(55m, 85m, 5m);
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles used for calculations", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_entryPrice = 0m;
_martingaleStep = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var rsi = new RelativeStrengthIndex { Length = CciPeriod };
var macd = new MovingAverageConvergenceDivergence(
new ExponentialMovingAverage { Length = MacdSlowPeriod },
new ExponentialMovingAverage { Length = MacdFastPeriod });
var subscription = SubscribeCandles(CandleType);
subscription.Bind(rsi, macd, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, rsi);
DrawIndicator(area, macd);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal rsiValue, decimal macdValue)
{
if (candle.State != CandleStates.Finished)
return;
var step = Security?.PriceStep ?? 1m;
var lowThreshold = 100m - Threshold;
// Short entry condition
if (rsiValue > Threshold && macdValue > 0m)
{
if (Position > 0)
{
var profit = candle.ClosePrice - _entryPrice;
_martingaleStep = profit > 0m ? 0 : _martingaleStep + 1;
}
SellMarket();
_entryPrice = candle.ClosePrice;
return;
}
// Long entry condition
if (rsiValue < lowThreshold && macdValue < 0m)
{
if (Position < 0)
{
var profit = _entryPrice - candle.ClosePrice;
_martingaleStep = profit > 0m ? 0 : _martingaleStep + 1;
}
BuyMarket();
_entryPrice = candle.ClosePrice;
return;
}
// Exit profitable long position
if (Position > 0 && candle.ClosePrice - _entryPrice > 120m * step)
{
SellMarket();
_martingaleStep += 2;
return;
}
// Exit profitable short position
if (Position < 0 && _entryPrice - candle.ClosePrice > 120m * step)
{
BuyMarket();
_martingaleStep += 2;
}
}
}
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,
MovingAverageConvergenceDivergence,
ExponentialMovingAverage,
)
from StockSharp.Algo.Strategies import Strategy
class double_up2_strategy(Strategy):
def __init__(self):
super(double_up2_strategy, self).__init__()
self._cci_period = self.Param("CciPeriod", 8)
self._macd_fast_period = self.Param("MacdFastPeriod", 13)
self._macd_slow_period = self.Param("MacdSlowPeriod", 33)
self._threshold = self.Param("Threshold", 70.0)
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4)))
self._entry_price = 0.0
self._martingale_step = 0
@property
def CciPeriod(self):
return self._cci_period.Value
@CciPeriod.setter
def CciPeriod(self, value):
self._cci_period.Value = value
@property
def MacdFastPeriod(self):
return self._macd_fast_period.Value
@MacdFastPeriod.setter
def MacdFastPeriod(self, value):
self._macd_fast_period.Value = value
@property
def MacdSlowPeriod(self):
return self._macd_slow_period.Value
@MacdSlowPeriod.setter
def MacdSlowPeriod(self, value):
self._macd_slow_period.Value = value
@property
def Threshold(self):
return self._threshold.Value
@Threshold.setter
def Threshold(self, value):
self._threshold.Value = value
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
def OnStarted2(self, time):
super(double_up2_strategy, self).OnStarted2(time)
self._entry_price = 0.0
self._martingale_step = 0
rsi = RelativeStrengthIndex()
rsi.Length = self.CciPeriod
slow_ema = ExponentialMovingAverage()
slow_ema.Length = self.MacdSlowPeriod
fast_ema = ExponentialMovingAverage()
fast_ema.Length = self.MacdFastPeriod
macd = MovingAverageConvergenceDivergence(slow_ema, fast_ema)
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(rsi, macd, self.ProcessCandle).Start()
def ProcessCandle(self, candle, rsi_value, macd_value):
if candle.State != CandleStates.Finished:
return
rsi_val = float(rsi_value)
macd_val = float(macd_value)
close = float(candle.ClosePrice)
step = float(self.Security.PriceStep) if self.Security is not None and self.Security.PriceStep is not None else 1.0
threshold = float(self.Threshold)
low_threshold = 100.0 - threshold
if rsi_val > threshold and macd_val > 0.0:
if self.Position > 0:
profit = close - self._entry_price
if profit > 0.0:
self._martingale_step = 0
else:
self._martingale_step += 1
self.SellMarket()
self._entry_price = close
return
if rsi_val < low_threshold and macd_val < 0.0:
if self.Position < 0:
profit = self._entry_price - close
if profit > 0.0:
self._martingale_step = 0
else:
self._martingale_step += 1
self.BuyMarket()
self._entry_price = close
return
if self.Position > 0 and close - self._entry_price > 120.0 * step:
self.SellMarket()
self._martingale_step += 2
return
if self.Position < 0 and self._entry_price - close > 120.0 * step:
self.BuyMarket()
self._martingale_step += 2
def OnReseted(self):
super(double_up2_strategy, self).OnReseted()
self._entry_price = 0.0
self._martingale_step = 0
def CreateClone(self):
return double_up2_strategy()