Diese Strategie implementiert den "Loco"-Indikator, der ursprünglich in MQL5 geschrieben wurde. Der Indikator analysiert Kerzenpreise und weist eine Farbe zu (grün oder magenta). Ein Farbwechsel signalisiert eine Trendumkehr.
Logik
Der Indikator berechnet eine Reihe anhand eines konfigurierbaren Preises (standardmäßig Schlusskurs) und einer Rückblicklänge.
Wenn die Farbe von Magenta auf Grün wechselt, schließt die Strategie jede Short-Position und öffnet eine Long-Position.
Wenn die Farbe von Grün auf Magenta wechselt, schließt die Strategie jede Long-Position und öffnet eine Short-Position.
Parameter
Candle Type – Typ der in der Strategie verwendeten Kerzen.
Length – Anzahl der Balken zum Preisvergleich.
Price Type – Preis, der bei der Indikatorberechnung verwendet wird.
Hinweise
Die Strategie verwendet eine eigene Implementierung des Loco-Indikators. Eine Python-Version ist nicht vorhanden.
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>
/// Strategy based on the Loco indicator (price direction detector).
/// </summary>
public class LocoStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _length;
private readonly Queue<decimal> _prices = new();
private decimal? _prev;
private int _prevColor = -1;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int Length { get => _length.Value; set => _length.Value = value; }
public LocoStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
_length = Param(nameof(Length), 1)
.SetDisplay("Length", "Lookback length", "Indicator")
.SetOptimize(1, 10, 1);
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prices.Clear();
_prev = null;
_prevColor = -1;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var subscription = SubscribeCandles(CandleType);
subscription.Bind(ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
var price = candle.ClosePrice;
_prices.Enqueue(price);
if (_prices.Count <= Length)
{
_prev = price;
return;
}
var series1 = _prices.Dequeue();
var prev = _prev ?? price;
decimal result;
int color;
if (price == prev)
{
result = prev;
color = 0;
}
else if (series1 > prev && price > prev)
{
result = Math.Max(prev, price * 0.999m);
color = 0;
}
else if (series1 < prev && price < prev)
{
result = Math.Min(prev, price * 1.001m);
color = 1;
}
else
{
if (price > prev)
{
result = price * 0.999m;
color = 0;
}
else
{
result = price * 1.001m;
color = 1;
}
}
_prev = result;
if (_prevColor == -1)
{
_prevColor = color;
return;
}
if (color != _prevColor)
{
if (color == 1)
{
if (Position < 0)
BuyMarket();
if (Position <= 0)
BuyMarket();
}
else
{
if (Position > 0)
SellMarket();
if (Position >= 0)
SellMarket();
}
}
_prevColor = color;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Strategies import Strategy
class loco_strategy(Strategy):
def __init__(self):
super(loco_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._length = self.Param("Length", 1) \
.SetDisplay("Length", "Lookback length", "Indicator")
self._prices = []
self._prev = None
self._prev_color = -1
@property
def candle_type(self):
return self._candle_type.Value
@property
def length(self):
return self._length.Value
def OnReseted(self):
super(loco_strategy, self).OnReseted()
self._prices = []
self._prev = None
self._prev_color = -1
def OnStarted2(self, time):
super(loco_strategy, self).OnStarted2(time)
self._prices = []
self._prev = None
self._prev_color = -1
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self.process_candle).Start()
def process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
price = float(candle.ClosePrice)
ln = int(self.length)
self._prices.append(price)
if len(self._prices) <= ln:
self._prev = price
return
series1 = self._prices.pop(0)
prev = self._prev if self._prev is not None else price
if price == prev:
result = prev
color = 0
elif series1 > prev and price > prev:
result = max(prev, price * 0.999)
color = 0
elif series1 < prev and price < prev:
result = min(prev, price * 1.001)
color = 1
else:
if price > prev:
result = price * 0.999
color = 0
else:
result = price * 1.001
color = 1
self._prev = result
if self._prev_color == -1:
self._prev_color = color
return
if color != self._prev_color:
if color == 1:
if self.Position < 0:
self.BuyMarket()
if self.Position <= 0:
self.BuyMarket()
else:
if self.Position > 0:
self.SellMarket()
if self.Position >= 0:
self.SellMarket()
self._prev_color = color
def CreateClone(self):
return loco_strategy()