AutoFib ブレイクアウト戦略
この戦略は、直近のスイング高値と安値から動的なフィボナッチ拡張を描き、200 EMAで定義された上昇トレンド中に価格が1.618レベルを上抜けたときにロングエントリーします。リスクはATRベースのストップとターゲットで管理されます。
詳細
- エントリー条件: フィボナッチ拡張1.618を上回るクローズかつEMA200を上回ること。
- ロング/ショート: ロングのみ。
- エグジット条件: ATRベースのストップロスまたは3×ATRのテイクプロフィット。
- ストップ: はい、ATRに基づく。
- デフォルト値:
EmaLength= 200AtrLength= 14FibLevel= 1.618PivotPeriod= 10CandleType= 5分
- フィルター:
- カテゴリ: ブレイクアウト
- 方向: ロング
- インジケーター: EMA, ATR, Highest, Lowest
- ストップ: はい
- 複雑さ: 基本
- 時間軸: イントラデイ
- 季節性: いいえ
- ニューラルネットワーク: いいえ
- ダイバージェンス: いいえ
- リスクレベル: 中
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>
/// AutoFib breakout strategy.
/// The swing low and high of the previous PivotPeriod candles span a Fibonacci extension at low + (high - low) * FibLevel. A
/// close above that level while the close is above the EMA opens a long. Each entry fixes a 1.5 ATR stop-loss and a 3 ATR
/// take-profit from the entry close. Long only.
/// </summary>
public class AutoFibBreakoutStrategy : Strategy
{
private const decimal _stopAtrMultiple = 1.5m;
private const decimal _takeAtrMultiple = 3m;
private readonly StrategyParam<int> _emaLength;
private readonly StrategyParam<int> _atrLength;
private readonly StrategyParam<decimal> _fibLevel;
private readonly StrategyParam<int> _pivotPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal? _prevHigh;
private decimal? _prevLow;
private decimal _stopPrice;
private decimal _takePrice;
/// <summary>
/// Trend EMA period.
/// </summary>
public int EmaLength
{
get => _emaLength.Value;
set => _emaLength.Value = value;
}
/// <summary>
/// ATR period of the stop-loss and take-profit.
/// </summary>
public int AtrLength
{
get => _atrLength.Value;
set => _atrLength.Value = value;
}
/// <summary>
/// Fibonacci extension level of the breakout.
/// </summary>
public decimal FibLevel
{
get => _fibLevel.Value;
set => _fibLevel.Value = value;
}
/// <summary>
/// Candles that define the swing high and low.
/// </summary>
public int PivotPeriod
{
get => _pivotPeriod.Value;
set => _pivotPeriod.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public AutoFibBreakoutStrategy()
{
_emaLength = Param(nameof(EmaLength), 200)
.SetGreaterThanZero()
.SetDisplay("EMA Length", "Trend EMA period", "Trend");
_atrLength = Param(nameof(AtrLength), 14)
.SetGreaterThanZero()
.SetDisplay("ATR Length", "ATR period of the stop-loss and take-profit", "Risk");
_fibLevel = Param(nameof(FibLevel), 1.618m)
.SetGreaterThanZero()
.SetDisplay("Fib Level", "Fibonacci extension level of the breakout", "Fibonacci");
_pivotPeriod = Param(nameof(PivotPeriod), 10)
.SetGreaterThanZero()
.SetDisplay("Pivot Period", "Candles that define the swing high and low", "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();
ResetState();
}
private void ResetState()
{
_prevHigh = null;
_prevLow = null;
_stopPrice = 0m;
_takePrice = 0m;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
ResetState();
var ema = new ExponentialMovingAverage { Length = EmaLength };
var atr = new AverageTrueRange { Length = AtrLength };
var highest = new Highest { Length = PivotPeriod };
var lowest = new Lowest { Length = PivotPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ema, atr, highest, lowest, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ema);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal ema, decimal atr, decimal highest, decimal lowest)
{
if (candle.State != CandleStates.Finished)
return;
// The swing range comes from the candles before this one.
var prevHigh = _prevHigh;
var prevLow = _prevLow;
_prevHigh = highest;
_prevLow = lowest;
if (prevHigh is not decimal swingHigh || prevLow is not decimal swingLow)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var close = candle.ClosePrice;
if (Position > 0)
{
if (candle.LowPrice <= _stopPrice || candle.HighPrice >= _takePrice)
SellMarket(Position);
return;
}
var extension = swingLow + (swingHigh - swingLow) * FibLevel;
if (Position == 0 && close > extension && close > ema)
{
BuyMarket(Volume);
_stopPrice = close - _stopAtrMultiple * atr;
_takePrice = close + _takeAtrMultiple * atr;
}
}
}
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 ExponentialMovingAverage, AverageTrueRange, Highest, Lowest
from StockSharp.Algo.Strategies import Strategy
STOP_ATR_MULTIPLE = 1.5
TAKE_ATR_MULTIPLE = 3.0
class auto_fib_breakout_strategy(Strategy):
"""
AutoFib breakout strategy.
The swing low and high of the previous PivotPeriod candles span a Fibonacci extension at low + (high - low) * FibLevel. A
close above that level while the close is above the EMA opens a long. Each entry fixes a 1.5 ATR stop-loss and a 3 ATR
take-profit from the entry close. Long only.
"""
def __init__(self):
super(auto_fib_breakout_strategy, self).__init__()
self._ema_length = self.Param("EmaLength", 200) \
.SetGreaterThanZero() \
.SetDisplay("EMA Length", "Trend EMA period", "Trend")
self._atr_length = self.Param("AtrLength", 14) \
.SetGreaterThanZero() \
.SetDisplay("ATR Length", "ATR period of the stop-loss and take-profit", "Risk")
self._fib_level = self.Param("FibLevel", 1.618) \
.SetGreaterThanZero() \
.SetDisplay("Fib Level", "Fibonacci extension level of the breakout", "Fibonacci")
self._pivot_period = self.Param("PivotPeriod", 10) \
.SetGreaterThanZero() \
.SetDisplay("Pivot Period", "Candles that define the swing high and low", "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 CandleType(self):
return self._candle_type.Value
def GetWorkingSecurities(self):
return [(self.Security, self.CandleType)]
def _reset_state(self):
self._prev_high = None
self._prev_low = None
self._stop_price = 0.0
self._take_price = 0.0
def OnReseted(self):
super(auto_fib_breakout_strategy, self).OnReseted()
self._reset_state()
def OnStarted2(self, time):
super(auto_fib_breakout_strategy, self).OnStarted2(time)
self._reset_state()
ema = ExponentialMovingAverage()
ema.Length = self._ema_length.Value
atr = AverageTrueRange()
atr.Length = self._atr_length.Value
highest = Highest()
highest.Length = self._pivot_period.Value
lowest = Lowest()
lowest.Length = self._pivot_period.Value
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(ema, atr, highest, lowest, 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, atr_value, highest_value, lowest_value):
if candle.State != CandleStates.Finished:
return
# The swing range comes from the candles before this one.
swing_high = self._prev_high
swing_low = self._prev_low
self._prev_high = float(highest_value)
self._prev_low = float(lowest_value)
if swing_high is None or swing_low is None:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
close = float(candle.ClosePrice)
if self.Position > 0:
if float(candle.LowPrice) <= self._stop_price or float(candle.HighPrice) >= self._take_price:
self.SellMarket(self.Position)
return
extension = swing_low + (swing_high - swing_low) * float(self._fib_level.Value)
atr = float(atr_value)
if self.Position == 0 and close > extension and close > float(ema_value):
self.BuyMarket(self.Volume)
self._stop_price = close - STOP_ATR_MULTIPLE * atr
self._take_price = close + TAKE_ATR_MULTIPLE * atr
def CreateClone(self):
return auto_fib_breakout_strategy()