Diese Strategie reproduziert die Kernlogik des ursprünglichen MQL4-Experten "trade panel with autopilot". Sie aggregiert die Preisrichtung über mehrere Zeitrahmen und öffnet oder schließt eine einzelne Position entsprechend der vorherrschenden Marktstimmung.
Die Strategie überwacht die letzten zwei Kerzen in acht verschiedenen Zeitrahmen (M1, M5, M15, M30, H1, H4, D1, W1). Für jeden Zeitrahmen vergleicht sie mehrere Preiskomponenten zwischen den beiden aktuellsten Kerzen:
Open
High
Low
(High + Low) / 2
Close
(High + Low + Close) / 3
(High + Low + Close + Close) / 4
Jeder Vergleich trägt zu einem Kauf- oder Verkaufs-Score bei. Scores aus allen Zeitrahmen werden summiert und in Prozente umgerechnet. Wenn der Kauf- oder Verkaufsprozentsatz einen konfigurierten Schwellenwert überschreitet, eröffnet die Strategie eine Position. Die bestehende Position wird geschlossen, wenn der entgegengesetzte Prozentsatz unter den Schließungsschwellenwert fällt.
Parameter
Autopilot — aktiviert oder deaktiviert den automatischen Handel.
OpenThreshold — Prozentniveau zum Öffnen einer neuen Position. Standard: 85.
CloseThreshold — Prozentniveau zum Schließen einer bestehenden Position. Standard: 55.
LotFixed — festes Ordervolumen wenn UseFixedLot aktiviert ist.
LotPercent — Volumen als Prozentsatz des Portfoliowerts wenn UseFixedLot deaktiviert ist.
UseFixedLot — wechselt zwischen festem und prozentualem Volumen.
UseStopLoss — aktiviert den Positionsschutz wenn eingeschaltet.
Handelslogik
Kerzen auf allen konfigurierten Zeitrahmen abonnieren.
Kauf-/Verkaufs-Scores für jede neue abgeschlossene Kerze berechnen.
Scores über alle Zeitrahmen summieren und Kauf-/Verkaufsprozentsätze berechnen.
Wenn Autopilot deaktiviert ist, verfolgt die Strategie nur die Scores.
Wenn keine Position offen ist und der Kaufprozentsatz OpenThreshold überschreitet, eine Long-Position eingehen. Wenn der Verkaufsprozentsatz den Schwellenwert überschreitet, eine Short-Position eingehen.
Wenn eine Long-Position besteht und der Kaufprozentsatz unter CloseThreshold fällt, die Position schließen. Die gleiche Logik gilt für Short-Positionen unter Verwendung des Verkaufsprozentsatzes.
Hinweise
Die Strategie hält zu einem Zeitpunkt höchstens eine offene Position.
Optionales Stop-Loss-Management wird über StartProtection() aktiviert, wenn UseStopLoss wahr ist.
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 v2.
/// Aggregates 7 price comparison metrics over rolling window.
/// Buys when buy percentage exceeds open threshold, sells on opposite.
/// </summary>
public class TradePanelAutopilotStrategy : 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 TradePanelAutopilotStrategy()
{
_openThreshold = Param(nameof(OpenThreshold), 65m)
.SetDisplay("Open %", "Threshold for new position", "General");
_closeThreshold = Param(nameof(CloseThreshold), 40m)
.SetDisplay("Close %", "Threshold for closing", "General");
_windowSize = Param(nameof(WindowSize), 8)
.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;
}
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;
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;
if (Position > 0 && buyPct < CloseThreshold)
SellMarket();
else if (Position < 0 && sellPct < CloseThreshold)
BuyMarket();
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_autopilot_strategy(Strategy):
def __init__(self):
super(trade_panel_autopilot_strategy, self).__init__()
self._open_threshold = self.Param("OpenThreshold", 65.0) \
.SetDisplay("Open %", "Threshold for new position", "General")
self._close_threshold = self.Param("CloseThreshold", 40.0) \
.SetDisplay("Close %", "Threshold for closing", "General")
self._window_size = self.Param("WindowSize", 8) \
.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_autopilot_strategy, self).OnReseted()
self._prev_candle = None
self._signal_window = []
def OnStarted2(self, time):
super(trade_panel_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_autopilot_strategy()