Ý tưởng cốt lõi của chiến lược này là kết hợp chỉ số đẩy kép với đường trung bình động cơ bản để thực hiện giao dịch theo xu hướng và đảo ngược xu hướng.
Chiến lược này chủ yếu dựa trên ba chỉ số tùy chỉnh:
Chỉ số đẩy kép (Trend): Tính toán mối quan hệ giữa giá và kênh mua quá mức / bán quá mức để xác định xu hướng tăng và giảm, trả về 1, 0, -1 ba trạng thái.
Kênh mua quá mức / bán quá mức (Tsl): Tính toán các đường ray trên và dưới liên quan đến ATR. Bước qua đường ray trên được coi là mua quá mức và bước qua đường ray dưới được coi là bán quá mức.
Đường trung bình động cơ bản (MA): Tính toán trung bình động đơn giản 20 giai đoạn của giá đóng cửa.
Cụ thể, chiến lược đánh giá giá liệu giá có ở trạng thái tăng, đi ngang hay giảm theo giá trị chỉ số đẩy kép. Khi chỉ số đẩy kép là 1, điều đó có nghĩa là trạng thái tăng; khi chỉ số đẩy kép là -1, điều đó có nghĩa là trạng thái giảm. Tại thời điểm này, nếu giá đi theo cùng một hướng với chỉ số, một chiến lược theo xu hướng được áp dụng, đi dài hoặc ngắn ở đúng vị trí. Nếu giá ở hướng ngược lại của chỉ số, chẳng hạn như chỉ số hiển thị tăng trong khi giá phá vỡ đường ray dưới, một chiến lược đảo ngược được áp dụng bằng cách đi ngắn để nắm bắt lợi nhuận.
Ngoài ra, việc phá vỡ giá trên đường trung bình động cũng phục vụ như một tín hiệu phụ để hướng dẫn hướng giao dịch. Đi dài khi giá phá vỡ đường trung bình lên, và đi ngắn khi giá phá vỡ đường trung bình xuống.
Các chiến lược giao dịch dài cụ thể là như sau:
Chỉ số đẩy kép > 0, giá tăng để phá vỡ đường ray trên, thuộc về xu hướng theo, đi dài.
Chỉ số đẩy kép < 0, giá giảm để phá vỡ đường ray dưới, thuộc về đảo ngược xu hướng, đi ngắn.
Giá đóng > Giá mở > Mức pivot, được coi là phá vỡ pivot để mua, mua.
Giá đóng phá vỡ đường sắt trên, và giá đóng > Đường trung bình động, đi dài.
Các chiến lược giao dịch ngắn là như sau:
Chỉ số đẩy kép < 0, giá giảm để phá vỡ đường ray dưới, thuộc về xu hướng theo, đi ngắn.
Chỉ số đẩy kép > 0, giá tăng để phá vỡ đường ray trên, thuộc về sự đảo ngược xu hướng, đi dài.
Giá mở > Giá đóng < Mức độ trục trục, được coi là phá vỡ trục để đi ngắn, đi ngắn.
Giá đóng phá vỡ qua đường sắt thấp hơn, và giá đóng < Đường trung bình động, đi ngắn.
Chiến lược thoát đơn giản bằng cách dừng lỗ khi giá phá vỡ kênh mua quá mức / bán quá mức một lần nữa.
Chiến lược có những lợi thế sau:
Chỉ số đẩy kép có thể xác định chính xác xu hướng thị trường và là chỉ số cốt lõi của chiến lược.
Kênh mua quá mức / bán quá mức kết hợp với chỉ số có thể phát hiện các cơ hội đảo ngược tiềm năng.
Đường trung bình động cơ bản có thể phục vụ như một tín hiệu lọc phụ để tránh đột phá sai.
Điểm pivot kết hợp với chỉ số đẩy kép tạo ra các điểm giao dịch có khả năng cao.
Nó có cả khả năng theo dõi xu hướng và đảo ngược giao dịch để có nhiều cơ hội lợi nhuận hơn.
Các kênh dừng lỗ mua quá mức / bán quá mức là đơn giản và rõ ràng, có lợi cho kiểm soát rủi ro.
Chiến lược này cũng có những rủi ro sau:
Chỉ số đẩy kép có thể đưa ra tín hiệu sai và cần được lọc với các chỉ số khác.
Giao dịch breakout dễ bị mắc kẹt, vì vậy cần phải dừng lỗ nghiêm ngặt.
Cài đặt thời gian trung bình động không chính xác có thể bỏ lỡ xu hướng hoặc tạo ra tín hiệu sai.
Các điểm pivot cần backtesting để xác minh độ tin cậy xác suất.
Kênh mua quá mức / bán quá mức cần tối ưu hóa các thông số để thích nghi với các sản phẩm khác nhau.
Sự không phù hợp của các thông số chỉ số có thể dẫn đến giao dịch thường xuyên.
Để đối phó với những rủi ro này, các biện pháp sau đây có thể được thực hiện:
Kết hợp các chỉ số khác như K-line, âm lượng để xác minh tín hiệu chỉ số đẩy kép.
Tiếp theo chặt chẽ chiến lược dừng lỗ kênh quá mua / quá bán để dừng lỗ nhanh chóng.
Kiểm tra các thông số thời gian trung bình động khác nhau để tìm ra thông số tối ưu.
Kiểm tra hoàn toàn khả năng chiến lược điểm pivot.
Tối ưu hóa các thông số để tìm ra sự kết hợp tối ưu cho mỗi sản phẩm.
Điều chỉnh các thông số chỉ số để giữ cho toàn bộ hệ thống hoạt động trơn tru.
Chiến lược cũng có thể được tối ưu hóa trong các khía cạnh sau:
Tăng thuật toán học máy để đào tạo chỉ số đẩy kép với dữ liệu lớn. Điều này có thể cải thiện độ chính xác và giảm tín hiệu sai.
Thêm các kênh thích nghi để tự động điều chỉnh các tham số kênh dựa trên biến động thị trường. Điều này có thể cải thiện độ chính xác đột phá.
Sử dụng học tập sâu để trích xuất các chỉ số có thể thay đổi hơn để tối ưu hóa các chiến lược nhập và xuất.
Thêm các thuật toán dừng lỗ tiên tiến có thể theo dõi xu hướng dừng lỗ, tránh bị dừng lại bởi sự đảo ngược.
Thực hiện tối ưu hóa tham số và thử nghiệm kết hợp để cải thiện tính ổn định chiến lược tổng thể.
Thêm các mô-đun quản lý rủi ro để kiểm soát rủi ro khoa học hơn.
Chiến lược này kết hợp theo dõi xu hướng và đảo ngược xu hướng một cách hữu cơ bằng cách đánh giá cấu trúc thị trường với chỉ số đẩy kép và tạo ra các tín hiệu giao dịch với các kênh và đường trung bình động. Nó có những lợi thế về hiệu quả chỉ số tốt, cơ hội giao dịch phong phú và dừng lỗ rõ ràng. Đồng thời, nó cũng có một số rủi ro cần tối ưu hóa hơn nữa để cải thiện sự ổn định. Nhìn chung, chiến lược tích hợp đầy đủ các ý tưởng về giao dịch xu hướng và giao dịch đảo ngược, và đáng để nghiên cứu và áp dụng thêm.
/*backtest start: 2023-08-25 00:00:00 end: 2023-09-24 00:00:00 period: 2h basePeriod: 15m 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/ // © amysojexson //@version=3 strategy(title="Pivots strategy", overlay=true) // Input settings // Create a pull-down menu for the pivot type pivotType = input(title="Pivot Type", options=["Daily", "Intraday", "Weekly"], defval="Daily") // Make toggles for pivot level options plotPP = input(title="Plot PP", type=bool, defval=true) plotS1R1 = input(title="Plot S1 and R1", type=bool, defval=true) plotS2R2 = input(title="Plot S2 and R2", type=bool, defval=true) plotS3R3 = input(title="Plot S3 and R3", type=bool, defval=true) plotTCBC = input(title="Plot S3 and R3", type=bool, defval=true) // Configure session options sessRange = input(title="Trading Session", defval="0800-1600") showSess = input(title="Highlight Session?", type=bool, defval=false) // Enable or disable pivot labels showLabels = input(title="Show Labels?", type=bool, defval=false) // Step 2. Calculate indicator values // Create a function to fetch daily and weekly data GetData(res, data) => security(syminfo.tickerid, res, data[1], lookahead=barmerge.lookahead_on) // Fetch daily and weekly price data dailyHigh = GetData("D", high) dailyLow = GetData("D", low) dailyClose = GetData("D", close) weeklyHigh = GetData("W", high) weeklyLow = GetData("W", low) weeklyClose = GetData("W", close) // Determine session pivot data // First see how the price bar relates to // the session time range inSession = not na(time(timeframe.period, sessRange)[1]) sessStart = inSession and not inSession[1] sessEnd = not inSession and inSession[1] // Determine session price data sessHigh = 0.0 sessLow = 0.0 sessClose = 0.0 sessHigh := sessStart ? high : inSession ? max(high, sessHigh[1]) : na sessLow := sessStart ? low : inSession ? min(low, sessLow[1]) : na sessClose := sessEnd ? close[1] : na // Compute high, low, close from previous intra-day session highPrevSess = 0.0 lowPrevSess = 0.0 closePrevSess = 0.0 highPrevSess := sessEnd ? fixnan(sessHigh) : highPrevSess[1] lowPrevSess := sessEnd ? fixnan(sessLow) : lowPrevSess[1] closePrevSess := sessEnd ? fixnan(sessClose) : closePrevSess[1] // Now figure out which kind of price data // to use for the pivot calculation theHigh = if (pivotType == "Daily") dailyHigh else if (pivotType == "Intraday") highPrevSess else weeklyHigh theLow = if (pivotType == "Daily") dailyLow else if (pivotType == "Intraday") lowPrevSess else weeklyLow theClose = if (pivotType == "Daily") dailyClose else if (pivotType == "Intraday") closePrevSess else weeklyClose // Finally calculate the pivot levels pp = (theHigh + theLow + theClose) / 3 bc= (theHigh + theLow)/2 tc= (pp-bc)+pp r1 = pp+(.382*(theHigh-theLow)) s1 = pp-(.382*(theHigh-theLow)) r2 = pp +(.618*(theHigh-theLow)) s2 = pp -(.618*(theHigh-theLow)) r3 = pp +(1*(theHigh-theLow)) s3 = pp -(1*(theHigh-theLow)) // Step 3. Output indicator data // Plot the various pivot levels plot(series=plotS3R3 ? r3 : na, title="R3", style=circles, linewidth=1, color=#0023FF) plot(series=plotS2R2 ? r2 : na, title="R2", style=circles, linewidth=1, color=#1E90FF) plot(series=plotS1R1 ? r1 : na, title="R1", style=circles, linewidth=1, color=#09E0F3) plot(series=plotTCBC ? tc : na, title="TC", style=circles, linewidth=.75, color=#FF00D1) plot(series=plotPP ? pp : na, title="PP", style=circles, linewidth=1, color=#000000) plot(series=plotTCBC ? bc : na, title="BC", style=circles, linewidth=.75, color=#FF00D1) plot(series=plotS1R1 ? s1 : na, title="S1", style=circles, linewidth=1, color=#09E0F3) plot(series=plotS2R2 ? s2 : na, title="S2", style=circles, linewidth=1, color=#1E90FF) plot(series=plotS3R3 ? s3 : na, title="S3", style=circles, linewidth=1, color=#0023FF) // Display the pivot names on the chart, if applicable newPivots = (showLabels == false) ? false : (pivotType == "Intraday") ? sessEnd : (pivotType == "Daily") ? dayofmonth != dayofmonth[1] : dayofweek == monday and dayofmonth != dayofmonth[1] plotchar(series=newPivots and plotS3R3 ? r3 : na, char='', text="R3", offset=1, location=location.absolute, color=#0023FF, title="R3 label") plotchar(series=newPivots and plotS2R2 ? r2 : na, char='', text="R2", offset=1, location=location.absolute, color=#1E90FF, title="R2 label") plotchar(series=newPivots and plotS1R1 ? r1 : na, char='', text="R1", offset=1, location=location.absolute, color=#09E0F3, title="R1 label") plotchar(series=newPivots and plotTCBC ? r1 : na, char='', text="TC", offset=1, location=location.absolute, color=#FF00D1, title="TC label") plotchar(series=newPivots and plotTCBC ? r1 : na, char='', text="BC", offset=1, location=location.absolute, color=#FF00D1, title="BC label") plotchar(series=newPivots and plotS1R1 ? s1 : na, char='', text="S1", offset=1, location=location.absolute, color=#09E0F3, title="S1 label") plotchar(series=newPivots and plotS2R2 ? s2 : na, char='', text="S2", offset=1, location=location.absolute, color=#1E90FF, title="S2 label") plotchar(series=newPivots and plotS3R3 ? s3 : na, char='', text="S3", offset=1, location=location.absolute, color=#0023FF, title="S3 label") // Highlight the intra-day price data session on the chart bgcolor(color=showSess and inSession and (pivotType == "Intraday") ? orange : na, transp=95) // Step 4. Create indicator alerts alertcondition(condition=cross(close, s3), title="Pivot S3 Cross", message="Prices crossed Pivot S3 level") alertcondition(condition=cross(close, s2), title="Pivot S2 Cross", message="Prices crossed Pivot S2 level") alertcondition(condition=cross(close, s1), title="Pivot S1 Cross", message="Prices crossed Pivot S1 level") alertcondition(condition=cross(close, tc), title="Pivot TC Cross", message="Prices crossed Pivot TC level") alertcondition(condition=cross(close, pp), title="Pivot PP Cross", message="Prices crossed the main Pivot Point level") alertcondition(condition=cross(close, bc), title="Pivot BC Cross", message="Prices crossed Pivot BC level") alertcondition(condition=cross(close, r1), title="Pivot R1 Cross", message="Prices crossed Pivot R1 level") alertcondition(condition=cross(close, r2), title="Pivot R2 Cross", message="Prices crossed Pivot R2 level") alertcondition(condition=cross(close, r3), title="Pivot R3 Cross", message="Prices crossed Pivot R3 level") MA = sma(close, 20) plot(MA, color=red) Factor = input(2, type=float) Pd = input(10, minval=1,maxval = 100) Up = hl2-(Factor*atr(Pd)) Dn = hl2+(Factor*atr(Pd)) TrendUp = 0.0 TrendUp := close[1]>TrendUp[1]? max(Up,TrendUp[1]) : Up TrendDown = 0.0 TrendDown := close[1]<TrendDown[1]? min(Dn,TrendDown[1]) : Dn Trend = 0.0 Trend := close > TrendDown[1] ? 1: close< TrendUp[1]? -1: nz(Trend[1],1) Tsl = Trend==1? TrendUp: TrendDown plot(Tsl, color=blue) if close>open if open<pp if close>pp if close>MA strategy.entry("long", true) if close<open if open>pp if close<pp if close<MA strategy.entry("short", false) strategy.close("long", when = open<Tsl) strategy.close("short", when = open>Tsl)