在 GitHub 上查看

彩色Schaff WPR趋势循环策略

该策略实现了MetaTrader中的 Color Schaff WPR Trend Cycle 专家顾问。 它利用快慢Williams %R计算的Schaff趋势循环来识别市场转向。

算法仅在已完成的K线运行。当指标值上穿上方阈值时,策略开多并平掉任何空头;当指标值下破下方阈值时,策略开空并平掉任何多头。

参数

  • Fast WPR – 快速Williams %R周期。
  • Slow WPR – 慢速Williams %R周期。
  • Cycle – Schaff趋势计算的周期长度。
  • High Level – 做多触发的上方阈值。
  • Low Level – 做空触发的下方阈值。
  • Candle Type – 用于评估指标的K线时间框架。

链接

  • 原始MQL源码:MQL/13489/mql5/Experts/exp_colorschaffwprtrendcycle.mq5
  • 指标:MQL/13489/mql5/Indicators/colorschaffwprtrendcycle.mq5
using System;
using System.Linq;
using System.Collections.Generic;

using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Strategy based on the Schaff Trend Cycle calculated from WPR.
/// </summary>
public class ColorSchaffWprTrendCycleStrategy : Strategy
{
	private readonly StrategyParam<int> _fastWpr;
	private readonly StrategyParam<int> _slowWpr;
	private readonly StrategyParam<int> _cycle;
	private readonly StrategyParam<int> _highLevel;
	private readonly StrategyParam<int> _lowLevel;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevStc;

	public int FastWpr { get => _fastWpr.Value; set => _fastWpr.Value = value; }
	public int SlowWpr { get => _slowWpr.Value; set => _slowWpr.Value = value; }
	public int Cycle { get => _cycle.Value; set => _cycle.Value = value; }
	public int HighLevel { get => _highLevel.Value; set => _highLevel.Value = value; }
	public int LowLevel { get => _lowLevel.Value; set => _lowLevel.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public ColorSchaffWprTrendCycleStrategy()
	{
		_fastWpr = Param(nameof(FastWpr), 23)
			.SetDisplay("Fast WPR", "Fast Williams %R period", "Indicator");

		_slowWpr = Param(nameof(SlowWpr), 50)
			.SetDisplay("Slow WPR", "Slow Williams %R period", "Indicator");

		_cycle = Param(nameof(Cycle), 10)
			.SetDisplay("Cycle", "Cycle length", "Indicator");

		_highLevel = Param(nameof(HighLevel), 60)
			.SetDisplay("High Level", "Upper trigger level", "Indicator");

		_lowLevel = Param(nameof(LowLevel), -60)
			.SetDisplay("Low Level", "Lower trigger level", "Indicator");

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

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

	protected override void OnReseted()
	{
		base.OnReseted();
		_prevStc = 0m;
	}

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

		// Schaff trend cycle indicator using WPR values
		var stc = new SchaffTrendCycle
		{
			Length = Cycle
		};
		stc.Macd.Macd.ShortMa.Length = FastWpr;
		stc.Macd.Macd.LongMa.Length = SlowWpr;

		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(stc, ProcessCandle).Start();
	}

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

		var prev = _prevStc;
		_prevStc = stcValue;

		// Generate buy signal when STC crosses above HighLevel
		var crossUp = prev <= HighLevel && stcValue > HighLevel;
		// Generate sell signal when STC crosses below LowLevel
		var crossDown = prev >= LowLevel && stcValue < LowLevel;

		if (crossUp)
		{
			if (Position <= 0)
				BuyMarket(Volume + Math.Abs(Position));
		}
		else if (crossDown)
		{
			if (Position >= 0)
				SellMarket(Volume + Math.Abs(Position));
		}
	}
}