Chiến lược này dựa trên đường trung bình chuyển động quang phổ, hình thành tín hiệu giao dịch bằng cách đúc kim vàng của đường trung bình chuyển động chậm. Đường trung bình chuyển động quang phổ bao gồm nhiều loại từ đường trung bình chuyển động đơn giản đến đường trung bình chuyển động rung động, có thể được điều chỉnh tự do qua các tham số, có khả năng thích nghi mạnh mẽ.
Chiến lược này sử dụng hàm đường trung bình chuyển động biến để tạo ra 12 loại đường trung bình chuyển động khác nhau. Nguyên tắc cơ bản là tính toán hai đường trung bình chuyển động (Close MA) và Slow MA (Open MA), tạo ra tín hiệu mua khi đường nhanh đi qua đường chậm và bán khi đường nhanh đi qua đường chậm.
Khóa học quan trọng là tạo ra hai đường trung bình di chuyển bằng hàm biến thể:closeSeries = variant(basisType, close, basisLen, offsetSigma, offsetALMA)
vàopenSeries = variant(basisType, open, basisLen, offsetSigma, offsetALMA)
Các hàm biến thể đóng gói 12 loại phương pháp tính toán đường trung bình khác nhau, được lựa chọn tự do thông qua các tham số basisType.
Các logic cơ bản để tạo ra tín hiệu giao dịch là:longCond = xlong
vàshortCond = xshort
Trong khi đó, một số người nói rằng, việc sử dụng đường dây chậm trên đường dây nhanh sẽ làm nhiều hơn, và đường dây chậm dưới đường dây nhanh sẽ làm trống.
Các quy tắc tham gia chiến lược là tăng giá khi các điều kiện longcond hoặc shortcond được đáp ứng. Các quy tắc stop-loss là dừng giá hoặc dừng giá khi giá di chuyển đến một số điểm stop-loss.
Lợi thế lớn nhất của chiến lược này là có thể tự do kết hợp nhiều loại đường trung bình di chuyển khác nhau. Các chu kỳ thị trường khác nhau, không rõ đường trung bình di chuyển nào phù hợp nhất, chiến lược này cung cấp khả năng tùy chỉnh mạnh mẽ. Người dùng có thể xác định sự kết hợp tốt nhất của các tham số thông qua thử nghiệm lặp đi lặp lại để đưa ra các giải pháp tối ưu nhất cho một thị trường cụ thể.
Một lợi thế khác là chính sách logic đơn giản rõ ràng, nhưng cung cấp các tính năng mạnh mẽ. Người dùng dễ dàng hiểu và sử dụng chính sách. Đồng thời, các tham số đầu vào phong phú cũng cung cấp đủ không gian tối ưu cho người dùng cao cấp.
Rủi ro lớn nhất của chiến lược này là có một mức độ chậm lại của đường trung bình chuyển động phổ rộng. Có thể gây ra tổn thất lớn hơn khi xảy ra sự đột phá giá bất thường. Ngoài ra, nếu lựa chọn các thông số không đúng, nó cũng có thể dẫn đến tần suất giao dịch quá cao hoặc tạo ra tín hiệu dư thừa.
Để giảm rủi ro, khuyến cáo kết hợp với các chỉ số khác để đánh giá hiệu quả của tín hiệu và tránh sự đột phá giả. Ngoài ra, tối ưu hóa và kiểm tra lại các tham số cũng rất cần thiết, cần phải thử nghiệm nhiều lần để tìm ra sự kết hợp tốt nhất.
Chiến lược này có một vài hướng tối ưu hóa chính:
Bằng cách tối ưu hóa các hướng trên, bạn có thể tiếp tục cải thiện hiệu suất thực tế của chiến lược.
Chiến lược giao dịch dựa trên đường trung bình chuyển động phổ rộng đạt được tính linh hoạt cao. Nó cung cấp tính năng tùy chỉnh mạnh mẽ, người dùng có thể tự do chọn và kết hợp các loại đường trung bình khác nhau. Chiến lược logic đơn giản, rõ ràng và dễ sử dụng, đồng thời cung cấp nhiều không gian tối ưu hóa.
/*backtest start: 2023-01-18 00:00:00 end: 2024-01-24 00:00:00 period: 1d basePeriod: 1h exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ //@version=4 // strategy(title="Long/Short", shorttitle="Banana Maker", overlay=true, pyramiding=0, default_qty_type=strategy.percent_of_equity, default_qty_value=100, calc_on_every_tick=false) // === INPUTS === useRes = input(defval=true, title="Use Alternate Resolution?") intRes = input(defval=7, title="Multiplier for Alernate Resolution") stratRes = timeframe.ismonthly ? tostring(timeframe.multiplier * intRes, "###M") : timeframe.isweekly ? tostring(timeframe.multiplier * intRes, "###W") : timeframe.isdaily ? tostring(timeframe.multiplier * intRes, "###D") : timeframe.isintraday ? tostring(timeframe.multiplier * intRes, "####") : '60' basisType = input(defval="DEMA", title="MA Type: ", options=["SMA", "EMA", "DEMA", "TEMA", "WMA", "VWMA", "SMMA", "HullMA", "LSMA", "ALMA", "SSMA", "TMA"]) basisLen = input(defval=8, title="MA Period", minval=1) offsetSigma = input(defval=6, title="Offset for LSMA / Sigma for ALMA", minval=0) offsetALMA = input(defval=0.85, title="Offset for ALMA", minval=0, step=0.01) scolor = input(false, title="Show coloured Bars to indicate Trend?") delayOffset = input(defval=0, title="Delay Open/Close MA (Forces Non-Repainting)", minval=0, step=1) tradeType = input("BOTH", title="What trades should be taken : ", options=["LONG", "SHORT", "BOTH", "NONE"]) // === /INPUTS === // Constants colours that include fully non-transparent option. green100 = #008000FF lime100 = #6ad279 red100 = #FF0000FF blue100 = #0000FFFF aqua100 = #00FFFFFF darkred100 = #8B0000FF gray100 = #808080FF // === BASE FUNCTIONS === variant(type, src, len, offSig, offALMA) => v1 = sma(src, len) // Simple v2 = ema(src, len) // Exponential v3 = 2 * v2 - ema(v2, len) // Double Exponential v4 = 3 * (v2 - ema(v2, len)) + ema(ema(v2, len), len) // Triple Exponential v5 = wma(src, len) // Weighted v6 = vwma(src, len) // Volume Weighted v7 = 0.0 sma_1 = sma(src, len) // Smoothed v7 := na(v7[1]) ? sma_1 : (v7[1] * (len - 1) + src) / len v8 = wma(2 * wma(src, len / 2) - wma(src, len), round(sqrt(len))) // Hull v9 = linreg(src, len, offSig) // Least Squares v10 = alma(src, len, offALMA, offSig) // Arnaud Legoux v11 = sma(v1, len) // Triangular (extreme smooth) // SuperSmoother filter // © 2013 John F. Ehlers a1 = exp(-1.414 * 3.14159 / len) b1 = 2 * a1 * cos(1.414 * 3.14159 / len) c2 = b1 c3 = -a1 * a1 c1 = 1 - c2 - c3 v12 = 0.0 v12 := c1 * (src + nz(src[1])) / 2 + c2 * nz(v12[1]) + c3 * nz(v12[2]) type == "EMA" ? v2 : type == "DEMA" ? v3 : type == "TEMA" ? v4 : type == "WMA" ? v5 : type == "VWMA" ? v6 : type == "SMMA" ? v7 : type == "HullMA" ? v8 : type == "LSMA" ? v9 : type == "ALMA" ? v10 : type == "TMA" ? v11 : type == "SSMA" ? v12 : v1 // security wrapper for repeat calls* NEEDS REFINEMENT- backtesting this shows repaint. need new wrapper reso(exp, use, res) => security_1 = security(syminfo.tickerid, res, exp, gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_on) use ? security_1 : exp // === /BASE FUNCTIONS === // === SERIES SETUP === closeSeries = variant(basisType, close[delayOffset], basisLen, offsetSigma, offsetALMA) openSeries = variant(basisType, open[delayOffset], basisLen, offsetSigma, offsetALMA) // === /SERIES === // === PLOTTING === // alt resulution closeSeriesAlt = reso(closeSeries, useRes, stratRes) openSeriesAlt = reso(openSeries, useRes, stratRes) // trendColour = closeSeriesAlt > openSeriesAlt ? color.green : color.red bcolour = closeSeries > openSeriesAlt ? lime100 : red100 barcolor(scolor ? bcolour : na, title="Bar Colours") closeP = plot(closeSeriesAlt, title="Close Series", color=trendColour, linewidth=0, style=plot.style_line, transp=1) openP = plot(openSeriesAlt, title="Open Series", color=trendColour, linewidth=0, style=plot.style_line, transp=1) fill(closeP, openP, color=trendColour, transp=80) // === /PLOTTING === // // // === ALERT conditions xlong = crossover(closeSeriesAlt, openSeriesAlt) xshort = crossunder(closeSeriesAlt, openSeriesAlt) longCond = xlong // alternative: longCond[1]? false : (xlong or xlong[1]) and close>closeSeriesAlt and close>=open shortCond = xshort // alternative: shortCond[1]? false : (xshort or xshort[1]) and close<closeSeriesAlt and close<=open // === /ALERT conditions. needs work in study mode. the banana maker is the study script. // Create alert for cross, shunt back 1 if source is not 'open', this should prevent repaint issue. //shunt = RSIsrc == open ? 0 : 1 //shunt = 0 //c_alert = (buy[shunt]==1 or sell[shunt]==1) //alertcondition(c_alert, title="QQECROSS Alert", message="QQECROSS Alert") // show only when alert condition is met and bar closed. //plotshape(c_alert,title= "Alert Indicator Closed", location=location.bottom, color=sell[shunt]==1?red:green, transp=0, style=shape.circle) //Repaint city, study mode will help but wont trigger the alerts // === STRATEGY === // stop loss slPoints = input(defval=0, title="Initial Stop Loss Points (zero to disable)", minval=0) tpPoints = input(defval=0, title="Initial Target Profit Points (zero for disable)", minval=0) // Include bar limiting algorithm ebar = input(defval=1000, title="Number of Bars for Back Testing", minval=0) dummy = input(false, title="- SET to ZERO for Daily or Longer Timeframes") // // Calculate how many mars since last bar tdays = (timenow - time) / 60000.0 // number of minutes since last bar tdays := timeframe.ismonthly ? tdays / 1440.0 / 5.0 / 4.3 / timeframe.multiplier : timeframe.isweekly ? tdays / 1440.0 / 5.0 / timeframe.multiplier : timeframe.isdaily ? tdays / 1440.0 / timeframe.multiplier : tdays / timeframe.multiplier // number of bars since last bar // //set up exit parameters TP = tpPoints > 0 ? tpPoints : na SL = slPoints > 0 ? slPoints : na // Make sure we are within the bar range, Set up entries and exit conditions if (ebar == 0 or tdays <= ebar) and tradeType != "NONE" strategy.entry("long", strategy.long, when=longCond == true and tradeType != "SHORT") strategy.entry("short", strategy.short, when=shortCond == true and tradeType != "LONG") strategy.close("long", when=shortCond == true and tradeType == "LONG") strategy.close("short", when=longCond == true and tradeType == "SHORT") strategy.exit("XL", from_entry="long", profit=TP, loss=SL) strategy.exit("XS", from_entry="short", profit=TP, loss=SL) // === /STRATEGY === // eof