가중화된 표준편차 거래 전략

저자:차오장, 날짜: 2023-11-24 13:54:58
태그:

img

전반적인 설명

이 전략은 암호화폐에 대한 트렌드 거래를 구현하기 위해 가중 표준편차 지표와 이동 평균을 결합하여 사용합니다. 특정 기간 동안의 폐쇄 가격과 볼륨에 따라 가중 표준편차 가격 채널을 계산합니다. 가격이 상위 또는 하위 채널을 통과하면 긴 또는 짧은 포지션을 취합니다. 거래 당 손실을 제한하기 위해 스톱 손실 및 수익 조건도 설정됩니다.

전략 논리

코드는 시간 계열과 배열에서 중량 표준편차를 계산하는 두 가지 사용자 정의 함수를 정의합니다. 주요 단계는 다음과 같습니다.

  1. 종료 가격과 부피를 기준으로 중소화 된 평균 가격을 계산합니다
  2. 각 촛불의 제곱 오류를 평균 가격에 비교하여 계산합니다.
  3. 표본 크기, 무게 및 조정된 평균에 기초하여 변수를 계산합니다.
  4. 표준편차를 도출하기 위해 제곱근을 씁니다

이것은 가중 평균 가격 중심의 채널을 제공합니다. 상단과 하단 한계가 표준편차에서 떨어져 있습니다. 가격이 채널 하단에서 넘어지면, 길게 가십시오. 위에서 상단으로 넘어지면, 짧게 가십시오.

이점 분석

이 전략의 가장 큰 장점은 이동 평균과 변동성 분석의 조합입니다. MA는 시장 트렌드 방향을 판단하고 SD 범위는 합리적인 대역을 정의합니다. 둘 다 더 높은 신뢰성을 위해 서로를 검증합니다. 또한 볼륨 가중화는 실제 파업에서 더 높은 성공 확률을 위해 잘못된 파장을 필터하는 데 도움이됩니다.

스톱 로스 및 영업 포인트 는 추세 에 따라 거래 하는 데 더 도움 이 되고, 역전 에 대한 과도 한 손실 을 피 하는 데 도움 이 된다. 이것은 많은 초보 트레이더 들 이 실행 하지 못하는 미묘 한 방법 이다.

위험 분석

주요 위험은 시장의 격렬한 변동입니다. 이것은 SD 채널이 야만적으로 변동 할 수 있으며 판단을 어렵게 할 수 있습니다. 또한 너무 짧은 기간을 선택하는 것은 소음과 오류에 의해 오해 될 위험이 있습니다.

치료법은 매개 변수와 기간 설정을 적절하게 매끄럽게 하는 것입니다. 브레이크아웃 확인을 향상시키기 위해 RSI와 같은 다른 지표를 결합하는 것을 고려하십시오.

최적화 방향

  1. 최적화 기간 매개 변수 - 테스트 5min, 15min, 30min 등 최고의 콤보
  2. 최대 수익을 위해 스톱 로스/익기율을 최적화
  3. 예를 들어 부피 필터를 추가하여 잘못된 파열을 피합니다.
  4. 촛불 필터를 추가 닫기 가격, 피크 등을 정확도를 향상시키기 위해

결론

이 전략은 암호화폐 트렌드를 추적하기 위해 MA와 함께 가중 표준 편차 지표를 성공적으로 사용합니다. 합리적인 스톱 로스/트랙 노프트 설정은 또한 거래 시장 리듬을 돕고 과도한 역전 손실을 피합니다. 매개 변수 조정 및 멀티 지표 확인을 통한 추가 최적화는 탄탄한 알고 거래 전략의 신뢰성을 향상시킬 수 있습니다.


/*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)

더 많은