View on GitHub

My Line Order

This strategy triggers market orders when price crosses predefined horizontal levels. The user specifies separate levels for long and short entries and risk parameters in pips. After opening a position the strategy tracks stop loss, take profit and optional trailing stop.

The system suits discretionary setups where entry levels are known in advance. It works on any instrument and timeframe because it relies only on price levels.

Details

  • Entry Criteria:
    • Long: Close price crosses above BuyPrice.
    • Short: Close price crosses below SellPrice.
  • Long/Short: Both sides.
  • Exit Criteria:
    • Stop-loss at StopLossPips.
    • Take-profit at TakeProfitPips.
    • Trailing stop if TrailingStopPips > 0.
  • Stops: Yes, in pips.
  • Default Values:
    • BuyPrice = 0 (disabled)
    • SellPrice = 0 (disabled)
    • TakeProfitPips = 30
    • StopLossPips = 20
    • TrailingStopPips = 0
    • CandleType = TimeSpan.FromMinutes(1)
  • Filters:
    • Category: Manual
    • Direction: Both
    • Indicators: None
    • Stops: Yes
    • Complexity: Basic
    • Timeframe: Any
    • Seasonality: No
    • Neural Networks: No
    • Divergence: No
    • Risk Level: Medium
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>
/// Line order strategy using SMA as dynamic support/resistance levels.
/// </summary>
public class MyLineOrderStrategy : Strategy
{
	private readonly StrategyParam<int> _smaLength;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevClose;
	private decimal _prevSma;
	private bool _hasPrev;

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

	public MyLineOrderStrategy()
	{
		_smaLength = Param(nameof(SmaLength), 14)
			.SetGreaterThanZero()
			.SetDisplay("SMA", "SMA period", "Indicators");

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

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

	protected override void OnReseted()
	{
		base.OnReseted();
		_prevClose = 0;
		_prevSma = 0;
		_hasPrev = false;
	}

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

		var sma = new SimpleMovingAverage { Length = SmaLength };

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

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

		var close = candle.ClosePrice;

		if (!_hasPrev)
		{
			_prevClose = close;
			_prevSma = sma;
			_hasPrev = true;
			return;
		}

		// Cross above SMA
		if (_prevClose <= _prevSma && close > sma)
		{
			if (Position < 0) BuyMarket();
			if (Position <= 0) BuyMarket();
		}
		// Cross below SMA
		else if (_prevClose >= _prevSma && close < sma)
		{
			if (Position > 0) SellMarket();
			if (Position >= 0) SellMarket();
		}

		_prevClose = close;
		_prevSma = sma;
	}
}