Chiến lược thời gian thị trường lọc biến động

Tác giả:ChaoZhang, Ngày: 2024-01-15 12:27:47
Tags:

img

Tổng quan

Chiến lược này thực hiện một chiến lược mua và giữ nâng cao bằng cách thêm một bộ lọc dựa trên biến động lịch sử. Bộ lọc đóng các vị trí dài trong các chế độ thị trường biến động cao và tái nhập các vị trí dài khi biến động thấp, để giảm rút tối đa.

Chiến lược logic

  1. Tính biến động lịch sử của SPY trong 100 ngày qua
  2. Nếu biến động hiện tại cao hơn phần trăm 95 của biến động trong 100 ngày qua, lọc ra ngày giao dịch đó, đóng vị trí dài
  3. Nếu biến động dưới 95 phần trăm, nhập vị trí dài

Phân tích lợi thế

So với mua và giữ đơn giản mà không có bộ lọc, chiến lược này cải thiện lợi nhuận hàng năm trong thời gian kiểm tra hậu quả 28 năm (7,95% so với 9,92%) và giảm đáng kể mức rút vốn tối đa (50,79% so với 31,57%).

Phân tích rủi ro

Các rủi ro chính đến từ tính chính xác của phương pháp tính toán biến động và điều chỉnh tham số bộ lọc. Nếu tính biến động không chính xác, bộ lọc sẽ thất bại. Nếu các tham số bộ lọc được điều chỉnh kém (quá bảo thủ hoặc hung hăng), nó có thể ảnh hưởng tiêu cực đến lợi nhuận chiến lược. Ngoài ra, hiệu suất trong quá khứ không đảm bảo kết quả trong tương lai.

Hướng dẫn tối ưu hóa

Xem xét thêm các chỉ số xác nhận khác như các bộ lọc bổ sung, chẳng hạn như trung bình động dài hạn, chỉ số ADX v.v. Điều chỉnh tham số cũng rất quan trọng, chẳng hạn như kiểm tra các khoảng thời gian xem xét khác nhau, lọc ngưỡng v.v. Các kỹ thuật phân tích chuỗi thời gian và máy học cũng có thể được sử dụng để xây dựng và tối ưu hóa mô hình dự đoán biến động.

Tóm lại

Chiến lược này đã cải thiện đáng kể lợi nhuận và giảm tối đa rút tiền của chiến lược mua & giữ SPY thông qua bộ lọc biến động đơn giản. Nó cho thấy tầm quan trọng của việc xác định chế độ thị trường và phân bổ tài sản. Chúng ta có thể tinh chỉnh thêm bằng cách tối ưu hóa mô hình biến động và thêm các tín hiệu xác nhận.


/*backtest
start: 2023-01-08 00:00:00
end: 2024-01-14 00:00:00
period: 1d
basePeriod: 1h
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/
// 
// @author Sunil Halai
//
// This script has been created to demonstrate the effectiveness of using market regime filters in your trading strategy, and how they can improve your returns and lower your drawdowns
//
// This strategy adds a simple filter (The historical volatility filter, which can be found on my trading profile) to a traditional buy and hold strategy of the index SPY. There are other filters
// that could also be added included a long term moving average / percentile rank filter / ADX filter etc, to improve the returns further.
//
// The filter added closes our long position during periods of volatility that exceed the 95th percentile (or in the top 5% of volatile days)
//
// Have included the back test results since 1993 which is 28 years of data at the time of writing,  Comparing  buy and hold of the SPY (S&P 500), to improved by and hold offered here.
//
// Traditional buy and hold:
//
// Return per year:     7.95   % (ex Dividends)
// Total return :       851.1  %
// Max drawdown:        50.79  %
//
// 'Modified' buy and hold (this script):
//
// Return per year:     9.92    % (ex Dividends)
// Total return:        1412.16 %
// Max drawdown:        31.57   %
//
// Feel free to use some of the market filters in my trading profile to improve and refine your strategies further, or make a copy and play around with the code yourself. This is just 
// a simple example for demo purposes.
//

//@version=4
strategy(title = "Simple way to beat the market [STRATEGY]", shorttitle = "Beat The Market [STRATEGY]", overlay=true, initial_capital=100000, default_qty_type=strategy.percent_of_equity, currency="USD", default_qty_value=100)


upperExtreme = input(title = "Upper percentile filter (Do not trade above this number)", type = input.integer, defval = 95)
lookbackPeriod = input(title = "Lookback period", type = input.integer, defval = 100)

annual = 365
per = timeframe.isintraday or timeframe.isdaily and timeframe.multiplier == 1 ? 1 : 7
hv = lookbackPeriod * stdev(log(close / close[1]), 10) * sqrt(annual / per)

filtered = hv >= percentile_nearest_rank(hv, 100, upperExtreme)

if(not(filtered))
    strategy.entry("LONG", strategy.long)
else
    strategy.close("LONG")

Thêm nữa