MTC Combo v2-Strategie
Konvertiert aus dem MetaTrader-Skript "MTC Combo v2 (barabashkakvn's edition)".
Logik
- Verwendet die Steigung eines gleitenden Durchschnitts zur Bestimmung des grundlegenden Trends.
- Optionaler Perzeptron-Filter berechnet die gewichtete Summe der letzten Eröffnungspreisunterschiede über konfigurierbare Verzögerungen.
- Der Parameter
Passwählt aus, welche Perzeptron-Zweige verwendet werden:- 4: erfordert perceptron3 > 0 und perceptron2 > 0 für Long; perceptron3 <= 0 und perceptron1 < 0 für Short.
- 3: verwendet perceptron2 > 0 für Long.
- 2: verwendet perceptron1 < 0 für Short.
- andere Werte: handelt nur auf Basis der MA-Steigung.
Stop-Loss- und Take-Profit-Level werden aus den Parametern Sl* und Tp* entnommen.
Parameter
MaPeriod– Länge des gleitenden Durchschnitts.P2,P3,P4– Verzögerungen für Perzeptronen.Pass– Entscheidungsmodus.Sl1/Tp1,Sl2/Tp2,Sl3/Tp3– Stop und Ziel für jeden Zweig.CandleType– zu verarbeitende Kerzenserie.
Hinweise
Die Strategie hält jeweils eine einzelne Position und schließt sie, wenn Stop Loss oder Take Profit erreicht wird.
Haftungsausschluss
Nur für Bildungszwecke. Keine Anlageberatung.
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>
/// Simplified MTC Combo v2 strategy.
/// </summary>
public class MtcComboV2Strategy : Strategy
{
private readonly StrategyParam<int> _maPeriod;
private readonly StrategyParam<int> _p2;
private readonly StrategyParam<int> _p3;
private readonly StrategyParam<int> _p4;
private readonly StrategyParam<int> _pass;
private readonly StrategyParam<decimal> _sl1;
private readonly StrategyParam<decimal> _tp1;
private readonly StrategyParam<decimal> _sl2;
private readonly StrategyParam<decimal> _tp2;
private readonly StrategyParam<decimal> _sl3;
private readonly StrategyParam<decimal> _tp3;
private readonly StrategyParam<DataType> _candleType;
private SimpleMovingAverage _ma;
private decimal? _prevMa;
private readonly Queue<decimal> _opens = new();
private decimal _entry;
private decimal _sl;
private decimal _tp;
public int MaPeriod { get => _maPeriod.Value; set => _maPeriod.Value = value; }
public int P2 { get => _p2.Value; set => _p2.Value = value; }
public int P3 { get => _p3.Value; set => _p3.Value = value; }
public int P4 { get => _p4.Value; set => _p4.Value = value; }
public int Pass { get => _pass.Value; set => _pass.Value = value; }
public decimal Sl1 { get => _sl1.Value; set => _sl1.Value = value; }
public decimal Tp1 { get => _tp1.Value; set => _tp1.Value = value; }
public decimal Sl2 { get => _sl2.Value; set => _sl2.Value = value; }
public decimal Tp2 { get => _tp2.Value; set => _tp2.Value = value; }
public decimal Sl3 { get => _sl3.Value; set => _sl3.Value = value; }
public decimal Tp3 { get => _tp3.Value; set => _tp3.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public MtcComboV2Strategy()
{
_maPeriod = Param(nameof(MaPeriod), 10).SetGreaterThanZero();
_p2 = Param(nameof(P2), 20).SetGreaterThanZero();
_p3 = Param(nameof(P3), 20).SetGreaterThanZero();
_p4 = Param(nameof(P4), 20).SetGreaterThanZero();
_pass = Param(nameof(Pass), 10);
_sl1 = Param(nameof(Sl1), 50m);
_tp1 = Param(nameof(Tp1), 50m);
_sl2 = Param(nameof(Sl2), 50m);
_tp2 = Param(nameof(Tp2), 50m);
_sl3 = Param(nameof(Sl3), 50m);
_tp3 = Param(nameof(Tp3), 50m);
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame());
Volume = 1m;
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() =>
[(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_ma = default;
_prevMa = null;
_opens.Clear();
_entry = 0m;
_sl = 0m;
_tp = 0m;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_ma = new SMA { Length = MaPeriod };
var sub = SubscribeCandles(CandleType);
sub.Bind(_ma, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, sub);
DrawIndicator(area, _ma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal maValue)
{
if (candle.State != CandleStates.Finished)
return;
_opens.Enqueue(candle.OpenPrice);
var max = Math.Max(Math.Max(P2, P3), P4) * 4 + 5;
while (_opens.Count > max)
_opens.Dequeue();
if (Position != 0)
{
var step = Security.PriceStep ?? 1m;
var stop = Position > 0 ? _entry - _sl * step : _entry + _sl * step;
var take = Position > 0 ? _entry + _tp * step : _entry - _tp * step;
if ((Position > 0 && candle.LowPrice <= stop) || (Position < 0 && candle.HighPrice >= stop))
{
ClosePos();
return;
}
if ((Position > 0 && candle.HighPrice >= take) || (Position < 0 && candle.LowPrice <= take))
{
ClosePos();
return;
}
}
var slope = _prevMa is null ? 0m : maValue - _prevMa.Value;
_prevMa = maValue;
if (Position != 0)
return;
_sl = Sl1;
_tp = Tp1;
var dir = Supervisor(slope);
if (dir > 0m)
{
BuyMarket();
_entry = candle.ClosePrice;
}
else if (dir < 0m)
{
SellMarket();
_entry = candle.ClosePrice;
}
}
private void ClosePos()
{
if (Position > 0)
SellMarket();
else if (Position < 0)
BuyMarket();
}
private decimal Supervisor(decimal slope)
{
if (Pass == 4)
{
if (Perceptron(P4) > 0m && Perceptron(P3) > 0m)
{ _sl = Sl3; _tp = Tp3; return 1m; }
if (Perceptron(P4) <= 0m && Perceptron(P2) < 0m)
{ _sl = Sl2; _tp = Tp2; return -1m; }
}
else if (Pass == 3)
{
if (Perceptron(P3) > 0m)
{ _sl = Sl3; _tp = Tp3; return 1m; }
}
else if (Pass == 2)
{
if (Perceptron(P2) < 0m)
{ _sl = Sl2; _tp = Tp2; return -1m; }
}
return slope;
}
private decimal Perceptron(int p)
{
if (_opens.Count <= p * 4)
return 0m;
var arr = _opens.ToArray();
var len = arr.Length;
var a1 = arr[len - 1] - arr[len - 1 - p];
var a2 = arr[len - 1 - p] - arr[len - 1 - p * 2];
var a3 = arr[len - 1 - p * 2] - arr[len - 1 - p * 3];
var a4 = arr[len - 1 - p * 3] - arr[len - 1 - p * 4];
return a1 + a2 + a3 + a4;
}
}
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 SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class mtc_combo_v2_strategy(Strategy):
"""
MTC Combo v2: SMA slope + perceptron-based direction with manual SL/TP.
"""
def __init__(self):
super(mtc_combo_v2_strategy, self).__init__()
self._ma_period = self.Param("MaPeriod", 10).SetDisplay("MA Period", "SMA period", "Indicators")
self._p2 = self.Param("P2", 20).SetDisplay("P2", "Perceptron P2", "Signals")
self._p3 = self.Param("P3", 20).SetDisplay("P3", "Perceptron P3", "Signals")
self._p4 = self.Param("P4", 20).SetDisplay("P4", "Perceptron P4", "Signals")
self._pass_val = self.Param("Pass", 10).SetDisplay("Pass", "Strategy pass", "Signals")
self._sl1 = self.Param("Sl1", 50.0).SetDisplay("SL1", "Stop loss 1", "Risk")
self._tp1 = self.Param("Tp1", 50.0).SetDisplay("TP1", "Take profit 1", "Risk")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))).SetDisplay("Candle Type", "Candles", "General")
self._prev_ma = None
self._opens = []
self._entry = 0.0
self._sl = 50.0
self._tp = 50.0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(mtc_combo_v2_strategy, self).OnReseted()
self._prev_ma = None
self._opens = []
self._entry = 0.0
self._sl = float(self._sl1.Value)
self._tp = float(self._tp1.Value)
def OnStarted2(self, time):
super(mtc_combo_v2_strategy, self).OnStarted2(time)
ma = SimpleMovingAverage()
ma.Length = self._ma_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(ma, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ma)
self.DrawOwnTrades(area)
def _process_candle(self, candle, ma_val):
if candle.State != CandleStates.Finished:
return
ma = float(ma_val)
close = float(candle.ClosePrice)
open_p = float(candle.OpenPrice)
high = float(candle.HighPrice)
low = float(candle.LowPrice)
self._opens.append(open_p)
max_len = max(self._p2.Value, self._p3.Value, self._p4.Value) * 4 + 5
while len(self._opens) > max_len:
self._opens.pop(0)
if self.Position != 0:
step = 1.0
stop = self._entry - self._sl * step if self.Position > 0 else self._entry + self._sl * step
take = self._entry + self._tp * step if self.Position > 0 else self._entry - self._tp * step
if (self.Position > 0 and low <= stop) or (self.Position < 0 and high >= stop):
if self.Position > 0:
self.SellMarket()
else:
self.BuyMarket()
return
if (self.Position > 0 and high >= take) or (self.Position < 0 and low <= take):
if self.Position > 0:
self.SellMarket()
else:
self.BuyMarket()
return
slope = ma - self._prev_ma if self._prev_ma is not None else 0.0
self._prev_ma = ma
if self.Position != 0:
return
self._sl = float(self._sl1.Value)
self._tp = float(self._tp1.Value)
direction = self._supervisor(slope)
if direction > 0:
self.BuyMarket()
self._entry = close
elif direction < 0:
self.SellMarket()
self._entry = close
def _supervisor(self, slope):
p = self._pass_val.Value
if p == 4:
if self._perceptron(self._p4.Value) > 0 and self._perceptron(self._p3.Value) > 0:
return 1.0
if self._perceptron(self._p4.Value) <= 0 and self._perceptron(self._p2.Value) < 0:
return -1.0
elif p == 3:
if self._perceptron(self._p3.Value) > 0:
return 1.0
elif p == 2:
if self._perceptron(self._p2.Value) < 0:
return -1.0
return slope
def _perceptron(self, p):
if len(self._opens) <= p * 4:
return 0.0
arr = self._opens
n = len(arr)
a1 = arr[n - 1] - arr[n - 1 - p]
a2 = arr[n - 1 - p] - arr[n - 1 - p * 2]
a3 = arr[n - 1 - p * 2] - arr[n - 1 - p * 3]
a4 = arr[n - 1 - p * 3] - arr[n - 1 - p * 4]
return a1 + a2 + a3 + a4
def CreateClone(self):
return mtc_combo_v2_strategy()