Strategie Handelspanel Mit Autopilot
Diese Strategie portiert das MQL5-Beispiel Trade panel with autopilot auf das StockSharp-Framework. Sie berechnet bullischen und bärischen Druck über mehrere Zeitrahmen. Eine Position wird eröffnet, wenn der entsprechende Prozentsatz den Open %-Schwellenwert überschreitet, und geschlossen, wenn er unter den Close %-Level fällt. Optional kann ein fraktalbasierter Stop-Loss mit 10-Minuten-Kerzen angewendet werden.
Parameter
- Autopilot – automatisierten Handel aktivieren oder deaktivieren.
- Open % – Stimmen-Schwellenwert zum Öffnen einer Position.
- Close % – Schwellenwert zum Schließen einer bestehenden Position.
- Use Fixed Volume – wenn wahr, den Wert aus Fixed Volume verwenden.
- Fixed Volume – absolutes Ordervolumen.
- Volume % – Portfolio-Prozentsatz bei dynamischem Volumen.
- Use Stop Loss – Stop-Loss basierend auf jüngsten Fraktalen aktivieren.
Logik
Für jeden Zeitrahmen von 1 Minute bis 1 Monat vergleicht die Strategie die letzte Kerze mit der vorherigen. Jeder Vergleich von Eröffnung, Hoch, Tief und abgeleiteten Durchschnittswerten fügt eine Stimme für Kauf oder Verkauf hinzu. Die Prozentsätze der Kauf- und Verkaufsstimmen steuern die Orderplatzierung. Wenn aktiviert, dient das letzte Fraktal der 10-Minuten-Kerzen als Trailing-Stop.
Dieses Beispiel dient ausschließlich Bildungszwecken und stellt keine Anlageberatung dar.
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Trade panel autopilot strategy.
/// Aggregates candle comparison signals over a rolling window.
/// Buys when buy signal percentage exceeds threshold, sells on opposite.
/// </summary>
public class TradePanelWithAutopilotStrategy : Strategy
{
private readonly StrategyParam<decimal> _openThreshold;
private readonly StrategyParam<decimal> _closeThreshold;
private readonly StrategyParam<int> _windowSize;
private readonly StrategyParam<DataType> _candleType;
private readonly Queue<(int buy, int sell)> _signalWindow = new();
private ICandleMessage _prevCandle;
public decimal OpenThreshold { get => _openThreshold.Value; set => _openThreshold.Value = value; }
public decimal CloseThreshold { get => _closeThreshold.Value; set => _closeThreshold.Value = value; }
public int WindowSize { get => _windowSize.Value; set => _windowSize.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public TradePanelWithAutopilotStrategy()
{
_openThreshold = Param(nameof(OpenThreshold), 70m)
.SetDisplay("Open %", "Threshold for new position", "General");
_closeThreshold = Param(nameof(CloseThreshold), 45m)
.SetDisplay("Close %", "Threshold for closing", "General");
_windowSize = Param(nameof(WindowSize), 10)
.SetGreaterThanZero()
.SetDisplay("Window Size", "Number of candles for signal aggregation", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevCandle = null;
_signalWindow.Clear();
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevCandle = null;
_signalWindow.Clear();
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
if (_prevCandle == null)
{
_prevCandle = candle;
return;
}
// Compare current vs previous candle across 7 metrics
int buy = 0, sell = 0;
if (candle.OpenPrice > _prevCandle.OpenPrice) buy++; else sell++;
if (candle.HighPrice > _prevCandle.HighPrice) buy++; else sell++;
if (candle.LowPrice > _prevCandle.LowPrice) buy++; else sell++;
if (candle.ClosePrice > _prevCandle.ClosePrice) buy++; else sell++;
var hlCurr = (candle.HighPrice + candle.LowPrice) / 2m;
var hlPrev = (_prevCandle.HighPrice + _prevCandle.LowPrice) / 2m;
if (hlCurr > hlPrev) buy++; else sell++;
var hlcCurr = (candle.HighPrice + candle.LowPrice + candle.ClosePrice) / 3m;
var hlcPrev = (_prevCandle.HighPrice + _prevCandle.LowPrice + _prevCandle.ClosePrice) / 3m;
if (hlcCurr > hlcPrev) buy++; else sell++;
var hlccCurr = (candle.HighPrice + candle.LowPrice + 2m * candle.ClosePrice) / 4m;
var hlccPrev = (_prevCandle.HighPrice + _prevCandle.LowPrice + 2m * _prevCandle.ClosePrice) / 4m;
if (hlccCurr > hlccPrev) buy++; else sell++;
_signalWindow.Enqueue((buy, sell));
while (_signalWindow.Count > WindowSize)
_signalWindow.Dequeue();
_prevCandle = candle;
if (_signalWindow.Count < WindowSize)
return;
// Aggregate signals
int totalBuy = 0, totalSell = 0;
foreach (var (b, s) in _signalWindow)
{
totalBuy += b;
totalSell += s;
}
var total = totalBuy + totalSell;
if (total == 0) return;
var buyPct = (decimal)totalBuy / total * 100m;
var sellPct = (decimal)totalSell / total * 100m;
// Close positions
if (Position > 0 && buyPct < CloseThreshold)
SellMarket();
else if (Position < 0 && sellPct < CloseThreshold)
BuyMarket();
// Open new positions
if (Position == 0)
{
if (buyPct >= OpenThreshold)
BuyMarket();
else if (sellPct >= OpenThreshold)
SellMarket();
}
}
}
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.Strategies import Strategy
class trade_panel_with_autopilot_strategy(Strategy):
def __init__(self):
super(trade_panel_with_autopilot_strategy, self).__init__()
self._open_threshold = self.Param("OpenThreshold", 70.0) \
.SetDisplay("Open %", "Threshold for new position", "General")
self._close_threshold = self.Param("CloseThreshold", 45.0) \
.SetDisplay("Close %", "Threshold for closing", "General")
self._window_size = self.Param("WindowSize", 10) \
.SetDisplay("Window Size", "Number of candles for signal aggregation", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._signal_window = []
self._prev_candle = None
@property
def open_threshold(self):
return self._open_threshold.Value
@property
def close_threshold(self):
return self._close_threshold.Value
@property
def window_size(self):
return self._window_size.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(trade_panel_with_autopilot_strategy, self).OnReseted()
self._prev_candle = None
self._signal_window = []
def OnStarted2(self, time):
super(trade_panel_with_autopilot_strategy, self).OnStarted2(time)
self._prev_candle = None
self._signal_window = []
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
if self._prev_candle is None:
self._prev_candle = candle
return
buy = 0
sell = 0
if float(candle.OpenPrice) > float(self._prev_candle.OpenPrice):
buy += 1
else:
sell += 1
if float(candle.HighPrice) > float(self._prev_candle.HighPrice):
buy += 1
else:
sell += 1
if float(candle.LowPrice) > float(self._prev_candle.LowPrice):
buy += 1
else:
sell += 1
if float(candle.ClosePrice) > float(self._prev_candle.ClosePrice):
buy += 1
else:
sell += 1
hl_curr = (float(candle.HighPrice) + float(candle.LowPrice)) / 2.0
hl_prev = (float(self._prev_candle.HighPrice) + float(self._prev_candle.LowPrice)) / 2.0
if hl_curr > hl_prev:
buy += 1
else:
sell += 1
hlc_curr = (float(candle.HighPrice) + float(candle.LowPrice) + float(candle.ClosePrice)) / 3.0
hlc_prev = (float(self._prev_candle.HighPrice) + float(self._prev_candle.LowPrice) + float(self._prev_candle.ClosePrice)) / 3.0
if hlc_curr > hlc_prev:
buy += 1
else:
sell += 1
hlcc_curr = (float(candle.HighPrice) + float(candle.LowPrice) + 2.0 * float(candle.ClosePrice)) / 4.0
hlcc_prev = (float(self._prev_candle.HighPrice) + float(self._prev_candle.LowPrice) + 2.0 * float(self._prev_candle.ClosePrice)) / 4.0
if hlcc_curr > hlcc_prev:
buy += 1
else:
sell += 1
self._signal_window.append((buy, sell))
ws = int(self.window_size)
while len(self._signal_window) > ws:
self._signal_window.pop(0)
self._prev_candle = candle
if len(self._signal_window) < ws:
return
total_buy = 0
total_sell = 0
for b, s in self._signal_window:
total_buy += b
total_sell += s
total = total_buy + total_sell
if total == 0:
return
buy_pct = float(total_buy) / float(total) * 100.0
sell_pct = float(total_sell) / float(total) * 100.0
close_threshold = float(self.close_threshold)
open_threshold = float(self.open_threshold)
if self.Position > 0 and buy_pct < close_threshold:
self.SellMarket()
elif self.Position < 0 and sell_pct < close_threshold:
self.BuyMarket()
if self.Position == 0:
if buy_pct >= open_threshold:
self.BuyMarket()
elif sell_pct >= open_threshold:
self.SellMarket()
def CreateClone(self):
return trade_panel_with_autopilot_strategy()