移動平均加重標準偏差取引戦略


作成日: 2023-11-24 13:54:58 最終変更日: 2023-11-24 13:54:58
コピー: 0 クリック数: 776
1
フォロー
1621
フォロワー

移動平均加重標準偏差取引戦略

概要

この戦略は,移動平均と組み合わせた加重標準差指数を使用して,暗号通貨のトレンド取引を実現します. 戦略は,特定の周期内の閉盘価格と取引量に基づいて,価格の加重標準差チャネルを計算します. 価格がチャネルを突破して下線すると,余分な空白を行います. 同時に,ストップ・ロスト条件を設定して,単価損失を減らす.

戦略原則

コードには2つのカスタム関数が定義されており,それぞれ時間序列と数列から計算される加重標準差である.主なステップは:

  1. 閉店価格と取引量に基づいて,重量平均価格を計算する
  2. 平均値とK線の誤差の2乗を計算します.
  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)