CC Trend Strategy 2 Downtrend Short
Short-only strategy that sells when the previous close is below a dynamic Fibonacci high and EMA21 is below EMA55. Exits when the price crosses above EMA200 with non-negative profit or when the previous close rises above the 0.236 Fibonacci level and no new short signal appears.
Details
- Entry Criteria:
- Short: previous close below Fibonacci high and EMA21 below EMA55
- Long/Short: Short
- Exit Criteria:
- Price crosses above EMA200 with profit
- Previous close above 0.236 Fibonacci level without new short signal
- Stops: None
- Default Values:
FibLength= 100CandleType= TimeSpan.FromMinutes(5).TimeFrame()
- Filters:
- Category: Trend
- Direction: Short
- Indicators: EMA, Fibonacci
- Stops: No
- Complexity: Basic
- Timeframe: Mid-term
- Seasonality: No
- Neural Networks: No
- Divergence: No
- Risk Level: Medium
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>
/// CC Trend Strategy 2 Downtrend Short.
/// Short only. The Fibonacci range spans the lowest low and the highest high of the last FibLength candles, and its 0.236 level lies
/// 23.6% of the range below the high. A short opens when the previous close is below the Fibonacci high and EMA21 is below EMA55.
/// It closes when the close crosses above EMA200 while the trade is not losing, or when the previous close is above the 0.236 level
/// and there is no new short signal.
/// </summary>
public class CCTrend2DowntrendShortStrategy : Strategy
{
private const int _fastEmaLength = 21;
private const int _slowEmaLength = 55;
private const int _trendEmaLength = 200;
private const decimal _fibLevel = 0.236m;
private readonly StrategyParam<int> _fibLength;
private readonly StrategyParam<DataType> _candleType;
private decimal? _prevClose;
private decimal? _prevTrendEma;
private decimal _entryPrice;
/// <summary>
/// Candles of the Fibonacci range.
/// </summary>
public int FibLength
{
get => _fibLength.Value;
set => _fibLength.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public CCTrend2DowntrendShortStrategy()
{
_fibLength = Param(nameof(FibLength), 100)
.SetGreaterThanZero()
.SetDisplay("Fib Length", "Candles of the Fibonacci range", "Fibonacci");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevClose = null;
_prevTrendEma = null;
_entryPrice = 0m;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevClose = null;
_prevTrendEma = null;
_entryPrice = 0m;
var fastEma = new ExponentialMovingAverage { Length = _fastEmaLength };
var slowEma = new ExponentialMovingAverage { Length = _slowEmaLength };
var trendEma = new ExponentialMovingAverage { Length = _trendEmaLength };
var highest = new Highest { Length = FibLength };
var lowest = new Lowest { Length = FibLength };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(fastEma, slowEma, trendEma, highest, lowest, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fastEma);
DrawIndicator(area, slowEma);
DrawIndicator(area, trendEma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue fastValue, IIndicatorValue slowValue, IIndicatorValue trendValue, IIndicatorValue highestValue, IIndicatorValue lowestValue)
{
if (candle.State != CandleStates.Finished)
return;
var close = candle.ClosePrice;
var prevClose = _prevClose;
var prevTrendEma = _prevTrendEma;
_prevClose = close;
if (!trendValue.IsFormed)
return;
var trendEma = trendValue.GetValue<decimal>();
_prevTrendEma = trendEma;
if (!fastValue.IsFormed || !slowValue.IsFormed || !highestValue.IsFormed || !lowestValue.IsFormed)
return;
if (prevClose is not decimal pc || prevTrendEma is not decimal pt)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var fibHigh = highestValue.GetValue<decimal>();
var fibLow = lowestValue.GetValue<decimal>();
var fib236 = fibHigh - (fibHigh - fibLow) * _fibLevel;
var shortSignal = pc < fibHigh && fastValue.GetValue<decimal>() < slowValue.GetValue<decimal>();
if (Position < 0)
{
var crossAboveTrend = pc <= pt && close > trendEma;
if ((crossAboveTrend && close <= _entryPrice) || (pc > fib236 && !shortSignal))
BuyMarket(-Position);
return;
}
if (Position == 0 && shortSignal)
{
SellMarket(Volume);
_entryPrice = close;
}
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Decimal
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ExponentialMovingAverage, Highest, Lowest
from StockSharp.Algo.Strategies import Strategy
FAST_EMA_LENGTH = 21
SLOW_EMA_LENGTH = 55
TREND_EMA_LENGTH = 200
FIB_LEVEL = 0.236
class cc_trend_2_downtrend_short_strategy(Strategy):
"""
CC Trend Strategy 2 Downtrend Short.
Short only. The Fibonacci range spans the lowest low and the highest high of the last FibLength candles, and its 0.236 level lies
23.6% of the range below the high. A short opens when the previous close is below the Fibonacci high and EMA21 is below EMA55.
It closes when the close crosses above EMA200 while the trade is not losing, or when the previous close is above the 0.236 level
and there is no new short signal.
"""
def __init__(self):
super(cc_trend_2_downtrend_short_strategy, self).__init__()
self._fib_length = self.Param("FibLength", 100).SetGreaterThanZero().SetDisplay("Fib Length", "Candles of the Fibonacci range", "Fibonacci")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._reset_state()
@property
def candle_type(self):
return self._candle_type.Value
def _reset_state(self):
self._prev_close = None
self._prev_trend_ema = None
self._entry_price = Decimal(0)
def OnReseted(self):
super(cc_trend_2_downtrend_short_strategy, self).OnReseted()
self._reset_state()
def OnStarted2(self, time):
super(cc_trend_2_downtrend_short_strategy, self).OnStarted2(time)
self._reset_state()
fast_ema = ExponentialMovingAverage()
fast_ema.Length = FAST_EMA_LENGTH
slow_ema = ExponentialMovingAverage()
slow_ema.Length = SLOW_EMA_LENGTH
trend_ema = ExponentialMovingAverage()
trend_ema.Length = TREND_EMA_LENGTH
highest = Highest()
highest.Length = self._fib_length.Value
lowest = Lowest()
lowest.Length = self._fib_length.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(fast_ema, slow_ema, trend_ema, highest, lowest, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast_ema)
self.DrawIndicator(area, slow_ema)
self.DrawIndicator(area, trend_ema)
self.DrawOwnTrades(area)
def _process_candle(self, candle, fast_value, slow_value, trend_value, highest_value, lowest_value):
if candle.State != CandleStates.Finished:
return
close = candle.ClosePrice
pc = self._prev_close
pt = self._prev_trend_ema
self._prev_close = close
if not trend_value.IsFormed:
return
trend_ema = trend_value.GetValue[Decimal](None)
self._prev_trend_ema = trend_ema
if not fast_value.IsFormed or not slow_value.IsFormed or not highest_value.IsFormed or not lowest_value.IsFormed:
return
if pc is None or pt is None:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
fib_high = highest_value.GetValue[Decimal](None)
fib_low = lowest_value.GetValue[Decimal](None)
fib236 = fib_high - (fib_high - fib_low) * Decimal(FIB_LEVEL)
short_signal = pc < fib_high and fast_value.GetValue[Decimal](None) < slow_value.GetValue[Decimal](None)
if self.Position < 0:
cross_above_trend = pc <= pt and close > trend_ema
if (cross_above_trend and close <= self._entry_price) or (pc > fib236 and not short_signal):
self.BuyMarket(-self.Position)
return
if self.Position == 0 and short_signal:
self.SellMarket(self.Volume)
self._entry_price = close
def CreateClone(self):
return cc_trend_2_downtrend_short_strategy()