Auf GitHub ansehen

Ten Pips Strategy

This hedging strategy opens long and short positions at the same time. Each position uses fixed take profit and stop loss levels measured in price units and can be protected by a trailing stop. When one side closes, the strategy immediately opens a new position in the same direction to keep both sides active.

Parameters

  • TakeProfitBuy – take profit distance for long positions.
  • StopLossBuy – stop loss distance for long positions.
  • TrailingStopBuy – trailing stop distance for long positions.
  • TakeProfitSell – take profit distance for short positions.
  • StopLossSell – stop loss distance for short positions.
  • TrailingStopSell – trailing stop distance for short positions.
  • Volume – order size used for all trades.

Notes

  • Positions are opened with market orders.
  • Protective orders are registered for each side separately.
  • Trailing stops are updated when the market moves in a favourable direction.
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>
/// Simple breakout strategy that enters on momentum moves
/// with fixed take profit and stop loss protection.
/// </summary>
public class TenPipsStrategy : Strategy
{
	private readonly StrategyParam<decimal> _takeProfit;
	private readonly StrategyParam<decimal> _stopLoss;
	private readonly StrategyParam<int> _lookback;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _entryPrice;
	private decimal _previousRoc;
	private bool _hasPreviousRoc;

	/// <summary>Take profit distance.</summary>
	public decimal TakeProfit { get => _takeProfit.Value; set => _takeProfit.Value = value; }
	/// <summary>Stop loss distance.</summary>
	public decimal StopLoss { get => _stopLoss.Value; set => _stopLoss.Value = value; }
	/// <summary>Lookback period for momentum.</summary>
	public int Lookback { get => _lookback.Value; set => _lookback.Value = value; }
	/// <summary>Candle type.</summary>
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	/// <summary>
	/// Initializes a new instance of the strategy.
	/// </summary>
	public TenPipsStrategy()
	{
		_takeProfit = Param(nameof(TakeProfit), 500m)
			.SetDisplay("Take Profit", "Take profit distance", "Risk")
			.SetGreaterThanZero();
		_stopLoss = Param(nameof(StopLoss), 300m)
			.SetDisplay("Stop Loss", "Stop loss distance", "Risk")
			.SetGreaterThanZero();
		_lookback = Param(nameof(Lookback), 30)
			.SetDisplay("Lookback", "Momentum lookback period", "Indicators")
			.SetGreaterThanZero();
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
			.SetDisplay("Candle Type", "Type of candles", "General");
	}

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

	/// <inheritdoc />
	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_entryPrice = 0m;
		_previousRoc = 0m;
		_hasPreviousRoc = false;
	}

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

		_entryPrice = 0;
		_previousRoc = 0m;
		_hasPreviousRoc = false;

		var roc = new RateOfChange { Length = Lookback };

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

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

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

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		var close = candle.ClosePrice;
		var buySignal = _hasPreviousRoc && _previousRoc <= 4m && rocValue > 4m;
		var sellSignal = _hasPreviousRoc && _previousRoc >= -4m && rocValue < -4m;

		if (Position == 0)
		{
			if (buySignal)
			{
				BuyMarket();
				_entryPrice = close;
			}
			else if (sellSignal)
			{
				SellMarket();
				_entryPrice = close;
			}
		}
		else if (Position > 0)
		{
			if (close >= _entryPrice + TakeProfit || close <= _entryPrice - StopLoss)
			{
				SellMarket(Math.Abs(Position));
			}
		}
		else if (Position < 0)
		{
			if (close <= _entryPrice - TakeProfit || close >= _entryPrice + StopLoss)
			{
				BuyMarket(Math.Abs(Position));
			}
		}

		_previousRoc = rocValue;
		_hasPreviousRoc = true;
	}
}