3バー安値戦略
3バー安値戦略は、終値が直近 3 本のバーの最安値終値を下回ったときに買いを入れ、価格が直近 7 本のバーの最高値終値を上回って終値をつけたときに決済します。オプションの EMA フィルターを使うと、エントリー前に価格が長期平均を上回っていることを条件にできます。
詳細
- エントリー条件:
- 終値が直近 3 本のバーの最安値終値を下回っている。
- オプション: フィルター有効時に終値が EMA を上回っている。
- ロング/ショート: ロングのみ。
- エグジット条件:
- 終値が直近 7 本のバーの最高値終値を上回っている。
- ストップ: なし。
- デフォルト値:
MaPeriod= 200LowestLength= 3HighestLength= 7UseEmaFilter= false
- フィルター:
- カテゴリ: ブレイクアウト
- 方向: Long
- インジケーター: EMA, Highest/Lowest
- ストップ: いいえ
- 複雑さ: 低
- 時間軸: 任意
- 季節性: いいえ
- ニューラルネットワーク: いいえ
- ダイバージェンス: いいえ
- リスクレベル: 低
namespace StockSharp.Samples.Strategies;
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
/// <summary>
/// Three Bar Low Strategy.
/// A long opens when the close falls below the lowest close of the previous LowestLength candles and, with UseEmaFilter,
/// the close is above the MaPeriod EMA. The long closes when the close rises above the highest close of the previous
/// HighestLength candles.
/// </summary>
public class ThreeBarLowStrategy : Strategy
{
private readonly StrategyParam<int> _maPeriod;
private readonly StrategyParam<int> _lowestLength;
private readonly StrategyParam<int> _highestLength;
private readonly StrategyParam<bool> _useEmaFilter;
private readonly StrategyParam<DataType> _candleType;
private Lowest _lowestClose;
private Highest _highestClose;
private decimal? _prevLowest;
private decimal? _prevHighest;
/// <summary>
/// EMA period of the filter.
/// </summary>
public int MaPeriod
{
get => _maPeriod.Value;
set => _maPeriod.Value = value;
}
/// <summary>
/// Previous candles of the lowest close.
/// </summary>
public int LowestLength
{
get => _lowestLength.Value;
set => _lowestLength.Value = value;
}
/// <summary>
/// Previous candles of the highest close.
/// </summary>
public int HighestLength
{
get => _highestLength.Value;
set => _highestLength.Value = value;
}
/// <summary>
/// Require the close above the EMA for entries.
/// </summary>
public bool UseEmaFilter
{
get => _useEmaFilter.Value;
set => _useEmaFilter.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public ThreeBarLowStrategy()
{
_maPeriod = Param(nameof(MaPeriod), 200)
.SetGreaterThanZero()
.SetDisplay("MA Period", "EMA period of the filter", "Indicators");
_lowestLength = Param(nameof(LowestLength), 3)
.SetGreaterThanZero()
.SetDisplay("Lowest Length", "Previous candles of the lowest close", "Indicators");
_highestLength = Param(nameof(HighestLength), 7)
.SetGreaterThanZero()
.SetDisplay("Highest Length", "Previous candles of the highest close", "Indicators");
_useEmaFilter = Param(nameof(UseEmaFilter), false)
.SetDisplay("Use EMA Filter", "Require the close above the EMA for entries", "Filters");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevLowest = null;
_prevHighest = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevLowest = null;
_prevHighest = null;
var ema = new ExponentialMovingAverage { Length = MaPeriod };
_lowestClose = new Lowest { Length = LowestLength };
_highestClose = new Highest { Length = HighestLength };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(ema, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ema);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue emaValue)
{
if (candle.State != CandleStates.Finished)
return;
var close = candle.ClosePrice;
// Both levels are measured on the candles before this one.
var lowest = _prevLowest;
var highest = _prevHighest;
var currentLowest = _lowestClose.Process(close, candle.OpenTime, true).ToDecimal();
var currentHighest = _highestClose.Process(close, candle.OpenTime, true).ToDecimal();
if (_lowestClose.IsFormed)
_prevLowest = currentLowest;
if (_highestClose.IsFormed)
_prevHighest = currentHighest;
if (lowest is not decimal lowLevel || highest is not decimal highLevel)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (Position > 0)
{
if (close > highLevel)
SellMarket(Position);
return;
}
var emaOk = !UseEmaFilter || (emaValue.IsFormed && close > emaValue.GetValue<decimal>());
if (Position == 0 && close < lowLevel && emaOk)
BuyMarket(Volume);
}
}
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
from indicator_extensions import *
class three_bar_low_strategy(Strategy):
"""
Three Bar Low Strategy.
A long opens when the close falls below the lowest close of the previous LowestLength candles and, with UseEmaFilter,
the close is above the MaPeriod EMA. The long closes when the close rises above the highest close of the previous
HighestLength candles.
"""
def __init__(self):
super(three_bar_low_strategy, self).__init__()
self._ma_period = self.Param("MaPeriod", 200).SetGreaterThanZero().SetDisplay("MA Period", "EMA period of the filter", "Indicators")
self._lowest_length = self.Param("LowestLength", 3).SetGreaterThanZero().SetDisplay("Lowest Length", "Previous candles of the lowest close", "Indicators")
self._highest_length = self.Param("HighestLength", 7).SetGreaterThanZero().SetDisplay("Highest Length", "Previous candles of the highest close", "Indicators")
self._use_ema_filter = self.Param("UseEmaFilter", False).SetDisplay("Use EMA Filter", "Require the close above the EMA for entries", "Filters")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._lowest_close = None
self._highest_close = None
self._prev_lowest = None
self._prev_highest = None
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(three_bar_low_strategy, self).OnReseted()
self._prev_lowest = None
self._prev_highest = None
def OnStarted2(self, time):
super(three_bar_low_strategy, self).OnStarted2(time)
self._prev_lowest = None
self._prev_highest = None
ema = ExponentialMovingAverage()
ema.Length = self._ma_period.Value
self._lowest_close = Lowest()
self._lowest_close.Length = self._lowest_length.Value
self._highest_close = Highest()
self._highest_close.Length = self._highest_length.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(ema, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ema)
self.DrawOwnTrades(area)
def _process_candle(self, candle, ema_value):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
# Both levels are measured on the candles before this one.
lowest = self._prev_lowest
highest = self._prev_highest
current_lowest = float(process_float(self._lowest_close, candle.ClosePrice, candle.OpenTime, True).GetValue[Decimal](None))
current_highest = float(process_float(self._highest_close, candle.ClosePrice, candle.OpenTime, True).GetValue[Decimal](None))
if self._lowest_close.IsFormed:
self._prev_lowest = current_lowest
if self._highest_close.IsFormed:
self._prev_highest = current_highest
if lowest is None or highest is None:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
if self.Position > 0:
if close > highest:
self.SellMarket(self.Position)
return
ema_ok = not self._use_ema_filter.Value or (ema_value.IsFormed and close > float(ema_value.GetValue[Decimal](None)))
if self.Position == 0 and close < lowest and ema_ok:
self.BuyMarket(self.Volume)
def CreateClone(self):
return three_bar_low_strategy()