Ichimoku by FarmerBTC 戦略
Ichimoku by FarmerBTC は、価格がIchimokuクラウドの上で推移し、クラウドが強気で、上位時間軸のSMAが上昇トレンドを確認し、出来高が移動平均に係数を掛けた値を上回るときにロングポジションを建てます。価格がクラウドを下回ると手仕舞います。
詳細
- エントリー条件: インジケーターシグナル
- ロング/ショート: ロングのみ
- エグジット条件: 反対のシグナル
- ストップ: いいえ
- デフォルト値:
TenkanPeriod= 10KijunPeriod= 30SenkouSpanBPeriod= 53SmaLength= 13VolumeLength= 20VolumeMultiplier= 1.5CandleType= 1 hourHtfCandleType= 1 day
- フィルター:
- カテゴリ: トレンドフォロー
- 方向: ロングのみ
- インジケーター: Ichimoku, SMA, 出来高
- ストップ: いいえ
- 複雑さ: 中級
- 時間軸: イントラデイ
- 季節性: いいえ
- ニューラルネットワーク: いいえ
- ダイバージェンス: いいえ
- リスクレベル: 中
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>
/// Ichimoku by FarmerBTC strategy.
/// Long only. A long opens when the close is above the Ichimoku cloud, the cloud is bullish (Senkou A above Senkou B), the close is above
/// the SmaLength SMA of the higher timeframe and the candle volume exceeds its VolumeLength average multiplied by VolumeMultiplier.
/// The position closes when the close falls below the cloud. There are no stops.
/// </summary>
public class IchimokuByFarmerBtcStrategy : Strategy
{
private readonly StrategyParam<int> _tenkanPeriod;
private readonly StrategyParam<int> _kijunPeriod;
private readonly StrategyParam<int> _senkouSpanBPeriod;
private readonly StrategyParam<int> _smaLength;
private readonly StrategyParam<int> _volumeLength;
private readonly StrategyParam<decimal> _volumeMultiplier;
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<DataType> _htfCandleType;
private SimpleMovingAverage _volumeSma;
private decimal? _htfSma;
/// <summary>
/// Tenkan-sen period.
/// </summary>
public int TenkanPeriod
{
get => _tenkanPeriod.Value;
set => _tenkanPeriod.Value = value;
}
/// <summary>
/// Kijun-sen period.
/// </summary>
public int KijunPeriod
{
get => _kijunPeriod.Value;
set => _kijunPeriod.Value = value;
}
/// <summary>
/// Senkou Span B period.
/// </summary>
public int SenkouSpanBPeriod
{
get => _senkouSpanBPeriod.Value;
set => _senkouSpanBPeriod.Value = value;
}
/// <summary>
/// Higher timeframe SMA period.
/// </summary>
public int SmaLength
{
get => _smaLength.Value;
set => _smaLength.Value = value;
}
/// <summary>
/// Volume moving average period.
/// </summary>
public int VolumeLength
{
get => _volumeLength.Value;
set => _volumeLength.Value = value;
}
/// <summary>
/// Factor applied to the volume average.
/// </summary>
public decimal VolumeMultiplier
{
get => _volumeMultiplier.Value;
set => _volumeMultiplier.Value = value;
}
/// <summary>
/// Working candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Higher timeframe candle type for the trend SMA.
/// </summary>
public DataType HtfCandleType
{
get => _htfCandleType.Value;
set => _htfCandleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public IchimokuByFarmerBtcStrategy()
{
_tenkanPeriod = Param(nameof(TenkanPeriod), 10)
.SetGreaterThanZero()
.SetDisplay("Tenkan Period", "Tenkan-sen period", "Ichimoku");
_kijunPeriod = Param(nameof(KijunPeriod), 30)
.SetGreaterThanZero()
.SetDisplay("Kijun Period", "Kijun-sen period", "Ichimoku");
_senkouSpanBPeriod = Param(nameof(SenkouSpanBPeriod), 53)
.SetGreaterThanZero()
.SetDisplay("Senkou Span B Period", "Senkou Span B period", "Ichimoku");
_smaLength = Param(nameof(SmaLength), 13)
.SetGreaterThanZero()
.SetDisplay("SMA Length", "Higher timeframe SMA period", "Trend");
_volumeLength = Param(nameof(VolumeLength), 20)
.SetGreaterThanZero()
.SetDisplay("Volume Length", "Volume moving average period", "Volume");
_volumeMultiplier = Param(nameof(VolumeMultiplier), 1.5m)
.SetGreaterThanZero()
.SetDisplay("Volume Multiplier", "Factor applied to the volume average", "Volume");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Working candle type", "General");
_htfCandleType = Param(nameof(HtfCandleType), TimeSpan.FromDays(1).TimeFrame())
.SetDisplay("HTF Candle Type", "Higher timeframe candle type for the trend SMA", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType), (Security, HtfCandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_volumeSma = null;
_htfSma = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_htfSma = null;
_volumeSma = new SimpleMovingAverage { Length = VolumeLength };
var ichimoku = new Ichimoku
{
Tenkan = { Length = TenkanPeriod },
Kijun = { Length = KijunPeriod },
SenkouB = { Length = SenkouSpanBPeriod },
};
var htfSma = new SimpleMovingAverage { Length = SmaLength };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(ichimoku, ProcessCandle)
.Start();
SubscribeCandles(HtfCandleType)
.BindEx(htfSma, ProcessHtfCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ichimoku);
DrawOwnTrades(area);
}
}
private void ProcessHtfCandle(ICandleMessage candle, IIndicatorValue smaValue)
{
if (candle.State != CandleStates.Finished || !smaValue.IsFormed)
return;
_htfSma = smaValue.GetValue<decimal>();
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue ichimokuValue)
{
if (candle.State != CandleStates.Finished)
return;
var volume = candle.TotalVolume;
var volumeValue = _volumeSma.Process(new DecimalIndicatorValue(_volumeSma, volume, candle.OpenTime) { IsFinal = true });
if (!_volumeSma.IsFormed || volumeValue.IsEmpty)
return;
var averageVolume = volumeValue.GetValue<decimal>();
if (!ichimokuValue.IsFormed || ichimokuValue is not IchimokuValue { SenkouA: decimal senkouA, SenkouB: decimal senkouB })
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var close = candle.ClosePrice;
var cloudTop = Math.Max(senkouA, senkouB);
var cloudBottom = Math.Min(senkouA, senkouB);
if (Position > 0)
{
if (close < cloudBottom)
SellMarket(Position);
return;
}
if (_htfSma is not decimal trendSma)
return;
if (close > cloudTop && senkouA > senkouB && close > trendSma && volume > averageVolume * VolumeMultiplier)
BuyMarket(Volume + Math.Abs(Position));
}
}
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 Ichimoku, SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
from indicator_extensions import *
class ichimoku_by_farmer_btc_strategy(Strategy):
"""
Ichimoku by FarmerBTC strategy.
Long only. A long opens when the close is above the Ichimoku cloud, the cloud is bullish (Senkou A above Senkou B), the close is above
the SmaLength SMA of the higher timeframe and the candle volume exceeds its VolumeLength average multiplied by VolumeMultiplier.
The position closes when the close falls below the cloud. There are no stops.
"""
def __init__(self):
super(ichimoku_by_farmer_btc_strategy, self).__init__()
self._tenkan_period = self.Param("TenkanPeriod", 10).SetGreaterThanZero().SetDisplay("Tenkan Period", "Tenkan-sen period", "Ichimoku")
self._kijun_period = self.Param("KijunPeriod", 30).SetGreaterThanZero().SetDisplay("Kijun Period", "Kijun-sen period", "Ichimoku")
self._senkou_span_b_period = self.Param("SenkouSpanBPeriod", 53).SetGreaterThanZero().SetDisplay("Senkou Span B Period", "Senkou Span B period", "Ichimoku")
self._sma_length = self.Param("SmaLength", 13).SetGreaterThanZero().SetDisplay("SMA Length", "Higher timeframe SMA period", "Trend")
self._volume_length = self.Param("VolumeLength", 20).SetGreaterThanZero().SetDisplay("Volume Length", "Volume moving average period", "Volume")
self._volume_multiplier = self.Param("VolumeMultiplier", 1.5).SetGreaterThanZero().SetDisplay("Volume Multiplier", "Factor applied to the volume average", "Volume")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))).SetDisplay("Candle Type", "Working candle type", "General")
self._htf_candle_type = self.Param("HtfCandleType", DataType.TimeFrame(TimeSpan.FromDays(1))).SetDisplay("HTF Candle Type", "Higher timeframe candle type for the trend SMA", "General")
self._volume_sma = None
self._htf_sma = None
@property
def candle_type(self):
return self._candle_type.Value
@property
def htf_candle_type(self):
return self._htf_candle_type.Value
def GetWorkingSecurities(self):
return [(self.Security, self.candle_type), (self.Security, self.htf_candle_type)]
def OnReseted(self):
super(ichimoku_by_farmer_btc_strategy, self).OnReseted()
self._volume_sma = None
self._htf_sma = None
def OnStarted2(self, time):
super(ichimoku_by_farmer_btc_strategy, self).OnStarted2(time)
self._htf_sma = None
self._volume_sma = SimpleMovingAverage()
self._volume_sma.Length = self._volume_length.Value
ichimoku = Ichimoku()
ichimoku.Tenkan.Length = self._tenkan_period.Value
ichimoku.Kijun.Length = self._kijun_period.Value
ichimoku.SenkouB.Length = self._senkou_span_b_period.Value
htf_sma = SimpleMovingAverage()
htf_sma.Length = self._sma_length.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(ichimoku, self._process_candle).Start()
self.SubscribeCandles(self.htf_candle_type).BindEx(htf_sma, self._process_htf_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ichimoku)
self.DrawOwnTrades(area)
def _process_htf_candle(self, candle, sma_value):
if candle.State != CandleStates.Finished or not sma_value.IsFormed:
return
self._htf_sma = sma_value.GetValue[Decimal](None)
def _process_candle(self, candle, ichimoku_value):
if candle.State != CandleStates.Finished:
return
volume = candle.TotalVolume
volume_value = process_value(self._volume_sma, volume, candle.OpenTime, True)
if not self._volume_sma.IsFormed or volume_value.IsEmpty:
return
average_volume = to_decimal(volume_value)
if not ichimoku_value.IsFormed or ichimoku_value.SenkouA is None or ichimoku_value.SenkouB is None:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
close = candle.ClosePrice
senkou_a = ichimoku_value.SenkouA
senkou_b = ichimoku_value.SenkouB
cloud_top = max(senkou_a, senkou_b)
cloud_bottom = min(senkou_a, senkou_b)
if self.Position > 0:
if close < cloud_bottom:
self.SellMarket(self.Position)
return
if self._htf_sma is None:
return
if close > cloud_top and senkou_a > senkou_b and close > self._htf_sma and volume > average_volume * Decimal(self._volume_multiplier.Value):
self.BuyMarket(self.Volume + abs(self.Position))
def CreateClone(self):
return ichimoku_by_farmer_btc_strategy()