BTC先物Gamma加重モメンタムモデル戦略
この戦略は、BTC先物のモメンタムを捉えるためにGamma加重平均価格(GWAP)を計算します。価格がGWAPを上回り、直近3本の終値が連続して上昇している場合にロングポジションを建てます。価格がGWAPを下回り、直近3本の終値が連続して下落している場合にショートポジションを建てます。
詳細
- エントリー条件:
- ロング: 終値がGWAPを上回り、直近3本の終値が上昇中。
- ショート: 終値がGWAPを下回り、直近3本の終値が下落中。
- ロング/ショート: 両方。
- エグジット条件: 逆シグナル。
- ストップ: なし。
- デフォルト値:
Length= 60GammaFactor= 0.75
- フィルター:
- カテゴリ: モメンタム
- 方向: 両方
- インジケーター: GWAP
- ストップ: なし
- 複雑さ: 低
- 時間軸: 1m
- 季節性: いいえ
- ニューラルネットワーク: いいえ
- ダイバージェンス: いいえ
- リスクレベル: 中
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>
/// BTC Future Gamma-Weighted Momentum Model strategy.
/// The gamma-weighted average price (GWAP) averages the last Length closes with weight GammaFactor^i for the close i bars ago.
/// A close above GWAP after three consecutively rising closes goes long, a close below GWAP after three consecutively falling closes
/// goes short, and the opposite signal reverses the position.
/// </summary>
public class BtcFutureGammaWeightedMomentumModelStrategy : Strategy
{
private readonly StrategyParam<int> _length;
private readonly StrategyParam<decimal> _gammaFactor;
private readonly StrategyParam<DataType> _candleType;
private readonly List<decimal> _closes = new();
/// <summary>
/// Closes in the GWAP window.
/// </summary>
public int Length
{
get => _length.Value;
set => _length.Value = value;
}
/// <summary>
/// Decay of the weight per bar back.
/// </summary>
public decimal GammaFactor
{
get => _gammaFactor.Value;
set => _gammaFactor.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public BtcFutureGammaWeightedMomentumModelStrategy()
{
_length = Param(nameof(Length), 60)
.SetGreaterThanZero()
.SetDisplay("Length", "Closes in the GWAP window", "GWAP");
_gammaFactor = Param(nameof(GammaFactor), 0.75m)
.SetRange(0.01m, 1m)
.SetDisplay("Gamma Factor", "Decay of the weight per bar back", "GWAP");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).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();
_closes.Clear();
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_closes.Clear();
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
_closes.Add(candle.ClosePrice);
var keep = Math.Max(Length, 3);
while (_closes.Count > keep)
_closes.RemoveAt(0);
if (_closes.Count < keep)
return;
var last = _closes.Count - 1;
decimal weighted = 0, weights = 0, weight = 1;
for (var i = 0; i < Length; i++)
{
weighted += _closes[last - i] * weight;
weights += weight;
weight *= GammaFactor;
}
var gwap = weighted / weights;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var close = _closes[last];
var rising = close > _closes[last - 1] && _closes[last - 1] > _closes[last - 2];
var falling = close < _closes[last - 1] && _closes[last - 1] < _closes[last - 2];
if (close > gwap && rising && Position <= 0)
BuyMarket(Volume + Math.Abs(Position));
else if (close < gwap && falling && Position >= 0)
SellMarket(Volume + Math.Abs(Position));
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Decimal
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Strategies import Strategy
class btc_future_gamma_weighted_momentum_model_strategy(Strategy):
"""
BTC Future Gamma-Weighted Momentum Model strategy.
The gamma-weighted average price (GWAP) averages the last Length closes with weight GammaFactor^i for the close i bars ago.
A close above GWAP after three consecutively rising closes goes long, a close below GWAP after three consecutively falling closes
goes short, and the opposite signal reverses the position.
"""
def __init__(self):
super(btc_future_gamma_weighted_momentum_model_strategy, self).__init__()
self._length = self.Param("Length", 60).SetGreaterThanZero().SetDisplay("Length", "Closes in the GWAP window", "GWAP")
self._gamma_factor = self.Param("GammaFactor", 0.75).SetRange(0.01, 1.0).SetDisplay("Gamma Factor", "Decay of the weight per bar back", "GWAP")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(1))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._closes = []
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(btc_future_gamma_weighted_momentum_model_strategy, self).OnReseted()
self._closes = []
def OnStarted2(self, time):
super(btc_future_gamma_weighted_momentum_model_strategy, self).OnStarted2(time)
self._closes = []
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def _process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
length = self._length.Value
self._closes.append(candle.ClosePrice)
keep = max(length, 3)
while len(self._closes) > keep:
self._closes.pop(0)
if len(self._closes) < keep:
return
last = len(self._closes) - 1
gamma = Decimal(self._gamma_factor.Value)
weighted = Decimal(0)
weights = Decimal(0)
weight = Decimal(1)
for i in range(length):
weighted += self._closes[last - i] * weight
weights += weight
weight *= gamma
gwap = weighted / weights
if not self.IsFormedAndOnlineAndAllowTrading():
return
close = self._closes[last]
rising = close > self._closes[last - 1] and self._closes[last - 1] > self._closes[last - 2]
falling = close < self._closes[last - 1] and self._closes[last - 1] < self._closes[last - 2]
if close > gwap and rising and self.Position <= 0:
self.BuyMarket(self.Volume + abs(self.Position))
elif close < gwap and falling and self.Position >= 0:
self.SellMarket(self.Volume + abs(self.Position))
def CreateClone(self):
return btc_future_gamma_weighted_momentum_model_strategy()