GitHub で見る

Godbot戦略

この戦略は、ボリンジャーバンドと移動平均線を組み合わせてリバーサルとトレンド強度を検出します。

ロジック

  • メインのローソク足時間軸(デフォルト30分)で動作します。
  • この時間軸でボリンジャーバンドとEMAを計算します。
  • 別途、上位時間軸(デフォルト1日)でDEMAを計算してグローバルトレンドを決定します。
  • 価格がボリンジャー上限バンドを再び下回ったときにロングポジションをクローズします。
  • 価格がボリンジャー下限バンドを再び上回ったときにショートポジションをクローズします。
  • DEMAとEMAの両方が上昇しながら価格が下限バンドを上抜けしたときにロングを開きます。
  • DEMAとEMAの両方が下落しながら価格が上限バンドを下抜けしたときにショートを開きます。

パラメーター

  • Bollinger Period – ボリンジャーバンドの期間。
  • Bollinger Deviation – バンドの幅乗数。
  • EMA Period – EMAトレンドフィルターの期間。
  • DEMA Period – 上位時間軸のDEMAの期間。
  • Candle Type – ボリンジャーバンドとEMAの計算に使用する時間軸。
  • DEMA Candle Type – DEMAに使用する上位時間軸。

注記

  • 同時に保持されるポジションは1つのみです。
  • 戦略はエントリーとエグジットに成行注文を使用します。
  • 取引開始前にDEMAデータが蓄積される必要があります。
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>
/// Strategy based on Bollinger Bands and EMA trend confirmation.
/// Buys when price crosses below lower band with uptrend, sells when above upper band with downtrend.
/// </summary>
public class GodbotStrategy : Strategy
{
	private readonly StrategyParam<int> _bollingerPeriod;
	private readonly StrategyParam<decimal> _bollingerDeviation;
	private readonly StrategyParam<int> _maPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevEma;
	private bool _hasPrevEma;

	public int BollingerPeriod { get => _bollingerPeriod.Value; set => _bollingerPeriod.Value = value; }
	public decimal BollingerDeviation { get => _bollingerDeviation.Value; set => _bollingerDeviation.Value = value; }
	public int MaPeriod { get => _maPeriod.Value; set => _maPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public GodbotStrategy()
	{
		_bollingerPeriod = Param(nameof(BollingerPeriod), 20)
			.SetGreaterThanZero()
			.SetDisplay("BB Period", "Bollinger Bands period", "Indicators");

		_bollingerDeviation = Param(nameof(BollingerDeviation), 2m)
			.SetGreaterThanZero()
			.SetDisplay("BB Deviation", "Bollinger Bands deviation", "Indicators");

		_maPeriod = Param(nameof(MaPeriod), 50)
			.SetGreaterThanZero()
			.SetDisplay("EMA Period", "EMA period for trend", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle type", "General");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
		=> [(Security, CandleType)];

	protected override void OnReseted()
	{
		base.OnReseted();
		_prevEma = 0;
		_hasPrevEma = false;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var bb = new BollingerBands
		{
			Length = BollingerPeriod,
			Width = BollingerDeviation
		};
		var ema = new ExponentialMovingAverage { Length = MaPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(ema, ProcessEma);
		subscription
			.BindEx(bb, ProcessBB)
			.Start();
	}

	private void ProcessEma(ICandleMessage candle, decimal emaVal)
	{
		if (candle.State != CandleStates.Finished)
			return;

		_prevEma = emaVal;
		_hasPrevEma = true;
	}

	private void ProcessBB(ICandleMessage candle, IIndicatorValue bbValue)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!_hasPrevEma)
			return;

		var bb = (BollingerBandsValue)bbValue;
		if (bb.UpBand is not decimal upper || bb.LowBand is not decimal lower || bb.MovingAverage is not decimal middle)
			return;

		var close = candle.ClosePrice;

		// Buy: price below lower band
		if (close < lower && Position <= 0)
			BuyMarket();
		// Sell: price above upper band
		else if (close > upper && Position >= 0)
			SellMarket();
	}
}