Ver en GitHub

Blonde Trader Strategy

Blonde Trader is a grid-based trading strategy converted from MQL. It searches for price moving away from recent extremes and opens positions with a grid of pending orders.

Concept

  • Calculate the highest high and lowest low over the last Period X candles.
  • If the current price is below the recent high by more than Limit ticks, open a long position and place a series of buy limit orders forming a grid.
  • If the current price is above the recent low by more than Limit ticks, open a short position and place a series of sell limit orders forming a grid.
  • Close all positions when the accumulated profit reaches Amount.
  • Optionally, after the price moves LockDown ticks in profit, a stop order is placed at the breakeven level to protect the position.

Parameters

Name Description
PeriodX Lookback period for highest high and lowest low.
Limit Minimal distance in ticks from current price to an extreme.
Grid Step in ticks between grid pending orders.
Amount Profit target in account currency.
LockDown Distance in ticks to move stop to breakeven.
CandleType Type of candles used for analysis.

Indicators

  • Highest – tracks the highest high over the lookback period.
  • Lowest – tracks the lowest low over the lookback period.

Order Logic

  1. When a long setup appears:
    • Buy at market with the default strategy volume.
    • Place four additional buy limit orders below the entry, each separated by Grid ticks and doubling the volume.
  2. When a short setup appears:
    • Sell at market with the default strategy volume.
    • Place four additional sell limit orders above the entry with the same grid and volume doubling rules.
  3. If PnL reaches Amount, all open positions and pending orders are closed.
  4. If LockDown is greater than zero and the price has moved the specified number of ticks in favor of the position, a protective stop order is placed one tick beyond the entry price.

Notes

This strategy demonstrates basic grid trading logic. It uses only high-level API features: SubscribeCandles, indicator binding and simple order helpers such as BuyMarket, SellLimit and SellStop.

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>
/// Blonde Trader strategy. Buys when price pulls back from recent high,
/// sells when price bounces from recent low. Uses Highest/Lowest indicators.
/// </summary>
public class BlondeTraderStrategy : Strategy
{
	private readonly StrategyParam<int> _lookback;
	private readonly StrategyParam<decimal> _threshold;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _entryPrice;

	public int Lookback { get => _lookback.Value; set => _lookback.Value = value; }
	public decimal Threshold { get => _threshold.Value; set => _threshold.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public BlondeTraderStrategy()
	{
		_lookback = Param(nameof(Lookback), 20)
			.SetGreaterThanZero()
			.SetDisplay("Lookback", "Period for Highest/Lowest", "General");

		_threshold = Param(nameof(Threshold), 0.002m)
			.SetDisplay("Threshold", "Min distance ratio from extreme", "General");

		_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();
		_entryPrice = 0;
	}

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

		var highest = new Highest { Length = Lookback };
		var lowest = new Lowest { Length = Lookback };

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

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

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

		var price = candle.ClosePrice;
		var range = high - low;

		if (range <= 0 || high == 0)
			return;

		var distFromHigh = (high - price) / high;
		var distFromLow = (price - low) / price;

		// Buy signal: price pulled back from high by at least threshold
		if (distFromHigh > Threshold && Position <= 0)
		{
			BuyMarket();
			_entryPrice = price;
		}
		// Sell signal: price bounced up from low by at least threshold
		else if (distFromLow > Threshold && Position >= 0)
		{
			SellMarket();
			_entryPrice = price;
		}
	}
}