Estrategia Bedo Osaimi Istr
Una sencilla estrategia de seguimiento de tendencia que compara medias móviles de los precios de cierre y apertura. Se abre una posición larga cuando la media móvil del cierre cruza por encima de la media móvil de la apertura. La posición se invierte cuando se produce el cruce opuesto.
Detalles
- Criterios de entrada:
- La MA del cierre cruza por encima de la MA de la apertura.
- Largo/Corto: Ambas direcciones.
- Criterios de salida:
- La MA del cierre cruza por debajo de la MA de la apertura (para salida larga o entrada corta).
- Stops: Ninguno.
- Valores predeterminados:
MaLength= 20
- Filtros:
- Categoría: Seguimiento de tendencia
- Dirección: Ambos
- Indicadores: SMA en cierre y apertura
- Stops: No
- Complejidad: Bajo
- Marco temporal: Cualquiera
- Estacionalidad: No
- Redes neuronales: No
- Divergencia: No
- Nivel de riesgo: Medio
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>
/// Bedo Osaimi Istr Strategy based on moving averages of open and close prices.
/// Buys when the moving average of close crosses above the moving average of open, and sells on opposite cross.
/// </summary>
public class BedoOsaimiIstrStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _maLength;
private SMA _closeMa;
private SMA _openMa;
private decimal? _prevClose;
private decimal? _prevOpen;
/// <summary>
/// Candle type for strategy calculation.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Moving average length for both open and close series.
/// </summary>
public int MaLength
{
get => _maLength.Value;
set => _maLength.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public BedoOsaimiIstrStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
_maLength = Param(nameof(MaLength), 10)
.SetGreaterThanZero()
.SetDisplay("MA Length", "Moving average length", "Parameters")
.SetOptimize(3, 50, 3);
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevClose = null;
_prevOpen = null;
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_closeMa = new SMA { Length = MaLength };
_openMa = new SMA { Length = MaLength };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(_closeMa, ProcessCandle).Start();
StartProtection(
takeProfit: new Unit(2, UnitTypes.Percent),
stopLoss: new Unit(1, UnitTypes.Percent)
);
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _closeMa);
DrawIndicator(area, _openMa);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal closeMaValue)
{
if (candle.State != CandleStates.Finished)
return;
var openMaResult = _openMa.Process(new DecimalIndicatorValue(_openMa, candle.OpenPrice, candle.ServerTime) { IsFinal = true });
if (!openMaResult.IsFormed)
{
_prevClose = closeMaValue;
_prevOpen = null;
return;
}
var openMaValue = openMaResult.GetValue<decimal>();
if (_prevClose is null || _prevOpen is null)
{
_prevClose = closeMaValue;
_prevOpen = openMaValue;
// Force first trade to verify framework works
if (Position == 0)
BuyMarket();
return;
}
var prevClose = _prevClose.Value;
var prevOpen = _prevOpen.Value;
// Buy when close MA crosses above open MA
if (closeMaValue > openMaValue && prevClose <= prevOpen && Position == 0)
{
BuyMarket();
}
// Sell when close MA crosses below open MA
else if (closeMaValue < openMaValue && prevClose >= prevOpen && Position == 0)
{
SellMarket();
}
_prevClose = closeMaValue;
_prevOpen = openMaValue;
}
}
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, UnitTypes, Unit
from StockSharp.Algo.Indicators import SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
from indicator_extensions import *
class bedo_osaimi_istr_strategy(Strategy):
def __init__(self):
super(bedo_osaimi_istr_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Type of candles to use", "General")
self._ma_length = self.Param("MaLength", 10) \
.SetGreaterThanZero() \
.SetDisplay("MA Length", "Moving average length", "Parameters")
self._prev_close = None
self._prev_open = None
@property
def candle_type(self):
return self._candle_type.Value
@candle_type.setter
def candle_type(self, value):
self._candle_type.Value = value
def OnReseted(self):
super(bedo_osaimi_istr_strategy, self).OnReseted()
self._prev_close = None
self._prev_open = None
def OnStarted2(self, time):
super(bedo_osaimi_istr_strategy, self).OnStarted2(time)
self._close_ma = SimpleMovingAverage()
self._close_ma.Length = self._ma_length.Value
self._open_ma = SimpleMovingAverage()
self._open_ma.Length = self._ma_length.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._close_ma, self._process_candle).Start()
self.StartProtection(
takeProfit=Unit(2, UnitTypes.Percent),
stopLoss=Unit(1, UnitTypes.Percent)
)
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, self._close_ma)
self.DrawIndicator(area, self._open_ma)
self.DrawOwnTrades(area)
def _process_candle(self, candle, close_ma_value):
if candle.State != CandleStates.Finished:
return
open_ma_result = process_float(self._open_ma, float(candle.OpenPrice), candle.ServerTime, True)
if not open_ma_result.IsFormed:
self._prev_close = float(close_ma_value)
self._prev_open = None
return
open_ma_value = float(open_ma_result)
close_ma_v = float(close_ma_value)
if self._prev_close is None or self._prev_open is None:
self._prev_close = close_ma_v
self._prev_open = open_ma_value
if self.Position == 0:
self.BuyMarket()
return
prev_close = self._prev_close
prev_open = self._prev_open
if close_ma_v > open_ma_value and prev_close <= prev_open and self.Position == 0:
self.BuyMarket()
elif close_ma_v < open_ma_value and prev_close >= prev_open and self.Position == 0:
self.SellMarket()
self._prev_close = close_ma_v
self._prev_open = open_ma_value
def CreateClone(self):
return bedo_osaimi_istr_strategy()