Chiến lược này sử dụng chỉ số lệch chuẩn cân kết hợp với trung bình động để thực hiện giao dịch xu hướng trên tiền điện tử. Nó tính toán một kênh giá lệch chuẩn cân dựa trên giá đóng cửa và khối lượng trong một khoảng thời gian nhất định. Khi giá vượt qua kênh trên hoặc dưới, các vị trí dài hoặc ngắn được thực hiện. Điều kiện dừng lỗ và lấy lợi nhuận cũng được thiết lập để hạn chế lỗ cho mỗi giao dịch.
Mã xác định hai hàm tùy chỉnh để tính lệch chuẩn cân nhắc từ chuỗi thời gian và mảng.
Điều này cung cấp cho chúng ta một kênh tập trung vào giá trung bình cân nhắc, với giới hạn trên và dưới cách nhau một độ lệch chuẩn. Khi giá vượt qua kênh dưới từ dưới, đi dài. Khi nó vượt qua đỉnh từ trên, đi ngắn.
Lợi thế lớn nhất của chiến lược này là sự kết hợp giữa trung bình động và phân tích biến động. MA đánh giá hướng xu hướng thị trường trong khi phạm vi SD xác định một dải hợp lý - cả hai đều xác minh lẫn nhau để có độ tin cậy cao hơn. Ngoài ra, trọng lượng khối lượng giúp lọc các đột phá sai để có khả năng thành công cao hơn trên các đột phá thực tế.
Các điểm dừng lỗ và lấy lợi nhuận tiếp tục giúp giao dịch theo xu hướng và tránh thua lỗ quá mức khi đảo ngược.
Rủi ro chính là do biến động thị trường dữ dội. Điều này có thể khiến kênh SD cũng dao động điên cuồng, làm cho việc đánh giá khó khăn. Ngoài ra, việc chọn thời gian quá ngắn có nguy cơ bị đánh lừa bởi tiếng ồn và lỗi.
Cách khắc phục là làm mịn các thông số và cài đặt thời gian một cách thích hợp.
Chiến lược này sử dụng thành công chỉ số lệch chuẩn cân bằng cùng với MA để theo dõi xu hướng tiền điện tử. Các thiết lập dừng lỗ / lấy lợi nhuận hợp lý cũng giúp nhịp thị trường giao dịch và tránh tổn thất đảo ngược quá mức. Tăng cường hơn nữa thông qua điều chỉnh tham số và xác nhận đa chỉ số có thể cải thiện độ tin cậy cho một chiến lược giao dịch algo vững chắc.
/*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)