Esta estratégia usa o indicador de desvio padrão ponderado combinado com a média móvel para implementar a negociação de tendências em criptomoedas. Ele calcula um canal de preço de desvio padrão ponderado com base nos preços de fechamento e volumes durante um determinado período. Quando o preço atravessa o canal superior ou inferior, são tomadas posições longas ou curtas. As condições de stop loss e take profit também são definidas para limitar as perdas por comércio.
O código define duas funções personalizadas para calcular o desvio padrão ponderado de séries temporais e matrizes.
Isso nos dá um canal centrado no preço médio ponderado, com limites superiores e inferiores a um desvio padrão de distância.
A maior vantagem desta estratégia é a combinação de média móvel e análise de volatilidade. O MA julga a direção da tendência do mercado, enquanto a faixa SD define uma faixa razoável - ambos se verificam para maior confiabilidade.
Os pontos stop loss e take profit ajudam ainda mais a negociar com a tendência e evitar perdas excessivas em reversões.
O principal risco é o de violentas oscilações do mercado, o que pode fazer com que o canal SD oscile muito, dificultando os julgamentos, além disso, escolher períodos demasiado curtos corre o risco de ser enganado por ruídos e erros.
O remédio é suavizar os parâmetros e as configurações de período adequadamente.
Esta estratégia emprega com sucesso o indicador de desvio padrão ponderado, juntamente com MA, para rastrear as tendências de criptomoedas. Configurações razoáveis de stop loss / take profit também ajudam o ritmo do mercado de negociação e evitam perdas de reversão excessivas.
/*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)