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
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.
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.
Si PnL alcanza Amount, todas las posiciones abiertas y las órdenes pendientes se cierran.
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;
}
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import Highest, Lowest
from StockSharp.Algo.Strategies import Strategy
class blonde_trader_strategy(Strategy):
def __init__(self):
super(blonde_trader_strategy, self).__init__()
self._lookback = self.Param("Lookback", 20) \
.SetDisplay("Lookback", "Period for Highest/Lowest", "General")
self._threshold = self.Param("Threshold", 0.002) \
.SetDisplay("Threshold", "Min distance ratio from extreme", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._entry_price = 0.0
@property
def lookback(self):
return self._lookback.Value
@property
def threshold(self):
return self._threshold.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(blonde_trader_strategy, self).OnReseted()
self._entry_price = 0.0
def OnStarted2(self, time):
super(blonde_trader_strategy, self).OnStarted2(time)
highest = Highest()
highest.Length = self.lookback
lowest = Lowest()
lowest.Length = self.lookback
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(highest, lowest, self.OnProcess).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def OnProcess(self, candle, high, low):
if candle.State != CandleStates.Finished:
return
price = float(candle.ClosePrice)
high_val = float(high)
low_val = float(low)
range_val = high_val - low_val
if range_val <= 0 or high_val == 0:
return
dist_from_high = (high_val - price) / high_val
dist_from_low = (price - low_val) / price
if dist_from_high > self.threshold and self.Position <= 0:
self.BuyMarket()
self._entry_price = price
elif dist_from_low > self.threshold and self.Position >= 0:
self.SellMarket()
self._entry_price = price
def CreateClone(self):
return blonde_trader_strategy()