Ver en GitHub

Estrategia Blonde Trader

Blonde Trader es una estrategia de trading en cuadrícula convertida desde MQL. Busca movimientos de precio alejándose de extremos recientes y abre posiciones con una cuadrícula de órdenes pendientes.

Concepto

  • Calcular el máximo más alto y el mínimo más bajo durante las últimas Period X velas.
  • Si el precio actual está por debajo del máximo reciente en más de Limit ticks, abrir una posición larga y colocar una serie de órdenes buy limit formando una cuadrícula.
  • Si el precio actual está por encima del mínimo reciente en más de Limit ticks, abrir una posición corta y colocar una serie de órdenes sell limit formando una cuadrícula.
  • Cerrar todas las posiciones cuando el beneficio acumulado alcance Amount.
  • Opcionalmente, cuando el precio se mueva LockDown ticks en beneficio, se coloca una orden stop en el nivel de punto de equilibrio para proteger la posición.

Parámetros

Nombre Descripción
PeriodX Período de retroceso para el máximo más alto y el mínimo más bajo.
Limit Distancia mínima en ticks desde el precio actual hasta un extremo.
Grid Paso en ticks entre las órdenes pendientes de la cuadrícula.
Amount Objetivo de beneficio en la moneda de la cuenta.
LockDown Distancia en ticks para mover el stop al punto de equilibrio.
CandleType Tipo de velas utilizadas para el análisis.

Indicadores

  • Highest – rastrea el máximo más alto durante el período de retroceso.
  • Lowest – rastrea el mínimo más bajo durante el período de retroceso.

Lógica de Órdenes

  1. Cuando aparece una configuración larga:
    • Comprar a mercado con el volumen predeterminado de la estrategia.
    • Colocar cuatro órdenes buy limit adicionales por debajo de la entrada, cada una separada por Grid ticks y doblando el volumen.
  2. Cuando aparece una configuración corta:
    • Vender a mercado con el volumen predeterminado de la estrategia.
    • Colocar cuatro órdenes sell limit adicionales por encima de la entrada con las mismas reglas de cuadrícula y duplicación de volumen.
  3. Si PnL alcanza Amount, todas las posiciones abiertas y las órdenes pendientes se cierran.
  4. Si LockDown es mayor que cero y el precio se ha movido el número especificado de ticks a favor de la posición, se coloca una orden stop protectora un tick más allá del precio de entrada.

Notas

Esta estrategia demuestra la lógica básica de trading en cuadrícula. Utiliza únicamente características de la API de alto nivel: SubscribeCandles, vinculación de indicadores y ayudantes de órdenes simples como BuyMarket, SellLimit y 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;
		}
	}
}