Blonde Trader ist eine aus MQL konvertierte Grid-Handelsstrategie. Sie sucht nach Preisbewegungen weg von jüngsten Extremen und eröffnet Positionen mit einem Grid aus ausstehenden Orders.
Konzept
Berechnung des höchsten Hochs und des niedrigsten Tiefs über die letzten Period X Kerzen.
Wenn der aktuelle Preis um mehr als Limit Ticks unter dem jüngsten Hoch liegt, wird eine Long-Position eröffnet und eine Reihe von Buy-Limit-Orders als Grid platziert.
Wenn der aktuelle Preis um mehr als Limit Ticks über dem jüngsten Tief liegt, wird eine Short-Position eröffnet und eine Reihe von Sell-Limit-Orders als Grid platziert.
Alle Positionen werden geschlossen, wenn der kumulierte Gewinn Amount erreicht.
Optional wird nach einer Preisbewegung von LockDown Ticks im Gewinn eine Stop-Order auf dem Breakeven-Niveau platziert.
Parameter
Name
Beschreibung
PeriodX
Rückblickperiode für das höchste Hoch und das niedrigste Tief.
Limit
Mindestabstand in Ticks vom aktuellen Preis zu einem Extrem.
Grid
Schrittweite in Ticks zwischen den Grid-Pending-Orders.
Amount
Gewinnziel in der Kontowährung.
LockDown
Abstand in Ticks zum Verschieben des Stops auf Breakeven.
CandleType
Kerzentyp für die Analyse.
Indikatoren
Highest – verfolgt das höchste Hoch über den Rückblickzeitraum.
Lowest – verfolgt das niedrigste Tief über den Rückblickzeitraum.
Order-Logik
Wenn ein Long-Setup erscheint:
Kauf zum Marktpreis mit dem Standard-Strategie-Volumen.
Vier zusätzliche Buy-Limit-Orders unterhalb des Einstiegs, jeweils um Grid Ticks getrennt und mit verdoppeltem Volumen.
Wenn ein Short-Setup erscheint:
Verkauf zum Marktpreis mit dem Standard-Strategie-Volumen.
Vier zusätzliche Sell-Limit-Orders oberhalb des Einstiegs mit denselben Grid- und Volumenverdopplungsregeln.
Wenn PnLAmount erreicht, werden alle offenen Positionen und ausstehenden Orders geschlossen.
Wenn LockDown größer als null ist und sich der Preis die angegebene Anzahl von Ticks zugunsten der Position bewegt hat, wird eine Schutz-Stop-Order einen Tick jenseits des Einstiegspreises platziert.
Hinweise
Diese Strategie demonstriert die grundlegende Grid-Handelslogik. Sie verwendet ausschließlich High-Level-API-Funktionen: SubscribeCandles, Indikator-Bindung und einfache Order-Hilfsfunktionen wie BuyMarket, SellLimit und 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()