Стратегия скальпинга AUD/USD
Стратегия предназначена для скальпинга пары AUD/USD на коротких таймфреймах с использованием фильтра тренда на EMA, полос Боллинджера и RSI. Быстрая и медленная EMA определяют направление тренда. Лонги открываются при восходящем тренде, когда цена касается нижней полосы Боллинджера и RSI выше уровня перепроданности. Шорты берутся в нисходящем тренде, когда цена достигает верхней полосы и RSI ниже уровня перекупленности. Управление риском осуществляется фиксированными уровнями take-profit и stop-loss.
Подробности
- Условия входа:
- Лонг: быстрая EMA выше медленной, цена на нижней полосе Боллинджера, RSI выше уровня перепроданности.
- Шорт: быстрая EMA ниже медленной, цена на верхней полосе Боллинджера, RSI ниже уровня перекупленности.
- Направление: обе стороны.
- Условия выхода: stop-loss или take-profit.
- Стопы: фиксированные stop-loss и take-profit.
- Параметры по умолчанию:
EmaShort= 13EmaLong= 26RsiPeriod= 4RsiOverbought= 70RsiOversold= 30BbLength= 20BbMultiplier= 2.0TakeProfit= 0.0005StopLoss= 0.0004
- Фильтры:
- Категория: Скальпинг
- Направление: Обе
- Индикаторы: EMA, полосы Боллинджера, RSI
- Стопы: Фиксированные
- Сложность: Низкая
- Таймфрейм: 1 минута
- Сезонность: Нет
- Нейросети: Нет
- Дивергенция: Нет
- Уровень риска: Средний
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Scalping strategy using EMA crossover with RSI filter.
/// Buys when fast EMA crosses above slow EMA and RSI exits oversold.
/// Sells when fast EMA crosses below slow EMA and RSI exits overbought.
/// </summary>
public class AudUsdScalpingStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _emaShort;
private readonly StrategyParam<int> _emaLong;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<int> _cooldownBars;
private decimal _prevFastEma;
private decimal _prevSlowEma;
private int _barIndex;
private int _lastTradeBar;
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Fast EMA period.
/// </summary>
public int EmaShort
{
get => _emaShort.Value;
set => _emaShort.Value = value;
}
/// <summary>
/// Slow EMA period.
/// </summary>
public int EmaLong
{
get => _emaLong.Value;
set => _emaLong.Value = value;
}
/// <summary>
/// RSI calculation period.
/// </summary>
public int RsiPeriod
{
get => _rsiPeriod.Value;
set => _rsiPeriod.Value = value;
}
/// <summary>
/// Cooldown bars between trades.
/// </summary>
public int CooldownBars
{
get => _cooldownBars.Value;
set => _cooldownBars.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public AudUsdScalpingStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
_emaShort = Param(nameof(EmaShort), 13)
.SetGreaterThanZero()
.SetDisplay("Short EMA", "Fast EMA period", "Indicators");
_emaLong = Param(nameof(EmaLong), 26)
.SetGreaterThanZero()
.SetDisplay("Long EMA", "Slow EMA period", "Indicators");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI calculation period", "Indicators");
_cooldownBars = Param(nameof(CooldownBars), 350)
.SetDisplay("Cooldown Bars", "Bars between trades", "Trading");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFastEma = 0;
_prevSlowEma = 0;
_barIndex = 0;
_lastTradeBar = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var emaFast = new ExponentialMovingAverage { Length = EmaShort };
var emaSlow = new ExponentialMovingAverage { Length = EmaLong };
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(emaFast, emaSlow, rsi, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, emaFast);
DrawIndicator(area, emaSlow);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue, decimal rsiValue)
{
if (candle.State != CandleStates.Finished)
return;
_barIndex++;
var cooldownOk = _barIndex - _lastTradeBar > CooldownBars;
// EMA crossover with RSI filter
var crossUp = _prevFastEma > 0 && _prevFastEma <= _prevSlowEma && fastValue > slowValue;
var crossDown = _prevFastEma > 0 && _prevFastEma >= _prevSlowEma && fastValue < slowValue;
if (crossUp && rsiValue < 60 && Position <= 0 && cooldownOk)
{
BuyMarket();
_lastTradeBar = _barIndex;
}
else if (crossDown && rsiValue > 40 && Position >= 0 && cooldownOk)
{
SellMarket();
_lastTradeBar = _barIndex;
}
_prevFastEma = fastValue;
_prevSlowEma = slowValue;
}
}
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 CandleStates
from StockSharp.Algo.Indicators import ExponentialMovingAverage, RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
from datatype_extensions import *
class aud_usd_scalping_strategy(Strategy):
"""
Scalping strategy using EMA crossover with RSI filter.
Buys when fast EMA crosses above slow EMA and RSI exits oversold.
Sells when fast EMA crosses below slow EMA and RSI exits overbought.
"""
def __init__(self):
super(aud_usd_scalping_strategy, self).__init__()
self._candle_type = self.Param("CandleType", tf(1)) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._ema_short = self.Param("EmaShort", 13) \
.SetGreaterThanZero() \
.SetDisplay("Short EMA", "Fast EMA period", "Indicators")
self._ema_long = self.Param("EmaLong", 26) \
.SetGreaterThanZero() \
.SetDisplay("Long EMA", "Slow EMA period", "Indicators")
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetGreaterThanZero() \
.SetDisplay("RSI Period", "RSI calculation period", "Indicators")
self._cooldown_bars = self.Param("CooldownBars", 350) \
.SetDisplay("Cooldown Bars", "Bars between trades", "Trading")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._bar_index = 0
self._last_trade_bar = 0
@property
def CandleType(self): return self._candle_type.Value
@CandleType.setter
def CandleType(self, v): self._candle_type.Value = v
@property
def EmaShort(self): return self._ema_short.Value
@EmaShort.setter
def EmaShort(self, v): self._ema_short.Value = v
@property
def EmaLong(self): return self._ema_long.Value
@EmaLong.setter
def EmaLong(self, v): self._ema_long.Value = v
@property
def RsiPeriod(self): return self._rsi_period.Value
@RsiPeriod.setter
def RsiPeriod(self, v): self._rsi_period.Value = v
@property
def CooldownBars(self): return self._cooldown_bars.Value
@CooldownBars.setter
def CooldownBars(self, v): self._cooldown_bars.Value = v
def OnReseted(self):
super(aud_usd_scalping_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._bar_index = 0
self._last_trade_bar = 0
def OnStarted2(self, time):
super(aud_usd_scalping_strategy, self).OnStarted2(time)
ema_fast = ExponentialMovingAverage()
ema_fast.Length = self.EmaShort
ema_slow = ExponentialMovingAverage()
ema_slow.Length = self.EmaLong
rsi = RelativeStrengthIndex()
rsi.Length = self.RsiPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(ema_fast, ema_slow, rsi, self.ProcessCandle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ema_fast)
self.DrawIndicator(area, ema_slow)
self.DrawOwnTrades(area)
def ProcessCandle(self, candle, fast_value, slow_value, rsi_value):
if candle.State != CandleStates.Finished:
return
self._bar_index += 1
cooldown_ok = self._bar_index - self._last_trade_bar > self.CooldownBars
cross_up = self._prev_fast > 0 and self._prev_fast <= self._prev_slow and fast_value > slow_value
cross_down = self._prev_fast > 0 and self._prev_fast >= self._prev_slow and fast_value < slow_value
if cross_up and rsi_value < 60 and self.Position <= 0 and cooldown_ok:
self.BuyMarket()
self._last_trade_bar = self._bar_index
elif cross_down and rsi_value > 40 and self.Position >= 0 and cooldown_ok:
self.SellMarket()
self._last_trade_bar = self._bar_index
self._prev_fast = fast_value
self._prev_slow = slow_value
def CreateClone(self):
"""!! REQUIRED!! Creates a new instance of the strategy."""
return aud_usd_scalping_strategy()