空头孕线策略
空头孕线是多头孕线的反向形态,出现在上涨后。 一根较小的蜡烛完全包在前一根上涨蜡烛内,说明上行动能正在衰退。 当这根内部蜡烛收盘后策略做空,押注多头力量减弱后的回落。 在形态高点上方设置百分比止损,若价格突破新高则退出。
测试表明年均收益约为 43%,该策略在股票市场表现最佳。
细节
- 入场条件:形态匹配
- 多/空:均可
- 退出条件:止损或反向信号
- 止损:是,按百分比
- 默认值:
CandleType= 15分钟StopLoss= 2%
- 过滤器:
- 类别:形态
- 方向:双向
- 指标:蜡烛图
- 止损:有
- 复杂度:中等
- 时间框架:日内
- 季节性:否
- 神经网络:否
- 背离:否
- 风险等级:中等
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>
/// Harami Bearish strategy.
/// Enters short on bearish harami (bullish candle followed by smaller bearish candle inside it).
/// Enters long on bullish harami (bearish candle followed by smaller bullish candle inside it).
/// Uses SMA for exit confirmation.
/// Uses cooldown to control trade frequency.
/// </summary>
public class HaramiBearishStrategy : Strategy
{
private readonly StrategyParam<int> _maLength;
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _cooldownBars;
private ICandleMessage _prevCandle;
private int _cooldown;
/// <summary>
/// MA period for exit.
/// </summary>
public int MaLength
{
get => _maLength.Value;
set => _maLength.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Cooldown bars.
/// </summary>
public int CooldownBars
{
get => _cooldownBars.Value;
set => _cooldownBars.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public HaramiBearishStrategy()
{
_maLength = Param(nameof(MaLength), 20)
.SetRange(10, 50)
.SetDisplay("MA Length", "Period of SMA for exit", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
_cooldownBars = Param(nameof(CooldownBars), 500)
.SetRange(1, 1000)
.SetDisplay("Cooldown Bars", "Bars to wait between trades", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevCandle = null;
_cooldown = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevCandle = null;
_cooldown = 0;
var sma = new SimpleMovingAverage { Length = MaLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(sma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, sma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal smaValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (_prevCandle == null)
{
_prevCandle = candle;
return;
}
if (_cooldown > 0)
{
_cooldown--;
_prevCandle = candle;
return;
}
// Bearish Harami: prev bullish, current bearish, current inside prev
var bearishHarami =
_prevCandle.ClosePrice > _prevCandle.OpenPrice &&
candle.ClosePrice < candle.OpenPrice &&
candle.HighPrice < _prevCandle.HighPrice &&
candle.LowPrice > _prevCandle.LowPrice;
// Bullish Harami: prev bearish, current bullish, current inside prev
var bullishHarami =
_prevCandle.ClosePrice < _prevCandle.OpenPrice &&
candle.ClosePrice > candle.OpenPrice &&
candle.HighPrice < _prevCandle.HighPrice &&
candle.LowPrice > _prevCandle.LowPrice;
if (Position == 0 && bearishHarami)
{
SellMarket();
_cooldown = CooldownBars;
}
else if (Position == 0 && bullishHarami)
{
BuyMarket();
_cooldown = CooldownBars;
}
else if (Position < 0 && candle.ClosePrice > smaValue)
{
BuyMarket();
_cooldown = CooldownBars;
}
else if (Position > 0 && candle.ClosePrice < smaValue)
{
SellMarket();
_cooldown = CooldownBars;
}
_prevCandle = candle;
}
}
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 SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class harami_bearish_strategy(Strategy):
"""
Harami Bearish strategy.
Enters short on bearish harami (bullish candle followed by smaller bearish candle inside it).
Enters long on bullish harami (bearish candle followed by smaller bullish candle inside it).
Uses SMA for exit confirmation.
"""
def __init__(self):
super(harami_bearish_strategy, self).__init__()
self._ma_length = self.Param("MaLength", 20).SetDisplay("MA Length", "Period of SMA for exit", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(1))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._cooldown_bars = self.Param("CooldownBars", 500).SetDisplay("Cooldown Bars", "Bars to wait between trades", "General")
self._prev_candle = None
self._cooldown = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(harami_bearish_strategy, self).OnReseted()
self._prev_candle = None
self._cooldown = 0
def OnStarted2(self, time):
super(harami_bearish_strategy, self).OnStarted2(time)
self._prev_candle = None
self._cooldown = 0
sma = SimpleMovingAverage()
sma.Length = self._ma_length.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(sma, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, sma)
self.DrawOwnTrades(area)
def _process_candle(self, candle, sma_val):
if candle.State != CandleStates.Finished:
return
if self._prev_candle is None:
self._prev_candle = candle
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_candle = candle
return
cd = self._cooldown_bars.Value
sv = float(sma_val)
# Bearish Harami: prev bullish, current bearish, current inside prev
bearish_harami = (
self._prev_candle.ClosePrice > self._prev_candle.OpenPrice and
candle.ClosePrice < candle.OpenPrice and
candle.HighPrice < self._prev_candle.HighPrice and
candle.LowPrice > self._prev_candle.LowPrice
)
# Bullish Harami: prev bearish, current bullish, current inside prev
bullish_harami = (
self._prev_candle.ClosePrice < self._prev_candle.OpenPrice and
candle.ClosePrice > candle.OpenPrice and
candle.HighPrice < self._prev_candle.HighPrice and
candle.LowPrice > self._prev_candle.LowPrice
)
if self.Position == 0 and bearish_harami:
self.SellMarket()
self._cooldown = cd
elif self.Position == 0 and bullish_harami:
self.BuyMarket()
self._cooldown = cd
elif self.Position < 0 and float(candle.ClosePrice) > sv:
self.BuyMarket()
self._cooldown = cd
elif self.Position > 0 and float(candle.ClosePrice) < sv:
self.SellMarket()
self._cooldown = cd
self._prev_candle = candle
def CreateClone(self):
return harami_bearish_strategy()