
Chiến lược này sử dụng chỉ số chênh lệch tiêu chuẩn có trọng lượng, kết hợp với đường trung bình di chuyển, để thực hiện giao dịch xu hướng đối với tiền điện tử. Chiến lược tính toán kênh chênh lệch tiêu chuẩn có trọng lượng của giá dựa trên giá đóng cửa và khối lượng giao dịch trong một chu kỳ nhất định.
Có hai hàm tùy chỉnh được định nghĩa trong mã, tương ứng với chênh lệch chuẩn cân nặng tính toán từ chuỗi thời gian và mảng. Các bước chính là:
Do đó, chúng ta có một đường dẫn trung tâm ở giá trung bình trọng lượng, với khoảng cách từ trên xuống là một chênh lệch chuẩn. Khi giá từ bên dưới phá vỡ đáy của đường dẫn, hãy làm nhiều hơn; khi từ trên phá vỡ đỉnh của đường dẫn, hãy làm trống.
Ưu điểm lớn nhất của chiến lược này là kết hợp giữa trung bình di chuyển và phân tích biến động. Trung bình di chuyển đánh giá xu hướng thị trường, chênh lệch chuẩn xác định khoảng cách hợp lý, cả hai đều được xác minh lẫn nhau và có độ tin cậy cao. Ngoài ra, trọng lượng giao dịch có thể lọc các đột phá giả mạo và xác suất đột phá thực tế cao hơn.
Chiến lược này cũng thiết lập điểm dừng lỗ, giúp nắm bắt xu hướng và tránh đảo ngược dẫn đến tổn thất quá lớn. Đây là một điểm quan trọng mà nhiều người mới bắt đầu không nắm được.
Rủi ro chính là thị trường có thể biến động mạnh. Khi đó, kênh chênh lệch tiêu chuẩn cũng có thể biến động mạnh, không có lợi cho phán đoán. Ngoài ra, nếu chu kỳ lựa chọn quá ngắn, dễ bị nhiễu loạn bởi tiếng ồn, tỷ lệ sai sót cao.
Ngược lại, các tham số chu kỳ có thể được điều chỉnh thích hợp, và đường cong được làm mịn. Các chỉ số khác, chẳng hạn như RSI, cũng có thể được xem xét để tăng hiệu quả xác nhận đột phá.
Chiến lược này đã sử dụng thành công các chỉ số chênh lệch tiêu chuẩn có trọng lượng, hỗ trợ định hướng phán đoán bằng đường trung bình di chuyển, để theo dõi xu hướng đối với tiền điện tử. Đồng thời, thiết lập dừng lỗ hợp lý sẽ giúp nắm bắt nhịp độ thị trường và tránh bị tổn thất do đảo ngược quá mức. Có thể tối ưu hóa hơn nữa và hình thành chiến lược giao dịch định lượng đáng tin cậy thông qua điều chỉnh tham số và xác minh đa chỉ số.
/*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)