Panel Joke-Strategie
Diese Strategie konvertiert das originale MetaTrader-panel-joke-System in StockSharp. Sie vergleicht die aktuelle Kerze mit der vorherigen anhand von sieben Preiskennzahlen (Eröffnung, Hoch, Tief, Durchschnitt von Hoch und Tief, Schluss, Durchschnitt von Hoch/Tief/Schluss und gewichteter Durchschnitt von Hoch/Tief/Schluss). Jede gestiegene Kennzahl zählt für ein potentielles Long-Setup; jede gefallene für ein Short-Setup.
Wenn der Parameter Enable Autopilot auf true gesetzt ist, öffnet oder kehrt die Strategie Positionen automatisch basierend darauf, welche Seite mehr Punkte hat. Keine zusätzlichen Indikatoren oder Stop-Regeln werden verwendet.
Details
- Einstiegskriterien:
- Long: Buy counter > Sell counter.
- Short: Sell counter > Buy counter.
- Ausstiegskriterien: Umkehrung bei entgegengesetztem Signal.
- Stops: Keine.
- Standardwerte:
Enable Autopilot=true.Candle Type= 5-Minuten-Zeitrahmen.
- Filter:
- Kategorie: Price action
- Richtung: Beide
- Indikatoren: Keine
- Stops: Nein
- Komplexität: Grundlegend
- Zeitrahmen: Intraday
- Saisonalität: Nein
- Neuronale Netze: Nein
- Divergenz: Nein
- Risikolevel: Hoch
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Simple heuristic strategy comparing current and previous candles.
/// Counts how many price components moved up or down and trades on majority.
/// </summary>
public class PanelJokeStrategy : Strategy
{
private readonly StrategyParam<bool> _enableAutopilot;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevOpen;
private decimal _prevHigh;
private decimal _prevLow;
private decimal _prevClose;
private bool _hasPrev;
/// <summary>
/// Enables automatic order execution.
/// </summary>
public bool EnableAutopilot
{
get => _enableAutopilot.Value;
set => _enableAutopilot.Value = value;
}
/// <summary>
/// Candle type used for calculations.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initializes parameters.
/// </summary>
public PanelJokeStrategy()
{
_enableAutopilot = Param(nameof(EnableAutopilot), true)
.SetDisplay("Enable Autopilot", "Automatically trade based on signals", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Timeframe for incoming candles", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevOpen = 0;
_prevHigh = 0;
_prevLow = 0;
_prevClose = 0;
_hasPrev = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var warmup = new ExponentialMovingAverage { Length = 5 };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(warmup, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal _warmupVal)
{
if (candle.State != CandleStates.Finished)
return;
if (!_hasPrev)
{
_prevOpen = candle.OpenPrice;
_prevHigh = candle.HighPrice;
_prevLow = candle.LowPrice;
_prevClose = candle.ClosePrice;
_hasPrev = true;
return;
}
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevOpen = candle.OpenPrice;
_prevHigh = candle.HighPrice;
_prevLow = candle.LowPrice;
_prevClose = candle.ClosePrice;
return;
}
var buy = 0;
var sell = 0;
// Compare each OHLC component
if (candle.OpenPrice > _prevOpen)
buy++;
else
sell++;
if (candle.HighPrice > _prevHigh)
buy++;
else
sell++;
if (candle.LowPrice > _prevLow)
buy++;
else
sell++;
var avgHL = (candle.HighPrice + candle.LowPrice) / 2m;
var prevAvgHL = (_prevHigh + _prevLow) / 2m;
if (avgHL > prevAvgHL)
buy++;
else
sell++;
if (candle.ClosePrice > _prevClose)
buy++;
else
sell++;
var avgHLC = (candle.HighPrice + candle.LowPrice + candle.ClosePrice) / 3m;
var prevAvgHLC = (_prevHigh + _prevLow + _prevClose) / 3m;
if (avgHLC > prevAvgHLC)
buy++;
else
sell++;
var avgHLCC = (candle.HighPrice + candle.LowPrice + 2m * candle.ClosePrice) / 4m;
var prevAvgHLCC = (_prevHigh + _prevLow + 2m * _prevClose) / 4m;
if (avgHLCC > prevAvgHLCC)
buy++;
else
sell++;
if (buy > sell && Position <= 0)
BuyMarket();
else if (sell > buy && Position >= 0)
SellMarket();
_prevOpen = candle.OpenPrice;
_prevHigh = candle.HighPrice;
_prevLow = candle.LowPrice;
_prevClose = candle.ClosePrice;
}
}
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 ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class panel_joke_strategy(Strategy):
def __init__(self):
super(panel_joke_strategy, self).__init__()
self._enable_autopilot = self.Param("EnableAutopilot", True) \
.SetDisplay("Enable Autopilot", "Automatically trade based on signals", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Timeframe for incoming candles", "General")
self._prev_open = 0.0
self._prev_high = 0.0
self._prev_low = 0.0
self._prev_close = 0.0
self._has_prev = False
@property
def enable_autopilot(self):
return self._enable_autopilot.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(panel_joke_strategy, self).OnReseted()
self._prev_open = 0.0
self._prev_high = 0.0
self._prev_low = 0.0
self._prev_close = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(panel_joke_strategy, self).OnStarted2(time)
warmup = ExponentialMovingAverage()
warmup.Length = 5
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(warmup, self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def process_candle(self, candle, _warmup_val):
if candle.State != CandleStates.Finished:
return
o = float(candle.OpenPrice)
h = float(candle.HighPrice)
l = float(candle.LowPrice)
c = float(candle.ClosePrice)
if not self._has_prev:
self._prev_open = o
self._prev_high = h
self._prev_low = l
self._prev_close = c
self._has_prev = True
return
buy = 0
sell = 0
if o > self._prev_open:
buy += 1
else:
sell += 1
if h > self._prev_high:
buy += 1
else:
sell += 1
if l > self._prev_low:
buy += 1
else:
sell += 1
avg_hl = (h + l) / 2.0
prev_avg_hl = (self._prev_high + self._prev_low) / 2.0
if avg_hl > prev_avg_hl:
buy += 1
else:
sell += 1
if c > self._prev_close:
buy += 1
else:
sell += 1
avg_hlc = (h + l + c) / 3.0
prev_avg_hlc = (self._prev_high + self._prev_low + self._prev_close) / 3.0
if avg_hlc > prev_avg_hlc:
buy += 1
else:
sell += 1
avg_hlcc = (h + l + 2.0 * c) / 4.0
prev_avg_hlcc = (self._prev_high + self._prev_low + 2.0 * self._prev_close) / 4.0
if avg_hlcc > prev_avg_hlcc:
buy += 1
else:
sell += 1
if buy > sell and self.Position <= 0:
self.BuyMarket()
elif sell > buy and self.Position >= 0:
self.SellMarket()
self._prev_open = o
self._prev_high = h
self._prev_low = l
self._prev_close = c
def CreateClone(self):
return panel_joke_strategy()