Относительная сила валют
Стратегия Relative Currency Strength сравнивает валютную пару с корзиной основных валют. Покупает, когда торгуемая пара сильнее среднего по другим валютам, и продаёт при слабости. Сравнение основано на процентном изменении с начала сессии.
Детали
- Условия входа: сила пары превышает среднее на порог.
- Направление: обе стороны.
- Условия выхода: сила падает ниже среднего на порог.
- Стопы: нет.
- Значения по умолчанию:
Threshold= 0.01mCandleType= TimeSpan.FromMinutes(5)
- Фильтры:
- Категория: Тренд
- Направление: Обе стороны
- Индикаторы: Изменение цены
- Стопы: Нет
- Сложность: Средняя
- Таймфрейм: Внутридневной
- Сезонность: Нет
- Нейросети: Нет
- Дивергенция: Нет
- Уровень риска: Средний
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;
using Ecng.ComponentModel;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Strategy that trades based on relative currency strength among major pairs.
/// It buys when the traded pair outperforms the average of other majors and sells when it underperforms.
/// </summary>
public class RelativeCurrencyStrengthStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<decimal> _threshold;
private readonly StrategyParam<Security> _audUsd;
private readonly StrategyParam<Security> _nzdUsd;
private readonly StrategyParam<Security> _usdJpy;
private readonly StrategyParam<Security> _usdChf;
private readonly StrategyParam<Security> _usdCad;
private readonly StrategyParam<Security> _gbpUsd;
private readonly StrategyParam<Security> _eurUsd;
private readonly StrategyParam<Security> _xauUsd;
private decimal? _mainStart;
private decimal _mainStrength;
private decimal? _audUsdStart;
private decimal _audUsdStrength;
private decimal? _nzdUsdStart;
private decimal _nzdUsdStrength;
private decimal? _usdJpyStart;
private decimal _usdJpyStrength;
private decimal? _usdChfStart;
private decimal _usdChfStrength;
private decimal? _usdCadStart;
private decimal _usdCadStrength;
private decimal? _gbpUsdStart;
private decimal _gbpUsdStrength;
private decimal? _eurUsdStart;
private decimal _eurUsdStrength;
private decimal? _xauUsdStart;
private decimal _xauUsdStrength;
/// <summary>
/// Type of candles used for calculations.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Strength difference needed for entry signal.
/// </summary>
public decimal Threshold
{
get => _threshold.Value;
set => _threshold.Value = value;
}
/// <summary>
/// AUD/USD security.
/// </summary>
public Security AudUsd
{
get => _audUsd.Value;
set => _audUsd.Value = value;
}
/// <summary>
/// NZD/USD security.
/// </summary>
public Security NzdUsd
{
get => _nzdUsd.Value;
set => _nzdUsd.Value = value;
}
/// <summary>
/// USD/JPY security.
/// </summary>
public Security UsdJpy
{
get => _usdJpy.Value;
set => _usdJpy.Value = value;
}
/// <summary>
/// USD/CHF security.
/// </summary>
public Security UsdChf
{
get => _usdChf.Value;
set => _usdChf.Value = value;
}
/// <summary>
/// USD/CAD security.
/// </summary>
public Security UsdCad
{
get => _usdCad.Value;
set => _usdCad.Value = value;
}
/// <summary>
/// GBP/USD security.
/// </summary>
public Security GbpUsd
{
get => _gbpUsd.Value;
set => _gbpUsd.Value = value;
}
/// <summary>
/// EUR/USD security.
/// </summary>
public Security EurUsd
{
get => _eurUsd.Value;
set => _eurUsd.Value = value;
}
/// <summary>
/// XAU/USD security.
/// </summary>
public Security XauUsd
{
get => _xauUsd.Value;
set => _xauUsd.Value = value;
}
/// <summary>
/// Initializes a new instance of the strategy.
/// </summary>
public RelativeCurrencyStrengthStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "Data");
_threshold = Param(nameof(Threshold), 0.01m)
.SetDisplay("Threshold", "Strength difference for signal", "Parameters")
.SetOptimize(0.005m, 0.05m, 0.005m);
_audUsd = Param<Security>(nameof(AudUsd))
.SetDisplay("AUDUSD", "AUD/USD pair", "Data")
.SetRequired();
_nzdUsd = Param<Security>(nameof(NzdUsd))
.SetDisplay("NZDUSD", "NZD/USD pair", "Data")
.SetRequired();
_usdJpy = Param<Security>(nameof(UsdJpy))
.SetDisplay("USDJPY", "USD/JPY pair", "Data")
.SetRequired();
_usdChf = Param<Security>(nameof(UsdChf))
.SetDisplay("USDCHF", "USD/CHF pair", "Data")
.SetRequired();
_usdCad = Param<Security>(nameof(UsdCad))
.SetDisplay("USDCAD", "USD/CAD pair", "Data")
.SetRequired();
_gbpUsd = Param<Security>(nameof(GbpUsd))
.SetDisplay("GBPUSD", "GBP/USD pair", "Data")
.SetRequired();
_eurUsd = Param<Security>(nameof(EurUsd))
.SetDisplay("EURUSD", "EUR/USD pair", "Data")
.SetRequired();
_xauUsd = Param<Security>(nameof(XauUsd))
.SetDisplay("XAUUSD", "Gold pair", "Data")
.SetRequired();
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return
[
(Security, CandleType),
(AudUsd, CandleType),
(NzdUsd, CandleType),
(UsdJpy, CandleType),
(UsdChf, CandleType),
(UsdCad, CandleType),
(GbpUsd, CandleType),
(EurUsd, CandleType),
(XauUsd, CandleType)
];
}
protected override void OnReseted()
{
base.OnReseted();
_mainStart = null;
_mainStrength = 0;
_audUsdStart = null;
_audUsdStrength = 0;
_nzdUsdStart = null;
_nzdUsdStrength = 0;
_usdJpyStart = null;
_usdJpyStrength = 0;
_usdChfStart = null;
_usdChfStrength = 0;
_usdCadStart = null;
_usdCadStrength = 0;
_gbpUsdStart = null;
_gbpUsdStrength = 0;
_eurUsdStart = null;
_eurUsdStrength = 0;
_xauUsdStart = null;
_xauUsdStrength = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
SubscribeCandles(CandleType)
.Bind(ProcessMain)
.Start();
SubscribeCandles(CandleType, security: AudUsd)
.Bind(ProcessAudUsd)
.Start();
SubscribeCandles(CandleType, security: NzdUsd)
.Bind(ProcessNzdUsd)
.Start();
SubscribeCandles(CandleType, security: UsdJpy)
.Bind(ProcessUsdJpy)
.Start();
SubscribeCandles(CandleType, security: UsdChf)
.Bind(ProcessUsdChf)
.Start();
SubscribeCandles(CandleType, security: UsdCad)
.Bind(ProcessUsdCad)
.Start();
SubscribeCandles(CandleType, security: GbpUsd)
.Bind(ProcessGbpUsd)
.Start();
SubscribeCandles(CandleType, security: EurUsd)
.Bind(ProcessEurUsd)
.Start();
SubscribeCandles(CandleType, security: XauUsd)
.Bind(ProcessXauUsd)
.Start();
}
private void ProcessAudUsd(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
if (_audUsdStart is null)
{
_audUsdStart = candle.ClosePrice;
return;
}
_audUsdStrength = candle.ClosePrice / _audUsdStart.Value - 1m;
}
private void ProcessNzdUsd(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
if (_nzdUsdStart is null)
{
_nzdUsdStart = candle.ClosePrice;
return;
}
_nzdUsdStrength = candle.ClosePrice / _nzdUsdStart.Value - 1m;
}
private void ProcessUsdJpy(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
if (_usdJpyStart is null)
{
_usdJpyStart = candle.ClosePrice;
return;
}
_usdJpyStrength = candle.ClosePrice / _usdJpyStart.Value - 1m;
}
private void ProcessUsdChf(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
if (_usdChfStart is null)
{
_usdChfStart = candle.ClosePrice;
return;
}
_usdChfStrength = candle.ClosePrice / _usdChfStart.Value - 1m;
}
private void ProcessUsdCad(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
if (_usdCadStart is null)
{
_usdCadStart = candle.ClosePrice;
return;
}
_usdCadStrength = candle.ClosePrice / _usdCadStart.Value - 1m;
}
private void ProcessGbpUsd(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
if (_gbpUsdStart is null)
{
_gbpUsdStart = candle.ClosePrice;
return;
}
_gbpUsdStrength = candle.ClosePrice / _gbpUsdStart.Value - 1m;
}
private void ProcessEurUsd(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
if (_eurUsdStart is null)
{
_eurUsdStart = candle.ClosePrice;
return;
}
_eurUsdStrength = candle.ClosePrice / _eurUsdStart.Value - 1m;
}
private void ProcessXauUsd(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
if (_xauUsdStart is null)
{
_xauUsdStart = candle.ClosePrice;
return;
}
_xauUsdStrength = candle.ClosePrice / _xauUsdStart.Value - 1m;
}
private void ProcessMain(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
if (_mainStart is null)
{
_mainStart = candle.ClosePrice;
return;
}
_mainStrength = candle.ClosePrice / _mainStart.Value - 1m;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (_audUsdStart is null || _nzdUsdStart is null || _usdJpyStart is null || _usdChfStart is null || _usdCadStart is null || _gbpUsdStart is null || _eurUsdStart is null || _xauUsdStart is null)
return;
var sum = _audUsdStrength + _nzdUsdStrength + _usdJpyStrength + _usdChfStrength + _usdCadStrength + _gbpUsdStrength + _eurUsdStrength + _xauUsdStrength;
var average = sum / 8m;
if (Position <= 0 && _mainStrength - average > Threshold)
BuyMarket(Volume);
else if (Position >= 0 && average - _mainStrength > Threshold)
SellMarket(Volume);
}
}
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 ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class relative_currency_strength_strategy(Strategy):
def __init__(self):
super(relative_currency_strength_strategy, self).__init__()
self._slow_length = self.Param("SlowLength", 40) \
.SetGreaterThanZero() \
.SetDisplay("Slow Length", "Slow EMA period", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Candle type", "General")
self._prev_f = 0.0
self._prev_s = 0.0
self._init = False
self._last_signal_ticks = 0
@property
def slow_length(self):
return self._slow_length.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(relative_currency_strength_strategy, self).OnReseted()
self._prev_f = 0.0
self._prev_s = 0.0
self._init = False
self._last_signal_ticks = 0
def OnStarted2(self, time):
super(relative_currency_strength_strategy, self).OnStarted2(time)
self._fast = ExponentialMovingAverage()
self._fast.Length = 14
self._slow = ExponentialMovingAverage()
self._slow.Length = self.slow_length
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._fast, self._slow, self.on_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, self._fast)
self.DrawIndicator(area, self._slow)
self.DrawOwnTrades(area)
def on_candle(self, candle, f, s):
if candle.State != CandleStates.Finished:
return
if not self._fast.IsFormed or not self._slow.IsFormed:
return
f = float(f)
s = float(s)
if not self._init:
self._prev_f = f
self._prev_s = s
self._init = True
return
cooldown_ticks = TimeSpan.FromMinutes(360).Ticks
current_ticks = candle.OpenTime.Ticks
if current_ticks - self._last_signal_ticks >= cooldown_ticks:
if self._prev_f <= self._prev_s and f > s and self.Position <= 0:
self.BuyMarket()
self._last_signal_ticks = current_ticks
elif self._prev_f >= self._prev_s and f < s and self.Position >= 0:
self.SellMarket()
self._last_signal_ticks = current_ticks
self._prev_f = f
self._prev_s = s
def CreateClone(self):
return relative_currency_strength_strategy()