PROphet Strategie
Die PROphet Strategie bewertet Preisbereiche der letzten drei abgeschlossenen Kerzen, um während bestimmter Handelszeiten Signale zu generieren. Eine benutzerdefinierte Funktion kombiniert die Bereiche mit benutzerdefinierten Koeffizienten. Wenn die Funktion positiv ist, öffnet die Strategie eine Position in der entsprechenden Richtung.
Long-Trades verwenden die Koeffizienten X1..X4 und einen Trailing Stop, der durch BuyStopPoints definiert wird. Short-Trades verwenden die Koeffizienten Y1..Y4 und SellStopPoints. Stops werden nachgezogen, wenn sich der Preis um mehr als den Spread plus das Doppelte der Stop-Distanz zugunsten der Position bewegt. Positionen werden nach 18:00 Uhr oder beim Erreichen des Trailing Stops geschlossen.
Details
- Einstiegskriterien
- Long:
Qu(X1,X2,X3,X4) > 0und aktuelle Stunde zwischen 10 und 18. - Short:
Qu(Y1,Y2,Y3,Y4) > 0und aktuelle Stunde zwischen 10 und 18.
- Long:
- Ausstiegskriterien
- Long: Stunde > 18 oder bestes Geldkurs fällt unter den Trailing Stop.
- Short: Stunde > 18 oder bester Briefkurs steigt über den Trailing Stop.
- Parameter
EnableBuy– Öffnen von Long-Positionen erlauben.EnableSell– Öffnen von Short-Positionen erlauben.X1, X2, X3, X4– Koeffizienten für die Long-Signalfunktion.Y1, Y2, Y3, Y4– Koeffizienten für die Short-Signalfunktion.BuyStopPoints– Trailing Stop-Abstand in Punkten für Long-Trades.SellStopPoints– Trailing Stop-Abstand in Punkten für Short-Trades.CandleType– Kerzentyp für Berechnungen (Standard 5 Minuten).
- Filter
- Kategorie: Intraday
- Richtung: Beide
- Indikatoren: Keine
- Stops: Trailing
- Komplexität: Moderat
- Zeitrahmen: Kurzfristig
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>
/// PROphet strategy translated from MQL.
/// Uses price ranges of previous candles to generate signals
/// and applies trailing stops.
/// </summary>
public class PROphetStrategy : Strategy
{
private readonly StrategyParam<int> _x1;
private readonly StrategyParam<int> _x2;
private readonly StrategyParam<int> _x3;
private readonly StrategyParam<int> _x4;
private readonly StrategyParam<int> _y1;
private readonly StrategyParam<int> _y2;
private readonly StrategyParam<int> _y3;
private readonly StrategyParam<int> _y4;
private readonly StrategyParam<decimal> _stopMultiplier;
private readonly StrategyParam<DataType> _candleType;
private decimal _stopPrice;
private decimal _prevHigh1;
private decimal _prevLow1;
private decimal _prevHigh2;
private decimal _prevLow2;
private decimal _prevHigh3;
private decimal _prevLow3;
private int _historyCount;
/// <summary>First coefficient for the buy signal.</summary>
public int X1 { get => _x1.Value; set => _x1.Value = value; }
/// <summary>Second coefficient for the buy signal.</summary>
public int X2 { get => _x2.Value; set => _x2.Value = value; }
/// <summary>Third coefficient for the buy signal.</summary>
public int X3 { get => _x3.Value; set => _x3.Value = value; }
/// <summary>Fourth coefficient for the buy signal.</summary>
public int X4 { get => _x4.Value; set => _x4.Value = value; }
/// <summary>First coefficient for the sell signal.</summary>
public int Y1 { get => _y1.Value; set => _y1.Value = value; }
/// <summary>Second coefficient for the sell signal.</summary>
public int Y2 { get => _y2.Value; set => _y2.Value = value; }
/// <summary>Third coefficient for the sell signal.</summary>
public int Y3 { get => _y3.Value; set => _y3.Value = value; }
/// <summary>Fourth coefficient for the sell signal.</summary>
public int Y4 { get => _y4.Value; set => _y4.Value = value; }
/// <summary>Stop loss multiplier.</summary>
public decimal StopMultiplier { get => _stopMultiplier.Value; set => _stopMultiplier.Value = value; }
/// <summary>The candle type.</summary>
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
/// <summary>
/// Constructor.
/// </summary>
public PROphetStrategy()
{
_x1 = Param(nameof(X1), 9).SetDisplay("X1", "First coefficient for buy", "Buy");
_x2 = Param(nameof(X2), 29).SetDisplay("X2", "Second coefficient for buy", "Buy");
_x3 = Param(nameof(X3), 94).SetDisplay("X3", "Third coefficient for buy", "Buy");
_x4 = Param(nameof(X4), 125).SetDisplay("X4", "Fourth coefficient for buy", "Buy");
_y1 = Param(nameof(Y1), 61).SetDisplay("Y1", "First coefficient for sell", "Sell");
_y2 = Param(nameof(Y2), 100).SetDisplay("Y2", "Second coefficient for sell", "Sell");
_y3 = Param(nameof(Y3), 117).SetDisplay("Y3", "Third coefficient for sell", "Sell");
_y4 = Param(nameof(Y4), 31).SetDisplay("Y4", "Fourth coefficient for sell", "Sell");
_stopMultiplier = Param(nameof(StopMultiplier), 0.005m)
.SetDisplay("Stop Multiplier", "Stop loss as fraction of price", "Risk");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles for calculations", "General");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_stopPrice = 0m;
_prevHigh1 = 0m;
_prevLow1 = 0m;
_prevHigh2 = 0m;
_prevLow2 = 0m;
_prevHigh3 = 0m;
_prevLow3 = 0m;
_historyCount = 0;
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_historyCount = 0;
_stopPrice = 0;
var atr = new AverageTrueRange { Length = 14 };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(atr, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, atr);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal atrValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var close = candle.ClosePrice;
if (_historyCount >= 3)
{
if (Position > 0)
{
// Trailing stop for long
var newStop = close - atrValue * 2;
if (newStop > _stopPrice)
_stopPrice = newStop;
if (close <= _stopPrice)
SellMarket(Math.Abs(Position));
}
else if (Position < 0)
{
// Trailing stop for short
var newStop = close + atrValue * 2;
if (newStop < _stopPrice || _stopPrice == 0)
_stopPrice = newStop;
if (close >= _stopPrice)
BuyMarket(Math.Abs(Position));
}
else
{
var buySignal = Qu(X1, X2, X3, X4);
var sellSignal = Qu(Y1, Y2, Y3, Y4);
if (buySignal > 0 && sellSignal <= 0)
{
_stopPrice = close - atrValue * 2;
BuyMarket();
}
else if (sellSignal > 0 && buySignal <= 0)
{
_stopPrice = close + atrValue * 2;
SellMarket();
}
}
}
UpdateHistory(candle);
}
private void UpdateHistory(ICandleMessage candle)
{
_prevHigh3 = _prevHigh2;
_prevLow3 = _prevLow2;
_prevHigh2 = _prevHigh1;
_prevLow2 = _prevLow1;
_prevHigh1 = candle.HighPrice;
_prevLow1 = candle.LowPrice;
if (_historyCount < 3)
_historyCount++;
}
private decimal Qu(int q1, int q2, int q3, int q4)
{
return (q1 - 100) * Math.Abs(_prevHigh1 - _prevLow2)
+ (q2 - 100) * Math.Abs(_prevHigh3 - _prevLow2)
+ (q3 - 100) * Math.Abs(_prevHigh2 - _prevLow1)
+ (q4 - 100) * Math.Abs(_prevHigh2 - _prevLow3);
}
}
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, Unit, UnitTypes
from StockSharp.Algo.Indicators import AverageTrueRange
from StockSharp.Algo.Strategies import Strategy
class pr_ophet_strategy(Strategy):
def __init__(self):
super(pr_ophet_strategy, self).__init__()
self._x1 = self.Param("X1", 9)
self._x2 = self.Param("X2", 29)
self._x3 = self.Param("X3", 94)
self._x4 = self.Param("X4", 125)
self._y1 = self.Param("Y1", 61)
self._y2 = self.Param("Y2", 100)
self._y3 = self.Param("Y3", 117)
self._y4 = self.Param("Y4", 31)
self._stop_multiplier = self.Param("StopMultiplier", 0.005)
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1)))
self._stop_price = 0.0
self._prev_high1 = 0.0
self._prev_low1 = 0.0
self._prev_high2 = 0.0
self._prev_low2 = 0.0
self._prev_high3 = 0.0
self._prev_low3 = 0.0
self._history_count = 0
@property
def X1(self):
return self._x1.Value
@X1.setter
def X1(self, value):
self._x1.Value = value
@property
def X2(self):
return self._x2.Value
@X2.setter
def X2(self, value):
self._x2.Value = value
@property
def X3(self):
return self._x3.Value
@X3.setter
def X3(self, value):
self._x3.Value = value
@property
def X4(self):
return self._x4.Value
@X4.setter
def X4(self, value):
self._x4.Value = value
@property
def Y1(self):
return self._y1.Value
@Y1.setter
def Y1(self, value):
self._y1.Value = value
@property
def Y2(self):
return self._y2.Value
@Y2.setter
def Y2(self, value):
self._y2.Value = value
@property
def Y3(self):
return self._y3.Value
@Y3.setter
def Y3(self, value):
self._y3.Value = value
@property
def Y4(self):
return self._y4.Value
@Y4.setter
def Y4(self, value):
self._y4.Value = value
@property
def StopMultiplier(self):
return self._stop_multiplier.Value
@StopMultiplier.setter
def StopMultiplier(self, value):
self._stop_multiplier.Value = value
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
def OnStarted2(self, time):
super(pr_ophet_strategy, self).OnStarted2(time)
self._history_count = 0
self._stop_price = 0.0
self._prev_high1 = 0.0
self._prev_low1 = 0.0
self._prev_high2 = 0.0
self._prev_low2 = 0.0
self._prev_high3 = 0.0
self._prev_low3 = 0.0
atr = AverageTrueRange()
atr.Length = 14
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(atr, self.ProcessCandle).Start()
self.StartProtection(
Unit(2000.0, UnitTypes.Absolute),
Unit(1000.0, UnitTypes.Absolute))
def _qu(self, q1, q2, q3, q4):
return ((q1 - 100) * abs(self._prev_high1 - self._prev_low2)
+ (q2 - 100) * abs(self._prev_high3 - self._prev_low2)
+ (q3 - 100) * abs(self._prev_high2 - self._prev_low1)
+ (q4 - 100) * abs(self._prev_high2 - self._prev_low3))
def ProcessCandle(self, candle, atr_value):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
atr_val = float(atr_value)
if self._history_count >= 3:
if self.Position > 0:
new_stop = close - atr_val * 2.0
if new_stop > self._stop_price:
self._stop_price = new_stop
if close <= self._stop_price:
self.SellMarket()
elif self.Position < 0:
new_stop = close + atr_val * 2.0
if new_stop < self._stop_price or self._stop_price == 0.0:
self._stop_price = new_stop
if close >= self._stop_price:
self.BuyMarket()
else:
buy_signal = self._qu(int(self.X1), int(self.X2), int(self.X3), int(self.X4))
sell_signal = self._qu(int(self.Y1), int(self.Y2), int(self.Y3), int(self.Y4))
if buy_signal > 0.0 and sell_signal <= 0.0:
self._stop_price = close - atr_val * 2.0
self.BuyMarket()
elif sell_signal > 0.0 and buy_signal <= 0.0:
self._stop_price = close + atr_val * 2.0
self.SellMarket()
self._update_history(candle)
def _update_history(self, candle):
self._prev_high3 = self._prev_high2
self._prev_low3 = self._prev_low2
self._prev_high2 = self._prev_high1
self._prev_low2 = self._prev_low1
self._prev_high1 = float(candle.HighPrice)
self._prev_low1 = float(candle.LowPrice)
if self._history_count < 3:
self._history_count += 1
def OnReseted(self):
super(pr_ophet_strategy, self).OnReseted()
self._stop_price = 0.0
self._prev_high1 = 0.0
self._prev_low1 = 0.0
self._prev_high2 = 0.0
self._prev_low2 = 0.0
self._prev_high3 = 0.0
self._prev_low3 = 0.0
self._history_count = 0
def CreateClone(self):
return pr_ophet_strategy()