在 GitHub 上查看

Simple Levels 策略

当价格穿越用户定义的趋势线时开仓。每条线可触发做多、做空或双向交易。止损和止盈以价格步长设置。

详情

  • 入场条件:价格突破设定的趋势线
  • 多/空:由趋势线方向决定(Buy/Sell/Both)
  • 出场条件:达到止损或止盈
  • 止损:是
  • 默认值
    • StopLoss = 300 步
    • TakeProfit = 900 步
    • Volume = 1
    • CandleType = 1 分钟
  • 筛选
    • 分类:水平
    • 方向:双向
    • 指标:无
    • 止损:是
    • 复杂度:基础
    • 时间框架:日内
    • 季节性:否
    • 神经网络:否
    • 背离:否
    • 风险等级:中

用法

  1. 使用 AddLine 创建并配置趋势线。
  2. 启动策略以监听新的蜡烛。
  3. 当价格在指定方向上穿越激活的趋势线时,策略发送市价单。
  4. 达到止损或止盈后持仓被关闭。
using System;
using System.Collections.Generic;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Strategy that trades when price breaks through recent high/low levels.
/// Tracks N-period high and low as support/resistance, enters on breakout.
/// Uses EMA as trend filter.
/// </summary>
public class SimpleLevelsStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _lookbackPeriod;
	private readonly StrategyParam<int> _emaPeriod;

	private decimal _highestHigh;
	private decimal _lowestLow;
	private int _barCount;

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public int LookbackPeriod
	{
		get => _lookbackPeriod.Value;
		set => _lookbackPeriod.Value = value;
	}

	public int EmaPeriod
	{
		get => _emaPeriod.Value;
		set => _emaPeriod.Value = value;
	}

	public SimpleLevelsStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Source candle timeframe", "General");

		_lookbackPeriod = Param(nameof(LookbackPeriod), 20)
			.SetDisplay("Lookback", "Period for high/low levels", "Parameters");

		_emaPeriod = Param(nameof(EmaPeriod), 50)
			.SetDisplay("EMA Period", "EMA period for trend filter", "Parameters");
	}

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_highestHigh = decimal.MinValue;
		_lowestLow = decimal.MaxValue;
		_barCount = 0;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_highestHigh = decimal.MinValue;
		_lowestLow = decimal.MaxValue;
		_barCount = 0;

		var highest = new Highest { Length = LookbackPeriod };
		var lowest = new Lowest { Length = LookbackPeriod };
		var ema = new ExponentialMovingAverage { Length = EmaPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(highest, lowest, ema, ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, ema);
			DrawOwnTrades(area);
		}
	}

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

		_barCount++;
		if (_barCount < 2)
		{
			_highestHigh = highLevel;
			_lowestLow = lowLevel;
			return;
		}

		var close = candle.ClosePrice;
		var prevHigh = _highestHigh;
		var prevLow = _lowestLow;

		// Breakout above previous resistance in uptrend
		if (close > prevHigh && close > emaValue && Position <= 0)
		{
			BuyMarket();
		}
		// Breakout below previous support in downtrend
		else if (close < prevLow && close < emaValue && Position >= 0)
		{
			SellMarket();
		}

		_highestHigh = highLevel;
		_lowestLow = lowLevel;
	}
}