Стратегия парного трейдинга
Обзор
PairsTradingStrategy - это стратегия парного трейдинга, основанная на статистическом арбитраже между двумя связанными инструментами. Она отслеживает спред между ценами двух активов и открывает позиции при значительном отклонении спреда от среднего значения, ожидая возврата к среднему.
Основные компоненты
Стратегия наследуется от Strategy и использует параметры для настройки:
public class PairsTradingStrategy : Strategy
{
private readonly StrategyParam<int> _spreadLength;
private readonly StrategyParam<decimal> _entryThreshold;
private readonly StrategyParam<decimal> _exitThreshold;
private readonly StrategyParam<DataType> _candleType;
// Последние цены по каждому инструменту
private decimal? _lastPrice1;
private decimal? _lastPrice2;
}
Параметры стратегии
Стратегия позволяет настраивать следующие параметры:
- SpreadLength - период расчета среднего и стандартного отклонения спреда (по умолчанию 20)
- EntryThreshold - порог Z-Score для входа в позицию (по умолчанию 2.0)
- ExitThreshold - порог Z-Score для выхода из позиции (по умолчанию 0.5)
- CandleType - тип свечей для работы (по умолчанию 5-минутные)
Параметры доступны для оптимизации с указанными диапазонами значений.
Инициализация стратегии
В методе OnStarted2 создаются индикаторы, настраиваются подписки на свечи для двух инструментов:
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
// Получение двух инструментов для парного трейдинга
var securities = GetWorkingSecurities().ToArray();
if (securities.Length < 2)
throw new InvalidOperationException("Необходимо указать 2 инструмента.");
var sec1 = securities[0].sec;
var sec2 = securities[1].sec;
// Индикаторы для расчета среднего и стандартного отклонения спреда
var sma = new SimpleMovingAverage { Length = SpreadLength };
var stdDev = new StandardDeviation { Length = SpreadLength };
_lastPrice1 = null;
_lastPrice2 = null;
// Подписка на свечи первого инструмента
SubscribeCandles(CandleType, security: sec1)
.Bind(c =>
{
if (c.State != CandleStates.Finished)
return;
_lastPrice1 = c.ClosePrice;
})
.Start();
// Подписка на свечи второго инструмента с обработкой спреда
SubscribeCandles(CandleType, security: sec2)
.Bind(c =>
{
if (c.State != CandleStates.Finished)
return;
_lastPrice2 = c.ClosePrice;
if (_lastPrice1 == null)
return;
ProcessSpread(_lastPrice1.Value, _lastPrice2.Value, sma, stdDev);
})
.Start();
}
Обработка спреда
Метод ProcessSpread рассчитывает Z-Score спреда и генерирует торговые сигналы:
private void ProcessSpread(decimal price1, decimal price2,
SimpleMovingAverage sma, StandardDeviation stdDev)
{
// Расчет спреда как разницы цен
var spread = price1 - price2;
// Обработка индикаторов
var smaValue = sma.Process(new DecimalIndicatorValue(sma, spread));
var devValue = stdDev.Process(new DecimalIndicatorValue(stdDev, spread));
if (!sma.IsFormed || !stdDev.IsFormed)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var mean = smaValue.ToDecimal();
var dev = devValue.ToDecimal();
if (dev == 0)
return;
// Расчет Z-Score: отклонение спреда от среднего в единицах стандартного отклонения
var zScore = (spread - mean) / dev;
// Спред слишком высокий: продаем первый инструмент, покупаем второй
if (zScore > EntryThreshold && Position >= 0)
{
SellMarket(Volume + Math.Abs(Position));
}
// Спред слишком низкий: покупаем первый инструмент, продаем второй
else if (zScore < -EntryThreshold && Position <= 0)
{
BuyMarket(Volume + Math.Abs(Position));
}
// Возврат к среднему: закрываем позицию
else if (Math.Abs(zScore) < ExitThreshold && Position != 0)
{
ClosePosition();
}
}
Логика торговли
- Сигнал на продажу: Z-Score спреда превышает порог входа (по умолчанию 2.0), при отсутствии короткой позиции
- Сигнал на покупку: Z-Score спреда ниже отрицательного порога входа (по умолчанию -2.0), при отсутствии длинной позиции
- Закрытие позиции: абсолютное значение Z-Score опускается ниже порога выхода (по умолчанию 0.5), что сигнализирует о возврате спреда к среднему
Особенности
- Стратегия работает с двумя инструментами, получаемыми через метод
GetWorkingSecurities() - Спред рассчитывается как разница цен закрытия свечей двух инструментов
- Используется Z-Score для нормализации отклонения спреда от среднего значения
- Стратегия реализует классическую идею возврата к среднему (mean reversion)
- Стратегия работает только с завершенными свечами
- Поддерживается оптимизация параметров для поиска оптимальных настроек стратегии