Торговая стратегия на основе скользящего среднего взвешенного стандартного отклонения


Дата создания: 2023-11-24 13:54:58 Последнее изменение: 2023-11-24 13:54:58
Копировать: 0 Количество просмотров: 773
1
Подписаться
1617
Подписчики

Торговая стратегия на основе скользящего среднего взвешенного стандартного отклонения

Обзор

Эта стратегия использует весовой стандартный разрыв в сочетании с движущейся средней, чтобы реализовать трендовую торговлю криптовалютами. Стратегия рассчитывает канал весового стандартного разрыва цены на основе цены закрытия и объема сделок в течение определенного периода.

Стратегический принцип

В коде определены две пользовательские функции, взвешенные стандартные отклонения от временной последовательности и расчетов с помощью матрицы. Основные шаги:

  1. Расчет средневзвешенной цены по цене закрытия и объему сделок
  2. Вычислить квадратную погрешность каждой линии K от среднего значения
  3. Разница рассчитывается по среднему значению, скорректированному на массу и вес
  4. Разрыв в диаграмме

Таким образом, мы получаем канал, центр которого находится на средневзвешенной цене, а расстояние вверх-вниз - стандартное отклонение. Когда цена снизу прорывает нижнюю часть канала, делаем больше; когда она сверху прорывает верхнюю часть канала, делаем больше.

Анализ преимуществ

Наибольшее преимущество этой стратегии заключается в том, что она объединяет в себе подвижные средние и волатильный анализ. Подвижные средние определяют направление тенденции рынка, стандартное расхождение определяет разумный диапазон, оба они взаимно проверяются, и имеют высокую надежность. Кроме того, вес оборота может фильтровать ложные прорывы, и вероятность фактического прорыва выше.

Эта стратегия также устанавливает стоп-стоп для уменьшения убытков, что помогает уловить тренд и избежать реверсий, которые приводят к чрезмерным потерям. Это то, что многие новички не могут понять.

Анализ рисков

Основной риск заключается в том, что рынок может сильно колебаться. В этом случае стандартный канал отклонения также может сильно колебаться, что не способствует суждению. Кроме того, если выбор цикла слишком короткий, легко подвержены помехам шума, ошибочность высока.

Контрацепция заключается в том, что можно соответствующим образом скорректировать циклические параметры, сгладить кривую. Также можно рассмотреть возможность использования других показателей, таких как RSI, для увеличения эффекта подтверждения прорыва.

Направление оптимизации

  1. Параметры оптимизации цикла: можно тестировать различные циклы, такие как 5 минут, 15 минут, 30 минут, чтобы найти оптимальную комбинацию
  2. Оптимизируйте коэффициент остановок убытков. Проверьте различные точки остановок убытков, чтобы получить оптимальную отдачу.
  3. Добавление условий фильтрации. Например, объединение объема трафика, чтобы избежать ложных прорывов, приводящих к Loss
  4. Добавление криптовалютных показателей, таких как подтверждение K-линейных объектов, например, путем определения позиции цены закрытия, длины теневой линии, снижение погрешности

Подвести итог

Эта стратегия успешно использует весомый стандартный разрыв, а также движущиеся средние, чтобы отслеживать тенденции в криптовалютах. В то же время, разумная установка стоп-лосса помогает уловить рыночную динамику и избежать потерь, вызванных чрезмерным переворотом.

Исходный код стратегии
/*backtest
start: 2023-11-16 00:00:00
end: 2023-11-23 00:00:00
period: 45m
basePeriod: 5m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © rumpypumpydumpy   © cache_that_pass

//@version=4
strategy("[cache_that_pass] 1m 15m Function - Weighted Standard Deviation", overlay=true, pyramiding=0, default_qty_type=strategy.percent_of_equity, default_qty_value=20, initial_capital=10000, commission_type=strategy.commission.percent, commission_value=0.075)

f_weighted_sd_from_series(_src, _weight, _n) => //{
//  @function: Calculates weighted mean, variance, standard deviation, MSE and RMSE from time series variables
//  @parameters:
//      _src: time series variable of sample values
//      _weight: time series of corresponding weight values.
//      _n : number of samples
    _xw = _src * _weight
    _sum_weight = sum(_weight, _n)
    _mean = sum(_xw, _n) / _sum_weight
    float _sqerror_sum = 0
    int _nonzero_n = 0
    for _i = 0 to _n - 1
        _sqerror_sum := _sqerror_sum + pow(_mean - _src[_i], 2) * _weight[_i]
        _nonzero_n := _weight[_i] != 0 ? _nonzero_n + 1 : _nonzero_n
    _variance = _sqerror_sum / ((_nonzero_n - 1) * _sum_weight / _nonzero_n)
    _dev = sqrt(_variance)
    _mse = _sqerror_sum / _sum_weight
    _rmse = sqrt(_mse)
    [_mean, _variance, _dev, _mse, _rmse]
//}
// -----------------------------------------------------------------------------

f_weighted_sd_from_arrays(_a_src, _a_weight, _n) => //{
//  @function: Calculates weighted mean, variance, standard deviation, MSE and RMSE from arrays
//  Expects index 0 of the arrays to be the most recent sample and weight values!
//  @parameters:
//      _a_src: array of sample values
//      _a_weight: array of corresponding weight values.
//      _n : number of samples
    float _mean = na, float _variance = na, float _dev = na, float _mse = na
    float _rmse = na, float _sqerror_sum = na, float _sum_weight = na
    float[] _a_xw = array.new_float(_n)
    int _nonzero_n = 0
    if array.size(_a_src) >= _n
        _sum_weight := 0
        _sqerror_sum := 0
        for _i = 0 to _n - 1
            array.set(_a_xw, _i, array.get(_a_src, _i) * array.get(_a_weight, _i))
            _sum_weight := _sum_weight + array.get(_a_weight, _i)
            _nonzero_n := array.get(_a_weight, _i) != 0 ? _nonzero_n + 1 : _nonzero_n
        _mean := array.sum(_a_xw) / _sum_weight
        for _j = 0 to _n - 1
            _sqerror_sum := _sqerror_sum + pow(_mean - array.get(_a_src, _j), 2) * array.get(_a_weight, _j)
        _variance := _sqerror_sum / ((_nonzero_n - 1) * _sum_weight / _nonzero_n)
        _dev := sqrt(_variance)
        _mse := _sqerror_sum / _sum_weight
        _rmse := sqrt(_mse)
    [_mean, _variance, _dev, _mse, _rmse]
//}


// -----------------------------------------------------------------------------
// Example usage : 
// -----------------------------------------------------------------------------

len = input(20)

// -----------------------------------------------------------------------------
// From series :
// -----------------------------------------------------------------------------
[m, v, d, mse, rmse] = f_weighted_sd_from_series(close, volume, len)


plot(m, color = color.blue)
plot(m + d * 2, color = color.blue)
plot(m - d * 2, color = color.blue)
// -----------------------------------------------------------------------------



// -----------------------------------------------------------------------------
// From arrays : 
// -----------------------------------------------------------------------------
var float[] a_src = array.new_float()
var float[] a_weight = array.new_float()

if barstate.isfirst
    for i = 1 to len
        array.unshift(a_weight, i)

array.unshift(a_src, close)

if array.size(a_src) > len
    array.pop(a_src)

[a_m, a_v, a_d, a_mse, a_rmse] = f_weighted_sd_from_arrays(a_src, a_weight, len)

plot(a_m, color = color.orange)
plot(a_m + a_d * 2, color = color.orange)
plot(a_m - a_d * 2, color = color.orange)
// -----------------------------------------------------------------------------


series_text = "Mean : " + tostring(m) + "\nVariance : " + tostring(v) + "\nSD : " + tostring(d) + "\nMSE : " + tostring(mse) +  "\nRMSE : " + tostring(rmse)
array_text = "Mean : " + tostring(a_m) + "\nVariance : " + tostring(a_v) + "\nSD : " + tostring(a_d) + "\nMSE : " + tostring(a_mse) +  "\nRMSE : " + tostring(a_rmse)
debug_text = "Volume weighted from time series : \n" + series_text + "\n\nLinearly weighted from arrays : \n" + array_text

//debug = label.new(x = bar_index, y = close, text = debug_text, style = label.style_label_left)
//.delete(debug[1])

//test strategy
if low <= (m - d * 2)
    strategy.entry("LE", strategy.long)
if high >= (m + d * 2)
    strategy.entry("SE", strategy.short)

// User Options to Change Inputs (%)
stopPer = input(3.11, title='Stop Loss %', type=input.float) / 100
takePer = input(7.50, title='Take Profit %', type=input.float) / 100

// Determine where you've entered and in what direction
longStop = strategy.position_avg_price * (1 - stopPer)
shortStop = strategy.position_avg_price * (1 + stopPer)
shortTake = strategy.position_avg_price * (1 - takePer)
longTake = strategy.position_avg_price * (1 + takePer)

if strategy.position_size > 0 
    strategy.exit(id="Close Long", stop=longStop, limit=longTake)
//    strategy.close("LE", when = (longStop) or (longTake), qty_percent = 100)
if strategy.position_size < 0 
    strategy.exit(id="Close Short", stop=shortStop, limit=shortTake)
//    strategy.close("SE", when = (shortStop) or (shortTake), qty_percent = 100)