SMA Multi Hedge2 策略
该策略在基础品种上进行交易,并用相关资产进行对冲。趋势方向由简单移动平均线 (SMA) 判断。当基础品种与对冲品种之间的相关性达到设定阈值时,同时交易两个品种以形成市场中性组合。
工作原理
- 使用可配置周期的 SMA 计算基础品种的趋势。
- 利用价格与其自身 SMA 的差值衡量基础品种与对冲品种之间的相关性。
- 当相关性达到预期水平时,同时在两个品种上开仓。根据配置,对冲方向可以与基础品种一致或相反。
- 当总盈利达到目标值时,仓位会自动平仓。
参数
SmaPeriod— 用于检测趋势的 SMA 周期,默认 20。CorrelationPeriod— 用于计算相关性的样本数,默认 20。ExpectedCorrelation— 激活对冲所需的最小相关性绝对值,默认 0.8。ProfitTarget— 以货币计的总体盈利目标,默认 30。CandleType— 订阅蜡烛图的数据类型,默认 1 分钟。FollowBase— 若为真且相关性为正,则对冲方向与基础品种一致。
指标
- SMA
- 相关性(自定义计算)
注意
这是原始 MQL 策略的简化移植版本。在实盘交易前应调整风险和资金管理参数。
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>
/// SMA trend direction strategy.
/// </summary>
public class SmaMultiHedge2Strategy : Strategy
{
private readonly StrategyParam<int> _emaPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevEma1;
private decimal _prevEma2;
private int _count;
public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public SmaMultiHedge2Strategy()
{
_emaPeriod = Param(nameof(EmaPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("EMA Period", "EMA trend period", "Parameters");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle type", "Parameters");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_prevEma1 = 0;
_prevEma2 = 0;
_count = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var ema = new ExponentialMovingAverage { Length = EmaPeriod };
SubscribeCandles(CandleType)
.Bind(ema, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal emaVal)
{
if (candle.State != CandleStates.Finished) return;
_count++;
if (_count < 3)
{
_prevEma2 = _prevEma1;
_prevEma1 = emaVal;
return;
}
var trend = 0;
if (_prevEma2 < _prevEma1 && _prevEma1 < emaVal)
trend = 1;
else if (_prevEma2 > _prevEma1 && _prevEma1 > emaVal)
trend = -1;
_prevEma2 = _prevEma1;
_prevEma1 = emaVal;
if (trend == 1 && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (trend == -1 && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
}
}
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
from StockSharp.Algo.Strategies import Strategy
class sma_multi_hedge2_strategy(Strategy):
def __init__(self):
super(sma_multi_hedge2_strategy, self).__init__()
self._ema_period = self.Param("EmaPeriod", 20) \
.SetDisplay("EMA Period", "EMA trend period", "Parameters")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle type", "Parameters")
self._prev_ema1 = 0.0
self._prev_ema2 = 0.0
self._count = 0
@property
def ema_period(self):
return self._ema_period.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(sma_multi_hedge2_strategy, self).OnReseted()
self._prev_ema1 = 0.0
self._prev_ema2 = 0.0
self._count = 0
def OnStarted2(self, time):
super(sma_multi_hedge2_strategy, self).OnStarted2(time)
ema = ExponentialMovingAverage()
ema.Length = self.ema_period
self.SubscribeCandles(self.candle_type) \
.Bind(ema, self.process_candle) \
.Start()
def process_candle(self, candle, ema_val):
if candle.State != CandleStates.Finished:
return
ema_val = float(ema_val)
self._count += 1
if self._count < 3:
self._prev_ema2 = self._prev_ema1
self._prev_ema1 = ema_val
return
trend = 0
if self._prev_ema2 < self._prev_ema1 and self._prev_ema1 < ema_val:
trend = 1
elif self._prev_ema2 > self._prev_ema1 and self._prev_ema1 > ema_val:
trend = -1
self._prev_ema2 = self._prev_ema1
self._prev_ema1 = ema_val
if trend == 1 and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif trend == -1 and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
def CreateClone(self):
return sma_multi_hedge2_strategy()